diff options
author | Chris Lattner <sabre@nondot.org> | 2010-01-24 00:09:49 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-01-24 00:09:49 +0000 |
commit | abb992d6a3d2dc05d3f3c62a367ea8977a7dd070 (patch) | |
tree | b2498eacd1dbdae0230b2b4037063bca999a4ea9 | |
parent | eb38ebf15c326a5bb45ca9da6329cdf19ad6df95 (diff) |
change the canonical form of "cond ? -1 : 0" to be
"sext cond" instead of a select. This simplifies some instcombine
code, matches the policy for zext (cond ? 1 : 0 -> zext), and allows
us to generate better code for a testcase on ppc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94339 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Support/PatternMatch.h | 16 | ||||
-rw-r--r-- | lib/Target/PowerPC/README.txt | 13 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 8 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCasts.cpp | 30 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineSelect.cpp | 66 | ||||
-rw-r--r-- | test/Transforms/InstCombine/logical-select.ll | 20 |
6 files changed, 80 insertions, 73 deletions
diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index 23daad9239..f02bc347a1 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -423,7 +423,7 @@ m_Select(const Cond &C, const LHS &L, const RHS &R) { } /// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst(m_Value(V), -1, 0) +/// m_SelectCst<-1, 0>(m_Value(V)) template<int64_t L, int64_t R, typename Cond> inline SelectClass_match<Cond, constantint_ty<L>, constantint_ty<R> > m_SelectCst(const Cond &C) { @@ -466,6 +466,20 @@ inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) { return CastClass_match<OpTy, Instruction::Trunc>(Op); } + +/// m_SExt +template<typename OpTy> +inline CastClass_match<OpTy, Instruction::SExt> +m_SExt(const OpTy &Op) { + return CastClass_match<OpTy, Instruction::SExt>(Op); +} + +/// m_ZExt +template<typename OpTy> +inline CastClass_match<OpTy, Instruction::ZExt> +m_ZExt(const OpTy &Op) { + return CastClass_match<OpTy, Instruction::ZExt>(Op); +} //===----------------------------------------------------------------------===// diff --git a/lib/Target/PowerPC/README.txt b/lib/Target/PowerPC/README.txt index a243543cd4..5af108ac68 100644 --- a/lib/Target/PowerPC/README.txt +++ b/lib/Target/PowerPC/README.txt @@ -640,22 +640,19 @@ We compile: define i32 @bar(i32 %x) nounwind readnone ssp { entry: %0 = icmp eq i32 %x, 0 ; <i1> [#uses=1] - %neg = select i1 %0, i32 -1, i32 0 ; <i32> [#uses=1] + %neg = sext i1 %0 to i32 ; <i32> [#uses=1] ret i32 %neg } to: _bar: - cmplwi cr0, r3, 0 - li r3, -1 - beq cr0, LBB1_2 -; BB#1: ; %entry - li r3, 0 -LBB1_2: ; %entry + cntlzw r2, r3 + slwi r2, r2, 26 + srawi r3, r2, 31 blr -it would be much better to produce: +it would be better to produce: _bar: addic r3,r3,-1 diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index fa7bb12ff2..806e7b5480 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1142,19 +1142,15 @@ static Instruction *MatchSelectFromAndOr(Value *A, Value *B, Value *C, Value *D) { // If A is not a select of -1/0, this cannot match. Value *Cond = 0; - if (!match(A, m_SelectCst<-1, 0>(m_Value(Cond)))) + if (!match(A, m_SExt(m_Value(Cond)))) return 0; // ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B. - if (match(D, m_SelectCst<0, -1>(m_Specific(Cond)))) - return SelectInst::Create(Cond, C, B); - if (match(D, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) + if (match(D, m_Not(m_SExt(m_Specific(Cond))))) return SelectInst::Create(Cond, C, B); // ((cond?-1:0)&C) | ((cond?0:-1)&D) -> cond ? C : D. if (match(B, m_SelectCst<0, -1>(m_Specific(Cond)))) return SelectInst::Create(Cond, C, D); - if (match(B, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) - return SelectInst::Create(Cond, C, D); return 0; } diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index f25dd3582b..377651e5b0 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -923,12 +923,6 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { Value *Src = CI.getOperand(0); const Type *SrcTy = Src->getType(), *DestTy = CI.getType(); - // Canonicalize sign-extend from i1 to a select. - if (Src->getType()->isInteger(1)) - return SelectInst::Create(Src, - Constant::getAllOnesValue(CI.getType()), - Constant::getNullValue(CI.getType())); - // Attempt to extend the entire input expression tree to the destination // type. Only do this if the dest type is a simple type, don't convert the // expression tree to something weird like i93 unless the source is also @@ -968,6 +962,30 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { return BinaryOperator::CreateAShr(Res, ShAmt); } + + // (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed + // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed + { + ICmpInst::Predicate Pred; Value *CmpLHS; ConstantInt *CmpRHS; + if (match(Src, m_ICmp(Pred, m_Value(CmpLHS), m_ConstantInt(CmpRHS)))) { + // sext (x <s 0) to i32 --> x>>s31 true if signbit set. + // sext (x >s -1) to i32 --> (x>>s31)^-1 true if signbit clear. + if ((Pred == ICmpInst::ICMP_SLT && CmpRHS->isZero()) || + (Pred == ICmpInst::ICMP_SGT && CmpRHS->isAllOnesValue())) { + Value *Sh = ConstantInt::get(CmpLHS->getType(), + CmpLHS->getType()->getScalarSizeInBits()-1); + Value *In = Builder->CreateAShr(CmpLHS, Sh, CmpLHS->getName()+".lobit"); + if (In->getType() != CI.getType()) + In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/, "tmp"); + + if (Pred == ICmpInst::ICMP_SGT) + In = Builder->CreateNot(In, In->getName()+".not"); + return ReplaceInstUsesWith(CI, In); + } + } + } + + // If the input is a shl/ashr pair of a same constant, then this is a sign // extension from a smaller value. If we could trust arbitrary bitwidth // integers, we could turn this into a truncate to the smaller bit and then diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 18b2dff2b6..9a02b33b7b 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -326,44 +326,6 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI, break; } } - - // (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed - // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed - CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; - if (match(TrueVal, m_ConstantInt<-1>()) && - match(FalseVal, m_ConstantInt<0>())) - Pred = ICI->getPredicate(); - else if (match(TrueVal, m_ConstantInt<0>()) && - match(FalseVal, m_ConstantInt<-1>())) - Pred = CmpInst::getInversePredicate(ICI->getPredicate()); - - if (Pred != CmpInst::BAD_ICMP_PREDICATE) { - // If we are just checking for a icmp eq of a single bit and zext'ing it - // to an integer, then shift the bit to the appropriate place and then - // cast to integer to avoid the comparison. - const APInt &Op1CV = CI->getValue(); - - // sext (x <s 0) to i32 --> x>>s31 true if signbit set. - // sext (x >s -1) to i32 --> (x>>s31)^-1 true if signbit clear. - if ((Pred == ICmpInst::ICMP_SLT && Op1CV == 0) || - (Pred == ICmpInst::ICMP_SGT && Op1CV.isAllOnesValue())) { - Value *In = ICI->getOperand(0); - Value *Sh = ConstantInt::get(In->getType(), - In->getType()->getScalarSizeInBits()-1); - In = InsertNewInstBefore(BinaryOperator::CreateAShr(In, Sh, - In->getName()+".lobit"), - *ICI); - if (In->getType() != SI.getType()) - In = CastInst::CreateIntegerCast(In, SI.getType(), - true/*SExt*/, "tmp", ICI); - - if (Pred == ICmpInst::ICMP_SGT) - In = InsertNewInstBefore(BinaryOperator::CreateNot(In, - In->getName()+".not"), *ICI); - - return ReplaceInstUsesWith(SI, In); - } - } } if (CmpLHS == TrueVal && CmpRHS == FalseVal) { @@ -516,16 +478,25 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { if (ConstantInt *TrueValC = dyn_cast<ConstantInt>(TrueVal)) if (ConstantInt *FalseValC = dyn_cast<ConstantInt>(FalseVal)) { // select C, 1, 0 -> zext C to int - if (FalseValC->isZero() && TrueValC->getValue() == 1) { - return CastInst::Create(Instruction::ZExt, CondVal, SI.getType()); - } else if (TrueValC->isZero() && FalseValC->getValue() == 1) { - // select C, 0, 1 -> zext !C to int - Value *NotCond = - InsertNewInstBefore(BinaryOperator::CreateNot(CondVal, - "not."+CondVal->getName()), SI); - return CastInst::Create(Instruction::ZExt, NotCond, SI.getType()); + if (FalseValC->isZero() && TrueValC->getValue() == 1) + return new ZExtInst(CondVal, SI.getType()); + + // select C, -1, 0 -> sext C to int + if (FalseValC->isZero() && TrueValC->isAllOnesValue()) + return new SExtInst(CondVal, SI.getType()); + + // select C, 0, 1 -> zext !C to int + if (TrueValC->isZero() && FalseValC->getValue() == 1) { + Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName()); + return new ZExtInst(NotCond, SI.getType()); } + // select C, 0, -1 -> sext !C to int + if (TrueValC->isZero() && FalseValC->isAllOnesValue()) { + Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName()); + return new SExtInst(NotCond, SI.getType()); + } + if (ICmpInst *IC = dyn_cast<ICmpInst>(SI.getCondition())) { // If one of the constants is zero (we know they can't both be) and we // have an icmp instruction with zero, and we have an 'and' with the @@ -547,8 +518,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE; Value *V = ICA; if (ShouldNotVal) - V = InsertNewInstBefore(BinaryOperator::Create( - Instruction::Xor, V, ICA->getOperand(1)), SI); + V = Builder->CreateXor(V, ICA->getOperand(1)); return ReplaceInstUsesWith(SI, V); } } diff --git a/test/Transforms/InstCombine/logical-select.ll b/test/Transforms/InstCombine/logical-select.ll index ece8bc317e..4e48b2dd7c 100644 --- a/test/Transforms/InstCombine/logical-select.ll +++ b/test/Transforms/InstCombine/logical-select.ll @@ -1,7 +1,4 @@ -; RUN: opt < %s -instcombine -S > %t -; RUN: grep select %t | count 5 -; RUN: not grep and %t -; RUN: not grep or %t +; RUN: opt < %s -instcombine -S > FileCheck %s define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %e = icmp slt i32 %a, %b @@ -11,6 +8,9 @@ define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %i = and i32 %d, %h %j = or i32 %g, %i ret i32 %j +; CHECK: %e = icmp slt i32 %a, %b +; CHECK: %j = select i1 %e, i32 %c, i32 %d +; CHECK: ret i32 %j } define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %e = icmp slt i32 %a, %b @@ -20,6 +20,9 @@ define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %i = and i32 %d, %h %j = or i32 %i, %g ret i32 %j +; CHECK: %e = icmp slt i32 %a, %b +; CHECK: %j = select i1 %e, i32 %c, i32 %d +; CHECK: ret i32 %j } define i32 @goo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { entry: @@ -30,6 +33,9 @@ entry: %2 = and i32 %not, %d %3 = or i32 %1, %2 ret i32 %3 +; CHECK: %0 = icmp slt i32 %a, %b +; CHECK: %1 = select i1 %0, i32 %c, i32 %d +; CHECK: ret i32 %1 } define i32 @poo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { entry: @@ -40,6 +46,9 @@ entry: %2 = and i32 %iftmp, %d %3 = or i32 %1, %2 ret i32 %3 +; CHECK: %0 = icmp slt i32 %a, %b +; CHECK: %1 = select i1 %0, i32 %c, i32 %d +; CHECK: ret i32 %1 } define i32 @par(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { @@ -51,4 +60,7 @@ entry: %2 = and i32 %not, %d %3 = or i32 %1, %2 ret i32 %3 +; CHECK: %0 = icmp slt i32 %a, %b +; CHECK: %1 = select i1 %0, i32 %c, i32 %d +; CHECK: ret i32 %1 } |