mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Allow folding several instructions into casts, which can simplify a lot
of codes. For example, short kernel (short t1) { t1 >>= 8; t1 <<= 8; return t1; } became: short %kernel(short %t1.1) { %tmp.3 = shr short %t1.1, ubyte 8 ; <short> [#uses=1] %tmp.5 = cast short %tmp.3 to int ; <int> [#uses=1] %tmp.7 = shl int %tmp.5, ubyte 8 ; <int> [#uses=1] %tmp.8 = cast int %tmp.7 to short ; <short> [#uses=1] ret short %tmp.8 } before, now it becomes: short %kernel(short %t1.1) { %tmp.3 = shr short %t1.1, ubyte 8 ; <short> [#uses=1] %tmp.8 = shl short %tmp.3, ubyte 8 ; <short> [#uses=1] ret short %tmp.8 } which will become: short %kernel(short %t1.1) { %tmp.3 = and short %t1.1, 0xFF00 ret short %tmp.3 } This implements cast-set.ll:test4 and test5 llvm-svn: 7290
This commit is contained in:
parent
9eb9ec67f7
commit
785e8453f0
@ -121,6 +121,13 @@ namespace {
|
||||
return &I;
|
||||
}
|
||||
|
||||
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
||||
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
||||
/// casts that are known to not do anything...
|
||||
///
|
||||
Value *InsertOperandCastBefore(Value *V, const Type *DestTy,
|
||||
Instruction *InsertBefore);
|
||||
|
||||
// SimplifyCommutative - This performs a few simplifications for commutative
|
||||
// operators...
|
||||
bool SimplifyCommutative(BinaryOperator &I);
|
||||
@ -307,6 +314,10 @@ static bool isSignBit(ConstantInt *CI) {
|
||||
return (CI->getRawValue() & ~(-1LL << NumBits)) == (1ULL << (NumBits-1));
|
||||
}
|
||||
|
||||
static unsigned getTypeSizeInBits(const Type *Ty) {
|
||||
return Ty == Type::BoolTy ? 1 : Ty->getPrimitiveSize()*8;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
@ -935,12 +946,8 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
|
||||
// isEliminableCastOfCast - Return true if it is valid to eliminate the CI
|
||||
// instruction.
|
||||
//
|
||||
static inline bool isEliminableCastOfCast(const CastInst &CI,
|
||||
const CastInst *CSrc) {
|
||||
assert(CI.getOperand(0) == CSrc);
|
||||
const Type *SrcTy = CSrc->getOperand(0)->getType();
|
||||
const Type *MidTy = CSrc->getType();
|
||||
const Type *DstTy = CI.getType();
|
||||
static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
|
||||
const Type *DstTy) {
|
||||
|
||||
// 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
|
||||
@ -1005,6 +1012,28 @@ static inline bool isEliminableCastOfCast(const CastInst &CI,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ValueRequiresCast(const Value *V, const Type *Ty) {
|
||||
if (V->getType() == Ty || isa<Constant>(V)) return false;
|
||||
if (const CastInst *CI = dyn_cast<CastInst>(V))
|
||||
if (isEliminableCastOfCast(CI->getOperand(0)->getType(), CI->getType(), Ty))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
||||
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
||||
/// casts that are known to not do anything...
|
||||
///
|
||||
Value *InstCombiner::InsertOperandCastBefore(Value *V, const Type *DestTy,
|
||||
Instruction *InsertBefore) {
|
||||
if (V->getType() == DestTy) return V;
|
||||
if (Constant *C = dyn_cast<Constant>(V))
|
||||
return ConstantExpr::getCast(C, DestTy);
|
||||
|
||||
CastInst *CI = new CastInst(V, DestTy, V->getName());
|
||||
InsertNewInstBefore(CI, *InsertBefore);
|
||||
return CI;
|
||||
}
|
||||
|
||||
// CastInst simplification
|
||||
//
|
||||
@ -1020,7 +1049,8 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||
// one!
|
||||
//
|
||||
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) {
|
||||
if (isEliminableCastOfCast(CI, CSrc)) {
|
||||
if (isEliminableCastOfCast(CSrc->getOperand(0)->getType(),
|
||||
CSrc->getType(), CI.getType())) {
|
||||
// This instruction now refers directly to the cast's src operand. This
|
||||
// has a good chance of making CSrc dead.
|
||||
CI.setOperand(0, CSrc->getOperand(0));
|
||||
@ -1119,6 +1149,53 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
|
||||
}
|
||||
}
|
||||
|
||||
// If the source value is an instruction with only this use, we can attempt to
|
||||
// propagate the cast into the instruction. Also, only handle integral types
|
||||
// for now.
|
||||
if (Instruction *SrcI = dyn_cast<Instruction>(Src))
|
||||
if (SrcI->use_size() == 1 && Src->getType()->isIntegral() &&
|
||||
CI.getType()->isInteger()) { // Don't mess with casts to bool here
|
||||
const Type *DestTy = CI.getType();
|
||||
unsigned SrcBitSize = getTypeSizeInBits(Src->getType());
|
||||
unsigned DestBitSize = getTypeSizeInBits(DestTy);
|
||||
|
||||
Value *Op0 = SrcI->getNumOperands() > 0 ? SrcI->getOperand(0) : 0;
|
||||
Value *Op1 = SrcI->getNumOperands() > 1 ? SrcI->getOperand(1) : 0;
|
||||
|
||||
switch (SrcI->getOpcode()) {
|
||||
case Instruction::Add:
|
||||
case Instruction::Mul:
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
// If we are discarding information, or just changing the sign, rewrite.
|
||||
if (DestBitSize <= SrcBitSize && DestBitSize != 1) {
|
||||
// Don't insert two casts if they cannot be eliminated. We allow two
|
||||
// casts to be inserted if the sizes are the same. This could only be
|
||||
// converting signedness, which is a noop.
|
||||
if (DestBitSize == SrcBitSize || !ValueRequiresCast(Op1, DestTy) ||
|
||||
!ValueRequiresCast(Op0, DestTy)) {
|
||||
Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
|
||||
Value *Op1c = InsertOperandCastBefore(Op1, DestTy, SrcI);
|
||||
return BinaryOperator::create(cast<BinaryOperator>(SrcI)
|
||||
->getOpcode(), Op0c, Op1c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::Shl:
|
||||
// Allow changing the sign of the source operand. Do not allow changing
|
||||
// the size of the shift, UNLESS the shift amount is a constant. We
|
||||
// mush not change variable sized shifts to a smaller size, because it
|
||||
// is undefined to shift more bits out than exist in the value.
|
||||
if (DestBitSize == SrcBitSize ||
|
||||
(DestBitSize < SrcBitSize && isa<Constant>(Op1))) {
|
||||
Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
|
||||
return new ShiftInst(Instruction::Shl, Op0c, Op1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user