1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

Make cast-cast code a bit more defensive

"simplify" a bit of code for comparison/and folding

llvm-svn: 15082
This commit is contained in:
Chris Lattner 2004-07-21 19:50:44 +00:00
parent 752584b520
commit a3c10c2012

View File

@ -1453,38 +1453,42 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
if (LHSI->hasOneUse())
switch (LHSI->getOpcode()) {
case Instruction::And:
if (isa<ConstantInt>(LHSI->getOperand(1))) {
if (isa<ConstantInt>(LHSI->getOperand(1)) &&
LHSI->getOperand(0)->hasOneUse()) {
// If this is: (X >> C1) & C2 != C3 (where any shift and any compare
// could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This
// happens a LOT in code produced by the C front-end, for bitfield
// access.
if (LHSI->getOperand(0)->hasOneUse())
if (ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0)))
if (ConstantUInt *ShAmt =
dyn_cast<ConstantUInt>(Shift->getOperand(1))) {
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0));
ConstantUInt *ShAmt;
ShAmt = Shift ? dyn_cast<ConstantUInt>(Shift->getOperand(1)) : 0;
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
const Type *Ty = LHSI->getType();
// We can fold this as long as we can't shift unknown bits
// into the mask. This can only happen with signed shift
// rights, as they sign-extend.
const Type *Ty = Shift->getType();
if (Shift->getOpcode() != Instruction::Shr ||
Shift->getType()->isUnsigned() ||
// To test for the bad case of the signed shr, see if any
// of the bits shifted in could be tested after the mask.
ConstantExpr::getAnd(ConstantExpr::getShl(ConstantInt::getAllOnesValue(Ty), ConstantUInt::get(Type::UByteTy, Ty->getPrimitiveSize()*8-ShAmt->getValue())), AndCST)->isNullValue()) {
unsigned ShiftOp = Shift->getOpcode() == Instruction::Shl
? Instruction::Shr : Instruction::Shl;
I.setOperand(1, ConstantExpr::get(ShiftOp, CI, ShAmt));
LHSI->setOperand(1,ConstantExpr::get(ShiftOp,AndCST,ShAmt));
LHSI->setOperand(0, Shift->getOperand(0));
WorkList.push_back(Shift); // Shift is probably dead.
AddUsesToWorkList(I);
return &I;
}
}
// We can fold this as long as we can't shift unknown bits
// into the mask. This can only happen with signed shift
// rights, as they sign-extend.
if (ShAmt) {
bool CanFold = Shift->getOpcode() != Instruction::Shr ||
Shift->getType()->isUnsigned();
if (!CanFold &&
// To test for the bad case of the signed shr, see if any
// of the bits shifted in could be tested after the mask.
ConstantExpr::getAnd(ConstantExpr::getShl(ConstantInt::getAllOnesValue(Ty), ConstantUInt::get(Type::UByteTy, Ty->getPrimitiveSize()*8-ShAmt->getValue())), AndCST)->isNullValue()) {
CanFold = true;
}
if (CanFold) {
unsigned ShiftOp = Shift->getOpcode() == Instruction::Shl
? Instruction::Shr : Instruction::Shl;
I.setOperand(1, ConstantExpr::get(ShiftOp, CI, ShAmt));
LHSI->setOperand(1,ConstantExpr::get(ShiftOp,AndCST,ShAmt));
LHSI->setOperand(0, Shift->getOperand(0));
WorkList.push_back(Shift); // Shift is dead.
AddUsesToWorkList(I);
return &I;
}
}
}
break;
case Instruction::Div:
@ -1970,7 +1974,7 @@ static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
// It is legal to eliminate the instruction if casting A->B->A if the sizes
// are identical and the bits don't get reinterpreted (for example
// int->float->int would not be allowed)
// int->float->int would not be allowed).
if (SrcTy == DstTy && SrcTy->isLosslesslyConvertibleTo(MidTy))
return true;
@ -1994,9 +1998,9 @@ static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
// First cast is a truncate
1, 1, 4, 4, // trunc->extend is not safe to eliminate
// First cast is a sign ext
2, 5, 2, 4, // signext->trunc always ok, signext->zeroext never ok
2, 5, 2, 4, // signext->zeroext never ok
// First cast is a zero ext
3, 5, 3, 3, // zeroext->trunc always ok
3, 5, 3, 3,
};
unsigned Result = CastResult[FirstCast*4+SecondCast];
@ -2012,8 +2016,14 @@ static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
case 4:
return false; // Not possible to eliminate this here.
case 5:
// Sign or zero extend followed by truncate is always ok
return true;
// Sign or zero extend followed by truncate is always ok if the result
// is a truncate or noop.
CastType ResultCast = getCastType(SrcTy, DstTy);
if (ResultCast == Noop || ResultCast == Truncate)
return true;
// Otherwise we are still growing the value, we are only safe if the
// result will match the sign/zeroextendness of the result.
return ResultCast == FirstCast;
}
}
return false;