+ // 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;
+ }
+ }
+