[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Jul 24 12:36:10 PDT 2003
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.106 -> 1.107
---
Log message:
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
---
Diffs of the changes:
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.106 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.107
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.106 Wed Jul 23 16:41:57 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jul 24 12:35:25 2003
@@ -121,6 +121,13 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
}
}
+ // 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;
}
More information about the llvm-commits
mailing list