CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
NumCastsRemoved);
+ case Instruction::UDiv:
+ case Instruction::URem: {
+ // UDiv and URem can be truncated if all the truncated bits are zero.
+ uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits();
+ uint32_t BitWidth = Ty->getScalarSizeInBits();
+ if (BitWidth < OrigBitWidth) {
+ APInt Mask = APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth);
+ if (MaskedValueIsZero(I->getOperand(0), Mask) &&
+ MaskedValueIsZero(I->getOperand(1), Mask)) {
+ return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
+ NumCastsRemoved) &&
+ CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
+ NumCastsRemoved);
+ }
+ }
+ break;
+ }
case Instruction::Shl:
// If we are truncating the result of this SHL, and if it's a shift of a
// constant amount, we can always perform a SHL in a smaller type.
case Instruction::Xor:
case Instruction::AShr:
case Instruction::LShr:
- case Instruction::Shl: {
+ case Instruction::Shl:
+ case Instruction::UDiv:
+ case Instruction::URem: {
Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned);
Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned);
Res = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
--- /dev/null
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep zext
+; PR4548
+
+define i8 @udiv_i8(i8 %a, i8 %b) nounwind {
+ %conv = zext i8 %a to i32
+ %conv2 = zext i8 %b to i32
+ %div = udiv i32 %conv, %conv2
+ %conv3 = trunc i32 %div to i8
+ ret i8 %conv3
+}
+
+define i8 @urem_i8(i8 %a, i8 %b) nounwind {
+ %conv = zext i8 %a to i32
+ %conv2 = zext i8 %b to i32
+ %div = urem i32 %conv, %conv2
+ %conv3 = trunc i32 %div to i8
+ ret i8 %conv3
+}
+