Skip to content

Commit 0e0b4c1

Browse files
committedAug 21, 2014
[FastISel][AArch64] Add support for variable shift.
This adds the missing variable shift support for value type i8, i16, and i32. This fixes <rdar://problem/18095685>. llvm-svn: 216242
1 parent 2c52c66 commit 0e0b4c1

File tree

2 files changed

+253
-44
lines changed

2 files changed

+253
-44
lines changed
 

‎llvm/lib/Target/AArch64/AArch64FastISel.cpp

+141-32
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class AArch64FastISel : public FastISel {
128128
bool SelectTrunc(const Instruction *I);
129129
bool SelectIntExt(const Instruction *I);
130130
bool SelectMul(const Instruction *I);
131-
bool SelectShift(const Instruction *I, bool IsLeftShift, bool IsArithmetic);
131+
bool SelectShift(const Instruction *I);
132132
bool SelectBitCast(const Instruction *I);
133133

134134
// Utility helper routines.
@@ -193,9 +193,15 @@ class AArch64FastISel : public FastISel {
193193
unsigned Op1, bool Op1IsKill);
194194
unsigned Emit_UMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
195195
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);
199205

200206
unsigned AArch64MaterializeInt(const ConstantInt *CI, MVT VT);
201207
unsigned AArch64MaterializeFP(const ConstantFP *CFP, MVT VT);
@@ -703,8 +709,8 @@ bool AArch64FastISel::SimplifyAddress(Address &Addr, MVT VT) {
703709
Addr.getOffsetReg(), /*TODO:IsKill=*/false,
704710
Addr.getShift());
705711
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());
708714
if (!ResultReg)
709715
return false;
710716

@@ -2366,7 +2372,7 @@ bool AArch64FastISel::FastLowerIntrinsicCall(const IntrinsicInst *II) {
23662372

23672373
if (VT == MVT::i32) {
23682374
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);
23702376
MulReg = FastEmitInst_extractsubreg(VT, MulReg, /*IsKill=*/true,
23712377
AArch64::sub_32);
23722378
ShiftReg = FastEmitInst_extractsubreg(VT, ShiftReg, /*IsKill=*/true,
@@ -2653,8 +2659,34 @@ unsigned AArch64FastISel::Emit_UMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
26532659
AArch64::XZR, /*IsKill=*/true);
26542660
}
26552661

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) {
26582690
unsigned Opc, ImmR, ImmS;
26592691
switch (RetVT.SimpleTy) {
26602692
default: return 0;
@@ -2673,8 +2705,35 @@ unsigned AArch64FastISel::Emit_LSL_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
26732705
return FastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
26742706
}
26752707

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) {
26782737
unsigned Opc, ImmS;
26792738
switch (RetVT.SimpleTy) {
26802739
default: return 0;
@@ -2689,8 +2748,35 @@ unsigned AArch64FastISel::Emit_LSR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
26892748
return FastEmitInst_rii(Opc, RC, Op0, Op0IsKill, Shift, ImmS);
26902749
}
26912750

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) {
26942780
unsigned Opc, ImmS;
26952781
switch (RetVT.SimpleTy) {
26962782
default: return 0;
@@ -2892,31 +2978,56 @@ bool AArch64FastISel::SelectMul(const Instruction *I) {
28922978
return true;
28932979
}
28942980

2895-
bool AArch64FastISel::SelectShift(const Instruction *I, bool IsLeftShift,
2896-
bool IsArithmetic) {
2981+
bool AArch64FastISel::SelectShift(const Instruction *I) {
28972982
EVT RetEVT = TLI.getValueType(I->getType(), true);
28982983
if (!RetEVT.isSimple())
28992984
return false;
29002985
MVT RetVT = RetEVT.getSimpleVT();
29012986

2902-
if (!isa<ConstantInt>(I->getOperand(1)))
2903-
return false;
2904-
29052987
unsigned Op0Reg = getRegForValue(I->getOperand(0));
29062988
if (!Op0Reg)
29072989
return false;
29082990
bool Op0IsKill = hasTrivialKill(I->getOperand(0));
29092991

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;
29113009

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;
29203031
}
29213032

29223033
if (!ResultReg)
@@ -3012,12 +3123,10 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
30123123
// selector -> improve FastISel tblgen.
30133124
case Instruction::Mul:
30143125
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
30193128
case Instruction::AShr:
3020-
return SelectShift(I, /*IsLeftShift=*/false, /*IsArithmetic=*/true);
3129+
return SelectShift(I);
30213130
case Instruction::BitCast:
30223131
return SelectBitCast(I);
30233132
}

‎llvm/test/CodeGen/AArch64/fast-isel-shift.ll

+112-12
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,187 @@
11
; RUN: llc -fast-isel -fast-isel-abort -mtriple=arm64-apple-darwin -verify-machineinstrs < %s | FileCheck %s
22

3+
; CHECK-LABEL: lslv_i8
4+
; CHECK: and [[REG1:w[0-9]+]], w1, #0xff
5+
; CHECK-NEXT: lsl [[REG2:w[0-9]+]], w0, [[REG1]]
6+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG2]], #0xff
7+
define zeroext i8 @lslv_i8(i8 %a, i8 %b) {
8+
%1 = shl i8 %a, %b
9+
ret i8 %1
10+
}
11+
312
; CHECK-LABEL: lsl_i8
4-
; CHECK: ubfiz {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
13+
; CHECK: ubfiz {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
514
define zeroext i8 @lsl_i8(i8 %a) {
615
%1 = shl i8 %a, 4
716
ret i8 %1
817
}
918

19+
; CHECK-LABEL: lslv_i16
20+
; CHECK: and [[REG1:w[0-9]+]], w1, #0xffff
21+
; CHECK-NEXT: lsl [[REG2:w[0-9]+]], w0, [[REG1]]
22+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG2]], #0xffff
23+
define zeroext i16 @lslv_i16(i16 %a, i16 %b) {
24+
%1 = shl i16 %a, %b
25+
ret i16 %1
26+
}
27+
1028
; CHECK-LABEL: lsl_i16
11-
; CHECK: ubfiz {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
29+
; CHECK: ubfiz {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
1230
define zeroext i16 @lsl_i16(i16 %a) {
1331
%1 = shl i16 %a, 8
1432
ret i16 %1
1533
}
1634

35+
; CHECK-LABEL: lslv_i32
36+
; CHECK: lsl {{w[0-9]*}}, w0, w1
37+
define zeroext i32 @lslv_i32(i32 %a, i32 %b) {
38+
%1 = shl i32 %a, %b
39+
ret i32 %1
40+
}
41+
1742
; CHECK-LABEL: lsl_i32
18-
; CHECK: lsl {{w[0-9]*}}, {{w[0-9]*}}, #16
43+
; CHECK: lsl {{w[0-9]*}}, {{w[0-9]*}}, #16
1944
define zeroext i32 @lsl_i32(i32 %a) {
2045
%1 = shl i32 %a, 16
2146
ret i32 %1
2247
}
2348

49+
; CHECK-LABEL: lslv_i64
50+
; CHECK: lsl {{x[0-9]*}}, x0, x1
51+
define i64 @lslv_i64(i64 %a, i64 %b) {
52+
%1 = shl i64 %a, %b
53+
ret i64 %1
54+
}
55+
2456
; FIXME: This shouldn't use the variable shift version.
2557
; CHECK-LABEL: lsl_i64
26-
; CHECK: lsl {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
58+
; CHECK: lsl {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
2759
define i64 @lsl_i64(i64 %a) {
2860
%1 = shl i64 %a, 32
2961
ret i64 %1
3062
}
3163

64+
; CHECK-LABEL: lsrv_i8
65+
; CHECK: and [[REG1:w[0-9]+]], w0, #0xff
66+
; CHECK-NEXT: and [[REG2:w[0-9]+]], w1, #0xff
67+
; CHECK-NEXT: lsr [[REG3:w[0-9]+]], [[REG1]], [[REG2]]
68+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG3]], #0xff
69+
define zeroext i8 @lsrv_i8(i8 %a, i8 %b) {
70+
%1 = lshr i8 %a, %b
71+
ret i8 %1
72+
}
73+
3274
; CHECK-LABEL: lsr_i8
33-
; CHECK: ubfx {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
75+
; CHECK: ubfx {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
3476
define zeroext i8 @lsr_i8(i8 %a) {
3577
%1 = lshr i8 %a, 4
3678
ret i8 %1
3779
}
3880

81+
; CHECK-LABEL: lsrv_i16
82+
; CHECK: and [[REG1:w[0-9]+]], w0, #0xffff
83+
; CHECK-NEXT: and [[REG2:w[0-9]+]], w1, #0xffff
84+
; CHECK-NEXT: lsr [[REG3:w[0-9]+]], [[REG1]], [[REG2]]
85+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG3]], #0xffff
86+
define zeroext i16 @lsrv_i16(i16 %a, i16 %b) {
87+
%1 = lshr i16 %a, %b
88+
ret i16 %1
89+
}
90+
3991
; CHECK-LABEL: lsr_i16
40-
; CHECK: ubfx {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
92+
; CHECK: ubfx {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
4193
define zeroext i16 @lsr_i16(i16 %a) {
4294
%1 = lshr i16 %a, 8
4395
ret i16 %1
4496
}
4597

98+
; CHECK-LABEL: lsrv_i32
99+
; CHECK: lsr {{w[0-9]*}}, w0, w1
100+
define zeroext i32 @lsrv_i32(i32 %a, i32 %b) {
101+
%1 = lshr i32 %a, %b
102+
ret i32 %1
103+
}
104+
46105
; CHECK-LABEL: lsr_i32
47-
; CHECK: lsr {{w[0-9]*}}, {{w[0-9]*}}, #16
106+
; CHECK: lsr {{w[0-9]*}}, {{w[0-9]*}}, #16
48107
define zeroext i32 @lsr_i32(i32 %a) {
49108
%1 = lshr i32 %a, 16
50109
ret i32 %1
51110
}
52111

112+
; CHECK-LABEL: lsrv_i64
113+
; CHECK: lsr {{x[0-9]*}}, x0, x1
114+
define i64 @lsrv_i64(i64 %a, i64 %b) {
115+
%1 = lshr i64 %a, %b
116+
ret i64 %1
117+
}
118+
53119
; FIXME: This shouldn't use the variable shift version.
54120
; CHECK-LABEL: lsr_i64
55-
; CHECK: lsr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
121+
; CHECK: lsr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
56122
define i64 @lsr_i64(i64 %a) {
57123
%1 = lshr i64 %a, 32
58124
ret i64 %1
59125
}
60126

127+
; CHECK-LABEL: asrv_i8
128+
; CHECK: sxtb [[REG1:w[0-9]+]], w0
129+
; CHECK-NEXT: and [[REG2:w[0-9]+]], w1, #0xff
130+
; CHECK-NEXT: asr [[REG3:w[0-9]+]], [[REG1]], [[REG2]]
131+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG3]], #0xff
132+
define zeroext i8 @asrv_i8(i8 %a, i8 %b) {
133+
%1 = ashr i8 %a, %b
134+
ret i8 %1
135+
}
136+
61137
; CHECK-LABEL: asr_i8
62-
; CHECK: sbfx {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
138+
; CHECK: sbfx {{w[0-9]*}}, {{w[0-9]*}}, #4, #4
63139
define zeroext i8 @asr_i8(i8 %a) {
64140
%1 = ashr i8 %a, 4
65141
ret i8 %1
66142
}
67143

144+
; CHECK-LABEL: asrv_i16
145+
; CHECK: sxth [[REG1:w[0-9]+]], w0
146+
; CHECK-NEXT: and [[REG2:w[0-9]+]], w1, #0xffff
147+
; CHECK-NEXT: asr [[REG3:w[0-9]+]], [[REG1]], [[REG2]]
148+
; CHECK-NEXT: and {{w[0-9]+}}, [[REG3]], #0xffff
149+
define zeroext i16 @asrv_i16(i16 %a, i16 %b) {
150+
%1 = ashr i16 %a, %b
151+
ret i16 %1
152+
}
153+
68154
; CHECK-LABEL: asr_i16
69-
; CHECK: sbfx {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
155+
; CHECK: sbfx {{w[0-9]*}}, {{w[0-9]*}}, #8, #8
70156
define zeroext i16 @asr_i16(i16 %a) {
71157
%1 = ashr i16 %a, 8
72158
ret i16 %1
73159
}
74160

161+
; CHECK-LABEL: asrv_i32
162+
; CHECK: asr {{w[0-9]*}}, w0, w1
163+
define zeroext i32 @asrv_i32(i32 %a, i32 %b) {
164+
%1 = ashr i32 %a, %b
165+
ret i32 %1
166+
}
167+
75168
; CHECK-LABEL: asr_i32
76-
; CHECK: asr {{w[0-9]*}}, {{w[0-9]*}}, #16
169+
; CHECK: asr {{w[0-9]*}}, {{w[0-9]*}}, #16
77170
define zeroext i32 @asr_i32(i32 %a) {
78171
%1 = ashr i32 %a, 16
79172
ret i32 %1
80173
}
81174

175+
; CHECK-LABEL: asrv_i64
176+
; CHECK: asr {{x[0-9]*}}, x0, x1
177+
define i64 @asrv_i64(i64 %a, i64 %b) {
178+
%1 = ashr i64 %a, %b
179+
ret i64 %1
180+
}
181+
82182
; FIXME: This shouldn't use the variable shift version.
83183
; CHECK-LABEL: asr_i64
84-
; CHECK: asr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
184+
; CHECK: asr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
85185
define i64 @asr_i64(i64 %a) {
86186
%1 = ashr i64 %a, 32
87187
ret i64 %1

0 commit comments

Comments
 (0)
Please sign in to comment.