mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-01 18:33:56 +00:00
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:
parent
eb38ebf15c
commit
abb992d6a3
@ -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);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user