@@ -90,3 +90,109 @@ define <2 x i1> @icmp_ugt_16x2(<2 x i32>) {
9090 %d = icmp ugt <2 x i32 > %c , <i32 1048575 , i32 1048575 >
9191 ret <2 x i1 > %d
9292}
93+
94+ define i1 @fold_icmp_shl_nuw_c1 (i32 %x ) {
95+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c1(
96+ ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 61440
97+ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
98+ ; CHECK-NEXT: ret i1 [[CMP]]
99+ ;
100+ %lshr = lshr i32 %x , 12
101+ %and = and i32 %lshr , 15
102+ %shl = shl nuw i32 2 , %and
103+ %cmp = icmp ult i32 %shl , 4
104+ ret i1 %cmp
105+ }
106+
107+ define i1 @fold_icmp_shl_nuw_c2 (i32 %x ) {
108+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2(
109+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 2
110+ ; CHECK-NEXT: ret i1 [[CMP]]
111+ ;
112+ %shl = shl nuw i32 16 , %x
113+ %cmp = icmp ult i32 %shl , 64
114+ ret i1 %cmp
115+ }
116+
117+ define i1 @fold_icmp_shl_nuw_c2_non_pow2 (i32 %x ) {
118+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_non_pow2(
119+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 2
120+ ; CHECK-NEXT: ret i1 [[CMP]]
121+ ;
122+ %shl = shl nuw i32 48 , %x
123+ %cmp = icmp ult i32 %shl , 192
124+ ret i1 %cmp
125+ }
126+
127+ define i1 @fold_icmp_shl_nuw_c2_div_non_pow2 (i32 %x ) {
128+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_div_non_pow2(
129+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 5
130+ ; CHECK-NEXT: ret i1 [[CMP]]
131+ ;
132+ %shl = shl nuw i32 2 , %x
133+ %cmp = icmp ult i32 %shl , 60
134+ ret i1 %cmp
135+ }
136+
137+ define i1 @fold_icmp_shl_nuw_c3 (i32 %x ) {
138+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c3(
139+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 1
140+ ; CHECK-NEXT: ret i1 [[CMP]]
141+ ;
142+ %shl = shl nuw i32 48 , %x
143+ %cmp = icmp uge i32 %shl , 144
144+ ret i1 %cmp
145+ }
146+
147+ define i1 @fold_icmp_shl_nuw_c2_indivisible (i32 %x ) {
148+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_indivisible(
149+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 2
150+ ; CHECK-NEXT: ret i1 [[CMP]]
151+ ;
152+ %shl = shl nuw i32 16 , %x
153+ %cmp = icmp ult i32 %shl , 63
154+ ret i1 %cmp
155+ }
156+
157+ ; Negative tests
158+
159+ define i1 @fold_icmp_shl_c2_without_nuw (i32 %x ) {
160+ ; CHECK-LABEL: @fold_icmp_shl_c2_without_nuw(
161+ ; CHECK-NEXT: [[SHL:%.*]] = shl i32 16, [[X:%.*]]
162+ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SHL]], 64
163+ ; CHECK-NEXT: ret i1 [[CMP]]
164+ ;
165+ %shl = shl i32 16 , %x
166+ %cmp = icmp ult i32 %shl , 64
167+ ret i1 %cmp
168+ }
169+
170+ ; Make sure this trivial case is folded by InstSimplify.
171+ define i1 @fold_icmp_shl_nuw_c2_precondition1 (i32 %x ) {
172+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_precondition1(
173+ ; CHECK-NEXT: ret i1 true
174+ ;
175+ %shl = shl nuw i32 0 , %x
176+ %cmp = icmp ult i32 %shl , 63
177+ ret i1 %cmp
178+ }
179+
180+ ; Make sure this trivial case is folded by InstSimplify.
181+ define i1 @fold_icmp_shl_nuw_c2_precondition2 (i32 %x ) {
182+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_precondition2(
183+ ; CHECK-NEXT: ret i1 false
184+ ;
185+ %shl = shl nuw i32 127 , %x
186+ %cmp = icmp ult i32 %shl , 63
187+ ret i1 %cmp
188+ }
189+
190+ ; Make sure we don't crash on this case.
191+ define i1 @fold_icmp_shl_nuw_c2_precondition3 (i32 %x ) {
192+ ; CHECK-LABEL: @fold_icmp_shl_nuw_c2_precondition3(
193+ ; CHECK-NEXT: ret i1 false
194+ ;
195+ %shl = shl nuw i32 1 , %x
196+ %cmp = icmp ult i32 %shl , 1
197+ ret i1 %cmp
198+ }
0 commit comments