rename CanEvaluateInDifferentType -> CanEvaluateTruncated and

simplify it now that it is only used for truncates.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93021 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2010-01-08 19:19:23 +00:00
parent ad5b52fd5e
commit 14bf8f0285

View File

@@ -147,29 +147,16 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
} }
/// CanEvaluateInDifferentType - Return true if we can take the specified value /// CanEvaluateTruncated - Return true if we can evaluate the specified
/// and return it as type Ty without inserting any new casts and without /// expression tree as type Ty instead of its larger type, and arrive with the
/// changing the computed value. This is used by code that tries to decide /// same value. This is used by code that tries to eliminate truncates.
/// whether promoting or shrinking integer operations to wider or smaller types
/// will allow us to eliminate a truncate or extend.
/// ///
/// This is a truncation operation if Ty is smaller than V->getType(), or a zero /// Ty will always be a type smaller than V. We should return true if trunc(V)
/// extension operation if Ty is larger. /// can be computed by computing V in the smaller type. If V is an instruction,
/// then trunc(inst(x,y)) can be computed as inst(trunc(x),trunc(y)), which only
/// makes sense if x and y can be efficiently truncated.
/// ///
/// If CastOpc is a truncation, then Ty will be a type smaller than V. We static bool CanEvaluateTruncated(Value *V, const Type *Ty) {
/// should return true if trunc(V) can be computed by computing V in the smaller
/// type. If V is an instruction, then trunc(inst(x,y)) can be computed as
/// inst(trunc(x),trunc(y)), which only makes sense if x and y can be
/// efficiently truncated.
///
/// If CastOpc is zext, we are asking if the low bits of the value can be
/// computed in a larger type, which is then and'd to get the final result.
static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
unsigned CastOpc,
unsigned &NumCastsRemoved) {
// FIXME: Eliminate CastOpc
assert(CastOpc == Instruction::Trunc);
// We can always evaluate constants in another type. // We can always evaluate constants in another type.
if (isa<Constant>(V)) if (isa<Constant>(V))
return true; return true;
@@ -179,19 +166,10 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
const Type *OrigTy = V->getType(); const Type *OrigTy = V->getType();
// If this is an extension or truncate, we can often eliminate it. // If this is an extension from the dest type, we can eliminate it.
if (isa<TruncInst>(I) || isa<ZExtInst>(I) || isa<SExtInst>(I)) { if ((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
// If this is a cast from the destination type, we can trivially eliminate I->getOperand(0)->getType() == Ty)
// it, and this will remove a cast overall.
if (I->getOperand(0)->getType() == Ty) {
// If the first operand is itself a cast, and is eliminable, do not count
// this as an eliminable cast. We would prefer to eliminate those two
// casts first.
if (!isa<CastInst>(I->getOperand(0)) && I->hasOneUse())
++NumCastsRemoved;
return true; return true;
}
}
// We can't extend or shrink something that has multiple uses: doing so would // We can't extend or shrink something that has multiple uses: doing so would
// require duplicating the instruction in general, which isn't profitable. // require duplicating the instruction in general, which isn't profitable.
@@ -206,10 +184,8 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
case Instruction::Or: case Instruction::Or:
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 CanEvaluateTruncated(I->getOperand(0), Ty) &&
NumCastsRemoved) && CanEvaluateTruncated(I->getOperand(1), Ty);
CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
NumCastsRemoved);
case Instruction::UDiv: case Instruction::UDiv:
case Instruction::URem: { case Instruction::URem: {
@@ -220,10 +196,8 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
APInt Mask = APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth); APInt Mask = APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth);
if (MaskedValueIsZero(I->getOperand(0), Mask) && if (MaskedValueIsZero(I->getOperand(0), Mask) &&
MaskedValueIsZero(I->getOperand(1), Mask)) { MaskedValueIsZero(I->getOperand(1), Mask)) {
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, return CanEvaluateTruncated(I->getOperand(0), Ty) &&
NumCastsRemoved) && CanEvaluateTruncated(I->getOperand(1), Ty);
CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
NumCastsRemoved);
} }
} }
break; break;
@@ -233,10 +207,8 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
// constant amount, we can always perform a SHL in a smaller type. // constant amount, we can always perform a SHL in a smaller type.
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
uint32_t BitWidth = Ty->getScalarSizeInBits(); uint32_t BitWidth = Ty->getScalarSizeInBits();
if (BitWidth < OrigTy->getScalarSizeInBits() && if (CI->getLimitedValue(BitWidth) < BitWidth)
CI->getLimitedValue(BitWidth) < BitWidth) return CanEvaluateTruncated(I->getOperand(0), Ty);
return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
NumCastsRemoved);
} }
break; break;
case Instruction::LShr: case Instruction::LShr:
@@ -246,34 +218,20 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits();
uint32_t BitWidth = Ty->getScalarSizeInBits(); uint32_t BitWidth = Ty->getScalarSizeInBits();
if (BitWidth < OrigBitWidth && if (MaskedValueIsZero(I->getOperand(0),
MaskedValueIsZero(I->getOperand(0),
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 CanEvaluateTruncated(I->getOperand(0), Ty);
NumCastsRemoved);
} }
} }
break; break;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc: case Instruction::Trunc:
// If this is the same kind of case as our original (e.g. zext+zext), we // trunc(trunc(x)) -> trunc(x)
// can safely replace it. Note that replacing it does not reduce the number
// of casts in the input.
if (Opc == CastOpc)
return true; return true;
// sext (zext ty1), ty2 -> zext ty2
if (CastOpc == Instruction::SExt && Opc == Instruction::ZExt)
return true;
break;
case Instruction::Select: { case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(I); SelectInst *SI = cast<SelectInst>(I);
return CanEvaluateInDifferentType(SI->getTrueValue(), Ty, CastOpc, return CanEvaluateTruncated(SI->getTrueValue(), Ty) &&
NumCastsRemoved) && CanEvaluateTruncated(SI->getFalseValue(), Ty);
CanEvaluateInDifferentType(SI->getFalseValue(), Ty, CastOpc,
NumCastsRemoved);
} }
case Instruction::PHI: { case Instruction::PHI: {
// We can change a phi if we can change all operands. Note that we never // We can change a phi if we can change all operands. Note that we never
@@ -281,8 +239,7 @@ static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
// instructions with a single use. // instructions with a single use.
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 (!CanEvaluateTruncated(PN->getIncomingValue(i), Ty))
NumCastsRemoved))
return false; return false;
return true; return true;
} }
@@ -515,10 +472,11 @@ static unsigned CanEvaluateSExtd(Value *V, const Type *Ty,
/// EvaluateInDifferentType - Given an expression that /// EvaluateInDifferentType - Given an expression that
/// CanEvaluateInDifferentType or CanEvaluateSExtd returns true for, actually /// CanEvaluateTruncated or CanEvaluateSExtd returns true for, actually
/// insert the code to evaluate the expression. /// insert the code to evaluate the expression.
Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
bool isSigned) { bool isSigned) {
// FIXME: use libanalysis constant folding.
if (Constant *C = dyn_cast<Constant>(V)) if (Constant *C = dyn_cast<Constant>(V))
return ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/); return ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/);
@@ -699,8 +657,7 @@ Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
switch (CI.getOpcode()) { switch (CI.getOpcode()) {
default: assert(0 && "not an integer cast"); default: assert(0 && "not an integer cast");
case Instruction::Trunc: { case Instruction::Trunc: {
if (!CanEvaluateInDifferentType(Src, DestTy, if (!CanEvaluateTruncated(Src, DestTy))
Instruction::Trunc, NumCastsRemoved))
return 0; return 0;
// If this cast is a truncate, evaluting in a different type always // If this cast is a truncate, evaluting in a different type always