@@ -208,6 +208,9 @@ class AArch64AsmPrinter : public AsmPrinter {
208
208
void emitAttributes (unsigned Flags, uint64_t PAuthABIPlatform,
209
209
uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
210
210
211
+ // Emit expansion of Compare-and-branch pseudo instructions
212
+ void emitCBPseudoExpansion (const MachineInstr *MI);
213
+
211
214
void EmitToStreamer (MCStreamer &S, const MCInst &Inst);
212
215
void EmitToStreamer (const MCInst &Inst) {
213
216
EmitToStreamer (*OutStreamer, Inst);
@@ -2589,6 +2592,160 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
2589
2592
return BAE;
2590
2593
}
2591
2594
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
+
2592
2749
// Simple pseudo-instructions have their lowering (with expansion to real
2593
2750
// instructions) auto-generated.
2594
2751
#include " AArch64GenMCPseudoLowering.inc"
@@ -3155,13 +3312,20 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
3155
3312
return ;
3156
3313
3157
3314
case AArch64::BLR:
3158
- case AArch64::BR:
3315
+ case AArch64::BR: {
3159
3316
recordIfImportCall (MI);
3160
3317
MCInst TmpInst;
3161
3318
MCInstLowering.Lower (MI, TmpInst);
3162
3319
EmitToStreamer (*OutStreamer, TmpInst);
3163
3320
return ;
3164
3321
}
3322
+ case AArch64::CBWPri:
3323
+ case AArch64::CBXPri:
3324
+ case AArch64::CBWPrr:
3325
+ case AArch64::CBXPrr:
3326
+ emitCBPseudoExpansion (MI);
3327
+ return ;
3328
+ }
3165
3329
3166
3330
// Finally, do the automated lowerings for everything else.
3167
3331
MCInst TmpInst;
0 commit comments