Skip to content

Commit 8320b97

Browse files
authored
[InstCombine] Fold an unsigned comparison of add nsw X, C with a constant into a signed comparison (llvm#103480)
Given an unsigned integer comparison of `add nsw X, C1` with some constant `C2` we can fold it into a signed comparison of `X` and `C2 - C1` under the following conditions: * There's a `nsw` flag on the addition * `C2` is non-negative * `X + C1` is non-negative * `C2 - C1` is non-negative
1 parent 5e990b0 commit 8320b97

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,6 +3077,12 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
30773077
return new ICmpInst(Pred, X, ConstantInt::get(Ty, NewC));
30783078
}
30793079

3080+
if (ICmpInst::isUnsigned(Pred) && Add->hasNoSignedWrap() &&
3081+
C.isNonNegative() && (C - *C2).isNonNegative() &&
3082+
computeConstantRange(X, /*ForSigned=*/true).add(*C2).isAllNonNegative())
3083+
return new ICmpInst(ICmpInst::getSignedPredicate(Pred), X,
3084+
ConstantInt::get(Ty, C - *C2));
3085+
30803086
auto CR = ConstantRange::makeExactICmpRegion(Pred, C).subtract(*C2);
30813087
const APInt &Upper = CR.getUpper();
30823088
const APInt &Lower = CR.getLower();

llvm/test/Transforms/InstCombine/icmp-add.ll

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3102,3 +3102,84 @@ define i1 @uge_add_C2_pow2_C_neg(i8 %x) {
31023102
}
31033103

31043104
declare void @llvm.assume(i1)
3105+
3106+
; Change an unsigned predicate to signed in icmp (add x, C1), C2
3107+
define i1 @icmp_add_constant_with_constant_ult_to_slt(i32 range(i32 -4, 10) %x) {
3108+
; CHECK-LABEL: @icmp_add_constant_with_constant_ult_to_slt(
3109+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 8
3110+
; CHECK-NEXT: ret i1 [[CMP]]
3111+
;
3112+
%add = add nsw i32 %x, 5
3113+
%cmp = icmp ult i32 %add, 13
3114+
ret i1 %cmp
3115+
}
3116+
3117+
define i1 @icmp_add_constant_with_constant_ugt_to_sgt(i32 range(i32 -4, 10) %x) {
3118+
; CHECK-LABEL: @icmp_add_constant_with_constant_ugt_to_sgt(
3119+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 2
3120+
; CHECK-NEXT: ret i1 [[CMP]]
3121+
;
3122+
%add = add nsw i32 %x, 10
3123+
%cmp = icmp ugt i32 %add, 12
3124+
ret i1 %cmp
3125+
}
3126+
3127+
; Negative test: x + C1 may be negative
3128+
define i1 @icmp_add_constant_with_constant_ult_to_slt_neg1(i32 range(i32 -5, 10) %x) {
3129+
; CHECK-LABEL: @icmp_add_constant_with_constant_ult_to_slt_neg1(
3130+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 4
3131+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 20
3132+
; CHECK-NEXT: ret i1 [[CMP]]
3133+
;
3134+
%add = add nsw i32 %x, 4
3135+
%cmp = icmp ult i32 %add, 20
3136+
ret i1 %cmp
3137+
}
3138+
3139+
; Negative test: missing nsw flag
3140+
define i1 @icmp_add_constant_with_constant_ult_to_slt_neg2(i8 range(i8 -4, 120) %x) {
3141+
; CHECK-LABEL: @icmp_add_constant_with_constant_ult_to_slt_neg2(
3142+
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 15
3143+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], 20
3144+
; CHECK-NEXT: ret i1 [[CMP]]
3145+
;
3146+
%add = add i8 %x, 15
3147+
%cmp = icmp ult i8 %add, 20
3148+
ret i1 %cmp
3149+
}
3150+
3151+
; Negative test: C2 is negative
3152+
define i1 @icmp_add_constant_with_constant_ult_to_slt_neg3(i32 range(i32 -4, 10) %x) {
3153+
; CHECK-LABEL: @icmp_add_constant_with_constant_ult_to_slt_neg3(
3154+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 4
3155+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -6
3156+
; CHECK-NEXT: ret i1 [[CMP]]
3157+
;
3158+
%add = add nsw i32 %x, 4
3159+
%cmp = icmp ult i32 %add, -6
3160+
ret i1 %cmp
3161+
}
3162+
3163+
; Negative test: C2 - C1 is negative
3164+
define i1 @icmp_add_constant_with_constant_ult_to_slt_neg4(i32 range(i32 -4, 10) %x) {
3165+
; CHECK-LABEL: @icmp_add_constant_with_constant_ult_to_slt_neg4(
3166+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], 5
3167+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 2
3168+
; CHECK-NEXT: ret i1 [[CMP]]
3169+
;
3170+
%add = add nsw i32 %x, 5
3171+
%cmp = icmp ult i32 %add, 2
3172+
ret i1 %cmp
3173+
}
3174+
3175+
; Same as before, but infer the range of ucmp
3176+
define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) {
3177+
; CHECK-LABEL: @icmp_of_ucmp_plus_const_with_const(
3178+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
3179+
; CHECK-NEXT: ret i1 [[CMP2]]
3180+
;
3181+
%cmp1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
3182+
%add = add i8 %cmp1, 1
3183+
%cmp2 = icmp ult i8 %add, 2
3184+
ret i1 %cmp2
3185+
}

llvm/test/Transforms/LoopVectorize/interleaved-accesses.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,7 @@ define void @PR27626_5(ptr %a, i32 %x, i32 %y, i32 %z, i64 %n) {
13591359
; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -4
13601360
; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 1
13611361
; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
1362-
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 6
1362+
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp slt i64 [[N]], 10
13631363
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
13641364
; CHECK: vector.ph:
13651365
; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 9223372036854775804

0 commit comments

Comments
 (0)