summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorZhan Jun Liau <zhanjunl@ca.ibm.com>2016-06-10 19:58:10 +0000
committerZhan Jun Liau <zhanjunl@ca.ibm.com>2016-06-10 19:58:10 +0000
commitab42cbce9807778d3087454f483dc7266833975a (patch)
treedb74411e2bea60c36ebf25b3c34fdffb38d8c8ae /llvm/lib/Target
parentf3af841462ad6dfc6c2fee5a441400b4bded931c (diff)
downloadbcm5719-llvm-ab42cbce9807778d3087454f483dc7266833975a.tar.gz
bcm5719-llvm-ab42cbce9807778d3087454f483dc7266833975a.zip
[SystemZ] Support Compare and Traps
Support and generate Compare and Traps like CRT, CIT, etc. Support Trap as legal DAG opcodes and generate "j .+2" for them by default. Add support for Conditional Traps and use the If Converter to convert them into the corresponding compare and trap opcodes. Differential Revision: http://reviews.llvm.org/D21155 llvm-svn: 272419
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/SystemZ/README.txt6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp30
-rw-r--r--llvm/lib/Target/SystemZ/SystemZElimCompare.cpp19
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.cpp3
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrFormats.td34
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp41
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.h21
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.td83
8 files changed, 193 insertions, 44 deletions
diff --git a/llvm/lib/Target/SystemZ/README.txt b/llvm/lib/Target/SystemZ/README.txt
index 7d58480e0c8..957a91e7379 100644
--- a/llvm/lib/Target/SystemZ/README.txt
+++ b/llvm/lib/Target/SystemZ/README.txt
@@ -158,12 +158,6 @@ We might want to model all access registers and use them to spill
--
-We might want to use 'j .+2' as a trap instruction, like gcc does. It can
-also be made conditional like the return instruction, allowing us to utilize
-compare-and-trap and load-and-trap instructions.
-
---
-
We might want to use the 'overflow' condition of eg. AR to support
llvm.sadd.with.overflow.i32 and related instructions - the generated code
for signed overflow check is currently quite bad. This would improve
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 9d8fb8c9e29..9c0f327ff74 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -430,6 +430,36 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutStreamer->emitRawComment("MEMBARRIER");
return;
+ // We want to emit "j .+2" for traps, jumping to the relative immediate field
+ // of the jump instruction, which is an illegal instruction. We cannot emit a
+ // "." symbol, so create and emit a temp label before the instruction and use
+ // that instead.
+ case SystemZ::Trap: {
+ MCSymbol *DotSym = OutContext.createTempSymbol();
+ OutStreamer->EmitLabel(DotSym);
+
+ const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
+ const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
+ LoweredMI = MCInstBuilder(SystemZ::J)
+ .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
+ }
+ break;
+
+ // Conditional traps will create a branch on condition instruction that jumps
+ // to the relative immediate field of the jump instruction. (eg. "jo .+2")
+ case SystemZ::CondTrap: {
+ MCSymbol *DotSym = OutContext.createTempSymbol();
+ OutStreamer->EmitLabel(DotSym);
+
+ const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
+ const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
+ LoweredMI = MCInstBuilder(SystemZ::BRC)
+ .addImm(MI->getOperand(0).getImm())
+ .addImm(MI->getOperand(1).getImm())
+ .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
+ }
+ break;
+
default:
Lower.lower(MI, LoweredMI);
break;
diff --git a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
index 1c791b6521d..9f9206814cf 100644
--- a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
@@ -78,8 +78,8 @@ private:
SmallVectorImpl<MachineInstr *> &CCUsers);
bool optimizeCompareZero(MachineInstr *Compare,
SmallVectorImpl<MachineInstr *> &CCUsers);
- bool fuseCompareAndBranch(MachineInstr *Compare,
- SmallVectorImpl<MachineInstr *> &CCUsers);
+ bool fuseCompareOperations(MachineInstr *Compare,
+ SmallVectorImpl<MachineInstr *> &CCUsers);
const SystemZInstrInfo *TII;
const TargetRegisterInfo *TRI;
@@ -377,13 +377,13 @@ optimizeCompareZero(MachineInstr *Compare,
// Try to fuse comparison instruction Compare into a later branch.
// Return true on success and if Compare is therefore redundant.
bool SystemZElimCompare::
-fuseCompareAndBranch(MachineInstr *Compare,
- SmallVectorImpl<MachineInstr *> &CCUsers) {
+fuseCompareOperations(MachineInstr *Compare,
+ SmallVectorImpl<MachineInstr *> &CCUsers) {
// See whether we have a single branch with which to fuse.
if (CCUsers.size() != 1)
return false;
MachineInstr *Branch = CCUsers[0];
- SystemZII::CompareAndBranchType Type;
+ SystemZII::FusedCompareType Type;
switch (Branch->getOpcode()) {
case SystemZ::BRC:
Type = SystemZII::CompareAndBranch;
@@ -394,13 +394,16 @@ fuseCompareAndBranch(MachineInstr *Compare,
case SystemZ::CallBCR:
Type = SystemZII::CompareAndSibcall;
break;
+ case SystemZ::CondTrap:
+ Type = SystemZII::CompareAndTrap;
+ break;
default:
return false;
}
// See whether we have a comparison that can be fused.
- unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
- Type, Compare);
+ unsigned FusedOpcode = TII->getFusedCompare(Compare->getOpcode(),
+ Type, Compare);
if (!FusedOpcode)
return false;
@@ -481,7 +484,7 @@ bool SystemZElimCompare::processBlock(MachineBasicBlock &MBB) {
if (CompleteCCUsers &&
(MI->isCompare() || isLoadAndTestAsCmp(MI)) &&
(optimizeCompareZero(MI, CCUsers) ||
- fuseCompareAndBranch(MI, CCUsers))) {
+ fuseCompareOperations(MI, CCUsers))) {
++MBBI;
MI->eraseFromParent();
Changed = true;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 2a29190a7f7..1c747990b8e 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -216,6 +216,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
+ // Traps are legal, as we will convert them to "j .+2".
+ setOperationAction(ISD::TRAP, MVT::Other, Legal);
+
// z10 has instructions for signed but not unsigned FP conversion.
// Handle unsigned 32-bit types as signed 64-bit types.
if (!Subtarget.hasFPExtension()) {
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
index efa0dc230f5..95b482e3864 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td
@@ -183,6 +183,24 @@ class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{15-0} = I2;
}
+class InstRIEa<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstSystemZ<6, outs, ins, asmstr, pattern> {
+ field bits<48> Inst;
+ field bits<48> SoftFail = 0;
+
+ bits<4> R1;
+ bits<16> I2;
+ bits<4> M3;
+
+ let Inst{47-40} = op{15-8};
+ let Inst{39-36} = R1;
+ let Inst{35-32} = 0;
+ let Inst{31-16} = I2;
+ let Inst{15-12} = M3;
+ let Inst{11-8} = 0;
+ let Inst{7-0} = op{7-0};
+}
+
class InstRIEb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
@@ -349,6 +367,22 @@ class InstRRF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{3-0} = R2;
}
+class InstRRFc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstSystemZ<4, outs, ins, asmstr, pattern> {
+ field bits<32> Inst;
+ field bits<32> SoftFail = 0;
+
+ bits<4> R1;
+ bits<4> R2;
+ bits<4> M3;
+
+ let Inst{31-16} = op;
+ let Inst{15-12} = M3;
+ let Inst{11-8} = 0;
+ let Inst{7-4} = R1;
+ let Inst{3-0} = R2;
+}
+
class InstRRS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index fa824d01065..463941940bd 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -543,6 +543,7 @@ bool SystemZInstrInfo::isPredicable(MachineInstr &MI) const {
if (STI.hasLoadStoreOnCond() && getConditionalMove(Opcode))
return true;
if (Opcode == SystemZ::Return ||
+ Opcode == SystemZ::Trap ||
Opcode == SystemZ::CallJG ||
Opcode == SystemZ::CallBR)
return true;
@@ -558,7 +559,11 @@ isProfitableToIfCvt(MachineBasicBlock &MBB,
// 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))
+ // However, since Compare and Trap instructions cost the same as a regular
+ // Compare instruction, we should allow the if conversion to convert this
+ // into a Conditional Compare regardless of the branch probability.
+ if (MBB.getLastNonDebugInstr()->getOpcode() != SystemZ::Trap &&
+ MBB.succ_empty() && Probability < BranchProbability(1, 8))
return false;
// For now only convert single instructions.
return NumCycles == 1;
@@ -598,6 +603,13 @@ bool SystemZInstrInfo::PredicateInstruction(
return true;
}
}
+ if (Opcode == SystemZ::Trap) {
+ MI.setDesc(get(SystemZ::CondTrap));
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI)
+ .addImm(CCValid).addImm(CCMask)
+ .addReg(SystemZ::CC, RegState::Implicit);
+ return true;
+ }
if (Opcode == SystemZ::Return) {
MI.setDesc(get(SystemZ::CondReturn));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
@@ -1370,9 +1382,9 @@ bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
return false;
}
-unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
- SystemZII::CompareAndBranchType Type,
- const MachineInstr *MI) const {
+unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
+ SystemZII::FusedCompareType Type,
+ const MachineInstr *MI) const {
switch (Opcode) {
case SystemZ::CHI:
case SystemZ::CGHI:
@@ -1448,6 +1460,27 @@ unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
default:
return 0;
}
+ case SystemZII::CompareAndTrap:
+ switch (Opcode) {
+ case SystemZ::CR:
+ return SystemZ::CRT;
+ case SystemZ::CGR:
+ return SystemZ::CGRT;
+ case SystemZ::CHI:
+ return SystemZ::CIT;
+ case SystemZ::CGHI:
+ return SystemZ::CGIT;
+ case SystemZ::CLR:
+ return SystemZ::CLRT;
+ case SystemZ::CLGR:
+ return SystemZ::CLGRT;
+ case SystemZ::CLFI:
+ return SystemZ::CLFIT;
+ case SystemZ::CLGFI:
+ return SystemZ::CLGIT;
+ default:
+ return 0;
+ }
}
return 0;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
index b5e4ff48733..615d2fc5bd1 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -111,10 +111,10 @@ 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
+// Kinds of fused compares in compare-and-* instructions. Together with type
+// of the converted compare, this identifies the compare-and-*
// instruction.
-enum CompareAndBranchType {
+enum FusedCompareType {
// Relative branch - CRJ etc.
CompareAndBranch,
@@ -122,7 +122,10 @@ enum CompareAndBranchType {
CompareAndReturn,
// Indirect branch, used for sibcall - CRBCall etc.
- CompareAndSibcall
+ CompareAndSibcall,
+
+ // Trap
+ CompareAndTrap
};
} // end namespace SystemZII
@@ -247,12 +250,12 @@ public:
bool isRxSBGMask(uint64_t Mask, unsigned BitSize,
unsigned &Start, unsigned &End) const;
- // If Opcode is a COMPARE opcode for which an associated COMPARE AND
- // BRANCH exists, return the opcode for the latter, otherwise return 0.
+ // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND *
+ // operation 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;
+ unsigned getFusedCompare(unsigned Opcode,
+ SystemZII::FusedCompareType Type,
+ const MachineInstr *MI = nullptr) const;
// Emit code before MBBI in MI to move immediate value Value into
// physical register Reg.
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index 36e8284c7c9..77a9fdd4add 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -67,6 +67,17 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, R1 = 15 in {
def JG : InstRIL<0xC04, (outs), (ins brtarget32:$I2), "jg\t$I2", []>;
}
+// FIXME: This trap instruction should be marked as isTerminator, but there is
+// currently a general bug that allows non-terminators to be placed between
+// terminators. Temporarily leave this unmarked until the bug is fixed.
+let isBarrier = 1, hasCtrlDep = 1 in {
+ def Trap : Alias<4, (outs), (ins), [(trap)]>;
+}
+
+let isTerminator = 1, hasCtrlDep = 1, Uses = [CC] in {
+ def CondTrap : Alias<4, (outs), (ins cond4:$valid, cond4:$R1), []>;
+}
+
// Conditional branches. It's easier for LLVM to handle these branches
// in their raw BRC/BRCL form, with the 4-bit condition-code mask being
// the first operand. It seems friendlier to use mnemonic forms like
@@ -109,59 +120,78 @@ multiclass CompareBranches<Operand ccmask, string pos1, string pos2> {
let isBranch = 1, isTerminator = 1, Defs = [CC] in {
def RJ : InstRIEb<0xEC76, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
brtarget16:$RI4),
- "crj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
+ "crj"##pos1##"\t$R1, $R2"##pos2##", $RI4", []>;
def GRJ : InstRIEb<0xEC64, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
brtarget16:$RI4),
- "cgrj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
+ "cgrj"##pos1##"\t$R1, $R2"##pos2##", $RI4", []>;
def IJ : InstRIEc<0xEC7E, (outs), (ins GR32:$R1, imm32sx8:$I2, ccmask:$M3,
brtarget16:$RI4),
- "cij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
+ "cij"##pos1##"\t$R1, $I2"##pos2##", $RI4", []>;
def GIJ : InstRIEc<0xEC7C, (outs), (ins GR64:$R1, imm64sx8:$I2, ccmask:$M3,
brtarget16:$RI4),
- "cgij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
+ "cgij"##pos1##"\t$R1, $I2"##pos2##", $RI4", []>;
def LRJ : InstRIEb<0xEC77, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
brtarget16:$RI4),
- "clrj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
+ "clrj"##pos1##"\t$R1, $R2"##pos2##", $RI4", []>;
def LGRJ : InstRIEb<0xEC65, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
brtarget16:$RI4),
- "clgrj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
+ "clgrj"##pos1##"\t$R1, $R2"##pos2##", $RI4", []>;
def LIJ : InstRIEc<0xEC7F, (outs), (ins GR32:$R1, imm32zx8:$I2, ccmask:$M3,
brtarget16:$RI4),
- "clij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
+ "clij"##pos1##"\t$R1, $I2"##pos2##", $RI4", []>;
def LGIJ : InstRIEc<0xEC7D, (outs), (ins GR64:$R1, imm64zx8:$I2, ccmask:$M3,
brtarget16:$RI4),
- "clgij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
+ "clgij"##pos1##"\t$R1, $I2"##pos2##", $RI4", []>;
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", []>;
+ "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", []>;
+ "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", []>;
+ "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", []>;
+ "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", []>;
+ "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", []>;
+ "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", []>;
+ "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", []>;
+ "clgib"##pos1##"\t$R1, $I2"##pos2##", $BD4", []>;
}
}
+
+ let isTerminator = 1, hasCtrlDep = 1 in {
+ def RT : InstRRFc<0xB972, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3),
+ "crt"##pos1##"\t$R1, $R2"##pos2, []>;
+ def GRT : InstRRFc<0xB960, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3),
+ "cgrt"##pos1##"\t$R1, $R2"##pos2, []>;
+ def LRT : InstRRFc<0xB973, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3),
+ "clrt"##pos1##"\t$R1, $R2"##pos2, []>;
+ def LGRT : InstRRFc<0xB961, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3),
+ "clgrt"##pos1##"\t$R1, $R2"##pos2, []>;
+ def IT : InstRIEa<0xEC72, (outs), (ins GR32:$R1, imm32sx16:$I2, ccmask:$M3),
+ "cit"##pos1##"\t$R1, $I2"##pos2, []>;
+ def GIT : InstRIEa<0xEC70, (outs), (ins GR64:$R1, imm32sx16:$I2, ccmask:$M3),
+ "cgit"##pos1##"\t$R1, $I2"##pos2, []>;
+ def LFIT : InstRIEa<0xEC73, (outs), (ins GR32:$R1, imm32zx16:$I2, ccmask:$M3),
+ "clfit"##pos1##"\t$R1, $I2"##pos2, []>;
+ def LGIT : InstRIEa<0xEC71, (outs), (ins GR64:$R1, imm32zx16:$I2, ccmask:$M3),
+ "clgit"##pos1##"\t$R1, $I2"##pos2, []>;
+ }
}
let isCodeGenOnly = 1 in
defm C : CompareBranches<cond4, "$M3", "">;
-defm AsmC : CompareBranches<imm32zx4, "", "$M3, ">;
+defm AsmC : CompareBranches<imm32zx4, "", ", $M3">;
// Define AsmParser mnemonics for each general condition-code mask
// (integer or floating-point)
@@ -262,6 +292,25 @@ multiclass IntCondExtendedMnemonicA<bits<4> ccmask, string name> {
"clgib"##name##"\t$R1, $I2, $BD4", []>;
}
}
+
+ let hasCtrlDep = 1, isTerminator = 1, M3 = ccmask in {
+ def CRT : InstRRFc<0xB972, (outs), (ins GR32:$R1, GR32:$R2),
+ "crt"##name##"\t$R1, $R2", []>;
+ def CGRT : InstRRFc<0xB960, (outs), (ins GR64:$R1, GR64:$R2),
+ "cgrt"##name##"\t$R1, $R2", []>;
+ def CLRT : InstRRFc<0xB973, (outs), (ins GR32:$R1, GR32:$R2),
+ "clrt"##name##"\t$R1, $R2", []>;
+ def CLGRT : InstRRFc<0xB961, (outs), (ins GR64:$R1, GR64:$R2),
+ "clgrt"##name##"\t$R1, $R2", []>;
+ def CIT : InstRIEa<0xEC72, (outs), (ins GR32:$R1, imm32sx16:$I2),
+ "cit"##name##"\t$R1, $I2", []>;
+ def CGIT : InstRIEa<0xEC70, (outs), (ins GR64:$R1, imm32sx16:$I2),
+ "cgit"##name##"\t$R1, $I2", []>;
+ def CLFIT : InstRIEa<0xEC73, (outs), (ins GR32:$R1, imm32zx16:$I2),
+ "clfit"##name##"\t$R1, $I2", []>;
+ def CLGIT : InstRIEa<0xEC71, (outs), (ins GR64:$R1, imm32zx16:$I2),
+ "clgit"##name##"\t$R1, $I2", []>;
+ }
}
multiclass IntCondExtendedMnemonic<bits<4> ccmask, string name1, string name2>
: IntCondExtendedMnemonicA<ccmask, name1> {
OpenPOWER on IntegriCloud