Skip to content

Commit cb02213

Browse files
[InstCombine] Optimize icmp with shl and add by folding (X << Log2) == ((Y << Log2) + K) into X == (Y + 1)
1 parent 3eacc36 commit cb02213

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6001,6 +6001,26 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
60016001

60026002
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
60036003
const CmpInst::Predicate Pred = I.getPredicate();
6004+
6005+
//icmp (shl nsw X, Log2), (add nsw (shl nsw Y, Log2), K) -> icmp X, (add nsw Y, 1)
6006+
Value *X, *Y;
6007+
ConstantInt *CLog2M0, *CLog2M1, *CVal;
6008+
auto M0 = m_NSWShl(m_Value(X), m_ConstantInt(CLog2M0));
6009+
auto M1 = m_NSWAdd(m_NSWShl (m_Value(Y), m_ConstantInt(CLog2M1)),
6010+
m_ConstantInt(CVal));
6011+
6012+
if (match(&I, m_c_ICmp(M0, M1)) && CLog2M0->getValue() == CLog2M1->getValue()) {
6013+
unsigned BitWidth = CLog2M0->getBitWidth();
6014+
unsigned ShAmt = (unsigned)CLog2M0->getLimitedValue(BitWidth);
6015+
APInt ExpectedK = APInt::getOneBitSet(BitWidth, ShAmt);
6016+
if (CVal->getValue() == ExpectedK) {
6017+
Value *NewRHS = Builder.CreateAdd(
6018+
Y, ConstantInt::get(Y->getType(), 1),
6019+
"", /*HasNUW=*/false, /*HasNSW=*/true);
6020+
return new ICmpInst(Pred, X, NewRHS);
6021+
}
6022+
}
6023+
60046024
Value *A, *B, *C, *D;
60056025
if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
60066026
if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0

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

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66

77
define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) {
88
; CHECK-LABEL: @shl_add_const_eq_base(
9-
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5
10-
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5
11-
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32
12-
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
9+
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
10+
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1:%.*]], [[V5]]
1311
; CHECK-NEXT: ret i1 [[V6]]
1412
;
1513
%v1 = shl nsw i64 %v0, 5
@@ -22,10 +20,8 @@ define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) {
2220
; Test: icmp ne
2321
define i1 @shl_add_const_ne(i64 %v0, i64 %v3) {
2422
; CHECK-LABEL: @shl_add_const_ne(
25-
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5
26-
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5
27-
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32
28-
; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1]], [[V5]]
23+
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1
24+
; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1:%.*]], [[V5]]
2925
; CHECK-NEXT: ret i1 [[V6]]
3026
;
3127
%v1 = shl nsw i64 %v0, 5
@@ -38,8 +34,8 @@ define i1 @shl_add_const_ne(i64 %v0, i64 %v3) {
3834
; Test: shl amounts do not match (5 vs 4).
3935
define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) {
4036
; CHECK-LABEL: @shl_add_const_eq_mismatch_shl_amt(
41-
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5
42-
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 4
37+
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5
38+
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 4
4339
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 16
4440
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
4541
; CHECK-NEXT: ret i1 [[V6]]
@@ -54,8 +50,8 @@ define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) {
5450
; Test: Constant is wrong (32 vs 64).
5551
define i1 @shl_add_const_eq_wrong_constant(i64 %v0, i64 %v3) {
5652
; CHECK-LABEL: @shl_add_const_eq_wrong_constant(
57-
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5
58-
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5
53+
; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5
54+
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5
5955
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 64
6056
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
6157
; CHECK-NEXT: ret i1 [[V6]]
@@ -70,8 +66,8 @@ define i1 @shl_add_const_eq_wrong_constant(i64 %v0, i64 %v3) {
7066
; Test: Missing NSW flag on one of the shl instructions.
7167
define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) {
7268
; CHECK-LABEL: @shl_add_const_eq_no_nsw_on_v1(
73-
; CHECK-NEXT: [[V1:%.*]] = shl i64 %v0, 5
74-
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5
69+
; CHECK-NEXT: [[V1:%.*]] = shl i64 [[V0:%.*]], 5
70+
; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5
7571
; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32
7672
; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]]
7773
; CHECK-NEXT: ret i1 [[V6]]
@@ -86,8 +82,8 @@ define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) {
8682
; Test: Lower bit width (i8) and different shift amount (3). Constant is 8.
8783
define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) {
8884
; CHECK-LABEL: @shl_add_const_eq_i8(
89-
; CHECK-NEXT: [[V7:%.*]] = add nsw i8 %v3, 1
90-
; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 %v0, [[V7]]
85+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[V3:%.*]], 1
86+
; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 [[V0:%.*]], [[TMP1]]
9187
; CHECK-NEXT: ret i1 [[V6]]
9288
;
9389
%v1 = shl nsw i8 %v0, 3
@@ -100,8 +96,8 @@ define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) {
10096
; Test: i32 bit width and larger shift amount (10). Constant is 1024.
10197
define i1 @shl_add_const_eq_i32(i32 %v0, i32 %v3) {
10298
; CHECK-LABEL: @shl_add_const_eq_i32(
103-
; CHECK-NEXT: [[V7:%.*]] = add nsw i32 %v3, 1
104-
; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 %v0, [[V7]]
99+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[V3:%.*]], 1
100+
; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 [[V0:%.*]], [[TMP1]]
105101
; CHECK-NEXT: ret i1 [[V6]]
106102
;
107103
%v1 = shl nsw i32 %v0, 10

0 commit comments

Comments
 (0)