1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; If we zero-extend some value, and then immediately left-shift-out all the new
5; sign bits, and apply a mask to keep only the sign bit (which is the original
6; sign bit from before zero-extension), we might as well just sign-extend
7; and apply the same signmask.
8
9declare void @use32(i32)
10
11; Basic pattern
12
13define i32 @t0(i16 %x) {
14; CHECK-LABEL: @t0(
15; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext i16 [[X:%.*]] to i32
16; CHECK-NEXT:    [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
17; CHECK-NEXT:    ret i32 [[R]]
18;
19  %i0 = zext i16 %x to i32
20  %i1 = shl i32 %i0, 16
21  %r = and i32 %i1, -2147483648
22  ret i32 %r
23}
24define i32 @t1(i8 %x) {
25; CHECK-LABEL: @t1(
26; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext i8 [[X:%.*]] to i32
27; CHECK-NEXT:    [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
28; CHECK-NEXT:    ret i32 [[R]]
29;
30  %i0 = zext i8 %x to i32
31  %i1 = shl i32 %i0, 24
32  %r = and i32 %i1, -2147483648
33  ret i32 %r
34}
35
36; Some negative tests
37
38define i32 @n2(i16 %x) {
39; CHECK-LABEL: @n2(
40; CHECK-NEXT:    ret i32 0
41;
42  %i0 = zext i16 %x to i32
43  %i1 = shl i32 %i0, 15 ; undershifting
44  %r = and i32 %i1, -2147483648
45  ret i32 %r
46}
47define i32 @n3(i16 %x) {
48; CHECK-LABEL: @n3(
49; CHECK-NEXT:    [[I0:%.*]] = zext i16 [[X:%.*]] to i32
50; CHECK-NEXT:    [[I1:%.*]] = shl i32 [[I0]], 17
51; CHECK-NEXT:    [[R:%.*]] = and i32 [[I1]], -2147483648
52; CHECK-NEXT:    ret i32 [[R]]
53;
54  %i0 = zext i16 %x to i32
55  %i1 = shl i32 %i0, 17 ; overshifting
56  %r = and i32 %i1, -2147483648
57  ret i32 %r
58}
59define i32 @n4(i16 %x) {
60; CHECK-LABEL: @n4(
61; CHECK-NEXT:    [[I0:%.*]] = zext i16 [[X:%.*]] to i32
62; CHECK-NEXT:    [[I1:%.*]] = shl nuw i32 [[I0]], 16
63; CHECK-NEXT:    [[R:%.*]] = and i32 [[I1]], -1073741824
64; CHECK-NEXT:    ret i32 [[R]]
65;
66  %i0 = zext i16 %x to i32
67  %i1 = shl i32 %i0, 16
68  %r = and i32 %i1, 3221225472 ; not a sign bit
69  ret i32 %r
70}
71
72; Extra-use tests
73
74define i32 @t5(i16 %x) {
75; CHECK-LABEL: @t5(
76; CHECK-NEXT:    [[I0:%.*]] = zext i16 [[X:%.*]] to i32
77; CHECK-NEXT:    call void @use32(i32 [[I0]])
78; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext i16 [[X]] to i32
79; CHECK-NEXT:    [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
80; CHECK-NEXT:    ret i32 [[R]]
81;
82  %i0 = zext i16 %x to i32
83  call void @use32(i32 %i0)
84  %i1 = shl i32 %i0, 16
85  %r = and i32 %i1, -2147483648
86  ret i32 %r
87}
88define i32 @n6(i16 %x) {
89; CHECK-LABEL: @n6(
90; CHECK-NEXT:    [[I0:%.*]] = zext i16 [[X:%.*]] to i32
91; CHECK-NEXT:    [[I1:%.*]] = shl nuw i32 [[I0]], 16
92; CHECK-NEXT:    call void @use32(i32 [[I1]])
93; CHECK-NEXT:    [[R:%.*]] = and i32 [[I1]], -2147483648
94; CHECK-NEXT:    ret i32 [[R]]
95;
96  %i0 = zext i16 %x to i32
97  %i1 = shl i32 %i0, 16 ; not one-use
98  call void @use32(i32 %i1)
99  %r = and i32 %i1, -2147483648
100  ret i32 %r
101}
102define i32 @n7(i16 %x) {
103; CHECK-LABEL: @n7(
104; CHECK-NEXT:    [[I0:%.*]] = zext i16 [[X:%.*]] to i32
105; CHECK-NEXT:    call void @use32(i32 [[I0]])
106; CHECK-NEXT:    [[I1:%.*]] = shl nuw i32 [[I0]], 16
107; CHECK-NEXT:    call void @use32(i32 [[I1]])
108; CHECK-NEXT:    [[R:%.*]] = and i32 [[I1]], -2147483648
109; CHECK-NEXT:    ret i32 [[R]]
110;
111  %i0 = zext i16 %x to i32 ; not one-use
112  call void @use32(i32 %i0)
113  %i1 = shl i32 %i0, 16 ; not one-use
114  call void @use32(i32 %i1)
115  %r = and i32 %i1, -2147483648
116  ret i32 %r
117}
118
119; Some vector tests
120
121define <2 x i32> @t8(<2 x i16> %x) {
122; CHECK-LABEL: @t8(
123; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
124; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 -2147483648>
125; CHECK-NEXT:    ret <2 x i32> [[R]]
126;
127  %i0 = zext <2 x i16> %x to <2 x i32>
128  %i1 = shl <2 x i32> %i0, <i32 16, i32 16>
129  %r = and <2 x i32> %i1, <i32 -2147483648, i32 -2147483648>
130  ret <2 x i32> %r
131}
132define <2 x i32> @t9(<2 x i16> %x) {
133; CHECK-LABEL: @t9(
134; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
135; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef>
136; CHECK-NEXT:    ret <2 x i32> [[R]]
137;
138  %i0 = zext <2 x i16> %x to <2 x i32>
139  %i1 = shl <2 x i32> %i0, <i32 16, i32 undef>
140  %r = and <2 x i32> %i1, <i32 -2147483648, i32 -2147483648>
141  ; Here undef can be propagated into the mask.
142  ret <2 x i32> %r
143}
144define <2 x i32> @t10(<2 x i16> %x) {
145; CHECK-LABEL: @t10(
146; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
147; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 0>
148; CHECK-NEXT:    ret <2 x i32> [[R]]
149;
150  %i0 = zext <2 x i16> %x to <2 x i32>
151  %i1 = shl <2 x i32> %i0, <i32 16, i32 16>
152  %r = and <2 x i32> %i1, <i32 -2147483648, i32 undef>
153  ; CAREFUL! We can't keep undef mask here, since high bits are no longer zero,
154  ; we must sanitize it to 0.
155  ret <2 x i32> %r
156}
157define <2 x i32> @t11(<2 x i16> %x) {
158; CHECK-LABEL: @t11(
159; CHECK-NEXT:    [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
160; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef>
161; CHECK-NEXT:    ret <2 x i32> [[R]]
162;
163  %i0 = zext <2 x i16> %x to <2 x i32>
164  %i1 = shl <2 x i32> %i0, <i32 16, i32 undef>
165  %r = and <2 x i32> %i1, <i32 -2147483648, i32 undef>
166  ; Here undef mask is fine.
167  ret <2 x i32> %r
168}
169