From 3eacc3647f45513cfb34932fe943c91dce42f5c8 Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <2802328816@qq.com> Date: Sat, 1 Nov 2025 14:58:47 +0800 Subject: [PATCH 1/4] [InstCombine] Add test case for fold (X << 5) == ((Y << 5) + 32) --- .../InstCombine/icmp-shl-add-to-add.ll | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll diff --git a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll new file mode 100644 index 0000000000000..95dda32394c58 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +; Test case: Fold (X << 5) == ((Y << 5) + 32) into X == (Y + 1). +; This corresponds to the provided alive2 proof. + +define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_eq_base( +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i64 %v0, 5 + %v4 = shl nsw i64 %v3, 5 + %v5 = add nsw i64 %v4, 32 + %v6 = icmp eq i64 %v1, %v5 + ret i1 %v6 +} + +; Test: icmp ne +define i1 @shl_add_const_ne(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_ne( +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 +; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i64 %v0, 5 + %v4 = shl nsw i64 %v3, 5 + %v5 = add nsw i64 %v4, 32 + %v6 = icmp ne i64 %v1, %v5 ; Note: icmp ne + ret i1 %v6 +} + +; Test: shl amounts do not match (5 vs 4). +define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_eq_mismatch_shl_amt( +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 4 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 16 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i64 %v0, 5 + %v4 = shl nsw i64 %v3, 4 ; Shift amount mismatch + %v5 = add nsw i64 %v4, 16 + %v6 = icmp eq i64 %v1, %v5 + ret i1 %v6 +} + +; Test: Constant is wrong (32 vs 64). +define i1 @shl_add_const_eq_wrong_constant(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_eq_wrong_constant( +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 64 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i64 %v0, 5 + %v4 = shl nsw i64 %v3, 5 + %v5 = add nsw i64 %v4, 64 ; Constant mismatch + %v6 = icmp eq i64 %v1, %v5 + ret i1 %v6 +} + +; Test: Missing NSW flag on one of the shl instructions. +define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_eq_no_nsw_on_v1( +; CHECK-NEXT: [[V1:%.*]] = shl i64 %v0, 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl i64 %v0, 5 ; Missing nsw + %v4 = shl nsw i64 %v3, 5 + %v5 = add nsw i64 %v4, 32 + %v6 = icmp eq i64 %v1, %v5 + ret i1 %v6 +} + +; Test: Lower bit width (i8) and different shift amount (3). Constant is 8. +define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) { +; CHECK-LABEL: @shl_add_const_eq_i8( +; CHECK-NEXT: [[V7:%.*]] = add nsw i8 %v3, 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 %v0, [[V7]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i8 %v0, 3 + %v4 = shl nsw i8 %v3, 3 + %v5 = add nsw i8 %v4, 8 ; 2^3 = 8 + %v6 = icmp eq i8 %v1, %v5 + ret i1 %v6 +} + +; Test: i32 bit width and larger shift amount (10). Constant is 1024. +define i1 @shl_add_const_eq_i32(i32 %v0, i32 %v3) { +; CHECK-LABEL: @shl_add_const_eq_i32( +; CHECK-NEXT: [[V7:%.*]] = add nsw i32 %v3, 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 %v0, [[V7]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i32 %v0, 10 + %v4 = shl nsw i32 %v3, 10 + %v5 = add nsw i32 %v4, 1024 ; 2^10 = 1024 + %v6 = icmp eq i32 %v1, %v5 + ret i1 %v6 +} From cb022137e9459586a606b22d1f3d7d2bf8ac81f8 Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <2802328816@qq.com> Date: Sat, 1 Nov 2025 15:19:28 +0800 Subject: [PATCH 2/4] [InstCombine] Optimize icmp with shl and add by folding (X << Log2) == ((Y << Log2) + K) into X == (Y + 1) --- .../InstCombine/InstCombineCompares.cpp | 20 ++++++++++++ .../InstCombine/icmp-shl-add-to-add.ll | 32 ++++++++----------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fba1ccf2c8c9b..28d3c772acdcc 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6001,6 +6001,26 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); const CmpInst::Predicate Pred = I.getPredicate(); + + //icmp (shl nsw X, Log2), (add nsw (shl nsw Y, Log2), K) -> icmp X, (add nsw Y, 1) + Value *X, *Y; + ConstantInt *CLog2M0, *CLog2M1, *CVal; + auto M0 = m_NSWShl(m_Value(X), m_ConstantInt(CLog2M0)); + auto M1 = m_NSWAdd(m_NSWShl (m_Value(Y), m_ConstantInt(CLog2M1)), + m_ConstantInt(CVal)); + + if (match(&I, m_c_ICmp(M0, M1)) && CLog2M0->getValue() == CLog2M1->getValue()) { + unsigned BitWidth = CLog2M0->getBitWidth(); + unsigned ShAmt = (unsigned)CLog2M0->getLimitedValue(BitWidth); + APInt ExpectedK = APInt::getOneBitSet(BitWidth, ShAmt); + if (CVal->getValue() == ExpectedK) { + Value *NewRHS = Builder.CreateAdd( + Y, ConstantInt::get(Y->getType(), 1), + "", /*HasNUW=*/false, /*HasNSW=*/true); + return new ICmpInst(Pred, X, NewRHS); + } + } + Value *A, *B, *C, *D; if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) { if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0 diff --git a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll index 95dda32394c58..0f375a05528a2 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll @@ -6,10 +6,8 @@ define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_base( -; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 -; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 -; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1:%.*]], [[V5]] ; CHECK-NEXT: ret i1 [[V6]] ; %v1 = shl nsw i64 %v0, 5 @@ -22,10 +20,8 @@ define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) { ; Test: icmp ne define i1 @shl_add_const_ne(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_ne( -; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 -; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 -; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1]], [[V5]] +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1 +; CHECK-NEXT: [[V6:%.*]] = icmp ne i64 [[V1:%.*]], [[V5]] ; CHECK-NEXT: ret i1 [[V6]] ; %v1 = shl nsw i64 %v0, 5 @@ -38,8 +34,8 @@ define i1 @shl_add_const_ne(i64 %v0, i64 %v3) { ; Test: shl amounts do not match (5 vs 4). define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_mismatch_shl_amt( -; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 4 +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 4 ; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 16 ; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] ; CHECK-NEXT: ret i1 [[V6]] @@ -54,8 +50,8 @@ define i1 @shl_add_const_eq_mismatch_shl_amt(i64 %v0, i64 %v3) { ; Test: Constant is wrong (32 vs 64). define i1 @shl_add_const_eq_wrong_constant(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_wrong_constant( -; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 %v0, 5 -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 ; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 64 ; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] ; CHECK-NEXT: ret i1 [[V6]] @@ -70,8 +66,8 @@ define i1 @shl_add_const_eq_wrong_constant(i64 %v0, i64 %v3) { ; Test: Missing NSW flag on one of the shl instructions. define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_no_nsw_on_v1( -; CHECK-NEXT: [[V1:%.*]] = shl i64 %v0, 5 -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 %v3, 5 +; CHECK-NEXT: [[V1:%.*]] = shl i64 [[V0:%.*]], 5 +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 ; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 ; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] ; CHECK-NEXT: ret i1 [[V6]] @@ -86,8 +82,8 @@ define i1 @shl_add_const_eq_no_nsw_on_v1(i64 %v0, i64 %v3) { ; Test: Lower bit width (i8) and different shift amount (3). Constant is 8. define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) { ; CHECK-LABEL: @shl_add_const_eq_i8( -; CHECK-NEXT: [[V7:%.*]] = add nsw i8 %v3, 1 -; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 %v0, [[V7]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[V3:%.*]], 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i8 [[V0:%.*]], [[TMP1]] ; CHECK-NEXT: ret i1 [[V6]] ; %v1 = shl nsw i8 %v0, 3 @@ -100,8 +96,8 @@ define i1 @shl_add_const_eq_i8(i8 %v0, i8 %v3) { ; Test: i32 bit width and larger shift amount (10). Constant is 1024. define i1 @shl_add_const_eq_i32(i32 %v0, i32 %v3) { ; CHECK-LABEL: @shl_add_const_eq_i32( -; CHECK-NEXT: [[V7:%.*]] = add nsw i32 %v3, 1 -; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 %v0, [[V7]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[V3:%.*]], 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i32 [[V0:%.*]], [[TMP1]] ; CHECK-NEXT: ret i1 [[V6]] ; %v1 = shl nsw i32 %v0, 10 From c32b54fc00827a65085f0e5eab67832d1b1cad63 Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <2802328816@qq.com> Date: Sat, 1 Nov 2025 18:45:17 +0800 Subject: [PATCH 3/4] [InstCombine] Add tests for multi-use cases and vector operations in icmp-shl-add optimization --- .../InstCombine/icmp-shl-add-to-add.ll | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll index 0f375a05528a2..f0f3ff0b9b2ef 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll @@ -4,6 +4,8 @@ ; Test case: Fold (X << 5) == ((Y << 5) + 32) into X == (Y + 1). ; This corresponds to the provided alive2 proof. +declare void @use_i64(i64) + define i1 @shl_add_const_eq_base(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_base( ; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V3:%.*]], 1 @@ -106,3 +108,70 @@ define i1 @shl_add_const_eq_i32(i32 %v0, i32 %v3) { %v6 = icmp eq i32 %v1, %v5 ret i1 %v6 } + +; Test: Multi-use case. The optimization should still occur if applicable, +; but the extraneous call must be preserved. +define i1 @shl_add_const_eq_multi_use(i64 %v0, i64 %v3) { +; CHECK-LABEL: @shl_add_const_eq_multi_use( +; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 +; CHECK-NEXT: call void @use_i64(i64 [[V1]]) +; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 +; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: ret i1 [[V6]] +; + %v1 = shl nsw i64 %v0, 5 + call void @use_i64(i64 %v1) ; Additional use of v1 + %v4 = shl nsw i64 %v3, 5 + %v5 = add nsw i64 %v4, 32 + %v6 = icmp eq i64 %v1, %v5 + ret i1 %v6 +} + +; Test: Vector splat. Should fold once optimization is applied. +define <2 x i1> @shl_add_const_eq_vec_splat(<2 x i64> %v0, <2 x i64> %v3) { +; CHECK-LABEL: @shl_add_const_eq_vec_splat( +; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], +; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], +; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], +; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]] +; CHECK-NEXT: ret <2 x i1> [[V6]] +; + %v1 = shl nsw <2 x i64> %v0, + %v4 = shl nsw <2 x i64> %v3, + %v5 = add nsw <2 x i64> %v4, + %v6 = icmp eq <2 x i64> %v1, %v5 + ret <2 x i1> %v6 +} + +; Test: Vector splat with poison. Should fold once optimization is applied. +define <2 x i1> @shl_add_const_eq_vec_splat_poison(<2 x i64> %v0, <2 x i64> %v3) { +; CHECK-LABEL: @shl_add_const_eq_vec_splat_poison( +; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], +; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], +; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], +; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]] +; CHECK-NEXT: ret <2 x i1> [[V6]] +; + %v1 = shl nsw <2 x i64> %v0, + %v4 = shl nsw <2 x i64> %v3, + %v5 = add nsw <2 x i64> %v4, + %v6 = icmp eq <2 x i64> %v1, %v5 + ret <2 x i1> %v6 +} + +; Test: Vector non-splat (should not fold). +define <2 x i1> @shl_add_const_eq_vec_non_splat(<2 x i64> %v0, <2 x i64> %v3) { +; CHECK-LABEL: @shl_add_const_eq_vec_non_splat( +; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], +; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], +; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], +; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]] +; CHECK-NEXT: ret <2 x i1> [[V6]] +; + %v1 = shl nsw <2 x i64> %v0, + %v4 = shl nsw <2 x i64> %v3, + %v5 = add nsw <2 x i64> %v4, + %v6 = icmp eq <2 x i64> %v1, %v5 + ret <2 x i1> %v6 +} From 6dc8405a47d4664c2ed345ee7b30e3f61938c4ae Mon Sep 17 00:00:00 2001 From: Michael-Chen-NJU <2802328816@qq.com> Date: Sat, 1 Nov 2025 19:22:15 +0800 Subject: [PATCH 4/4] [InstCombine] Refactor icmp folding logic for shl and add operations with APInt --- .../InstCombine/InstCombineCompares.cpp | 22 +++++++++---------- .../InstCombine/icmp-shl-add-to-add.ll | 17 +++++--------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 28d3c772acdcc..734d27c70705e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6002,25 +6002,25 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); const CmpInst::Predicate Pred = I.getPredicate(); - //icmp (shl nsw X, Log2), (add nsw (shl nsw Y, Log2), K) -> icmp X, (add nsw Y, 1) + // icmp (shl nsw X, Log2), (add nsw (shl nsw Y, Log2), K) -> icmp X, (add nsw + // Y, 1) Value *X, *Y; - ConstantInt *CLog2M0, *CLog2M1, *CVal; - auto M0 = m_NSWShl(m_Value(X), m_ConstantInt(CLog2M0)); - auto M1 = m_NSWAdd(m_NSWShl (m_Value(Y), m_ConstantInt(CLog2M1)), - m_ConstantInt(CVal)); + const APInt *CLog2M0, *CLog2M1, *CVal; + auto M0 = m_NSWShl(m_Value(X), m_APIntAllowPoison(CLog2M0)); + auto M1 = m_NSWAdd(m_NSWShl(m_Value(Y), m_APIntAllowPoison(CLog2M1)), + m_APIntAllowPoison(CVal)); - if (match(&I, m_c_ICmp(M0, M1)) && CLog2M0->getValue() == CLog2M1->getValue()) { + if (match(&I, m_c_ICmp(M0, M1)) && *CLog2M0 == *CLog2M1) { unsigned BitWidth = CLog2M0->getBitWidth(); unsigned ShAmt = (unsigned)CLog2M0->getLimitedValue(BitWidth); APInt ExpectedK = APInt::getOneBitSet(BitWidth, ShAmt); - if (CVal->getValue() == ExpectedK) { - Value *NewRHS = Builder.CreateAdd( - Y, ConstantInt::get(Y->getType(), 1), - "", /*HasNUW=*/false, /*HasNSW=*/true); + if (*CVal == ExpectedK) { + Value *NewRHS = Builder.CreateAdd(Y, ConstantInt::get(Y->getType(), 1), + "", /*HasNUW=*/false, /*HasNSW=*/true); return new ICmpInst(Pred, X, NewRHS); } } - + Value *A, *B, *C, *D; if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) { if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0 diff --git a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll index f0f3ff0b9b2ef..1523b283b8b08 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shl-add-to-add.ll @@ -115,9 +115,8 @@ define i1 @shl_add_const_eq_multi_use(i64 %v0, i64 %v3) { ; CHECK-LABEL: @shl_add_const_eq_multi_use( ; CHECK-NEXT: [[V1:%.*]] = shl nsw i64 [[V0:%.*]], 5 ; CHECK-NEXT: call void @use_i64(i64 [[V1]]) -; CHECK-NEXT: [[V4:%.*]] = shl nsw i64 [[V3:%.*]], 5 -; CHECK-NEXT: [[V5:%.*]] = add nsw i64 [[V4]], 32 -; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V1]], [[V5]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[V3:%.*]], 1 +; CHECK-NEXT: [[V6:%.*]] = icmp eq i64 [[V0]], [[TMP1]] ; CHECK-NEXT: ret i1 [[V6]] ; %v1 = shl nsw i64 %v0, 5 @@ -131,10 +130,8 @@ define i1 @shl_add_const_eq_multi_use(i64 %v0, i64 %v3) { ; Test: Vector splat. Should fold once optimization is applied. define <2 x i1> @shl_add_const_eq_vec_splat(<2 x i64> %v0, <2 x i64> %v3) { ; CHECK-LABEL: @shl_add_const_eq_vec_splat( -; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], -; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], -; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], -; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]] +; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V3:%.*]], splat (i64 1) +; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1:%.*]], [[V5]] ; CHECK-NEXT: ret <2 x i1> [[V6]] ; %v1 = shl nsw <2 x i64> %v0, @@ -147,10 +144,8 @@ define <2 x i1> @shl_add_const_eq_vec_splat(<2 x i64> %v0, <2 x i64> %v3) { ; Test: Vector splat with poison. Should fold once optimization is applied. define <2 x i1> @shl_add_const_eq_vec_splat_poison(<2 x i64> %v0, <2 x i64> %v3) { ; CHECK-LABEL: @shl_add_const_eq_vec_splat_poison( -; CHECK-NEXT: [[V1:%.*]] = shl nsw <2 x i64> [[V0:%.*]], -; CHECK-NEXT: [[V4:%.*]] = shl nsw <2 x i64> [[V3:%.*]], -; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V4]], -; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1]], [[V5]] +; CHECK-NEXT: [[V5:%.*]] = add nsw <2 x i64> [[V3:%.*]], splat (i64 1) +; CHECK-NEXT: [[V6:%.*]] = icmp eq <2 x i64> [[V1:%.*]], [[V5]] ; CHECK-NEXT: ret <2 x i1> [[V6]] ; %v1 = shl nsw <2 x i64> %v0,