aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-07-24 17:35:25 +0000
committerChris Lattner <sabre@nondot.org>2003-07-24 17:35:25 +0000
commit24c8e38455539103a3f5e48564fce8acb62550f6 (patch)
treee33d31305c2bd9d72c536cdbfe5b332cd3cbc33d /lib/Transforms
parent8baa92ef0bc7a412c166a5d2ca0c7d31a2f0bd9a (diff)
downloadexternal_llvm-24c8e38455539103a3f5e48564fce8acb62550f6.zip
external_llvm-24c8e38455539103a3f5e48564fce8acb62550f6.tar.gz
external_llvm-24c8e38455539103a3f5e48564fce8acb62550f6.tar.bz2
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7290 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp91
1 files changed, 84 insertions, 7 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 6d55025..0db6dcf 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -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;
}