@@ -208,6 +208,9 @@ class AArch64AsmPrinter : public AsmPrinter {
208208 void emitAttributes (unsigned Flags, uint64_t PAuthABIPlatform,
209209 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
210210
211+ // Emit expansion of Compare-and-branch pseudo instructions
212+ void emitCBPseudoExpansion (const MachineInstr *MI);
213+
211214 void EmitToStreamer (MCStreamer &S, const MCInst &Inst);
212215 void EmitToStreamer (const MCInst &Inst) {
213216 EmitToStreamer (*OutStreamer, Inst);
@@ -2589,6 +2592,124 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
25892592 return BAE;
25902593}
25912594
2595+ void AArch64AsmPrinter::emitCBPseudoExpansion (const MachineInstr *MI) {
2596+ bool IsImm = false ;
2597+ bool Is32Bit = false ;
2598+
2599+ switch (MI->getOpcode ()) {
2600+ default :
2601+ llvm_unreachable (" This is not a CB pseudo instruction" );
2602+ case AArch64::CBWPrr:
2603+ Is32Bit = true ;
2604+ break ;
2605+ case AArch64::CBXPrr:
2606+ Is32Bit = false ;
2607+ break ;
2608+ case AArch64::CBWPri:
2609+ IsImm = true ;
2610+ Is32Bit = true ;
2611+ break ;
2612+ case AArch64::CBXPri:
2613+ IsImm = true ;
2614+ break ;
2615+ }
2616+
2617+ AArch64CC::CondCode CC =
2618+ static_cast <AArch64CC::CondCode>(MI->getOperand (0 ).getImm ());
2619+ bool NeedsRegSwap = false ;
2620+ bool NeedsImmDec = false ;
2621+ bool NeedsImmInc = false ;
2622+
2623+ // Decide if we need to either swap register operands or increment/decrement
2624+ // immediate operands
2625+ unsigned MCOpC;
2626+ switch (CC) {
2627+ default :
2628+ llvm_unreachable (" Invalid CB condition code" );
2629+ case AArch64CC::EQ:
2630+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
2631+ : (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
2632+ break ;
2633+ case AArch64CC::NE:
2634+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
2635+ : (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
2636+ break ;
2637+ case AArch64CC::HS:
2638+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2639+ : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2640+ NeedsImmDec = IsImm;
2641+ break ;
2642+ case AArch64CC::LO:
2643+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2644+ : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2645+ NeedsRegSwap = !IsImm;
2646+ break ;
2647+ case AArch64CC::HI:
2648+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2649+ : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2650+ break ;
2651+ case AArch64CC::LS:
2652+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2653+ : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2654+ NeedsRegSwap = !IsImm;
2655+ NeedsImmInc = IsImm;
2656+ break ;
2657+ case AArch64CC::GE:
2658+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2659+ : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2660+ NeedsImmDec = IsImm;
2661+ break ;
2662+ case AArch64CC::LT:
2663+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2664+ : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2665+ NeedsRegSwap = !IsImm;
2666+ break ;
2667+ case AArch64CC::GT:
2668+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2669+ : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2670+ break ;
2671+ case AArch64CC::LE:
2672+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2673+ : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2674+ NeedsRegSwap = !IsImm;
2675+ NeedsImmInc = IsImm;
2676+ break ;
2677+ }
2678+
2679+ MCInst Inst;
2680+ Inst.setOpcode (MCOpC);
2681+
2682+ MCOperand Lhs, Rhs, Trgt;
2683+ lowerOperand (MI->getOperand (1 ), Lhs);
2684+ lowerOperand (MI->getOperand (2 ), Rhs);
2685+ lowerOperand (MI->getOperand (3 ), Trgt);
2686+
2687+ // Now swap, increment or decrement
2688+ if (NeedsRegSwap) {
2689+ assert (Lhs.isReg () && " Expected register operand for CB" );
2690+ assert (Rhs.isReg () && " Expected register operand for CB" );
2691+ Inst.addOperand (Rhs);
2692+ Inst.addOperand (Lhs);
2693+ } else if (NeedsImmDec) {
2694+ Rhs.setImm (Rhs.getImm () - 1 );
2695+ Inst.addOperand (Lhs);
2696+ Inst.addOperand (Rhs);
2697+ } else if (NeedsImmInc) {
2698+ Rhs.setImm (Rhs.getImm () + 1 );
2699+ Inst.addOperand (Lhs);
2700+ Inst.addOperand (Rhs);
2701+ } else {
2702+ Inst.addOperand (Lhs);
2703+ Inst.addOperand (Rhs);
2704+ }
2705+
2706+ assert ((!IsImm || (Rhs.getImm () >= 0 && Rhs.getImm () < 64 )) &&
2707+ " CB immediate operand out-of-bounds" );
2708+
2709+ Inst.addOperand (Trgt);
2710+ EmitToStreamer (*OutStreamer, Inst);
2711+ }
2712+
25922713// Simple pseudo-instructions have their lowering (with expansion to real
25932714// instructions) auto-generated.
25942715#include " AArch64GenMCPseudoLowering.inc"
@@ -3155,13 +3276,20 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
31553276 return ;
31563277
31573278 case AArch64::BLR:
3158- case AArch64::BR:
3279+ case AArch64::BR: {
31593280 recordIfImportCall (MI);
31603281 MCInst TmpInst;
31613282 MCInstLowering.Lower (MI, TmpInst);
31623283 EmitToStreamer (*OutStreamer, TmpInst);
31633284 return ;
31643285 }
3286+ case AArch64::CBWPri:
3287+ case AArch64::CBXPri:
3288+ case AArch64::CBWPrr:
3289+ case AArch64::CBXPrr:
3290+ emitCBPseudoExpansion (MI);
3291+ return ;
3292+ }
31653293
31663294 // Finally, do the automated lowerings for everything else.
31673295 MCInst TmpInst;
0 commit comments