diff options
author | Zhan Jun Liau <zhanjunl@ca.ibm.com> | 2016-06-10 19:58:10 +0000 |
---|---|---|
committer | Zhan Jun Liau <zhanjunl@ca.ibm.com> | 2016-06-10 19:58:10 +0000 |
commit | ab42cbce9807778d3087454f483dc7266833975a (patch) | |
tree | db74411e2bea60c36ebf25b3c34fdffb38d8c8ae /llvm/lib/Target | |
parent | f3af841462ad6dfc6c2fee5a441400b4bded931c (diff) | |
download | bcm5719-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.txt | 6 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZElimCompare.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrFormats.td | 34 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 41 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.h | 21 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 83 |
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> { |