Skip to content

Commit 9423f78

Browse files
committed
[InstCombine] Fold multiuse shr eq zero
The single-use case is handled implicity by converting the icmp into a mask check first. When comparing with zero in particular, we don't need the one-use restriction, as we only produce a single icmp. https://alive2.llvm.org/ce/z/MSixcm https://alive2.llvm.org/ce/z/GwpG0M
1 parent 3d385cc commit 9423f78

File tree

4 files changed

+18
-9
lines changed

4 files changed

+18
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,16 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
22742274
if (Shr->isExact())
22752275
return new ICmpInst(Pred, X, ConstantInt::get(ShrTy, C << ShAmtVal));
22762276

2277+
if (C.isNullValue()) {
2278+
// == 0 is u< 1.
2279+
if (Pred == CmpInst::ICMP_EQ)
2280+
return new ICmpInst(CmpInst::ICMP_ULT, X,
2281+
ConstantInt::get(ShrTy, (C + 1).shl(ShAmtVal)));
2282+
else
2283+
return new ICmpInst(CmpInst::ICMP_UGT, X,
2284+
ConstantInt::get(ShrTy, (C + 1).shl(ShAmtVal) - 1));
2285+
}
2286+
22772287
if (Shr->hasOneUse()) {
22782288
// Canonicalize the shift into an 'and':
22792289
// icmp eq/ne (shr X, ShAmt), C --> icmp eq/ne (and X, HiMask), (C << ShAmt)

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ define i1 @lshr_eq_0_multiuse(i8 %x) {
875875
; CHECK-LABEL: @lshr_eq_0_multiuse(
876876
; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 2
877877
; CHECK-NEXT: call void @use(i8 [[S]])
878-
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[S]], 0
878+
; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X]], 4
879879
; CHECK-NEXT: ret i1 [[C]]
880880
;
881881
%s = lshr i8 %x, 2
@@ -888,7 +888,7 @@ define i1 @lshr_ne_0_multiuse(i8 %x) {
888888
; CHECK-LABEL: @lshr_ne_0_multiuse(
889889
; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 2
890890
; CHECK-NEXT: call void @use(i8 [[S]])
891-
; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[S]], 0
891+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X]], 3
892892
; CHECK-NEXT: ret i1 [[C]]
893893
;
894894
%s = lshr i8 %x, 2
@@ -901,7 +901,7 @@ define i1 @ashr_eq_0_multiuse(i8 %x) {
901901
; CHECK-LABEL: @ashr_eq_0_multiuse(
902902
; CHECK-NEXT: [[S:%.*]] = ashr i8 [[X:%.*]], 2
903903
; CHECK-NEXT: call void @use(i8 [[S]])
904-
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[S]], 0
904+
; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X]], 4
905905
; CHECK-NEXT: ret i1 [[C]]
906906
;
907907
%s = ashr i8 %x, 2
@@ -914,7 +914,7 @@ define i1 @ashr_ne_0_multiuse(i8 %x) {
914914
; CHECK-LABEL: @ashr_ne_0_multiuse(
915915
; CHECK-NEXT: [[S:%.*]] = ashr i8 [[X:%.*]], 2
916916
; CHECK-NEXT: call void @use(i8 [[S]])
917-
; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[S]], 0
917+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X]], 3
918918
; CHECK-NEXT: ret i1 [[C]]
919919
;
920920
%s = ashr i8 %x, 2

llvm/test/Transforms/InstCombine/icmp_sdiv_with_and_without_range.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; RUN: opt -instcombine -S < %s | FileCheck %s
33

44
; Test that presence of range does not cause unprofitable transforms with bit
5-
; arithmetics, and instcombine behaves exactly the same as without the range.
5+
; arithmetics.
66

77
define i1 @without_range(i32* %A) {
88
; CHECK-LABEL: @without_range(
@@ -18,9 +18,8 @@ define i1 @without_range(i32* %A) {
1818

1919
define i1 @with_range(i32* %A) {
2020
; CHECK-LABEL: @with_range(
21-
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, i32* [[A:%.*]], align 8, !range !0
22-
; CHECK-NEXT: [[B_MASK:%.*]] = and i32 [[A_VAL]], 2147483646
23-
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B_MASK]], 0
21+
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, i32* [[A:%.*]], align 8, !range [[RNG0:![0-9]+]]
22+
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A_VAL]], 2
2423
; CHECK-NEXT: ret i1 [[C]]
2524
;
2625
%A.val = load i32, i32* %A, align 8, !range !0

llvm/test/Transforms/PhaseOrdering/X86/ctlz-loop.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ define i32 @ctlz_loop_with_abs(i32 %n) {
3232
; CHECK-NEXT: [[I_02:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
3333
; CHECK-NEXT: [[TMP1]] = lshr i32 [[N_ADDR_03]], 1
3434
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_02]], 1
35-
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP1]], 0
35+
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp ult i32 [[N_ADDR_03]], 2
3636
; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[WHILE_END]], label [[WHILE_BODY]]
3737
; CHECK: while.end:
3838
; CHECK-NEXT: [[I_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC]], [[WHILE_BODY]] ]

0 commit comments

Comments
 (0)