@@ -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,160 @@ 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+ IsImm = false ;
2604+ Is32Bit = true ;
2605+ break ;
2606+ case AArch64::CBXPrr:
2607+ IsImm = false ;
2608+ Is32Bit = false ;
2609+ break ;
2610+ case AArch64::CBWPri:
2611+ IsImm = true ;
2612+ Is32Bit = true ;
2613+ break ;
2614+ case AArch64::CBXPri:
2615+ IsImm = true ;
2616+ Is32Bit = false ;
2617+ break ;
2618+ }
2619+
2620+ AArch64CC::CondCode CC =
2621+ static_cast <AArch64CC::CondCode>(MI->getOperand (0 ).getImm ());
2622+ bool NeedsRegSwap = false ;
2623+ bool NeedsImmDec = false ;
2624+ bool NeedsImmInc = false ;
2625+
2626+ // Decide if we need to either swap register operands or increment/decrement
2627+ // immediate operands
2628+ unsigned MCOpC;
2629+ switch (CC) {
2630+ default :
2631+ llvm_unreachable (" Invalid CB condition code" );
2632+ case AArch64CC::EQ:
2633+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
2634+ : (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
2635+ NeedsRegSwap = false ;
2636+ NeedsImmDec = false ;
2637+ NeedsImmInc = false ;
2638+ break ;
2639+ case AArch64CC::NE:
2640+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
2641+ : (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
2642+ NeedsRegSwap = false ;
2643+ NeedsImmDec = false ;
2644+ NeedsImmInc = false ;
2645+ break ;
2646+ case AArch64CC::HS:
2647+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2648+ : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2649+ NeedsRegSwap = false ;
2650+ NeedsImmDec = IsImm;
2651+ NeedsImmInc = false ;
2652+ break ;
2653+ case AArch64CC::LO:
2654+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2655+ : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2656+ NeedsRegSwap = !IsImm;
2657+ NeedsImmDec = false ;
2658+ NeedsImmInc = false ;
2659+ break ;
2660+ case AArch64CC::HI:
2661+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2662+ : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2663+ NeedsRegSwap = false ;
2664+ NeedsImmDec = false ;
2665+ NeedsImmInc = false ;
2666+ break ;
2667+ case AArch64CC::LS:
2668+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2669+ : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2670+ NeedsRegSwap = !IsImm;
2671+ NeedsImmDec = false ;
2672+ NeedsImmInc = IsImm;
2673+ break ;
2674+ case AArch64CC::GE:
2675+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2676+ : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2677+ NeedsRegSwap = false ;
2678+ NeedsImmDec = IsImm;
2679+ NeedsImmInc = false ;
2680+ break ;
2681+ case AArch64CC::LT:
2682+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2683+ : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2684+ NeedsRegSwap = !IsImm;
2685+ NeedsImmDec = false ;
2686+ NeedsImmInc = false ;
2687+ break ;
2688+ case AArch64CC::GT:
2689+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2690+ : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2691+ NeedsRegSwap = false ;
2692+ NeedsImmDec = false ;
2693+ NeedsImmInc = false ;
2694+ break ;
2695+ case AArch64CC::LE:
2696+ MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2697+ : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2698+ NeedsRegSwap = !IsImm;
2699+ NeedsImmDec = false ;
2700+ NeedsImmInc = IsImm;
2701+ break ;
2702+ }
2703+
2704+ assert (!(NeedsImmDec && NeedsImmInc) &&
2705+ " Cannot require increment and decrement of CB immediate operand at "
2706+ " the same time" );
2707+
2708+ MCInst Inst;
2709+ Inst.setOpcode (MCOpC);
2710+
2711+ MCOperand Lhs, Rhs, Trgt;
2712+ lowerOperand (MI->getOperand (1 ), Lhs);
2713+ lowerOperand (MI->getOperand (2 ), Rhs);
2714+ lowerOperand (MI->getOperand (3 ), Trgt);
2715+
2716+ // Now swap, increment or decrement
2717+ if (NeedsRegSwap) {
2718+ assert (
2719+ !IsImm &&
2720+ " Unexpected register swap for CB instruction with immediate operand" );
2721+ assert (Lhs.isReg () && " Expected register operand for CB" );
2722+ assert (Rhs.isReg () && " Expected register operand for CB" );
2723+ Inst.addOperand (Rhs);
2724+ Inst.addOperand (Lhs);
2725+ } else if (NeedsImmDec) {
2726+ assert (IsImm && " Unexpected immediate decrement for CB instruction with "
2727+ " reg-reg operands" );
2728+ Rhs.setImm (Rhs.getImm () - 1 );
2729+ Inst.addOperand (Lhs);
2730+ Inst.addOperand (Rhs);
2731+ } else if (NeedsImmInc) {
2732+ assert (IsImm && " Unexpected immediate increment for CB instruction with "
2733+ " reg-reg operands" );
2734+ Rhs.setImm (Rhs.getImm () + 1 );
2735+ Inst.addOperand (Lhs);
2736+ Inst.addOperand (Rhs);
2737+ } else {
2738+ Inst.addOperand (Lhs);
2739+ Inst.addOperand (Rhs);
2740+ }
2741+
2742+ assert ((!IsImm || (Rhs.getImm () >= 0 && Rhs.getImm () < 64 )) &&
2743+ " CB immediate operand out-of-bounds" );
2744+
2745+ Inst.addOperand (Trgt);
2746+ EmitToStreamer (*OutStreamer, Inst);
2747+ }
2748+
25922749// Simple pseudo-instructions have their lowering (with expansion to real
25932750// instructions) auto-generated.
25942751#include " AArch64GenMCPseudoLowering.inc"
@@ -3155,13 +3312,20 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
31553312 return ;
31563313
31573314 case AArch64::BLR:
3158- case AArch64::BR:
3315+ case AArch64::BR: {
31593316 recordIfImportCall (MI);
31603317 MCInst TmpInst;
31613318 MCInstLowering.Lower (MI, TmpInst);
31623319 EmitToStreamer (*OutStreamer, TmpInst);
31633320 return ;
31643321 }
3322+ case AArch64::CBWPri:
3323+ case AArch64::CBXPri:
3324+ case AArch64::CBWPrr:
3325+ case AArch64::CBXPrr:
3326+ emitCBPseudoExpansion (MI);
3327+ return ;
3328+ }
31653329
31663330 // Finally, do the automated lowerings for everything else.
31673331 MCInst TmpInst;
0 commit comments