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
This commit is contained in:
Chris Lattner 2010-01-24 00:09:49 +00:00
parent eb38ebf15c
commit abb992d6a3
6 changed files with 80 additions and 73 deletions

View File

@ -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);
}
//===----------------------------------------------------------------------===//

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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
}