1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; If we have a shift by sign-extended value, we can replace sign-extension
5; with zero-extension.
6
7define i32 @t0_shl(i32 %x, i8 %shamt) {
8; CHECK-LABEL: @t0_shl(
9; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext i8 [[SHAMT:%.*]] to i32
10; CHECK-NEXT:    [[R:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE1]]
11; CHECK-NEXT:    ret i32 [[R]]
12;
13  %shamt_wide = sext i8 %shamt to i32
14  %r = shl i32 %x, %shamt_wide
15  ret i32 %r
16}
17define i32 @t1_lshr(i32 %x, i8 %shamt) {
18; CHECK-LABEL: @t1_lshr(
19; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext i8 [[SHAMT:%.*]] to i32
20; CHECK-NEXT:    [[R:%.*]] = lshr i32 [[X:%.*]], [[SHAMT_WIDE1]]
21; CHECK-NEXT:    ret i32 [[R]]
22;
23  %shamt_wide = sext i8 %shamt to i32
24  %r = lshr i32 %x, %shamt_wide
25  ret i32 %r
26}
27define i32 @t2_ashr(i32 %x, i8 %shamt) {
28; CHECK-LABEL: @t2_ashr(
29; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext i8 [[SHAMT:%.*]] to i32
30; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[X:%.*]], [[SHAMT_WIDE1]]
31; CHECK-NEXT:    ret i32 [[R]]
32;
33  %shamt_wide = sext i8 %shamt to i32
34  %r = ashr i32 %x, %shamt_wide
35  ret i32 %r
36}
37
38define <2 x i32> @t3_vec_shl(<2 x i32> %x, <2 x i8> %shamt) {
39; CHECK-LABEL: @t3_vec_shl(
40; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext <2 x i8> [[SHAMT:%.*]] to <2 x i32>
41; CHECK-NEXT:    [[R:%.*]] = shl <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]
42; CHECK-NEXT:    ret <2 x i32> [[R]]
43;
44  %shamt_wide = sext <2 x i8> %shamt to <2 x i32>
45  %r = shl <2 x i32> %x, %shamt_wide
46  ret <2 x i32> %r
47}
48define <2 x i32> @t4_vec_lshr(<2 x i32> %x, <2 x i8> %shamt) {
49; CHECK-LABEL: @t4_vec_lshr(
50; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext <2 x i8> [[SHAMT:%.*]] to <2 x i32>
51; CHECK-NEXT:    [[R:%.*]] = lshr <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]
52; CHECK-NEXT:    ret <2 x i32> [[R]]
53;
54  %shamt_wide = sext <2 x i8> %shamt to <2 x i32>
55  %r = lshr <2 x i32> %x, %shamt_wide
56  ret <2 x i32> %r
57}
58define <2 x i32> @t5_vec_ashr(<2 x i32> %x, <2 x i8> %shamt) {
59; CHECK-LABEL: @t5_vec_ashr(
60; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext <2 x i8> [[SHAMT:%.*]] to <2 x i32>
61; CHECK-NEXT:    [[R:%.*]] = ashr <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]
62; CHECK-NEXT:    ret <2 x i32> [[R]]
63;
64  %shamt_wide = sext <2 x i8> %shamt to <2 x i32>
65  %r = ashr <2 x i32> %x, %shamt_wide
66  ret <2 x i32> %r
67}
68
69define i32 @t6_twoshifts(i32 %x, i8 %shamt) {
70; CHECK-LABEL: @t6_twoshifts(
71; CHECK-NEXT:  bb:
72; CHECK-NEXT:    [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32
73; CHECK-NEXT:    br label [[WORK:%.*]]
74; CHECK:       work:
75; CHECK-NEXT:    br label [[END:%.*]]
76; CHECK:       end:
77; CHECK-NEXT:    [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]
78; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[N0]], [[SHAMT_WIDE]]
79; CHECK-NEXT:    ret i32 [[R]]
80;
81bb:
82  %shamt_wide = sext i8 %shamt to i32
83  br label %work
84work:
85  %n0 = shl i32 %x, %shamt_wide
86  %r = ashr i32 %n0, %shamt_wide
87  br label %end
88end:
89  ret i32 %r
90}
91
92; This is not valid for funnel shifts in general
93declare i7 @llvm.fshl.i7(i7 %a, i7 %b, i7 %c)
94declare i7 @llvm.fshr.i7(i7 %a, i7 %b, i7 %c)
95define i7 @n7_fshl(i7 %x, i7 %y, i6 %shamt) {
96; CHECK-LABEL: @n7_fshl(
97; CHECK-NEXT:    [[SHAMT_WIDE:%.*]] = sext i6 [[SHAMT:%.*]] to i7
98; CHECK-NEXT:    [[R:%.*]] = call i7 @llvm.fshl.i7(i7 [[X:%.*]], i7 [[Y:%.*]], i7 [[SHAMT_WIDE]])
99; CHECK-NEXT:    ret i7 [[R]]
100;
101  %shamt_wide = sext i6 %shamt to i7
102  %r = call i7 @llvm.fshl.i7(i7 %x, i7 %y, i7 %shamt_wide)
103  ret i7 %r
104}
105define i7 @n8_fshr(i7 %x, i7 %y, i6 %shamt) {
106; CHECK-LABEL: @n8_fshr(
107; CHECK-NEXT:    [[SHAMT_WIDE:%.*]] = sext i6 [[SHAMT:%.*]] to i7
108; CHECK-NEXT:    [[R:%.*]] = call i7 @llvm.fshr.i7(i7 [[X:%.*]], i7 [[Y:%.*]], i7 [[SHAMT_WIDE]])
109; CHECK-NEXT:    ret i7 [[R]]
110;
111  %shamt_wide = sext i6 %shamt to i7
112  %r = call i7 @llvm.fshr.i7(i7 %x, i7 %y, i7 %shamt_wide)
113  ret i7 %r
114}
115; And the cases that are safe are handled by SimplifyDemandedBits().
116declare i8 @llvm.fshl.i8(i8 %a, i8 %b, i8 %c)
117declare i8 @llvm.fshr.i8(i8 %a, i8 %b, i8 %c)
118define i8 @t9_fshl(i8 %x, i8 %y, i6 %shamt) {
119; CHECK-LABEL: @t9_fshl(
120; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext i6 [[SHAMT:%.*]] to i8
121; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SHAMT_WIDE1]])
122; CHECK-NEXT:    ret i8 [[R]]
123;
124  %shamt_wide = sext i6 %shamt to i8
125  %r = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %shamt_wide)
126  ret i8 %r
127}
128define i8 @t10_fshr(i8 %x, i8 %y, i6 %shamt) {
129; CHECK-LABEL: @t10_fshr(
130; CHECK-NEXT:    [[SHAMT_WIDE1:%.*]] = zext i6 [[SHAMT:%.*]] to i8
131; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SHAMT_WIDE1]])
132; CHECK-NEXT:    ret i8 [[R]]
133;
134  %shamt_wide = sext i6 %shamt to i8
135  %r = call i8 @llvm.fshr.i8(i8 %x, i8 %y, i8 %shamt_wide)
136  ret i8 %r
137}
138
139declare void @use32(i32)
140define i32 @n11_extrause(i32 %x, i8 %shamt) {
141; CHECK-LABEL: @n11_extrause(
142; CHECK-NEXT:    [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32
143; CHECK-NEXT:    call void @use32(i32 [[SHAMT_WIDE]])
144; CHECK-NEXT:    [[R:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]
145; CHECK-NEXT:    ret i32 [[R]]
146;
147  %shamt_wide = sext i8 %shamt to i32
148  call void @use32(i32 %shamt_wide)
149  %r = shl i32 %x, %shamt_wide
150  ret i32 %r
151}
152define i32 @n12_twoshifts_and_extrause(i32 %x, i8 %shamt) {
153; CHECK-LABEL: @n12_twoshifts_and_extrause(
154; CHECK-NEXT:    [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32
155; CHECK-NEXT:    br label [[WORK:%.*]]
156; CHECK:       work:
157; CHECK-NEXT:    br label [[END:%.*]]
158; CHECK:       end:
159; CHECK-NEXT:    [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]
160; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[N0]], [[SHAMT_WIDE]]
161; CHECK-NEXT:    call void @use32(i32 [[SHAMT_WIDE]])
162; CHECK-NEXT:    ret i32 [[R]]
163;
164  %shamt_wide = sext i8 %shamt to i32
165  br label %work
166work:
167  %n0 = shl i32 %x, %shamt_wide
168  %r = ashr i32 %n0, %shamt_wide
169  br label %end
170end:
171  call void @use32(i32 %shamt_wide)
172  ret i32 %r
173}
174