Index: llvm/include/llvm/CodeGen/TargetInstrInfo.h =================================================================== --- llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -1306,6 +1306,9 @@ /// Returns true if the instruction is already predicated. virtual bool isPredicated(const MachineInstr &MI) const { return false; } + /// Returns the name for the specified condition code + virtual const char *getPredicateByName(int CC) const {return nullptr; }; + /// Returns true if the instruction is a /// terminator instruction that has not been predicated. virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const; Index: llvm/lib/CodeGen/MIRParser/MILexer.h =================================================================== --- llvm/lib/CodeGen/MIRParser/MILexer.h +++ llvm/lib/CodeGen/MIRParser/MILexer.h @@ -49,6 +49,7 @@ greater, // Keywords + kw_cond_code, kw_implicit, kw_implicit_define, kw_def, Index: llvm/lib/CodeGen/MIRParser/MILexer.cpp =================================================================== --- llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -181,6 +181,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { return StringSwitch(Identifier) .Case("_", MIToken::underscore) + .Case("cond", MIToken::kw_cond_code) .Case("implicit", MIToken::kw_implicit) .Case("implicit-def", MIToken::kw_implicit_define) .Case("def", MIToken::kw_def) Index: llvm/lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -455,6 +455,7 @@ bool parseIRConstant(StringRef::iterator Loc, const Constant *&C); bool parseLowLevelType(StringRef::iterator Loc, LLT &Ty); bool parseTypedImmediateOperand(MachineOperand &Dest); + bool parseConditionCodeOperand(MachineOperand &Dest, const unsigned OpIdx); bool parseFPImmediateOperand(MachineOperand &Dest); bool parseMBBReference(MachineBasicBlock *&MBB); bool parseMBBOperand(MachineOperand &Dest); @@ -1679,6 +1680,43 @@ return false; } +unsigned getPredicateCondCode(StringRef Pred) { + return StringSwitch(Pred) + .Case("equal", 0) + .Case("notequal", 1) + .Case("highersame", 2) + .Case("lower", 3) + .Case("minus", 4) + .Case("plus", 5) + .Case("overflow", 6) + .Case("nooverflow", 7) + .Case("higher", 8) + .Case("lowersame", 9) + .Case("greaterequal", 10) + .Case("less", 11) + .Case("greater", 12) + .Case("lessequal", 13) + .Case("always", 14) + .Default(~0); +} + +bool MIParser::parseConditionCodeOperand(MachineOperand &Dest, const unsigned OpIdx) { + if (Token.range() != "cond") + return true; + + lex(); + if (expectAndConsume(MIToken::colon)) + return error("expected ':'"); + + int CC = getPredicateCondCode(Token.range()); + if (CC == ~0) + return error("unknown condition code"); + + lex(); + Dest = MachineOperand::CreateImm(CC); + return false; +} + bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) { assert(Token.is(MIToken::Identifier)); StringRef TypeStr = Token.range(); @@ -2515,6 +2553,8 @@ MachineOperand &Dest, Optional &TiedDefIdx) { switch (Token.kind()) { + case MIToken::kw_cond_code: + return parseConditionCodeOperand(Dest, OpIdx); case MIToken::kw_implicit: case MIToken::kw_implicit_define: case MIToken::kw_def: Index: llvm/lib/CodeGen/MIRPrinter.cpp =================================================================== --- llvm/lib/CodeGen/MIRPrinter.cpp +++ llvm/lib/CodeGen/MIRPrinter.cpp @@ -828,13 +828,26 @@ bool PrintDef) { const MachineOperand &Op = MI.getOperand(OpIdx); switch (Op.getType()) { - case MachineOperand::MO_Immediate: + case MachineOperand::MO_Immediate: { + int FirstPredOp = MI.findFirstPredOperandIdx(); + if (FirstPredOp == (int)OpIdx) { + const auto *MF = MI.getMF(); + const auto &SubTarget = MF->getSubtarget(); + const auto *TRI = SubTarget.getRegisterInfo(); + assert(TRI && "Expected target register info"); + const auto *TII = SubTarget.getInstrInfo(); + if (const char *PredName = TII->getPredicateByName(Op.getImm())) { + OS << "cond:" << PredName; + return; + } + } if (MI.isOperandSubregIdx(OpIdx)) { MachineOperand::printTargetFlags(OS, Op); MachineOperand::printSubRegIdx(OS, Op.getImm(), TRI); break; } LLVM_FALLTHROUGH; + } case MachineOperand::MO_Register: case MachineOperand::MO_CImmediate: case MachineOperand::MO_FPImmediate: Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -146,6 +146,8 @@ // Predication support. bool isPredicated(const MachineInstr &MI) const override; + const char *getPredicateByName(int CC) const override; + ARMCC::CondCodes getPredicate(const MachineInstr &MI) const { int PIdx = MI.findFirstPredOperandIdx(); return PIdx != -1 ? (ARMCC::CondCodes)MI.getOperand(PIdx).getImm() Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -495,6 +495,28 @@ return PIdx != -1 && MI.getOperand(PIdx).getImm() != ARMCC::AL; } +const char *ARMBaseInstrInfo::getPredicateByName(int CC) const { + switch (CC) { + case 0: return "equal"; + case 1: return "notequal"; + case 2: return "highersame"; + case 3: return "lower"; + case 4: return "minus"; + case 5: return "plus"; + case 6: return "overflow"; + case 7: return "nooverflow"; + case 8: return "higher"; + case 9: return "lowersame"; + case 10: return "greaterequal"; + case 11: return "less"; + case 12: return "greater"; + case 13: return "lessequal"; + case 14: return "always"; + default: + llvm_unreachable("unexpected condition code"); + } +} + bool ARMBaseInstrInfo::PredicateInstruction( MachineInstr &MI, ArrayRef Pred) const { unsigned Opc = MI.getOpcode(); Index: llvm/test/CodeGen/Thumb2/t2-teq-reduce.mir =================================================================== --- llvm/test/CodeGen/Thumb2/t2-teq-reduce.mir +++ llvm/test/CodeGen/Thumb2/t2-teq-reduce.mir @@ -100,38 +100,38 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.2(0x80000000) ; CHECK: liveins: $r0, $r1 - ; CHECK: t2B %bb.2, 14, $noreg + ; CHECK: t2B %bb.2, cond:always, $noreg ; CHECK: bb.1.while.body.end: ; CHECK: successors: %bb.2(0x80000000) ; CHECK: liveins: $r0, $r1 - ; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next.i.14) - ; CHECK: tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr + ; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, cond:always, $noreg :: (load 4 from %ir.next.i.14) + ; CHECK: tCMPi8 renamable $r0, 0, cond:always, $noreg, implicit-def $cpsr ; CHECK: BUNDLE implicit-def dead $itstate, implicit killed $cpsr, implicit $r0 { ; CHECK: t2IT 0, 8, implicit-def $itstate - ; CHECK: tBX_RET 0, killed $cpsr, implicit $r0, implicit internal killed $itstate + ; CHECK: tBX_RET cond:equal, killed $cpsr, implicit $r0, implicit internal killed $itstate ; CHECK: } ; CHECK: bb.2.while.begin: ; CHECK: successors: %bb.4(0x04000000), %bb.3(0x7c000000) ; CHECK: liveins: $r0, $r1 - ; CHECK: renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info.i) - ; CHECK: renamable $r2 = tLDRHi killed renamable $r2, 0, 14, $noreg :: (load 2 from %ir.data16.i1) - ; CHECK: dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg - ; CHECK: t2Bcc %bb.4, 0, killed $cpsr + ; CHECK: renamable $r2 = tLDRi renamable $r0, 1, cond:always, $noreg :: (load 4 from %ir.info.i) + ; CHECK: renamable $r2 = tLDRHi killed renamable $r2, 0, cond:always, $noreg :: (load 2 from %ir.data16.i1) + ; CHECK: dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, cond:always, $noreg + ; CHECK: t2Bcc %bb.4, cond:equal, killed $cpsr ; CHECK: bb.3.while.body.a: ; CHECK: successors: %bb.4(0x4207fef8), %bb.1(0x3df80108) ; CHECK: liveins: $r0, $r1 - ; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next.i2) - ; CHECK: tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr + ; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, cond:always, $noreg :: (load 4 from %ir.next.i2) + ; CHECK: tCMPi8 renamable $r0, 0, cond:always, $noreg, implicit-def $cpsr ; CHECK: BUNDLE implicit-def dead $itstate, implicit-def dead $r2, implicit-def $cpsr, implicit $r0, implicit killed $cpsr, implicit $r1 { ; CHECK: t2IT 1, 30, implicit-def $itstate - ; CHECK: renamable $r2 = tLDRi renamable $r0, 1, 1, $cpsr, implicit internal $itstate :: (load 4 from %ir.info.i.1) - ; CHECK: renamable $r2 = tLDRHi internal killed renamable $r2, 0, 1, $cpsr, implicit internal killed $r2, implicit internal $itstate :: (load 2 from %ir.data16.i.13) - ; CHECK: t2TEQrr internal killed renamable $r2, renamable $r1, 1, killed $cpsr, implicit-def $cpsr, implicit internal killed $itstate + ; CHECK: renamable $r2 = tLDRi renamable $r0, 1, cond:notequal, $cpsr, implicit internal $itstate :: (load 4 from %ir.info.i.1) + ; CHECK: renamable $r2 = tLDRHi internal killed renamable $r2, 0, cond:notequal, $cpsr, implicit internal killed $r2, implicit internal $itstate :: (load 2 from %ir.data16.i.13) + ; CHECK: t2TEQrr internal killed renamable $r2, renamable $r1, cond:notequal, killed $cpsr, implicit-def $cpsr, implicit internal killed $itstate ; CHECK: } - ; CHECK: t2Bcc %bb.1, 1, killed $cpsr + ; CHECK: t2Bcc %bb.1, cond:notequal, killed $cpsr ; CHECK: bb.4.exit: ; CHECK: liveins: $r0 - ; CHECK: tBX_RET 14, $noreg, implicit killed $r0 + ; CHECK: tBX_RET cond:always, $noreg, implicit killed $r0 bb.0.entry: successors: %bb.1(0x80000000) liveins: $r0, $r1 @@ -189,36 +189,36 @@ ; CHECK: bb.0.entry: ; CHECK: successors: %bb.1(0x80000000) ; CHECK: liveins: $r0, $r1 - ; CHECK: $r2 = tMOVr $r0, 14, $noreg + ; CHECK: $r2 = tMOVr $r0, cond:always, $noreg ; CHECK: bb.1.while.begin: ; CHECK: successors: %bb.5(0x04000000), %bb.2(0x7c000000) ; CHECK: liveins: $r1, $r2 - ; CHECK: renamable $r0 = tLDRi renamable $r2, 1, 14, $noreg :: (load 4 from %ir.info.i) - ; CHECK: renamable $r0 = tLDRHi killed renamable $r0, 0, 14, $noreg :: (load 2 from %ir.data16.i1) - ; CHECK: t2TEQrr renamable $r0, renamable $r1, 14, $noreg, implicit-def $cpsr - ; CHECK: t2Bcc %bb.5, 0, killed $cpsr + ; CHECK: renamable $r0 = tLDRi renamable $r2, 1, cond:always, $noreg :: (load 4 from %ir.info.i) + ; CHECK: renamable $r0 = tLDRHi killed renamable $r0, 0, cond:always, $noreg :: (load 2 from %ir.data16.i1) + ; CHECK: t2TEQrr renamable $r0, renamable $r1, cond:always, $noreg, implicit-def $cpsr + ; CHECK: t2Bcc %bb.5, cond:equal, killed $cpsr ; CHECK: bb.2.while.body.a: ; CHECK: successors: %bb.5(0x04000000), %bb.3(0x7c000000) ; CHECK: liveins: $r0, $r1, $r2 - ; CHECK: renamable $r2 = tLDRi killed renamable $r2, 0, 14, $noreg :: (load 4 from %ir.next.i2) - ; CHECK: tCMPi8 renamable $r2, 0, 14, $noreg, implicit-def $cpsr - ; CHECK: t2Bcc %bb.5, 0, killed $cpsr + ; CHECK: renamable $r2 = tLDRi killed renamable $r2, 0, cond:always, $noreg :: (load 4 from %ir.next.i2) + ; CHECK: tCMPi8 renamable $r2, 0, cond:always, $noreg, implicit-def $cpsr + ; CHECK: t2Bcc %bb.5, cond:equal, killed $cpsr ; CHECK: bb.3.it.block: ; CHECK: successors: %bb.5(0x04000000), %bb.4(0x7c000000) ; CHECK: liveins: $r1, $r2 - ; CHECK: renamable $r0 = tLDRi renamable $r2, 1, 14, $noreg :: (load 4 from %ir.info.i.1) - ; CHECK: renamable $r0 = tLDRHi killed renamable $r0, 0, 14, $noreg :: (load 2 from %ir.data16.i.13) - ; CHECK: t2TEQrr renamable $r0, renamable $r1, 14, $noreg, implicit-def $cpsr - ; CHECK: t2Bcc %bb.5, 0, killed $cpsr + ; CHECK: renamable $r0 = tLDRi renamable $r2, 1, cond:always, $noreg :: (load 4 from %ir.info.i.1) + ; CHECK: renamable $r0 = tLDRHi killed renamable $r0, 0, cond:always, $noreg :: (load 2 from %ir.data16.i.13) + ; CHECK: t2TEQrr renamable $r0, renamable $r1, cond:always, $noreg, implicit-def $cpsr + ; CHECK: t2Bcc %bb.5, cond:equal, killed $cpsr ; CHECK: bb.4.while.body.end: ; CHECK: successors: %bb.5(0x04000000), %bb.1(0x7c000000) ; CHECK: liveins: $r0, $r1, $r2 - ; CHECK: renamable $r2 = tLDRi killed renamable $r2, 0, 14, $noreg :: (load 4 from %ir.next.i.14) - ; CHECK: tCMPi8 renamable $r2, 0, 14, $noreg, implicit-def $cpsr - ; CHECK: t2Bcc %bb.1, 1, killed $cpsr + ; CHECK: renamable $r2 = tLDRi killed renamable $r2, 0, cond:always, $noreg :: (load 4 from %ir.next.i.14) + ; CHECK: tCMPi8 renamable $r2, 0, cond:always, $noreg, implicit-def $cpsr + ; CHECK: t2Bcc %bb.1, cond:notequal, killed $cpsr ; CHECK: bb.5.exit: ; CHECK: liveins: $r0 - ; CHECK: tBX_RET 14, $noreg, implicit $r0 + ; CHECK: tBX_RET cond:always, $noreg, implicit $r0 bb.0.entry: successors: %bb.1(0x80000000) liveins: $r0, $r1