From: David Majnemer Date: Sat, 20 Dec 2014 03:04:38 +0000 (+0000) Subject: InstSimplify: Optimize away pointless comparisons X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9cd99a07248d6870462120dc4512692f77b32e20;p=oota-llvm.git InstSimplify: Optimize away pointless comparisons (X & INT_MIN) ? X & INT_MAX : X into X & INT_MAX (X & INT_MIN) ? X : X & INT_MAX into X (X & INT_MIN) ? X | INT_MIN : X into X (X & INT_MIN) ? X : X | INT_MIN into X | INT_MIN git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224669 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 1152af92394..f94e1057689 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -272,6 +272,13 @@ struct is_power2 { inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } +inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } + template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 1db7ab7bf03..b7882651d36 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -3155,10 +3155,10 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal, if (const auto *ICI = dyn_cast(CondVal)) { Value *X; const APInt *Y; - if (ICI->isEquality() && + ICmpInst::Predicate Pred = ICI->getPredicate(); + if (ICmpInst::isEquality(Pred) && match(ICI->getOperand(0), m_And(m_Value(X), m_APInt(Y))) && match(ICI->getOperand(1), m_Zero())) { - ICmpInst::Predicate Pred = ICI->getPredicate(); const APInt *C; // (X & Y) == 0 ? X & ~Y : X --> X // (X & Y) != 0 ? X & ~Y : X --> X & ~Y @@ -3184,6 +3184,42 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal, return Pred == ICmpInst::ICMP_EQ ? TrueVal : FalseVal; } } + if (Pred == ICmpInst::ICMP_SLT && match(ICI->getOperand(1), m_Zero())) { + // (X < 0) ? X : X | SignBit --> X | SignBit + if (TrueVal == ICI->getOperand(0) && + match(FalseVal, m_Or(m_Specific(TrueVal), m_SignBit()))) + return FalseVal; + // (X < 0) ? X | SignBit : X --> X + if (FalseVal == ICI->getOperand(0) && + match(TrueVal, m_Or(m_Specific(FalseVal), m_SignBit()))) + return FalseVal; + // (X < 0) ? X & INT_MAX : X --> X & INT_MAX + if (FalseVal == ICI->getOperand(0) && + match(TrueVal, m_And(m_Specific(FalseVal), m_MaxSignedValue()))) + return TrueVal; + // (X < 0) ? X : X & INT_MAX --> X + if (TrueVal == ICI->getOperand(0) && + match(FalseVal, m_And(m_Specific(TrueVal), m_MaxSignedValue()))) + return TrueVal; + } + if (Pred == ICmpInst::ICMP_SGT && match(ICI->getOperand(1), m_AllOnes())) { + // (X > -1) ? X : X | SignBit --> X + if (TrueVal == ICI->getOperand(0) && + match(FalseVal, m_Or(m_Specific(TrueVal), m_SignBit()))) + return TrueVal; + // (X > -1) ? X | SignBit : X --> X | SignBit + if (FalseVal == ICI->getOperand(0) && + match(TrueVal, m_Or(m_Specific(FalseVal), m_SignBit()))) + return TrueVal; + // (X > -1) ? X & INT_MAX : X --> X + if (FalseVal == ICI->getOperand(0) && + match(TrueVal, m_And(m_Specific(FalseVal), m_MaxSignedValue()))) + return FalseVal; + // (X > -1) ? X : X & INT_MAX --> X & INT_MAX + if (TrueVal == ICI->getOperand(0) && + match(FalseVal, m_And(m_Specific(TrueVal), m_MaxSignedValue()))) + return FalseVal; + } } return nullptr; diff --git a/test/Transforms/InstSimplify/select.ll b/test/Transforms/InstSimplify/select.ll index b30416e9d26..1d45e5728e6 100644 --- a/test/Transforms/InstSimplify/select.ll +++ b/test/Transforms/InstSimplify/select.ll @@ -31,6 +31,82 @@ define i32 @test3(i32 %x) { ; CHECK: ret i32 %[[and]] } +define i32 @test4(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %X, i32 %or + ret i32 %cond +; CHECK-LABEL: @test4 +; CHECK: %[[or:.*]] = or i32 %X, -2147483648 +; CHECK: ret i32 %[[or]] +} + +define i32 @test5(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %or, i32 %X + ret i32 %cond +; CHECK-LABEL: @test5 +; CHECK: ret i32 %X +} + +define i32 @test6(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %and, i32 %X + ret i32 %cond +; CHECK-LABEL: @test6 +; CHECK: %[[and:.*]] = and i32 %X, 2147483647 +; CHECK: ret i32 %[[and]] +} + +define i32 @test7(i32 %X) { + %cmp = icmp slt i32 %X, 0 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %X, i32 %and + ret i32 %cond +; CHECK-LABEL: @test7 +; CHECK: ret i32 %X +} + +define i32 @test8(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %X, i32 %or + ret i32 %cond +; CHECK-LABEL: @test8 +; CHECK: ret i32 %X +} + +define i32 @test9(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %or = or i32 %X, -2147483648 + %cond = select i1 %cmp, i32 %or, i32 %X + ret i32 %cond +; CHECK-LABEL: @test9 +; CHECK: %[[or:.*]] = or i32 %X, -2147483648 +; CHECK: ret i32 %[[or]] +} + +define i32 @test10(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %and, i32 %X + ret i32 %cond +; CHECK-LABEL: @test10 +; CHECK: ret i32 %X +} + +define i32 @test11(i32 %X) { + %cmp = icmp sgt i32 %X, -1 + %and = and i32 %X, 2147483647 + %cond = select i1 %cmp, i32 %X, i32 %and + ret i32 %cond +; CHECK-LABEL: @test11 +; CHECK: %[[and:.*]] = and i32 %X, 2147483647 +; CHECK: ret i32 %[[and]] +} + ; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8( ; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 8 ; CHECK-NEXT: ret i32 [[OR]]