llvm.org GIT mirror llvm / 1485367
[InstSimplify] fold icmp based on range of abs/nabs (2nd try) This is retrying the fold from rL345717 (reverted at rL347780) ...with a fix for the miscompile demonstrated by PR39510: https://bugs.llvm.org/show_bug.cgi?id=39510 Original commit message: This is a fix for PR39475: https://bugs.llvm.org/show_bug.cgi?id=39475 We managed to get some of these patterns using computeKnownBits in https://reviews.llvm.org/D47041, but that can't be used for nabs(). Instead, put in some range-based logic, so we can fold both abs/nabs with icmp with a constant value. Alive proofs: https://rise4fun.com/Alive/21r Name: abs_nsw_is_positive %cmp = icmp slt i32 %x, 0 %negx = sub nsw i32 0, %x %abs = select i1 %cmp, i32 %negx, i32 %x %r = icmp sgt i32 %abs, -1 => %r = i1 true Name: abs_nsw_is_not_negative %cmp = icmp slt i32 %x, 0 %negx = sub nsw i32 0, %x %abs = select i1 %cmp, i32 %negx, i32 %x %r = icmp slt i32 %abs, 0 => %r = i1 false Name: nabs_is_negative_or_0 %cmp = icmp slt i32 %x, 0 %negx = sub i32 0, %x %nabs = select i1 %cmp, i32 %x, i32 %negx %r = icmp slt i32 %nabs, 1 => %r = i1 true Name: nabs_is_not_over_0 %cmp = icmp slt i32 %x, 0 %negx = sub i32 0, %x %nabs = select i1 %cmp, i32 %x, i32 %negx %r = icmp sgt i32 %nabs, 0 => %r = i1 false Differential Revision: https://reviews.llvm.org/D53844 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@345832 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 11 months ago
2 changed file(s) with 56 addition(s) and 75 deletion(s). Raw diff Collapse all Expand all
29952995 return nullptr;
29962996 }
29972997
2998 static Value *simplifyICmpWithAbsNabs(CmpInst::Predicate Pred, Value *Op0,
2999 Value *Op1) {
3000 // We need a comparison with a constant.
3001 const APInt *C;
3002 if (!match(Op1, m_APInt(C)))
3003 return nullptr;
3004
3005 // matchSelectPattern returns the negation part of an abs pattern in SP1.
3006 // If the negate has an NSW flag, abs(INT_MIN) is undefined. Without that
3007 // constraint, we can't make a contiguous range for the result of abs.
3008 ICmpInst::Predicate AbsPred = ICmpInst::BAD_ICMP_PREDICATE;
3009 Value *SP0, *SP1;
3010 SelectPatternFlavor SPF = matchSelectPattern(Op0, SP0, SP1).Flavor;
3011 if (SPF == SelectPatternFlavor::SPF_ABS &&
3012 cast(SP1)->hasNoSignedWrap())
3013 // The result of abs(X) is >= 0 (with nsw).
3014 AbsPred = ICmpInst::ICMP_SGE;
3015 if (SPF == SelectPatternFlavor::SPF_NABS)
3016 // The result of -abs(X) is <= 0.
3017 AbsPred = ICmpInst::ICMP_SLE;
3018
3019 if (AbsPred == ICmpInst::BAD_ICMP_PREDICATE)
3020 return nullptr;
3021
3022 // If there is no intersection between abs/nabs and the range of this icmp,
3023 // the icmp must be false. If the abs/nabs range is a subset of the icmp
3024 // range, the icmp must be true.
3025 APInt Zero = APInt::getNullValue(C->getBitWidth());
3026 ConstantRange AbsRange = ConstantRange::makeExactICmpRegion(AbsPred, Zero);
3027 ConstantRange CmpRange = ConstantRange::makeExactICmpRegion(Pred, *C);
3028 if (AbsRange.intersectWith(CmpRange).isEmptySet())
3029 return getFalse(GetCompareTy(Op0));
3030 if (CmpRange.contains(AbsRange))
3031 return getTrue(GetCompareTy(Op0));
3032
3033 return nullptr;
3034 }
3035
29983036 /// Simplify integer comparisons where at least one operand of the compare
29993037 /// matches an integer min/max idiom.
30003038 static Value *simplifyICmpWithMinMax(CmpInst::Predicate Pred, Value *LHS,
34243462 return V;
34253463
34263464 if (Value *V = simplifyICmpWithMinMax(Pred, LHS, RHS, Q, MaxRecurse))
3465 return V;
3466
3467 if (Value *V = simplifyICmpWithAbsNabs(Pred, LHS, RHS))
34273468 return V;
34283469
34293470 // Simplify comparisons of related pointers using a powerful, recursive
44
55 define i1 @abs_nsw_is_positive(i32 %x) {
66 ; CHECK-LABEL: @abs_nsw_is_positive(
7 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
8 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X]]
9 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
10 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[ABS]], -1
11 ; CHECK-NEXT: ret i1 [[R]]
7 ; CHECK-NEXT: ret i1 true
128 ;
139 %cmp = icmp slt i32 %x, 0
1410 %negx = sub nsw i32 0, %x
3430
3531 define i1 @abs_nsw_is_positive_reduced_range(i32 %x) {
3632 ; CHECK-LABEL: @abs_nsw_is_positive_reduced_range(
37 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
38 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X]]
39 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
40 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[ABS]], -42
41 ; CHECK-NEXT: ret i1 [[R]]
33 ; CHECK-NEXT: ret i1 true
4234 ;
4335 %cmp = icmp slt i32 %x, 0
4436 %negx = sub nsw i32 0, %x
9890
9991 define i1 @abs_nsw_is_not_negative_sle(i32 %x) {
10092 ; CHECK-LABEL: @abs_nsw_is_not_negative_sle(
101 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
102 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X]]
103 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
104 ; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[ABS]], -1
105 ; CHECK-NEXT: ret i1 [[R]]
93 ; CHECK-NEXT: ret i1 false
10694 ;
10795 %cmp = icmp slt i32 %x, 1
10896 %negx = sub nsw i32 0, %x
115103
116104 define i1 @abs_nsw_is_not_negative_reduced_range(i32 %x) {
117105 ; CHECK-LABEL: @abs_nsw_is_not_negative_reduced_range(
118 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
119 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X]]
120 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
121 ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[ABS]], -24
122 ; CHECK-NEXT: ret i1 [[R]]
106 ; CHECK-NEXT: ret i1 false
123107 ;
124108 %cmp = icmp slt i32 %x, 0
125109 %negx = sub nsw i32 0, %x
166150
167151 define i1 @nabs_is_negative_or_0(i32 %x) {
168152 ; CHECK-LABEL: @nabs_is_negative_or_0(
169 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
170 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
171 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
172 ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[NABS]], 1
173 ; CHECK-NEXT: ret i1 [[R]]
153 ; CHECK-NEXT: ret i1 true
174154 ;
175155 %cmp = icmp slt i32 %x, 0
176156 %negx = sub i32 0, %x
183163
184164 define i1 @nabs_is_negative_or_0_sle(i32 %x) {
185165 ; CHECK-LABEL: @nabs_is_negative_or_0_sle(
186 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
187 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
188 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
189 ; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[NABS]], 0
190 ; CHECK-NEXT: ret i1 [[R]]
166 ; CHECK-NEXT: ret i1 true
191167 ;
192168 %cmp = icmp slt i32 %x, 1
193169 %negx = sub i32 0, %x
200176
201177 define i1 @nabs_is_negative_or_0_reduced_range(i32 %x) {
202178 ; CHECK-LABEL: @nabs_is_negative_or_0_reduced_range(
203 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
204 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
205 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
206 ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[NABS]], 421
207 ; CHECK-NEXT: ret i1 [[R]]
179 ; CHECK-NEXT: ret i1 true
208180 ;
209181 %cmp = icmp slt i32 %x, 1
210182 %negx = sub i32 0, %x
234206
235207 define i1 @nabs_is_not_over_0(i32 %x) {
236208 ; CHECK-LABEL: @nabs_is_not_over_0(
237 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
238 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
239 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
240 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[NABS]], 0
241 ; CHECK-NEXT: ret i1 [[R]]
209 ; CHECK-NEXT: ret i1 false
242210 ;
243211 %cmp = icmp slt i32 %x, 0
244212 %negx = sub i32 0, %x
251219
252220 define i1 @nabs_is_not_over_0_sle(i32 %x) {
253221 ; CHECK-LABEL: @nabs_is_not_over_0_sle(
254 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
255 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
256 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
257 ; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[NABS]], 1
258 ; CHECK-NEXT: ret i1 [[R]]
222 ; CHECK-NEXT: ret i1 false
259223 ;
260224 %cmp = icmp slt i32 %x, 1
261225 %negx = sub i32 0, %x
268232
269233 define i1 @nabs_is_not_over_0_reduced_range(i32 %x) {
270234 ; CHECK-LABEL: @nabs_is_not_over_0_reduced_range(
271 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
272 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X]]
273 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
274 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[NABS]], 4223
275 ; CHECK-NEXT: ret i1 [[R]]
235 ; CHECK-NEXT: ret i1 false
276236 ;
277237 %cmp = icmp slt i32 %x, 1
278238 %negx = sub i32 0, %x
317277
318278 define i1 @abs_nsw_is_positive_ult(i8 %x) {
319279 ; CHECK-LABEL: @abs_nsw_is_positive_ult(
320 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
321 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i8 0, [[X]]
322 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEGX]], i8 [[X]]
323 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[ABS]], -117
324 ; CHECK-NEXT: ret i1 [[R]]
280 ; CHECK-NEXT: ret i1 true
325281 ;
326282 %cmp = icmp slt i8 %x, 0
327283 %negx = sub nsw i8 0, %x
334290
335291 define i1 @abs_nsw_is_not_negative_ugt(i8 %x) {
336292 ; CHECK-LABEL: @abs_nsw_is_not_negative_ugt(
337 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
338 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i8 0, [[X]]
339 ; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEGX]], i8 [[X]]
340 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[ABS]], 127
341 ; CHECK-NEXT: ret i1 [[R]]
293 ; CHECK-NEXT: ret i1 false
342294 ;
343295 %cmp = icmp slt i8 %x, 0
344296 %negx = sub nsw i8 0, %x
351303
352304 define <2 x i1> @abs_nsw_is_not_negative_vec_splat(<2 x i32> %x) {
353305 ; CHECK-LABEL: @abs_nsw_is_not_negative_vec_splat(
354 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer
355 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X]]
356 ; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[NEGX]], <2 x i32> [[X]]
357 ; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i32> [[ABS]],
358 ; CHECK-NEXT: ret <2 x i1> [[R]]
306 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
359307 ;
360308 %cmp = icmp slt <2 x i32> %x, zeroinitializer
361309 %negx = sub nsw <2 x i32> zeroinitializer, %x
368316
369317 define i1 @nabs_is_negative_or_0_ne(i8 %x) {
370318 ; CHECK-LABEL: @nabs_is_negative_or_0_ne(
371 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
372 ; CHECK-NEXT: [[NEGX:%.*]] = sub i8 0, [[X]]
373 ; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEGX]]
374 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[NABS]], 12
375 ; CHECK-NEXT: ret i1 [[R]]
319 ; CHECK-NEXT: ret i1 true
376320 ;
377321 %cmp = icmp slt i8 %x, 0
378322 %negx = sub i8 0, %x
385329
386330 define <3 x i1> @nabs_is_not_over_0_sle_vec_splat(<3 x i33> %x) {
387331 ; CHECK-LABEL: @nabs_is_not_over_0_sle_vec_splat(
388 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt <3 x i33> [[X:%.*]],
389 ; CHECK-NEXT: [[NEGX:%.*]] = sub <3 x i33> zeroinitializer, [[X]]
390 ; CHECK-NEXT: [[NABS:%.*]] = select <3 x i1> [[CMP]], <3 x i33> [[X]], <3 x i33> [[NEGX]]
391 ; CHECK-NEXT: [[R:%.*]] = icmp sge <3 x i33> [[NABS]],
392 ; CHECK-NEXT: ret <3 x i1> [[R]]
332 ; CHECK-NEXT: ret <3 x i1> zeroinitializer
393333 ;
394334 %cmp = icmp slt <3 x i33> %x,
395335 %negx = sub <3 x i33> zeroinitializer, %x