Transform (zext (or (icmp), (icmp))) to (or (zext (cimp), (zext icmp))) if at least one of the (zext icmp) can be transformed to eliminate an icmp.

llvm-svn: 48715
This commit is contained in:
Evan Cheng 2008-03-24 00:21:34 +00:00
parent 58db865d6e
commit c3cf9f872a
2 changed files with 164 additions and 96 deletions

View File

@ -236,6 +236,8 @@ namespace {
Instruction *visitCallSite(CallSite CS); Instruction *visitCallSite(CallSite CS);
bool transformConstExprCastCall(CallSite CS); bool transformConstExprCastCall(CallSite CS);
Instruction *transformCallThroughTrampoline(CallSite CS); Instruction *transformCallThroughTrampoline(CallSite CS);
Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI,
bool DoXform = true);
public: public:
// InsertNewInstBefore - insert an instruction New before instruction Old // InsertNewInstBefore - insert an instruction New before instruction Old
@ -4363,9 +4365,12 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) { if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ? if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ?
if (!isa<ICmpInst>(Op0C->getOperand(0)) ||
!isa<ICmpInst>(Op1C->getOperand(0))) {
const Type *SrcTy = Op0C->getOperand(0)->getType(); const Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isInteger() && if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isInteger() &&
// Only do this if the casts both really cause code to be generated. // Only do this if the casts both really cause code to be
// generated.
ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0),
I.getType(), TD) && I.getType(), TD) &&
ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0),
@ -4378,6 +4383,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
} }
} }
}
// (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y) // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y)
@ -7188,43 +7194,10 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
return 0; return 0;
} }
Instruction *InstCombiner::visitZExt(ZExtInst &CI) { /// transformZExtICmp - Transform (zext icmp) to bitwise / integer operations
// If one of the common conversion will work .. /// in order to eliminate the icmp.
if (Instruction *Result = commonIntCastTransforms(CI)) Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
return Result; bool DoXform) {
Value *Src = CI.getOperand(0);
// If this is a cast of a cast
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
// If this is a TRUNC followed by a ZEXT then we are dealing with integral
// types and if the sizes are just right we can convert this into a logical
// 'and' which will be much cheaper than the pair of casts.
if (isa<TruncInst>(CSrc)) {
// Get the sizes of the types involved
Value *A = CSrc->getOperand(0);
uint32_t SrcSize = A->getType()->getPrimitiveSizeInBits();
uint32_t MidSize = CSrc->getType()->getPrimitiveSizeInBits();
uint32_t DstSize = CI.getType()->getPrimitiveSizeInBits();
// If we're actually extending zero bits and the trunc is a no-op
if (MidSize < DstSize && SrcSize == DstSize) {
// Replace both of the casts with an And of the type mask.
APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
Constant *AndConst = ConstantInt::get(AndValue);
Instruction *And =
BinaryOperator::createAnd(CSrc->getOperand(0), AndConst);
// Unfortunately, if the type changed, we need to cast it back.
if (And->getType() != CI.getType()) {
And->setName(CSrc->getName()+".mask");
InsertNewInstBefore(And, CI);
And = CastInst::createIntegerCast(And, CI.getType(), false/*ZExt*/);
}
return And;
}
}
}
if (ICmpInst *ICI = dyn_cast<ICmpInst>(Src)) {
// If we are just checking for a icmp eq of a single bit and zext'ing it // 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 // to an integer, then shift the bit to the appropriate place and then
// cast to integer to avoid the comparison. // cast to integer to avoid the comparison.
@ -7235,6 +7208,8 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
// zext (x >s -1) to i32 --> (x>>u31)^1 true if signbit clear. // zext (x >s -1) to i32 --> (x>>u31)^1 true if signbit clear.
if ((ICI->getPredicate() == ICmpInst::ICMP_SLT && Op1CV == 0) || if ((ICI->getPredicate() == ICmpInst::ICMP_SLT && Op1CV == 0) ||
(ICI->getPredicate() == ICmpInst::ICMP_SGT &&Op1CV.isAllOnesValue())) { (ICI->getPredicate() == ICmpInst::ICMP_SGT &&Op1CV.isAllOnesValue())) {
if (!DoXform) return ICI;
Value *In = ICI->getOperand(0); Value *In = ICI->getOperand(0);
Value *Sh = ConstantInt::get(In->getType(), Value *Sh = ConstantInt::get(In->getType(),
In->getType()->getPrimitiveSizeInBits()-1); In->getType()->getPrimitiveSizeInBits()-1);
@ -7276,6 +7251,8 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
APInt KnownZeroMask(~KnownZero); APInt KnownZeroMask(~KnownZero);
if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1? if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1?
if (!DoXform) return ICI;
bool isNE = ICI->getPredicate() == ICmpInst::ICMP_NE; bool isNE = ICI->getPredicate() == ICmpInst::ICMP_NE;
if (Op1CV != 0 && (Op1CV != KnownZeroMask)) { if (Op1CV != 0 && (Op1CV != KnownZeroMask)) {
// (X&4) == 2 --> false // (X&4) == 2 --> false
@ -7290,8 +7267,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
if (ShiftAmt) { if (ShiftAmt) {
// Perform a logical shr by shiftamt. // Perform a logical shr by shiftamt.
// Insert the shift to put the result in the low bit. // Insert the shift to put the result in the low bit.
In = InsertNewInstBefore( In = InsertNewInstBefore(BinaryOperator::createLShr(In,
BinaryOperator::createLShr(In,
ConstantInt::get(In->getType(), ShiftAmt), ConstantInt::get(In->getType(), ShiftAmt),
In->getName()+".lobit"), CI); In->getName()+".lobit"), CI);
} }
@ -7309,7 +7285,64 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
} }
} }
} }
return 0;
} }
Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
// If one of the common conversion will work ..
if (Instruction *Result = commonIntCastTransforms(CI))
return Result;
Value *Src = CI.getOperand(0);
// If this is a cast of a cast
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
// If this is a TRUNC followed by a ZEXT then we are dealing with integral
// types and if the sizes are just right we can convert this into a logical
// 'and' which will be much cheaper than the pair of casts.
if (isa<TruncInst>(CSrc)) {
// Get the sizes of the types involved
Value *A = CSrc->getOperand(0);
uint32_t SrcSize = A->getType()->getPrimitiveSizeInBits();
uint32_t MidSize = CSrc->getType()->getPrimitiveSizeInBits();
uint32_t DstSize = CI.getType()->getPrimitiveSizeInBits();
// If we're actually extending zero bits and the trunc is a no-op
if (MidSize < DstSize && SrcSize == DstSize) {
// Replace both of the casts with an And of the type mask.
APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
Constant *AndConst = ConstantInt::get(AndValue);
Instruction *And =
BinaryOperator::createAnd(CSrc->getOperand(0), AndConst);
// Unfortunately, if the type changed, we need to cast it back.
if (And->getType() != CI.getType()) {
And->setName(CSrc->getName()+".mask");
InsertNewInstBefore(And, CI);
And = CastInst::createIntegerCast(And, CI.getType(), false/*ZExt*/);
}
return And;
}
}
}
if (ICmpInst *ICI = dyn_cast<ICmpInst>(Src))
return transformZExtICmp(ICI, CI);
BinaryOperator *SrcI = dyn_cast<BinaryOperator>(Src);
if (SrcI && SrcI->getOpcode() == Instruction::Or) {
// zext (or icmp, icmp) --> or (zext icmp), (zext icmp) if at least one
// of the (zext icmp) will be transformed.
ICmpInst *LHS = dyn_cast<ICmpInst>(SrcI->getOperand(0));
ICmpInst *RHS = dyn_cast<ICmpInst>(SrcI->getOperand(1));
if (LHS && RHS && LHS->hasOneUse() && RHS->hasOneUse() &&
(transformZExtICmp(LHS, CI, false) ||
transformZExtICmp(RHS, CI, false))) {
Value *LCast = InsertCastBefore(Instruction::ZExt, LHS, CI.getType(), CI);
Value *RCast = InsertCastBefore(Instruction::ZExt, RHS, CI.getType(), CI);
return BinaryOperator::create(Instruction::Or, LCast, RCast);
}
}
return 0; return 0;
} }

View File

@ -0,0 +1,35 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep icmp | count 1
%struct.FooBar = type <{ i8, i8, [2 x i8], i8, i8, i8, i8, i16, i16, [4 x i8], [8 x %struct.Rock] }>
%struct.Rock = type { i16, i16 }
@some_idx = internal constant [4 x i8] c"\0A\0B\0E\0F" ; <[4 x i8]*> [#uses=1]
define i8 @t(%struct.FooBar* %up, i8 zeroext %intra_flag, i32 %blk_i) zeroext nounwind {
entry:
%tmp2 = lshr i32 %blk_i, 1 ; <i32> [#uses=1]
%tmp3 = and i32 %tmp2, 2 ; <i32> [#uses=1]
%tmp5 = and i32 %blk_i, 1 ; <i32> [#uses=1]
%tmp6 = or i32 %tmp3, %tmp5 ; <i32> [#uses=1]
%tmp8 = getelementptr %struct.FooBar* %up, i32 0, i32 7 ; <i16*> [#uses=1]
%tmp9 = load i16* %tmp8, align 1 ; <i16> [#uses=1]
%tmp910 = zext i16 %tmp9 to i32 ; <i32> [#uses=1]
%tmp12 = getelementptr [4 x i8]* @some_idx, i32 0, i32 %tmp6 ; <i8*> [#uses=1]
%tmp13 = load i8* %tmp12, align 1 ; <i8> [#uses=1]
%tmp1314 = zext i8 %tmp13 to i32 ; <i32> [#uses=1]
%tmp151 = lshr i32 %tmp910, %tmp1314 ; <i32> [#uses=1]
%tmp1516 = trunc i32 %tmp151 to i8 ; <i8> [#uses=1]
%tmp18 = getelementptr %struct.FooBar* %up, i32 0, i32 0 ; <i8*> [#uses=1]
%tmp19 = load i8* %tmp18, align 1 ; <i8> [#uses=1]
%tmp22 = and i8 %tmp1516, %tmp19 ; <i8> [#uses=1]
%tmp24 = getelementptr %struct.FooBar* %up, i32 0, i32 0 ; <i8*> [#uses=1]
%tmp25 = load i8* %tmp24, align 1 ; <i8> [#uses=1]
%tmp26.mask = and i8 %tmp25, 1 ; <i8> [#uses=1]
%toBool = icmp eq i8 %tmp26.mask, 0 ; <i1> [#uses=1]
%toBool.not = xor i1 %toBool, true ; <i1> [#uses=1]
%toBool33 = icmp eq i8 %intra_flag, 0 ; <i1> [#uses=1]
%bothcond = or i1 %toBool.not, %toBool33 ; <i1> [#uses=1]
%iftmp.1.0 = select i1 %bothcond, i8 0, i8 1 ; <i8> [#uses=1]
%tmp40 = or i8 %tmp22, %iftmp.1.0 ; <i8> [#uses=1]
%tmp432 = and i8 %tmp40, 1 ; <i8> [#uses=1]
ret i8 %tmp432
}