Skip to content

Commit 0c03b4c

Browse files
authored
[InstCombine] Infer sub nuw from dominating conditions (#100164)
Alive2: https://alive2.llvm.org/ce/z/g3xxnM
1 parent 4e28d30 commit 0c03b4c

File tree

3 files changed

+144
-11
lines changed

3 files changed

+144
-11
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7110,16 +7110,13 @@ OverflowResult llvm::computeOverflowForUnsignedSub(const Value *LHS,
71107110
if (isGuaranteedNotToBeUndef(LHS, SQ.AC, SQ.CxtI, SQ.DT))
71117111
return OverflowResult::NeverOverflows;
71127112

7113-
// Checking for conditions implied by dominating conditions may be expensive.
7114-
// Limit it to usub_with_overflow calls for now.
7115-
if (match(SQ.CxtI,
7116-
m_Intrinsic<Intrinsic::usub_with_overflow>(m_Value(), m_Value())))
7117-
if (auto C = isImpliedByDomCondition(CmpInst::ICMP_UGE, LHS, RHS, SQ.CxtI,
7118-
SQ.DL)) {
7119-
if (*C)
7120-
return OverflowResult::NeverOverflows;
7121-
return OverflowResult::AlwaysOverflowsLow;
7122-
}
7113+
if (auto C = isImpliedByDomCondition(CmpInst::ICMP_UGE, LHS, RHS, SQ.CxtI,
7114+
SQ.DL)) {
7115+
if (*C)
7116+
return OverflowResult::NeverOverflows;
7117+
return OverflowResult::AlwaysOverflowsLow;
7118+
}
7119+
71237120
ConstantRange LHSRange =
71247121
computeConstantRangeIncludingKnownBits(LHS, /*ForSigned=*/false, SQ);
71257122
ConstantRange RHSRange =

llvm/test/Transforms/InstCombine/abs-intrinsic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ define i32 @sub_abs_wrong_pred(i32 %x, i32 %y) {
800800
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
801801
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
802802
; CHECK: cond.true:
803-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]]
803+
; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[X]], [[Y]]
804804
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 true)
805805
; CHECK-NEXT: br label [[COND_END]]
806806
; CHECK: cond.end:

llvm/test/Transforms/InstCombine/sub.ll

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,3 +2661,139 @@ define i8 @sub_of_adds_2xc(i8 %x, i8 %y) {
26612661
%r = sub i8 %xc, %yc
26622662
ret i8 %r
26632663
}
2664+
2665+
define i32 @sub_infer_nuw_from_domcond(i32 %x, i32 %y) {
2666+
; CHECK-LABEL: @sub_infer_nuw_from_domcond(
2667+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
2668+
; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
2669+
; CHECK: if.then:
2670+
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[X]], [[Y]]
2671+
; CHECK-NEXT: ret i32 [[SUB]]
2672+
; CHECK: if.else:
2673+
; CHECK-NEXT: ret i32 0
2674+
;
2675+
%cond = icmp uge i32 %x, %y
2676+
br i1 %cond, label %if.then, label %if.else
2677+
2678+
if.then:
2679+
%sub = sub i32 %x, %y
2680+
ret i32 %sub
2681+
2682+
if.else:
2683+
ret i32 0
2684+
}
2685+
2686+
define i1 @sub_infer_nuw_from_domcond_fold1(i32 %x, i32 %y) {
2687+
; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold1(
2688+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
2689+
; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
2690+
; CHECK: if.then:
2691+
; CHECK-NEXT: ret i1 false
2692+
; CHECK: if.else:
2693+
; CHECK-NEXT: ret i1 false
2694+
;
2695+
%cond = icmp uge i32 %x, %y
2696+
br i1 %cond, label %if.then, label %if.else
2697+
2698+
if.then:
2699+
%ext0 = zext i32 %y to i64
2700+
%ext1 = zext i32 %x to i64
2701+
%sub = sub i32 %x, %y
2702+
%ext2 = zext i32 %sub to i64
2703+
%add = add nuw nsw i64 %ext2, %ext0
2704+
%cmp = icmp ugt i64 %add, %ext1
2705+
ret i1 %cmp
2706+
2707+
if.else:
2708+
ret i1 false
2709+
}
2710+
2711+
define i64 @sub_infer_nuw_from_domcond_fold2(i32 range(i32 0, 2147483648) %x, i32 range(i32 0, 2147483648) %y) {
2712+
; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold2(
2713+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
2714+
; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
2715+
; CHECK: if.then:
2716+
; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[X]], [[Y]]
2717+
; CHECK-NEXT: [[EXT:%.*]] = zext nneg i32 [[SUB]] to i64
2718+
; CHECK-NEXT: ret i64 [[EXT]]
2719+
; CHECK: if.else:
2720+
; CHECK-NEXT: ret i64 0
2721+
;
2722+
%cond = icmp uge i32 %x, %y
2723+
br i1 %cond, label %if.then, label %if.else
2724+
2725+
if.then:
2726+
%sub = sub i32 %x, %y
2727+
%ext = zext i32 %sub to i64
2728+
ret i64 %ext
2729+
2730+
if.else:
2731+
ret i64 0
2732+
}
2733+
2734+
define i1 @sub_infer_nuw_from_domcond_fold3(i16 %xx, i32 range(i32 0, 12) %y) {
2735+
; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold3(
2736+
; CHECK-NEXT: [[X:%.*]] = zext i16 [[XX:%.*]] to i32
2737+
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], [[Y:%.*]]
2738+
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
2739+
; CHECK: if.then:
2740+
; CHECK-NEXT: ret i1 false
2741+
; CHECK: if.else:
2742+
; CHECK-NEXT: ret i1 false
2743+
;
2744+
%x = zext i16 %xx to i32
2745+
%cond = icmp ult i32 %x, %y
2746+
br i1 %cond, label %if.then, label %if.else
2747+
2748+
if.then:
2749+
%sub = sub nsw i32 %y, %x
2750+
%cmp = icmp eq i32 %sub, -1
2751+
ret i1 %cmp
2752+
2753+
if.else:
2754+
ret i1 false
2755+
}
2756+
2757+
; negative tests
2758+
2759+
define i32 @sub_infer_nuw_from_domcond_wrong_pred(i32 %x, i32 %y) {
2760+
; CHECK-LABEL: @sub_infer_nuw_from_domcond_wrong_pred(
2761+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
2762+
; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
2763+
; CHECK: if.then:
2764+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
2765+
; CHECK-NEXT: ret i32 [[SUB]]
2766+
; CHECK: if.else:
2767+
; CHECK-NEXT: ret i32 0
2768+
;
2769+
%cond = icmp sge i32 %x, %y
2770+
br i1 %cond, label %if.then, label %if.else
2771+
2772+
if.then:
2773+
%sub = sub i32 %x, %y
2774+
ret i32 %sub
2775+
2776+
if.else:
2777+
ret i32 0
2778+
}
2779+
2780+
define i32 @sub_infer_nuw_from_domcond_lhs_is_false(i32 %x, i32 %y) {
2781+
; CHECK-LABEL: @sub_infer_nuw_from_domcond_lhs_is_false(
2782+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
2783+
; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
2784+
; CHECK: if.then:
2785+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]
2786+
; CHECK-NEXT: ret i32 [[SUB]]
2787+
; CHECK: if.else:
2788+
; CHECK-NEXT: ret i32 0
2789+
;
2790+
%cond = icmp uge i32 %x, %y
2791+
br i1 %cond, label %if.else, label %if.then
2792+
2793+
if.then:
2794+
%sub = sub i32 %x, %y
2795+
ret i32 %sub
2796+
2797+
if.else:
2798+
ret i32 0
2799+
}

0 commit comments

Comments
 (0)