xref: /aosp_15_r20/external/llvm/test/CodeGen/SystemZ/shift-08.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; Test 32-bit rotates left.
2*9880d681SAndroid Build Coastguard Worker;
3*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker; Check the low end of the RLLG range.
6*9880d681SAndroid Build Coastguard Workerdefine i64 @f1(i64 %a) {
7*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f1:
8*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 1
9*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
10*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, 1
11*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, 63
12*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
13*9880d681SAndroid Build Coastguard Worker  ret i64 %or
14*9880d681SAndroid Build Coastguard Worker}
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker; Check the high end of the defined RLLG range.
17*9880d681SAndroid Build Coastguard Workerdefine i64 @f2(i64 %a) {
18*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f2:
19*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 63
20*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
21*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, 63
22*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, 1
23*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
24*9880d681SAndroid Build Coastguard Worker  ret i64 %or
25*9880d681SAndroid Build Coastguard Worker}
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker; We don't generate shifts by out-of-range values.
28*9880d681SAndroid Build Coastguard Workerdefine i64 @f3(i64 %a) {
29*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f3:
30*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: rllg
31*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
32*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, 64
33*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, 0
34*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
35*9880d681SAndroid Build Coastguard Worker  ret i64 %or
36*9880d681SAndroid Build Coastguard Worker}
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker; Check variable shifts.
39*9880d681SAndroid Build Coastguard Workerdefine i64 @f4(i64 %a, i64 %amt) {
40*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f4:
41*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 0(%r3)
42*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
43*9880d681SAndroid Build Coastguard Worker  %amtb = sub i64 64, %amt
44*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %amt
45*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %amtb
46*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
47*9880d681SAndroid Build Coastguard Worker  ret i64 %or
48*9880d681SAndroid Build Coastguard Worker}
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker; Check shift amounts that have a constant term.
51*9880d681SAndroid Build Coastguard Workerdefine i64 @f5(i64 %a, i64 %amt) {
52*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f5:
53*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 10(%r3)
54*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
55*9880d681SAndroid Build Coastguard Worker  %add = add i64 %amt, 10
56*9880d681SAndroid Build Coastguard Worker  %sub = sub i64 64, %add
57*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %add
58*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %sub
59*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
60*9880d681SAndroid Build Coastguard Worker  ret i64 %or
61*9880d681SAndroid Build Coastguard Worker}
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker; ...and again with a sign-extended 32-bit shift amount.
64*9880d681SAndroid Build Coastguard Workerdefine i64 @f6(i64 %a, i32 %amt) {
65*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f6:
66*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 10(%r3)
67*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
68*9880d681SAndroid Build Coastguard Worker  %add = add i32 %amt, 10
69*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 64, %add
70*9880d681SAndroid Build Coastguard Worker  %addext = sext i32 %add to i64
71*9880d681SAndroid Build Coastguard Worker  %subext = sext i32 %sub to i64
72*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %addext
73*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %subext
74*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
75*9880d681SAndroid Build Coastguard Worker  ret i64 %or
76*9880d681SAndroid Build Coastguard Worker}
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker; ...and now with a zero-extended 32-bit shift amount.
79*9880d681SAndroid Build Coastguard Workerdefine i64 @f7(i64 %a, i32 %amt) {
80*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f7:
81*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 10(%r3)
82*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
83*9880d681SAndroid Build Coastguard Worker  %add = add i32 %amt, 10
84*9880d681SAndroid Build Coastguard Worker  %sub = sub i32 64, %add
85*9880d681SAndroid Build Coastguard Worker  %addext = zext i32 %add to i64
86*9880d681SAndroid Build Coastguard Worker  %subext = zext i32 %sub to i64
87*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %addext
88*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %subext
89*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
90*9880d681SAndroid Build Coastguard Worker  ret i64 %or
91*9880d681SAndroid Build Coastguard Worker}
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker; Check shift amounts that have the largest in-range constant term.  We could
94*9880d681SAndroid Build Coastguard Worker; mask the amount instead.
95*9880d681SAndroid Build Coastguard Workerdefine i64 @f8(i64 %a, i64 %amt) {
96*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f8:
97*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 524287(%r3)
98*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
99*9880d681SAndroid Build Coastguard Worker  %add = add i64 %amt, 524287
100*9880d681SAndroid Build Coastguard Worker  %sub = sub i64 64, %add
101*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %add
102*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %sub
103*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
104*9880d681SAndroid Build Coastguard Worker  ret i64 %or
105*9880d681SAndroid Build Coastguard Worker}
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker; Check the next value up, which without masking must use a separate
108*9880d681SAndroid Build Coastguard Worker; addition.
109*9880d681SAndroid Build Coastguard Workerdefine i64 @f9(i64 %a, i64 %amt) {
110*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f9:
111*9880d681SAndroid Build Coastguard Worker; CHECK: a{{g?}}fi %r3, 524288
112*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 0(%r3)
113*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
114*9880d681SAndroid Build Coastguard Worker  %add = add i64 %amt, 524288
115*9880d681SAndroid Build Coastguard Worker  %sub = sub i64 64, %add
116*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %add
117*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %sub
118*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
119*9880d681SAndroid Build Coastguard Worker  ret i64 %or
120*9880d681SAndroid Build Coastguard Worker}
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker; Check cases where 1 is subtracted from the shift amount.
123*9880d681SAndroid Build Coastguard Workerdefine i64 @f10(i64 %a, i64 %amt) {
124*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f10:
125*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, -1(%r3)
126*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
127*9880d681SAndroid Build Coastguard Worker  %suba = sub i64 %amt, 1
128*9880d681SAndroid Build Coastguard Worker  %subb = sub i64 64, %suba
129*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %suba
130*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %subb
131*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
132*9880d681SAndroid Build Coastguard Worker  ret i64 %or
133*9880d681SAndroid Build Coastguard Worker}
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker; Check the lowest value that can be subtracted from the shift amount.
136*9880d681SAndroid Build Coastguard Worker; Again, we could mask the shift amount instead.
137*9880d681SAndroid Build Coastguard Workerdefine i64 @f11(i64 %a, i64 %amt) {
138*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f11:
139*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, -524288(%r3)
140*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
141*9880d681SAndroid Build Coastguard Worker  %suba = sub i64 %amt, 524288
142*9880d681SAndroid Build Coastguard Worker  %subb = sub i64 64, %suba
143*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %suba
144*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %subb
145*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
146*9880d681SAndroid Build Coastguard Worker  ret i64 %or
147*9880d681SAndroid Build Coastguard Worker}
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker; Check the next value down, which without masking must use a separate
150*9880d681SAndroid Build Coastguard Worker; addition.
151*9880d681SAndroid Build Coastguard Workerdefine i64 @f12(i64 %a, i64 %amt) {
152*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f12:
153*9880d681SAndroid Build Coastguard Worker; CHECK: a{{g?}}fi %r3, -524289
154*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 0(%r3)
155*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
156*9880d681SAndroid Build Coastguard Worker  %suba = sub i64 %amt, 524289
157*9880d681SAndroid Build Coastguard Worker  %subb = sub i64 64, %suba
158*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %suba
159*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %subb
160*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
161*9880d681SAndroid Build Coastguard Worker  ret i64 %or
162*9880d681SAndroid Build Coastguard Worker}
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker; Check that we don't try to generate "indexed" shifts.
165*9880d681SAndroid Build Coastguard Workerdefine i64 @f13(i64 %a, i64 %b, i64 %c) {
166*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f13:
167*9880d681SAndroid Build Coastguard Worker; CHECK: a{{g?}}r {{%r3, %r4|%r4, %r3}}
168*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 0({{%r[34]}})
169*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
170*9880d681SAndroid Build Coastguard Worker  %add = add i64 %b, %c
171*9880d681SAndroid Build Coastguard Worker  %sub = sub i64 64, %add
172*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %add
173*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %sub
174*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
175*9880d681SAndroid Build Coastguard Worker  ret i64 %or
176*9880d681SAndroid Build Coastguard Worker}
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker; Check that the shift amount uses an address register.  It cannot be in %r0.
179*9880d681SAndroid Build Coastguard Workerdefine i64 @f14(i64 %a, i64 *%ptr) {
180*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: f14:
181*9880d681SAndroid Build Coastguard Worker; CHECK: l %r1, 4(%r3)
182*9880d681SAndroid Build Coastguard Worker; CHECK: rllg %r2, %r2, 0(%r1)
183*9880d681SAndroid Build Coastguard Worker; CHECK: br %r14
184*9880d681SAndroid Build Coastguard Worker  %amt = load i64 , i64 *%ptr
185*9880d681SAndroid Build Coastguard Worker  %amtb = sub i64 64, %amt
186*9880d681SAndroid Build Coastguard Worker  %parta = shl i64 %a, %amt
187*9880d681SAndroid Build Coastguard Worker  %partb = lshr i64 %a, %amtb
188*9880d681SAndroid Build Coastguard Worker  %or = or i64 %parta, %partb
189*9880d681SAndroid Build Coastguard Worker  ret i64 %or
190*9880d681SAndroid Build Coastguard Worker}
191