From 689547b2df9826bc7df694a9a15cb1e8eb921a2b Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 5 Dec 2024 17:49:07 -0800 Subject: [PATCH 1/5] Match range check pattern with SExt = Background LLVM optimizes range check patterns like the following: ``` %nn = and i32 %n, 2147483647 ; %nn is non-negative %a = icmp sge i32 %x, 0 %b = icmp slt i32 %x, %nn %c = and i1 %a, %b ``` to a single unsigned comparison: ``` %nn = and i32 %n, 2147483647 %c = icmp ult i32 %x, %nn ``` = Extended Pattern This adds support for an extended version of this pattern where the upper range is compared with an `sext` value. Example: ``` %nn = and i64 %n, 2147483647 %x_sext = sext i32 %x to i64 %a = icmp sge i32 %x, 0 %b = icmp slt i64 %x_sext, %nn %c = and i1 %a, %b ``` is now optimized to: ``` %nn = and i64 %n, 2147483647 %x_sext = sext i32 %x to i64 %c = icmp ugt i64 %nn, %x_sext ``` In Alive2: https://alive2.llvm.org/ce/z/Ff7KJ_ --- .../InstCombine/InstCombineAndOrXor.cpp | 21 ++- .../Transforms/InstCombine/range-check.ll | 120 ++++++++++++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index b4033fc2a418a..dddab2efd80fb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -695,14 +695,27 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, Cmp1->getPredicate()); Value *Input = Cmp0->getOperand(0); + Value *Cmp1Op0 = Cmp1->getOperand(0); + Value *Cmp1Op1 = Cmp1->getOperand(1); Value *RangeEnd; - if (Cmp1->getOperand(0) == Input) { + if (Cmp1Op0 == Input) { // For the upper range compare we have: icmp x, n - RangeEnd = Cmp1->getOperand(1); - } else if (Cmp1->getOperand(1) == Input) { + RangeEnd = Cmp1Op1; + } else if (isa(Cmp1Op0) && + cast(Cmp1Op0)->getOperand(0) == Input) { + // For the upper range compare we have: icmp (sext x), n + Input = Cmp1Op0; + RangeEnd = Cmp1Op1; + } else if (Cmp1Op1 == Input) { // For the upper range compare we have: icmp n, x - RangeEnd = Cmp1->getOperand(0); Pred1 = ICmpInst::getSwappedPredicate(Pred1); + RangeEnd = Cmp1Op0; + } else if (isa(Cmp1Op1) && + cast(Cmp1Op1)->getOperand(0) == Input) { + // For the upper range compare we have: icmp n, (sext x) + Pred1 = ICmpInst::getSwappedPredicate(Pred1); + Input = Cmp1Op1; + RangeEnd = Cmp1Op0; } else { return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/range-check.ll b/llvm/test/Transforms/InstCombine/range-check.ll index ebb310fb7c1f8..161fc2d7fdc1d 100644 --- a/llvm/test/Transforms/InstCombine/range-check.ll +++ b/llvm/test/Transforms/InstCombine/range-check.ll @@ -32,6 +32,21 @@ define i1 @test_and1_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_and1_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_and1_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sge i32 %x, 0 + %b = icmp slt i64 %x_sext, %nn + %c = and i1 %a, %b + ret i1 %c +} + define i1 @test_and2(i32 %x, i32 %n) { ; CHECK-LABEL: @test_and2( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -60,6 +75,21 @@ define i1 @test_and2_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_and2_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_and2_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sgt i32 %x, -1 + %b = icmp sle i64 %x_sext, %nn + %c = and i1 %a, %b + ret i1 %c +} + define i1 @test_and3(i32 %x, i32 %n) { ; CHECK-LABEL: @test_and3( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -86,6 +116,21 @@ define i1 @test_and3_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_and3_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_and3_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sgt i64 %nn, %x_sext + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + define i1 @test_and4(i32 %x, i32 %n) { ; CHECK-LABEL: @test_and4( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -112,6 +157,21 @@ define i1 @test_and4_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_and4_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_and4_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sge i64 %nn, %x_sext + %b = icmp sge i32 %x, 0 + %c = and i1 %a, %b + ret i1 %c +} + define i1 @test_or1(i32 %x, i32 %n) { ; CHECK-LABEL: @test_or1( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -140,6 +200,21 @@ define i1 @test_or1_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_or1_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_or1_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp slt i32 %x, 0 + %b = icmp sge i64 %x_sext, %nn + %c = or i1 %a, %b + ret i1 %c +} + define i1 @test_or2(i32 %x, i32 %n) { ; CHECK-LABEL: @test_or2( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -168,6 +243,21 @@ define i1 @test_or2_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_or2_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_or2_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sle i32 %x, -1 + %b = icmp sgt i64 %x_sext, %nn + %c = or i1 %a, %b + ret i1 %c +} + define i1 @test_or3(i32 %x, i32 %n) { ; CHECK-LABEL: @test_or3( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -194,6 +284,21 @@ define i1 @test_or3_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_or3_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_or3_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp sle i64 %nn, %x_sext + %b = icmp slt i32 %x, 0 + %c = or i1 %a, %b + ret i1 %c +} + define i1 @test_or4(i32 %x, i32 %n) { ; CHECK-LABEL: @test_or4( ; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647 @@ -220,6 +325,21 @@ define i1 @test_or4_logical(i32 %x, i32 %n) { ret i1 %c } +define i1 @test_or4_sext(i32 %x, i64 %n) { +; CHECK-LABEL: @test_or4_sext( +; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]] +; CHECK-NEXT: ret i1 [[C]] +; + %nn = and i64 %n, 2147483647 + %x_sext = sext i32 %x to i64 + %a = icmp slt i64 %nn, %x_sext + %b = icmp slt i32 %x, 0 + %c = or i1 %a, %b + ret i1 %c +} + ; Negative tests define i1 @negative1(i32 %x, i32 %n) { From db77078bec2f6ece52b6955a117d827c8400b8ee Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 6 Dec 2024 13:33:17 -0800 Subject: [PATCH 2/5] Address review feedback --- .../Transforms/InstCombine/InstCombineAndOrXor.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index dddab2efd80fb..b607536c2ff97 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -698,20 +698,10 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, Value *Cmp1Op0 = Cmp1->getOperand(0); Value *Cmp1Op1 = Cmp1->getOperand(1); Value *RangeEnd; - if (Cmp1Op0 == Input) { - // For the upper range compare we have: icmp x, n - RangeEnd = Cmp1Op1; - } else if (isa(Cmp1Op0) && - cast(Cmp1Op0)->getOperand(0) == Input) { - // For the upper range compare we have: icmp (sext x), n + if (match(Cmp1Op0, m_SExtOrSelf(m_Specific(Input)))) { Input = Cmp1Op0; RangeEnd = Cmp1Op1; - } else if (Cmp1Op1 == Input) { - // For the upper range compare we have: icmp n, x - Pred1 = ICmpInst::getSwappedPredicate(Pred1); - RangeEnd = Cmp1Op0; - } else if (isa(Cmp1Op1) && - cast(Cmp1Op1)->getOperand(0) == Input) { + } else if (match(Cmp1Op1, m_SExtOrSelf(m_Specific(Input)))) { // For the upper range compare we have: icmp n, (sext x) Pred1 = ICmpInst::getSwappedPredicate(Pred1); Input = Cmp1Op1; From 288977872b761c8e17cd1f443c5735f3994d84af Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 6 Dec 2024 13:35:40 -0800 Subject: [PATCH 3/5] adjust --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index b607536c2ff97..1ce0aee955015 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -699,13 +699,14 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, Value *Cmp1Op1 = Cmp1->getOperand(1); Value *RangeEnd; if (match(Cmp1Op0, m_SExtOrSelf(m_Specific(Input)))) { + // For the upper range compare we have: icmp x, n Input = Cmp1Op0; RangeEnd = Cmp1Op1; } else if (match(Cmp1Op1, m_SExtOrSelf(m_Specific(Input)))) { // For the upper range compare we have: icmp n, (sext x) - Pred1 = ICmpInst::getSwappedPredicate(Pred1); Input = Cmp1Op1; RangeEnd = Cmp1Op0; + Pred1 = ICmpInst::getSwappedPredicate(Pred1); } else { return nullptr; } From 76e6a24015d7fca101c9ab14fe704ec28b147e73 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Fri, 6 Dec 2024 14:13:01 -0800 Subject: [PATCH 4/5] Update InstCombineAndOrXor.cpp --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 1ce0aee955015..314b1f0b43e3b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -703,7 +703,7 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, Input = Cmp1Op0; RangeEnd = Cmp1Op1; } else if (match(Cmp1Op1, m_SExtOrSelf(m_Specific(Input)))) { - // For the upper range compare we have: icmp n, (sext x) + // For the upper range compare we have: icmp n, x Input = Cmp1Op1; RangeEnd = Cmp1Op0; Pred1 = ICmpInst::getSwappedPredicate(Pred1); From 107b0e951473fddbff0e0c049618ae737b873f54 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 9 Dec 2024 10:56:20 -0800 Subject: [PATCH 5/5] Use assume instead of and for the tests --- .../Transforms/InstCombine/range-check.ll | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/range-check.ll b/llvm/test/Transforms/InstCombine/range-check.ll index 161fc2d7fdc1d..002f0224af6b0 100644 --- a/llvm/test/Transforms/InstCombine/range-check.ll +++ b/llvm/test/Transforms/InstCombine/range-check.ll @@ -34,15 +34,17 @@ define i1 @test_and1_logical(i32 %x, i32 %n) { define i1 @test_and1_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_and1_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %a = icmp sge i32 %x, 0 - %b = icmp slt i64 %x_sext, %nn + %b = icmp slt i64 %x_sext, %n %c = and i1 %a, %b ret i1 %c } @@ -77,15 +79,17 @@ define i1 @test_and2_logical(i32 %x, i32 %n) { define i1 @test_and2_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_and2_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %a = icmp sgt i32 %x, -1 - %b = icmp sle i64 %x_sext, %nn + %b = icmp sle i64 %x_sext, %n %c = and i1 %a, %b ret i1 %c } @@ -118,14 +122,16 @@ define i1 @test_and3_logical(i32 %x, i32 %n) { define i1 @test_and3_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_and3_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 - %a = icmp sgt i64 %nn, %x_sext + %a = icmp sgt i64 %n, %x_sext %b = icmp sge i32 %x, 0 %c = and i1 %a, %b ret i1 %c @@ -159,14 +165,16 @@ define i1 @test_and4_logical(i32 %x, i32 %n) { define i1 @test_and4_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_and4_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 - %a = icmp sge i64 %nn, %x_sext + %a = icmp sge i64 %n, %x_sext %b = icmp sge i32 %x, 0 %c = and i1 %a, %b ret i1 %c @@ -202,15 +210,17 @@ define i1 @test_or1_logical(i32 %x, i32 %n) { define i1 @test_or1_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_or1_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %a = icmp slt i32 %x, 0 - %b = icmp sge i64 %x_sext, %nn + %b = icmp sge i64 %x_sext, %n %c = or i1 %a, %b ret i1 %c } @@ -245,15 +255,17 @@ define i1 @test_or2_logical(i32 %x, i32 %n) { define i1 @test_or2_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_or2_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %a = icmp sle i32 %x, -1 - %b = icmp sgt i64 %x_sext, %nn + %b = icmp sgt i64 %x_sext, %n %c = or i1 %a, %b ret i1 %c } @@ -286,14 +298,16 @@ define i1 @test_or3_logical(i32 %x, i32 %n) { define i1 @test_or3_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_or3_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 - %a = icmp sle i64 %nn, %x_sext + %a = icmp sle i64 %n, %x_sext %b = icmp slt i32 %x, 0 %c = or i1 %a, %b ret i1 %c @@ -327,14 +341,16 @@ define i1 @test_or4_logical(i32 %x, i32 %n) { define i1 @test_or4_sext(i32 %x, i64 %n) { ; CHECK-LABEL: @test_or4_sext( -; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647 +; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]]) ; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64 ; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]] ; CHECK-NEXT: ret i1 [[C]] ; - %nn = and i64 %n, 2147483647 + %n_not_negative = icmp sge i64 %n, 0 + call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 - %a = icmp slt i64 %nn, %x_sext + %a = icmp slt i64 %n, %x_sext %b = icmp slt i32 %x, 0 %c = or i1 %a, %b ret i1 %c