[SystemZ] Implement conditional returns
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
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index be729d3..309c4e4 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -109,6 +109,85 @@
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)
diff --git a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
index 37a6674..59a3670 100644
--- a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
@@ -380,17 +380,26 @@
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.
@@ -403,28 +412,37 @@
(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;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index d2b5070..0dc32b5 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -508,13 +508,24 @@
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;
}
@@ -529,6 +540,13 @@
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");
@@ -546,6 +564,13 @@
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;
}
@@ -1253,24 +1278,62 @@
}
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;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
index 06ed3eb..baa126f 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -111,6 +111,16 @@
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;
@@ -165,6 +175,8 @@
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,
@@ -233,6 +245,7 @@
// 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
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index 4ecca97..8a58b0d 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -36,6 +36,22 @@
let isReturn = 1, isTerminator = 1, isBarrier = 1, hasCtrlDep = 1 in
def Return : Alias<2, (outs), (ins), [(z_retflag)]>;
+// A conditional return instruction (bcr <cond>, %r14).
+let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, CCMaskFirst = 1, Uses = [CC] in
+ def CondReturn : Alias<2, (outs), (ins cond4:$valid, cond4:$R1), []>;
+
+// Fused compare and conditional returns.
+let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, Uses = [CC] in {
+ def CRBReturn : Alias<6, (outs), (ins GR32:$R1, GR32:$R2, cond4:$M3), []>;
+ def CGRBReturn : Alias<6, (outs), (ins GR64:$R1, GR64:$R2, cond4:$M3), []>;
+ def CIBReturn : Alias<6, (outs), (ins GR32:$R1, imm32sx8:$I2, cond4:$M3), []>;
+ def CGIBReturn : Alias<6, (outs), (ins GR64:$R1, imm64sx8:$I2, cond4:$M3), []>;
+ def CLRBReturn : Alias<6, (outs), (ins GR32:$R1, GR32:$R2, cond4:$M3), []>;
+ def CLGRBReturn : Alias<6, (outs), (ins GR64:$R1, GR64:$R2, cond4:$M3), []>;
+ def CLIBReturn : Alias<6, (outs), (ins GR32:$R1, imm32zx8:$I2, cond4:$M3), []>;
+ def CLGIBReturn : Alias<6, (outs), (ins GR64:$R1, imm64zx8:$I2, cond4:$M3), []>;
+}
+
// Unconditional branches. R1 is the condition-code mask (all 1s).
let isBranch = 1, isTerminator = 1, isBarrier = 1, R1 = 15 in {
let isIndirectBranch = 1 in
@@ -62,15 +78,20 @@
[(z_br_ccmask cond4:$valid, cond4:$R1, bb:$I2)]>;
def BRCL : InstRIL<0xC04, (outs), (ins cond4:$valid, cond4:$R1,
brtarget32:$I2), "jg$R1\t$I2", []>;
+ let isIndirectBranch = 1 in
+ def BCR : InstRR<0x07, (outs), (ins cond4:$valid, cond4:$R1, GR64:$R2),
+ "b${R1}r\t$R2", []>;
}
def AsmBRC : InstRI<0xA74, (outs), (ins imm32zx4:$R1, brtarget16:$I2),
"brc\t$R1, $I2", []>;
def AsmBRCL : InstRIL<0xC04, (outs), (ins imm32zx4:$R1, brtarget32:$I2),
"brcl\t$R1, $I2", []>;
- def AsmBC : InstRX<0x47, (outs), (ins imm32zx4:$R1, bdxaddr12only:$XBD2),
- "bc\t$R1, $XBD2", []>;
- def AsmBCR : InstRR<0x07, (outs), (ins imm32zx4:$R1, GR64:$R2),
- "bcr\t$R1, $R2", []>;
+ let isIndirectBranch = 1 in {
+ def AsmBC : InstRX<0x47, (outs), (ins imm32zx4:$R1, bdxaddr12only:$XBD2),
+ "bc\t$R1, $XBD2", []>;
+ def AsmBCR : InstRR<0x07, (outs), (ins imm32zx4:$R1, GR64:$R2),
+ "bcr\t$R1, $R2", []>;
+ }
}
def AsmNop : InstAlias<"nop\t$XBD", (AsmBC 0, bdxaddr12only:$XBD), 0>;
@@ -110,30 +131,32 @@
def LGIJ : InstRIEc<0xEC7D, (outs), (ins GR64:$R1, imm64zx8:$I2, ccmask:$M3,
brtarget16:$RI4),
"clgij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
- def RB : InstRRS<0xECF6, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
- bdaddr12only:$BD4),
- "crb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
- def GRB : InstRRS<0xECE4, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
- bdaddr12only:$BD4),
- "cgrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
- def IB : InstRIS<0xECFE, (outs), (ins GR32:$R1, imm32sx8:$I2, ccmask:$M3,
- bdaddr12only:$BD4),
- "cib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
- def GIB : InstRIS<0xECFC, (outs), (ins GR64:$R1, imm64sx8:$I2, ccmask:$M3,
- bdaddr12only:$BD4),
- "cgib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
- def LRB : InstRRS<0xECF7, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
- bdaddr12only:$BD4),
- "clrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
- def LGRB : InstRRS<0xECE5, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
- bdaddr12only:$BD4),
- "clgrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
- def LIB : InstRIS<0xECFF, (outs), (ins GR32:$R1, imm32zx8:$I2, ccmask:$M3,
- bdaddr12only:$BD4),
- "clib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
- def LGIB : InstRIS<0xECFD, (outs), (ins GR64:$R1, imm64zx8:$I2, ccmask:$M3,
- bdaddr12only:$BD4),
- "clgib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
+ let isIndirectBranch = 1 in {
+ def RB : InstRRS<0xECF6, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "crb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
+ def GRB : InstRRS<0xECE4, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "cgrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
+ def IB : InstRIS<0xECFE, (outs), (ins GR32:$R1, imm32sx8:$I2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "cib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
+ def GIB : InstRIS<0xECFC, (outs), (ins GR64:$R1, imm64sx8:$I2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "cgib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
+ def LRB : InstRRS<0xECF7, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "clrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
+ def LGRB : InstRRS<0xECE5, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "clgrb"##pos1##"\t$R1, $R2, "##pos2##"$BD4", []>;
+ def LIB : InstRIS<0xECFF, (outs), (ins GR32:$R1, imm32zx8:$I2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "clib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
+ def LGIB : InstRIS<0xECFD, (outs), (ins GR64:$R1, imm64zx8:$I2, ccmask:$M3,
+ bdaddr12only:$BD4),
+ "clgib"##pos1##"\t$R1, $I2, "##pos2##"$BD4", []>;
+ }
}
}
let isCodeGenOnly = 1 in
@@ -205,30 +228,32 @@
def CLGIJ : InstRIEc<0xEC7D, (outs), (ins GR64:$R1, imm64zx8:$I2,
brtarget16:$RI4),
"clgij"##name##"\t$R1, $I2, $RI4", []>;
- def CRB : InstRRS<0xECF6, (outs), (ins GR32:$R1, GR32:$R2,
- bdaddr12only:$BD4),
- "crb"##name##"\t$R1, $R2, $BD4", []>;
- def CGRB : InstRRS<0xECE4, (outs), (ins GR64:$R1, GR64:$R2,
- bdaddr12only:$BD4),
- "cgrb"##name##"\t$R1, $R2, $BD4", []>;
- def CIB : InstRIS<0xECFE, (outs), (ins GR32:$R1, imm32sx8:$I2,
- bdaddr12only:$BD4),
- "cib"##name##"\t$R1, $I2, $BD4", []>;
- def CGIB : InstRIS<0xECFC, (outs), (ins GR64:$R1, imm64sx8:$I2,
- bdaddr12only:$BD4),
- "cgib"##name##"\t$R1, $I2, $BD4", []>;
- def CLRB : InstRRS<0xECF7, (outs), (ins GR32:$R1, GR32:$R2,
- bdaddr12only:$BD4),
- "clrb"##name##"\t$R1, $R2, $BD4", []>;
- def CLGRB : InstRRS<0xECE5, (outs), (ins GR64:$R1, GR64:$R2,
- bdaddr12only:$BD4),
- "clgrb"##name##"\t$R1, $R2, $BD4", []>;
- def CLIB : InstRIS<0xECFF, (outs), (ins GR32:$R1, imm32zx8:$I2,
- bdaddr12only:$BD4),
- "clib"##name##"\t$R1, $I2, $BD4", []>;
- def CLGIB : InstRIS<0xECFD, (outs), (ins GR64:$R1, imm64zx8:$I2,
- bdaddr12only:$BD4),
- "clgib"##name##"\t$R1, $I2, $BD4", []>;
+ let isIndirectBranch = 1 in {
+ def CRB : InstRRS<0xECF6, (outs), (ins GR32:$R1, GR32:$R2,
+ bdaddr12only:$BD4),
+ "crb"##name##"\t$R1, $R2, $BD4", []>;
+ def CGRB : InstRRS<0xECE4, (outs), (ins GR64:$R1, GR64:$R2,
+ bdaddr12only:$BD4),
+ "cgrb"##name##"\t$R1, $R2, $BD4", []>;
+ def CIB : InstRIS<0xECFE, (outs), (ins GR32:$R1, imm32sx8:$I2,
+ bdaddr12only:$BD4),
+ "cib"##name##"\t$R1, $I2, $BD4", []>;
+ def CGIB : InstRIS<0xECFC, (outs), (ins GR64:$R1, imm64sx8:$I2,
+ bdaddr12only:$BD4),
+ "cgib"##name##"\t$R1, $I2, $BD4", []>;
+ def CLRB : InstRRS<0xECF7, (outs), (ins GR32:$R1, GR32:$R2,
+ bdaddr12only:$BD4),
+ "clrb"##name##"\t$R1, $R2, $BD4", []>;
+ def CLGRB : InstRRS<0xECE5, (outs), (ins GR64:$R1, GR64:$R2,
+ bdaddr12only:$BD4),
+ "clgrb"##name##"\t$R1, $R2, $BD4", []>;
+ def CLIB : InstRIS<0xECFF, (outs), (ins GR32:$R1, imm32zx8:$I2,
+ bdaddr12only:$BD4),
+ "clib"##name##"\t$R1, $I2, $BD4", []>;
+ def CLGIB : InstRIS<0xECFD, (outs), (ins GR64:$R1, imm64zx8:$I2,
+ bdaddr12only:$BD4),
+ "clgib"##name##"\t$R1, $I2, $BD4", []>;
+ }
}
}
multiclass IntCondExtendedMnemonic<bits<4> ccmask, string name1, string name2>
diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
index f305e85..baa6907 100644
--- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -125,8 +125,7 @@
}
void SystemZPassConfig::addPreSched2() {
- if (getOptLevel() != CodeGenOpt::None &&
- getSystemZTargetMachine().getSubtargetImpl()->hasLoadStoreOnCond())
+ if (getOptLevel() != CodeGenOpt::None)
addPass(&IfConverterID);
}