Skip to content

Commit 48585ca

Browse files
authored
InstCombine: Avoid counting uses of constants (#136566)
Logically it does not matter; getFreelyInvertedImpl doesn't depend on the value for the m_ImmConstant case. This use count logic should probably sink into getFreelyInvertedImpl, every use of this appears to just be a hasOneUse or hasNUse count, so this could change to just be a use count threshold.
1 parent 4a58071 commit 48585ca

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5034,8 +5034,8 @@ static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
50345034

50355035
if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) {
50365036
// icmp (X | Y) eq/ne Y --> (X & ~Y) eq/ne 0 if Y is freely invertible
5037-
if (Value *NotOp1 =
5038-
IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder))
5037+
if (Value *NotOp1 = IC.getFreelyInverted(
5038+
Op1, !isa<Constant>(Op1) && !Op1->hasNUsesOrMore(3), &IC.Builder))
50395039
return new ICmpInst(Pred, IC.Builder.CreateAnd(A, NotOp1),
50405040
Constant::getNullValue(Op1->getType()));
50415041
// icmp (X | Y) eq/ne Y --> (~X | Y) eq/ne -1 if X is freely invertible.

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2954,6 +2954,99 @@ define i1 @or1_eq1(i32 %x) {
29542954
ret i1 %t1
29552955
}
29562956

2957+
define <2 x i1> @or1_eq1_vec(<2 x i32> %x) {
2958+
; CHECK-LABEL: @or1_eq1_vec(
2959+
; CHECK-NEXT: [[T1:%.*]] = icmp ult <2 x i32> [[X:%.*]], splat (i32 2)
2960+
; CHECK-NEXT: ret <2 x i1> [[T1]]
2961+
;
2962+
%t0 = or <2 x i32> %x, splat (i32 1)
2963+
%t1 = icmp eq <2 x i32> %t0, splat (i32 1)
2964+
ret <2 x i1> %t1
2965+
}
2966+
2967+
define <2 x i1> @or_eq_vec_nonsplat(<2 x i32> %x) {
2968+
; CHECK-LABEL: @or_eq_vec_nonsplat(
2969+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -3>
2970+
; CHECK-NEXT: [[T1:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
2971+
; CHECK-NEXT: ret <2 x i1> [[T1]]
2972+
;
2973+
%t0 = or <2 x i32> %x, <i32 1, i32 2>
2974+
%t1 = icmp eq <2 x i32> %t0, <i32 1, i32 2>
2975+
ret <2 x i1> %t1
2976+
}
2977+
2978+
define void @or_eq_vec_multiple_nonsplat(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z, ptr %ptr0, ptr %ptr1, ptr %ptr2) {
2979+
; CHECK-LABEL: @or_eq_vec_multiple_nonsplat(
2980+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -3>
2981+
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
2982+
; CHECK-NEXT: store <2 x i1> [[CMP0]], ptr [[PTR0:%.*]], align 1
2983+
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -2, i32 -3>
2984+
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer
2985+
; CHECK-NEXT: store <2 x i1> [[CMP1]], ptr [[PTR1:%.*]], align 1
2986+
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[Z:%.*]], <i32 -2, i32 -3>
2987+
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq <2 x i32> [[TMP3]], zeroinitializer
2988+
; CHECK-NEXT: store <2 x i1> [[CMP2]], ptr [[PTR2:%.*]], align 1
2989+
; CHECK-NEXT: ret void
2990+
;
2991+
%t0 = or <2 x i32> %x, <i32 1, i32 2>
2992+
%cmp0 = icmp eq <2 x i32> %t0, <i32 1, i32 2>
2993+
store <2 x i1> %cmp0, ptr %ptr0
2994+
2995+
%t1 = or <2 x i32> %y, <i32 1, i32 2>
2996+
%cmp1 = icmp eq <2 x i32> %t1, <i32 1, i32 2>
2997+
store <2 x i1> %cmp1, ptr %ptr1
2998+
2999+
%t2 = or <2 x i32> %z, <i32 1, i32 2>
3000+
%cmp2 = icmp eq <2 x i32> %t2, <i32 1, i32 2>
3001+
store <2 x i1> %cmp2, ptr %ptr2
3002+
ret void
3003+
}
3004+
3005+
; Make sure use count of 1 doesn't matter
3006+
define i1 @or1_eq1_multiple(i32 %x, i32 %y, i32 %z, ptr %ptr0, ptr %ptr1) {
3007+
; CHECK-LABEL: @or1_eq1_multiple(
3008+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 2
3009+
; CHECK-NEXT: store i1 [[CMP1]], ptr [[PTR:%.*]], align 1
3010+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 2
3011+
; CHECK-NEXT: store i1 [[CMP2]], ptr [[PTR1:%.*]], align 1
3012+
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[Z:%.*]], 2
3013+
; CHECK-NEXT: ret i1 [[CMP3]]
3014+
;
3015+
%t0 = or i32 %x, 1
3016+
%cmp0 = icmp eq i32 %t0, 1
3017+
store i1 %cmp0, ptr %ptr0
3018+
3019+
%t1 = or i32 %y, 1
3020+
%cmp1 = icmp eq i32 %t1, 1
3021+
store i1 %cmp1, ptr %ptr1
3022+
3023+
%t2 = or i32 %z, 1
3024+
%cmp2 = icmp eq i32 %t2, 1
3025+
ret i1 %cmp2
3026+
}
3027+
3028+
define <2 x i1> @or1_eq1_multiple_vec(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z, ptr %ptr0, ptr %ptr1) {
3029+
; CHECK-LABEL: @or1_eq1_multiple_vec(
3030+
; CHECK-NEXT: [[CMP0:%.*]] = icmp ult <2 x i32> [[X:%.*]], splat (i32 2)
3031+
; CHECK-NEXT: store <2 x i1> [[CMP0]], ptr [[PTR0:%.*]], align 1
3032+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> [[Y:%.*]], splat (i32 2)
3033+
; CHECK-NEXT: store <2 x i1> [[CMP1]], ptr [[PTR1:%.*]], align 1
3034+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i32> [[Z:%.*]], splat (i32 2)
3035+
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
3036+
;
3037+
%t0 = or <2 x i32> %x, splat (i32 1)
3038+
%cmp0 = icmp eq <2 x i32> %t0, splat (i32 1)
3039+
store <2 x i1> %cmp0, ptr %ptr0
3040+
3041+
%t1 = or <2 x i32> %y, splat (i32 1)
3042+
%cmp1 = icmp eq <2 x i32> %t1, splat (i32 1)
3043+
store <2 x i1> %cmp1, ptr %ptr1
3044+
3045+
%t2 = or <2 x i32> %z, splat (i32 1)
3046+
%cmp2 = icmp eq <2 x i32> %t2, splat (i32 1)
3047+
ret <2 x i1> %cmp2
3048+
}
3049+
29573050
; X | C == C --> X <=u C (when C+1 is PowerOf2).
29583051

29593052
define <2 x i1> @or3_eq3_vec(<2 x i8> %x) {

0 commit comments

Comments
 (0)