Skip to content

Commit

Permalink
[SystemZ] Implement conditional returns
Browse files Browse the repository at this point in the history
Return is now considered a predicable instruction, and is converted
to a newly-added CondReturn (which maps to BCR to %r14) instruction by
the if conversion pass.

Also, fused compare-and-branch transform knows about conditional
returns, emitting the proper fused instructions for them.

This transform triggers on a *lot* of tests, hence the huge diffstat.
The changes are mostly jX to br %r14 -> bXr %r14.

Author: koriakin

Differential Revision: http://reviews.llvm.org/D17339

llvm-svn: 265689
  • Loading branch information
uweigand committed Apr 7, 2016
1 parent 14e351a commit 2eb027d
Show file tree
Hide file tree
Showing 79 changed files with 1,023 additions and 813 deletions.
79 changes: 79 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Expand Up @@ -109,6 +109,85 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
break;

case SystemZ::CondReturn:
LoweredMI = MCInstBuilder(SystemZ::BCR)
.addImm(MI->getOperand(0).getImm())
.addImm(MI->getOperand(1).getImm())
.addReg(SystemZ::R14D);
break;

case SystemZ::CRBReturn:
LoweredMI = MCInstBuilder(SystemZ::CRB)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CGRBReturn:
LoweredMI = MCInstBuilder(SystemZ::CGRB)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CIBReturn:
LoweredMI = MCInstBuilder(SystemZ::CIB)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CGIBReturn:
LoweredMI = MCInstBuilder(SystemZ::CGIB)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CLRBReturn:
LoweredMI = MCInstBuilder(SystemZ::CLRB)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CLGRBReturn:
LoweredMI = MCInstBuilder(SystemZ::CLGRB)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CLIBReturn:
LoweredMI = MCInstBuilder(SystemZ::CLIB)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CLGIBReturn:
LoweredMI = MCInstBuilder(SystemZ::CLGIB)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(MI->getOperand(2).getImm())
.addReg(SystemZ::R14D)
.addImm(0);
break;

case SystemZ::CallBRASL:
LoweredMI = MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
Expand Down
52 changes: 35 additions & 17 deletions llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
Expand Up @@ -380,17 +380,26 @@ optimizeCompareZero(MachineInstr *Compare,
bool SystemZElimCompare::
fuseCompareAndBranch(MachineInstr *Compare,
SmallVectorImpl<MachineInstr *> &CCUsers) {
// See whether we have a comparison that can be fused.
unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
Compare);
if (!FusedOpcode)
return false;

// See whether we have a single branch with which to fuse.
if (CCUsers.size() != 1)
return false;
MachineInstr *Branch = CCUsers[0];
if (Branch->getOpcode() != SystemZ::BRC)
SystemZII::CompareAndBranchType Type;
switch (Branch->getOpcode()) {
case SystemZ::BRC:
Type = SystemZII::CompareAndBranch;
break;
case SystemZ::CondReturn:
Type = SystemZII::CompareAndReturn;
break;
default:
return false;
}

// See whether we have a comparison that can be fused.
unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
Type, Compare);
if (!FusedOpcode)
return false;

// Make sure that the operands are available at the branch.
Expand All @@ -403,28 +412,37 @@ fuseCompareAndBranch(MachineInstr *Compare,
(SrcReg2 && MBBI->modifiesRegister(SrcReg2, TRI)))
return false;

// Read the branch mask and target.
// Read the branch mask and target (if applicable).
MachineOperand CCMask(MBBI->getOperand(1));
MachineOperand Target(MBBI->getOperand(2));
assert((CCMask.getImm() & ~SystemZ::CCMASK_ICMP) == 0 &&
"Invalid condition-code mask for integer comparison");
// This is only valid for CompareAndBranch.
MachineOperand Target(MBBI->getOperand(
Type == SystemZII::CompareAndBranch ? 2 : 0));

// Clear out all current operands.
int CCUse = MBBI->findRegisterUseOperandIdx(SystemZ::CC, false, TRI);
assert(CCUse >= 0 && "BRC must use CC");
assert(CCUse >= 0 && "BRC/BCR must use CC");
Branch->RemoveOperand(CCUse);
Branch->RemoveOperand(2);
if (Type == SystemZII::CompareAndBranch)
Branch->RemoveOperand(2);
Branch->RemoveOperand(1);
Branch->RemoveOperand(0);

// Rebuild Branch as a fused compare and branch.
Branch->setDesc(TII->get(FusedOpcode));
MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
.addOperand(Compare->getOperand(0))
.addOperand(Compare->getOperand(1))
.addOperand(CCMask)
.addOperand(Target)
.addReg(SystemZ::CC, RegState::ImplicitDefine);
MachineInstrBuilder MIB(*Branch->getParent()->getParent(), Branch);
MIB.addOperand(Compare->getOperand(0))
.addOperand(Compare->getOperand(1))
.addOperand(CCMask);

if (Type == SystemZII::CompareAndBranch) {
// Only conditional branches define CC, as they may be converted back
// to a non-fused branch because of a long displacement. Conditional
// returns don't have that problem.
MIB.addOperand(Target)
.addReg(SystemZ::CC, RegState::ImplicitDefine);
}

// Clear any intervening kills of SrcReg and SrcReg2.
MBBI = Compare;
Expand Down
89 changes: 76 additions & 13 deletions llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
Expand Up @@ -508,13 +508,24 @@ static unsigned getConditionalMove(unsigned Opcode) {

bool SystemZInstrInfo::isPredicable(MachineInstr &MI) const {
unsigned Opcode = MI.getOpcode();
return STI.hasLoadStoreOnCond() && getConditionalMove(Opcode);
if (STI.hasLoadStoreOnCond() && getConditionalMove(Opcode))
return true;
if (Opcode == SystemZ::Return)
return true;
return false;
}

bool SystemZInstrInfo::
isProfitableToIfCvt(MachineBasicBlock &MBB,
unsigned NumCycles, unsigned ExtraPredCycles,
BranchProbability Probability) const {
// Avoid using conditional returns at the end of a loop (since then
// we'd need to emit an unconditional branch to the beginning anyway,
// making the loop body longer). This doesn't apply for low-probability
// loops (eg. compare-and-swap retry), so just decide based on branch
// probability instead of looping structure.
if (MBB.succ_empty() && Probability < BranchProbability(1, 8))
return false;
// For now only convert single instructions.
return NumCycles == 1;
}
Expand All @@ -529,6 +540,13 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB,
return false;
}

bool SystemZInstrInfo::
isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
BranchProbability Probability) const {
// For now only duplicate single instructions.
return NumCycles == 1;
}

bool SystemZInstrInfo::PredicateInstruction(
MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {
assert(Pred.size() == 2 && "Invalid condition");
Expand All @@ -546,6 +564,13 @@ bool SystemZInstrInfo::PredicateInstruction(
return true;
}
}
if (Opcode == SystemZ::Return) {
MI.setDesc(get(SystemZ::CondReturn));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
.addImm(CCValid).addImm(CCMask)
.addReg(SystemZ::CC, RegState::Implicit);
return true;
}
return false;
}

Expand Down Expand Up @@ -1253,24 +1278,62 @@ bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
}

unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
SystemZII::CompareAndBranchType Type,
const MachineInstr *MI) const {
switch (Opcode) {
case SystemZ::CR:
return SystemZ::CRJ;
case SystemZ::CGR:
return SystemZ::CGRJ;
case SystemZ::CHI:
return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CIJ : 0;
case SystemZ::CGHI:
return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CGIJ : 0;
case SystemZ::CLR:
return SystemZ::CLRJ;
case SystemZ::CLGR:
return SystemZ::CLGRJ;
if (!(MI && isInt<8>(MI->getOperand(1).getImm())))
return 0;
break;
case SystemZ::CLFI:
return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLIJ : 0;
case SystemZ::CLGFI:
return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLGIJ : 0;
if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
return 0;
}
switch (Type) {
case SystemZII::CompareAndBranch:
switch (Opcode) {
case SystemZ::CR:
return SystemZ::CRJ;
case SystemZ::CGR:
return SystemZ::CGRJ;
case SystemZ::CHI:
return SystemZ::CIJ;
case SystemZ::CGHI:
return SystemZ::CGIJ;
case SystemZ::CLR:
return SystemZ::CLRJ;
case SystemZ::CLGR:
return SystemZ::CLGRJ;
case SystemZ::CLFI:
return SystemZ::CLIJ;
case SystemZ::CLGFI:
return SystemZ::CLGIJ;
default:
return 0;
}
case SystemZII::CompareAndReturn:
switch (Opcode) {
case SystemZ::CR:
return SystemZ::CRBReturn;
case SystemZ::CGR:
return SystemZ::CGRBReturn;
case SystemZ::CHI:
return SystemZ::CIBReturn;
case SystemZ::CGHI:
return SystemZ::CGIBReturn;
case SystemZ::CLR:
return SystemZ::CLRBReturn;
case SystemZ::CLGR:
return SystemZ::CLGRBReturn;
case SystemZ::CLFI:
return SystemZ::CLIBReturn;
case SystemZ::CLGFI:
return SystemZ::CLGIBReturn;
default:
return 0;
}
default:
return 0;
}
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZInstrInfo.h
Expand Up @@ -111,6 +111,16 @@ struct Branch {
const MachineOperand *target)
: Type(type), CCValid(ccValid), CCMask(ccMask), Target(target) {}
};
// Kinds of branch in compare-and-branch instructions. Together with type
// of the converted compare, this identifies the compare-and-branch
// instruction.
enum CompareAndBranchType {
// Relative branch - CRJ etc.
CompareAndBranch,

// Indirect branch, used for return - CRBReturn etc.
CompareAndReturn
};
} // end namespace SystemZII

class SystemZSubtarget;
Expand Down Expand Up @@ -165,6 +175,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
MachineBasicBlock &FMBB,
unsigned NumCyclesF, unsigned ExtraPredCyclesF,
BranchProbability Probability) const override;
bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
BranchProbability Probability) const override;
bool PredicateInstruction(MachineInstr &MI,
ArrayRef<MachineOperand> Pred) const override;
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
Expand Down Expand Up @@ -233,6 +245,7 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
// BRANCH exists, return the opcode for the latter, otherwise return 0.
// MI, if nonnull, is the compare instruction.
unsigned getCompareAndBranch(unsigned Opcode,
SystemZII::CompareAndBranchType Type,
const MachineInstr *MI = nullptr) const;

// Emit code before MBBI in MI to move immediate value Value into
Expand Down

0 comments on commit 2eb027d

Please sign in to comment.