From 24c8e38455539103a3f5e48564fce8acb62550f6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 24 Jul 2003 17:35:25 +0000 Subject: [PATCH] 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 ; [#uses=1] %tmp.5 = cast short %tmp.3 to int ; [#uses=1] %tmp.7 = shl int %tmp.5, ubyte 8 ; [#uses=1] %tmp.8 = cast int %tmp.7 to short ; [#uses=1] ret short %tmp.8 } before, now it becomes: short %kernel(short %t1.1) { %tmp.3 = shr short %t1.1, ubyte 8 ; [#uses=1] %tmp.8 = shl short %tmp.3, ubyte 8 ; [#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 --- .../Scalar/InstructionCombining.cpp | 91 +++++++++++++++++-- 1 file changed, 84 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 6d5502533a0..0db6dcfb527 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(V)) return false; + if (const CastInst *CI = dyn_cast(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(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(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(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(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(Op1))) { + Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI); + return new ShiftInst(Instruction::Shl, Op0c, Op1); + } + break; + } + } + return 0; } -- 2.34.1