diff options
author | Chris Lattner <sabre@nondot.org> | 2003-07-24 17:35:25 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2003-07-24 17:35:25 +0000 |
commit | 24c8e38455539103a3f5e48564fce8acb62550f6 (patch) | |
tree | e33d31305c2bd9d72c536cdbfe5b332cd3cbc33d /lib/Transforms | |
parent | 8baa92ef0bc7a412c166a5d2ca0c7d31a2f0bd9a (diff) | |
download | external_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.cpp | 91 |
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; } |