forked from OSchip/llvm-project
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:
parent
58db865d6e
commit
c3cf9f872a
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue