From 58bfcdbcf6a7c1cac0187f7c6beb3afe9d8f5411 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 5 Mar 2011 05:19:11 +0000 Subject: [PATCH] Thread comparisons over udiv/sdiv/ashr/lshr exact and lshr nuw/nsw whenever possible. This goes into instcombine and instsimplify because instsimplify doesn't need to check hasOneUse since it returns (almost exclusively) constants. This fixes PR9343 #4 #5 and #8! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127064 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 34 +++++++++++++- .../InstCombine/InstCombineCompares.cpp | 21 +++++++++ test/Transforms/InstCombine/icmp.ll | 46 +++++++++++++++++++ test/Transforms/InstSimplify/compare.ll | 9 ++++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 1076eeff2d8..48edc5ceaca 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -1344,7 +1344,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // the compare, and if only one of them is then we moved it to RHS already. if (isa(LHS) && (isa(RHS) || isa(RHS) || isa(RHS))) - // We already know that LHS != LHS. + // We already know that LHS != RHS. return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); // If we are comparing with zero then try hard since this is a common case. @@ -1700,6 +1700,38 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, } } + if (MaxRecurse && LBO && RBO && LBO->getOpcode() == RBO->getOpcode() && + LBO->getOperand(1) == RBO->getOperand(1)) { + switch (LBO->getOpcode()) { + default: break; + case Instruction::UDiv: + case Instruction::LShr: + if (ICmpInst::isSigned(Pred)) + break; + // fall-through + case Instruction::SDiv: + case Instruction::AShr: + if (!LBO->isExact() && !RBO->isExact()) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + case Instruction::Shl: { + bool NUW = LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap(); + bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap(); + if (!NUW && !NSW) + break; + if (!NSW && ICmpInst::isSigned(Pred)) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + } + } + } + // If the comparison is with the result of a select instruction, check whether // comparing with either branch of the select always yields the same value. if (isa(LHS) || isa(RHS)) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 239cd23a2c6..bdef3dbc536 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2393,6 +2393,27 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } } break; + case Instruction::UDiv: + case Instruction::LShr: + if (I.isSigned()) + break; + // fall-through + case Instruction::SDiv: + case Instruction::AShr: + if (!BO0->isExact() && !BO1->isExact()) + break; + return new ICmpInst(I.getPredicate(), BO0->getOperand(0), + BO1->getOperand(0)); + case Instruction::Shl: { + bool NUW = BO0->hasNoUnsignedWrap() && BO1->hasNoUnsignedWrap(); + bool NSW = BO0->hasNoSignedWrap() && BO1->hasNoSignedWrap(); + if (!NUW && !NSW) + break; + if (!NSW && I.isSigned()) + break; + return new ICmpInst(I.getPredicate(), BO0->getOperand(0), + BO1->getOperand(0)); + } } } } diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index fb43e594535..0230506697b 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -419,3 +419,49 @@ define i1 @test43(i32 %X, i32 %Y) { %B = icmp slt i32 %Y, %A ret i1 %B } + +; CHECK: @test44 +; CHECK: %B = icmp sgt i32 %Y, -1 +define i1 @test44(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %A, %Y + ret i1 %B +} + +; CHECK: @test45 +; CHECK: %B = icmp slt i32 %Y, 0 +define i1 @test45(i32 %X, i32 %Y) { + %A = srem i32 %X, %Y + %B = icmp slt i32 %Y, %A + ret i1 %B +} + +; PR9343 #4 +; CHECK: @test46 +; CHECK: %C = icmp ult i32 %X, %Y +define i1 @test46(i32 %X, i32 %Y, i32 %Z) { + %A = ashr exact i32 %X, %Z + %B = ashr exact i32 %Y, %Z + %C = icmp ult i32 %A, %B + ret i1 %C +} + +; PR9343 #5 +; CHECK: @test47 +; CHECK: %C = icmp ugt i32 %X, %Y +define i1 @test47(i32 %X, i32 %Y, i32 %Z) { + %A = ashr exact i32 %X, %Z + %B = ashr exact i32 %Y, %Z + %C = icmp ugt i32 %A, %B + ret i1 %C +} + +; PR9343 #8 +; CHECK: @test48 +; CHECK: %C = icmp eq i32 %X, %Y +define i1 @test48(i32 %X, i32 %Y, i32 %Z) { + %A = sdiv exact i32 %X, %Z + %B = sdiv exact i32 %Y, %Z + %C = icmp eq i32 %A, %B + ret i1 %C +} diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index 7b92de156d2..7174e7fc61a 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -261,6 +261,15 @@ define i1 @udiv1(i32 %X) { ; CHECK: ret i1 true } +define i1 @udiv2(i32 %X, i32 %Y, i32 %Z) { +; CHECK: @udiv2 + %A = udiv exact i32 10, %Z + %B = udiv exact i32 20, %Z + %C = icmp ult i32 %A, %B + ret i1 %C +; CHECK: ret i1 true +} + define i1 @sdiv1(i32 %X) { ; CHECK: @sdiv1 %A = sdiv i32 %X, 1000000 -- 2.34.1