Clean up previous cast optimization a bit. Also make zext elimination a bit more aggressive: if it's not necessary to emit an AND (i.e. high bits are already zero), it's profitable to evaluate the operand at a different type.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62297 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-01-16 02:11:43 +00:00
parent 05aae18165
commit 4e56ab2cf4
2 changed files with 62 additions and 30 deletions

View File

@ -394,8 +394,7 @@ namespace {
Value *EvaluateInDifferentType(Value *V, const Type *Ty, bool isSigned); Value *EvaluateInDifferentType(Value *V, const Type *Ty, bool isSigned);
bool CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, bool CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
unsigned CastOpc, unsigned CastOpc, int &NumCastsRemoved);
int &NumCastsRemoved, bool &SeenTrunc);
unsigned GetOrEnforceKnownAlignment(Value *V, unsigned GetOrEnforceKnownAlignment(Value *V,
unsigned PrefAlign = 0); unsigned PrefAlign = 0);
@ -7497,10 +7496,9 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
/// If CastOpc is a sext or zext, we are asking if the low bits of the value can /// If CastOpc is a sext or zext, we are asking if the low bits of the value can
/// bit computed in a larger type, which is then and'd or sext_in_reg'd to get /// bit computed in a larger type, which is then and'd or sext_in_reg'd to get
/// the final result. /// the final result.
bool bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, unsigned CastOpc,
unsigned CastOpc, int &NumCastsRemoved){
int &NumCastsRemoved, bool &SeenTrunc){
// We can always evaluate constants in another type. // We can always evaluate constants in another type.
if (isa<ConstantInt>(V)) if (isa<ConstantInt>(V))
return true; return true;
@ -7520,8 +7518,6 @@ InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
// casts first. // casts first.
if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse()) if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse())
++NumCastsRemoved; ++NumCastsRemoved;
if (isa<TruncInst>(I))
SeenTrunc = true;
return true; return true;
} }
} }
@ -7540,9 +7536,9 @@ InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
case Instruction::Xor: case Instruction::Xor:
// These operators can all arbitrarily be extended or truncated. // These operators can all arbitrarily be extended or truncated.
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
NumCastsRemoved, SeenTrunc) && NumCastsRemoved) &&
CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc, CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
NumCastsRemoved, SeenTrunc); NumCastsRemoved);
case Instruction::Shl: case Instruction::Shl:
// If we are truncating the result of this SHL, and if it's a shift of a // If we are truncating the result of this SHL, and if it's a shift of a
@ -7552,7 +7548,7 @@ InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
if (BitWidth < OrigTy->getBitWidth() && if (BitWidth < OrigTy->getBitWidth() &&
CI->getLimitedValue(BitWidth) < BitWidth) CI->getLimitedValue(BitWidth) < BitWidth)
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
NumCastsRemoved, SeenTrunc); NumCastsRemoved);
} }
break; break;
case Instruction::LShr: case Instruction::LShr:
@ -7567,7 +7563,7 @@ InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) && APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) &&
CI->getLimitedValue(BitWidth) < BitWidth) { CI->getLimitedValue(BitWidth) < BitWidth) {
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
NumCastsRemoved, SeenTrunc); NumCastsRemoved);
} }
} }
break; break;
@ -7587,16 +7583,16 @@ InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
case Instruction::Select: { case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(I); SelectInst *SI = cast<SelectInst>(I);
return CanEvaluateInDifferentType(SI->getTrueValue(), Ty, CastOpc, return CanEvaluateInDifferentType(SI->getTrueValue(), Ty, CastOpc,
NumCastsRemoved, SeenTrunc) && NumCastsRemoved) &&
CanEvaluateInDifferentType(SI->getFalseValue(), Ty, CastOpc, CanEvaluateInDifferentType(SI->getFalseValue(), Ty, CastOpc,
NumCastsRemoved, SeenTrunc); NumCastsRemoved);
} }
case Instruction::PHI: { case Instruction::PHI: {
// We can change a phi if we can change all operands. // We can change a phi if we can change all operands.
PHINode *PN = cast<PHINode>(I); PHINode *PN = cast<PHINode>(I);
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, CastOpc, if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, CastOpc,
NumCastsRemoved, SeenTrunc)) NumCastsRemoved))
return false; return false;
return true; return true;
} }
@ -7845,10 +7841,9 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
// Attempt to propagate the cast into the instruction for int->int casts. // Attempt to propagate the cast into the instruction for int->int casts.
int NumCastsRemoved = 0; int NumCastsRemoved = 0;
bool SeenTrunc = false;
if (!isa<BitCastInst>(CI) && if (!isa<BitCastInst>(CI) &&
CanEvaluateInDifferentType(SrcI, cast<IntegerType>(DestTy), CanEvaluateInDifferentType(SrcI, cast<IntegerType>(DestTy),
CI.getOpcode(), NumCastsRemoved, SeenTrunc)) { CI.getOpcode(), NumCastsRemoved)) {
// If this cast is a truncate, evaluting in a different type always // If this cast is a truncate, evaluting in a different type always
// eliminates the cast, so it is always a win. If this is a zero-extension, // eliminates the cast, so it is always a win. If this is a zero-extension,
// we need to do an AND to maintain the clear top-part of the computation, // we need to do an AND to maintain the clear top-part of the computation,
@ -7865,14 +7860,27 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
case Instruction::Trunc: case Instruction::Trunc:
DoXForm = true; DoXForm = true;
break; break;
case Instruction::ZExt: case Instruction::ZExt: {
DoXForm = NumCastsRemoved >= 1; DoXForm = NumCastsRemoved >= 1;
// TODO: Check if we need to insert an AND. if (!DoXForm) {
// If it's unnecessary to issue an AND to clear the high bits, it's
// always profitable to do this xform.
Value *TryRes = EvaluateInDifferentType(SrcI, DestTy,
CI.getOpcode() == Instruction::SExt);
APInt Mask(APInt::getBitsSet(DestBitSize, SrcBitSize, DestBitSize));
if (MaskedValueIsZero(TryRes, Mask))
return ReplaceInstUsesWith(CI, TryRes);
else if (Instruction *TryI = dyn_cast<Instruction>(TryRes))
if (TryI->use_empty())
EraseInstFromFunction(*TryI);
}
break; break;
}
case Instruction::SExt: { case Instruction::SExt: {
DoXForm = NumCastsRemoved >= 2; DoXForm = NumCastsRemoved >= 2;
if (!SeenTrunc) { if (!DoXForm && !isa<TruncInst>(SrcI)) {
// Do we have to emit a truncate to SrcBitSize followed by a sext? // If we do not have to emit the truncate + sext pair, then it's always
// profitable to do this xform.
// //
// It's not safe to eliminate the trunc + sext pair if one of the // It's not safe to eliminate the trunc + sext pair if one of the
// eliminated cast is a truncate. e.g. // eliminated cast is a truncate. e.g.
@ -7880,11 +7888,14 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
// t3 = sext i16 t2 to i32 // t3 = sext i16 t2 to i32
// != // !=
// i32 t1 // i32 t1
unsigned NumSignBits = ComputeNumSignBits(&CI); Value *TryRes = EvaluateInDifferentType(SrcI, DestTy,
if (NumSignBits > (DestBitSize - SrcBitSize)) { CI.getOpcode() == Instruction::SExt);
DoXForm = true; unsigned NumSignBits = ComputeNumSignBits(TryRes);
JustReplace = true; if (NumSignBits > (DestBitSize - SrcBitSize))
} return ReplaceInstUsesWith(CI, TryRes);
else if (Instruction *TryI = dyn_cast<Instruction>(TryRes))
if (TryI->use_empty())
EraseInstFromFunction(*TryI);
} }
break; break;
} }
@ -7893,6 +7904,10 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
if (DoXForm) { if (DoXForm) {
Value *Res = EvaluateInDifferentType(SrcI, DestTy, Value *Res = EvaluateInDifferentType(SrcI, DestTy,
CI.getOpcode() == Instruction::SExt); CI.getOpcode() == Instruction::SExt);
if (JustReplace)
// Just replace this cast with the result.
return ReplaceInstUsesWith(CI, Res);
assert(Res->getType() == DestTy); assert(Res->getType() == DestTy);
switch (CI.getOpcode()) { switch (CI.getOpcode()) {
default: assert(0 && "Unknown cast type!"); default: assert(0 && "Unknown cast type!");
@ -7901,15 +7916,24 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
// Just replace this cast with the result. // Just replace this cast with the result.
return ReplaceInstUsesWith(CI, Res); return ReplaceInstUsesWith(CI, Res);
case Instruction::ZExt: { case Instruction::ZExt: {
// We need to emit an AND to clear the high bits.
assert(SrcBitSize < DestBitSize && "Not a zext?"); assert(SrcBitSize < DestBitSize && "Not a zext?");
// If the high bits are already zero, just replace this cast with the
// result.
APInt Mask(APInt::getBitsSet(DestBitSize, SrcBitSize, DestBitSize));
if (MaskedValueIsZero(Res, Mask))
return ReplaceInstUsesWith(CI, Res);
// We need to emit an AND to clear the high bits.
Constant *C = ConstantInt::get(APInt::getLowBitsSet(DestBitSize, Constant *C = ConstantInt::get(APInt::getLowBitsSet(DestBitSize,
SrcBitSize)); SrcBitSize));
return BinaryOperator::CreateAnd(Res, C); return BinaryOperator::CreateAnd(Res, C);
} }
case Instruction::SExt: case Instruction::SExt: {
if (JustReplace) // If the high bits are already filled with sign bit, just replace this
// Just replace this cast with the result. // cast with the result.
unsigned NumSignBits = ComputeNumSignBits(Res);
if (NumSignBits > (DestBitSize - SrcBitSize))
return ReplaceInstUsesWith(CI, Res); return ReplaceInstUsesWith(CI, Res);
// We need to emit a cast to truncate, then a cast to sext. // We need to emit a cast to truncate, then a cast to sext.
@ -7917,6 +7941,7 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
InsertCastBefore(Instruction::Trunc, Res, Src->getType(), InsertCastBefore(Instruction::Trunc, Res, Src->getType(),
CI), DestTy); CI), DestTy);
} }
}
} }
} }

View File

@ -254,3 +254,10 @@ define i1 @test37(i32 %a) {
ret i1 %e ret i1 %e
} }
define i64 @test38(i32 %a) {
%1 = icmp eq i32 %a, -2
%2 = zext i1 %1 to i8
%3 = xor i8 %2, 1
%4 = zext i8 %3 to i64
ret i64 %4
}