@@ -128,7 +128,7 @@ class AArch64FastISel : public FastISel {
128
128
bool SelectTrunc (const Instruction *I);
129
129
bool SelectIntExt (const Instruction *I);
130
130
bool SelectMul (const Instruction *I);
131
- bool SelectShift (const Instruction *I, bool IsLeftShift, bool IsArithmetic );
131
+ bool SelectShift (const Instruction *I);
132
132
bool SelectBitCast (const Instruction *I);
133
133
134
134
// Utility helper routines.
@@ -193,9 +193,15 @@ class AArch64FastISel : public FastISel {
193
193
unsigned Op1, bool Op1IsKill);
194
194
unsigned Emit_UMULL_rr (MVT RetVT, unsigned Op0, bool Op0IsKill,
195
195
unsigned Op1, bool Op1IsKill);
196
- unsigned Emit_LSL_ri (MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
197
- unsigned Emit_LSR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
198
- unsigned Emit_ASR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
196
+ unsigned emitLSL_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
197
+ unsigned Op1Reg, bool Op1IsKill);
198
+ unsigned emitLSL_ri (MVT RetVT, unsigned Op0Reg, bool Op0IsKill, uint64_t Imm);
199
+ unsigned emitLSR_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
200
+ unsigned Op1Reg, bool Op1IsKill);
201
+ unsigned emitLSR_ri (MVT RetVT, unsigned Op0Reg, bool Op0IsKill, uint64_t Imm);
202
+ unsigned emitASR_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
203
+ unsigned Op1Reg, bool Op1IsKill);
204
+ unsigned emitASR_ri (MVT RetVT, unsigned Op0Reg, bool Op0IsKill, uint64_t Imm);
199
205
200
206
unsigned AArch64MaterializeInt (const ConstantInt *CI, MVT VT);
201
207
unsigned AArch64MaterializeFP (const ConstantFP *CFP, MVT VT);
@@ -703,8 +709,8 @@ bool AArch64FastISel::SimplifyAddress(Address &Addr, MVT VT) {
703
709
Addr.getOffsetReg (), /* TODO:IsKill=*/ false ,
704
710
Addr.getShift ());
705
711
else
706
- ResultReg = Emit_LSL_ri (MVT::i64, Addr.getOffsetReg (),
707
- /* Op0IsKill= */ false , Addr.getShift ());
712
+ ResultReg = emitLSL_ri (MVT::i64, Addr.getOffsetReg (), /* Op0IsKill= */ false ,
713
+ Addr.getShift ());
708
714
if (!ResultReg)
709
715
return false ;
710
716
@@ -2366,7 +2372,7 @@ bool AArch64FastISel::FastLowerIntrinsicCall(const IntrinsicInst *II) {
2366
2372
2367
2373
if (VT == MVT::i32) {
2368
2374
MulReg = Emit_SMULL_rr (MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
2369
- unsigned ShiftReg = Emit_LSR_ri (MVT::i64, MulReg, false , 32 );
2375
+ unsigned ShiftReg = emitLSR_ri (MVT::i64, MulReg, /* IsKill= */ false , 32 );
2370
2376
MulReg = FastEmitInst_extractsubreg (VT, MulReg, /* IsKill=*/ true ,
2371
2377
AArch64::sub_32);
2372
2378
ShiftReg = FastEmitInst_extractsubreg (VT, ShiftReg, /* IsKill=*/ true ,
@@ -2653,8 +2659,34 @@ unsigned AArch64FastISel::Emit_UMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
2653
2659
AArch64::XZR, /* IsKill=*/ true );
2654
2660
}
2655
2661
2656
- unsigned AArch64FastISel::Emit_LSL_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2657
- uint64_t Shift) {
2662
+ unsigned AArch64FastISel::emitLSL_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
2663
+ unsigned Op1Reg, bool Op1IsKill) {
2664
+ unsigned Opc = 0 ;
2665
+ bool NeedTrunc = false ;
2666
+ uint64_t Mask = 0 ;
2667
+ switch (RetVT.SimpleTy ) {
2668
+ default : return 0 ;
2669
+ case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc = true ; Mask = 0xff ; break ;
2670
+ case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc = true ; Mask = 0xffff ; break ;
2671
+ case MVT::i32: Opc = AArch64::LSLVWr; break ;
2672
+ case MVT::i64: Opc = AArch64::LSLVXr; break ;
2673
+ }
2674
+
2675
+ const TargetRegisterClass *RC =
2676
+ (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2677
+ if (NeedTrunc) {
2678
+ Op1Reg = emitAND_ri (MVT::i32, Op1Reg, Op1IsKill, Mask);
2679
+ Op1IsKill = true ;
2680
+ }
2681
+ unsigned ResultReg = FastEmitInst_rr (Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
2682
+ Op1IsKill);
2683
+ if (NeedTrunc)
2684
+ ResultReg = emitAND_ri (MVT::i32, ResultReg, /* IsKill=*/ true , Mask);
2685
+ return ResultReg;
2686
+ }
2687
+
2688
+ unsigned AArch64FastISel::emitLSL_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2689
+ uint64_t Shift) {
2658
2690
unsigned Opc, ImmR, ImmS;
2659
2691
switch (RetVT.SimpleTy ) {
2660
2692
default : return 0 ;
@@ -2673,8 +2705,35 @@ unsigned AArch64FastISel::Emit_LSL_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
2673
2705
return FastEmitInst_rii (Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
2674
2706
}
2675
2707
2676
- unsigned AArch64FastISel::Emit_LSR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2677
- uint64_t Shift) {
2708
+ unsigned AArch64FastISel::emitLSR_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
2709
+ unsigned Op1Reg, bool Op1IsKill) {
2710
+ unsigned Opc = 0 ;
2711
+ bool NeedTrunc = false ;
2712
+ uint64_t Mask = 0 ;
2713
+ switch (RetVT.SimpleTy ) {
2714
+ default : return 0 ;
2715
+ case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc = true ; Mask = 0xff ; break ;
2716
+ case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc = true ; Mask = 0xffff ; break ;
2717
+ case MVT::i32: Opc = AArch64::LSRVWr; break ;
2718
+ case MVT::i64: Opc = AArch64::LSRVXr; break ;
2719
+ }
2720
+
2721
+ const TargetRegisterClass *RC =
2722
+ (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2723
+ if (NeedTrunc) {
2724
+ Op0Reg = emitAND_ri (MVT::i32, Op0Reg, Op0IsKill, Mask);
2725
+ Op1Reg = emitAND_ri (MVT::i32, Op1Reg, Op1IsKill, Mask);
2726
+ Op0IsKill = Op1IsKill = true ;
2727
+ }
2728
+ unsigned ResultReg = FastEmitInst_rr (Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
2729
+ Op1IsKill);
2730
+ if (NeedTrunc)
2731
+ ResultReg = emitAND_ri (MVT::i32, ResultReg, /* IsKill=*/ true , Mask);
2732
+ return ResultReg;
2733
+ }
2734
+
2735
+ unsigned AArch64FastISel::emitLSR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2736
+ uint64_t Shift) {
2678
2737
unsigned Opc, ImmS;
2679
2738
switch (RetVT.SimpleTy ) {
2680
2739
default : return 0 ;
@@ -2689,8 +2748,35 @@ unsigned AArch64FastISel::Emit_LSR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
2689
2748
return FastEmitInst_rii (Opc, RC, Op0, Op0IsKill, Shift, ImmS);
2690
2749
}
2691
2750
2692
- unsigned AArch64FastISel::Emit_ASR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2693
- uint64_t Shift) {
2751
+ unsigned AArch64FastISel::emitASR_rr (MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
2752
+ unsigned Op1Reg, bool Op1IsKill) {
2753
+ unsigned Opc = 0 ;
2754
+ bool NeedTrunc = false ;
2755
+ uint64_t Mask = 0 ;
2756
+ switch (RetVT.SimpleTy ) {
2757
+ default : return 0 ;
2758
+ case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc = true ; Mask = 0xff ; break ;
2759
+ case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc = true ; Mask = 0xffff ; break ;
2760
+ case MVT::i32: Opc = AArch64::ASRVWr; break ;
2761
+ case MVT::i64: Opc = AArch64::ASRVXr; break ;
2762
+ }
2763
+
2764
+ const TargetRegisterClass *RC =
2765
+ (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
2766
+ if (NeedTrunc) {
2767
+ Op0Reg = EmitIntExt (RetVT, Op0Reg, MVT::i32, /* IsZExt=*/ false );
2768
+ Op1Reg = emitAND_ri (MVT::i32, Op1Reg, Op1IsKill, Mask);
2769
+ Op0IsKill = Op1IsKill = true ;
2770
+ }
2771
+ unsigned ResultReg = FastEmitInst_rr (Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
2772
+ Op1IsKill);
2773
+ if (NeedTrunc)
2774
+ ResultReg = emitAND_ri (MVT::i32, ResultReg, /* IsKill=*/ true , Mask);
2775
+ return ResultReg;
2776
+ }
2777
+
2778
+ unsigned AArch64FastISel::emitASR_ri (MVT RetVT, unsigned Op0, bool Op0IsKill,
2779
+ uint64_t Shift) {
2694
2780
unsigned Opc, ImmS;
2695
2781
switch (RetVT.SimpleTy ) {
2696
2782
default : return 0 ;
@@ -2892,31 +2978,56 @@ bool AArch64FastISel::SelectMul(const Instruction *I) {
2892
2978
return true ;
2893
2979
}
2894
2980
2895
- bool AArch64FastISel::SelectShift (const Instruction *I, bool IsLeftShift,
2896
- bool IsArithmetic) {
2981
+ bool AArch64FastISel::SelectShift (const Instruction *I) {
2897
2982
EVT RetEVT = TLI.getValueType (I->getType (), true );
2898
2983
if (!RetEVT.isSimple ())
2899
2984
return false ;
2900
2985
MVT RetVT = RetEVT.getSimpleVT ();
2901
2986
2902
- if (!isa<ConstantInt>(I->getOperand (1 )))
2903
- return false ;
2904
-
2905
2987
unsigned Op0Reg = getRegForValue (I->getOperand (0 ));
2906
2988
if (!Op0Reg)
2907
2989
return false ;
2908
2990
bool Op0IsKill = hasTrivialKill (I->getOperand (0 ));
2909
2991
2910
- uint64_t ShiftVal = cast<ConstantInt>(I->getOperand (1 ))->getZExtValue ();
2992
+ if (const auto *C = dyn_cast<ConstantInt>(I->getOperand (1 ))) {
2993
+ unsigned ResultReg = 0 ;
2994
+ uint64_t ShiftVal = C->getZExtValue ();
2995
+ switch (I->getOpcode ()) {
2996
+ default : llvm_unreachable (" Unexpected instruction." );
2997
+ case Instruction::Shl:
2998
+ ResultReg = emitLSL_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
2999
+ break ;
3000
+ case Instruction::AShr:
3001
+ ResultReg = emitASR_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
3002
+ break ;
3003
+ case Instruction::LShr:
3004
+ ResultReg = emitLSR_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
3005
+ break ;
3006
+ }
3007
+ if (!ResultReg)
3008
+ return false ;
2911
3009
2912
- unsigned ResultReg;
2913
- if (IsLeftShift)
2914
- ResultReg = Emit_LSL_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
2915
- else {
2916
- if (IsArithmetic)
2917
- ResultReg = Emit_ASR_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
2918
- else
2919
- ResultReg = Emit_LSR_ri (RetVT, Op0Reg, Op0IsKill, ShiftVal);
3010
+ UpdateValueMap (I, ResultReg);
3011
+ return true ;
3012
+ }
3013
+
3014
+ unsigned Op1Reg = getRegForValue (I->getOperand (1 ));
3015
+ if (!Op1Reg)
3016
+ return false ;
3017
+ bool Op1IsKill = hasTrivialKill (I->getOperand (1 ));
3018
+
3019
+ unsigned ResultReg = 0 ;
3020
+ switch (I->getOpcode ()) {
3021
+ default : llvm_unreachable (" Unexpected instruction." );
3022
+ case Instruction::Shl:
3023
+ ResultReg = emitLSL_rr (RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
3024
+ break ;
3025
+ case Instruction::AShr:
3026
+ ResultReg = emitASR_rr (RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
3027
+ break ;
3028
+ case Instruction::LShr:
3029
+ ResultReg = emitLSR_rr (RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
3030
+ break ;
2920
3031
}
2921
3032
2922
3033
if (!ResultReg)
@@ -3012,12 +3123,10 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
3012
3123
// selector -> improve FastISel tblgen.
3013
3124
case Instruction::Mul:
3014
3125
return SelectMul (I);
3015
- case Instruction::Shl:
3016
- return SelectShift (I, /* IsLeftShift=*/ true , /* IsArithmetic=*/ false );
3017
- case Instruction::LShr:
3018
- return SelectShift (I, /* IsLeftShift=*/ false , /* IsArithmetic=*/ false );
3126
+ case Instruction::Shl: // fall-through
3127
+ case Instruction::LShr: // fall-through
3019
3128
case Instruction::AShr:
3020
- return SelectShift (I, /* IsLeftShift= */ false , /* IsArithmetic= */ true );
3129
+ return SelectShift (I);
3021
3130
case Instruction::BitCast:
3022
3131
return SelectBitCast (I);
3023
3132
}
0 commit comments