Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3737,6 +3737,11 @@ const APInt &CVal = CI->getValue(); if (CVal.getBitWidth() - CVal.countLeadingZeros() > MulWidth) return nullptr; + } else { + // In this case we could have the operand of the binary operation + // being defined in another block, and performing the replacement + // could break the dominance relation. + return nullptr; } } else { // Other uses prohibit this transformation. @@ -3856,18 +3861,17 @@ } else if (BinaryOperator *BO = dyn_cast(U)) { assert(BO->getOpcode() == Instruction::And); // Replace (mul & mask) --> zext (mul.with.overflow & short_mask) - Value *ShortMask = - Builder.CreateTrunc(BO->getOperand(1), Builder.getIntNTy(MulWidth)); + ConstantInt *CI = cast(BO->getOperand(1)); + APInt ShortMask = CI->getValue().trunc(MulWidth); Value *ShortAnd = Builder.CreateAnd(Mul, ShortMask); - Value *Zext = Builder.CreateZExt(ShortAnd, BO->getType()); - if (auto *ZextI = dyn_cast(Zext)) - IC.Worklist.Add(ZextI); + Instruction *Zext = + cast(Builder.CreateZExt(ShortAnd, BO->getType())); + IC.Worklist.Add(Zext); IC.replaceInstUsesWith(*BO, Zext); } else { llvm_unreachable("Unexpected Binary operation"); } - if (auto *UI = dyn_cast(U)) - IC.Worklist.Add(UI); + IC.Worklist.Add(cast(U)); } } if (isa(OtherVal)) Index: test/Transforms/InstCombine/2017-07-07-UMul-ZExt.ll =================================================================== --- test/Transforms/InstCombine/2017-07-07-UMul-ZExt.ll +++ test/Transforms/InstCombine/2017-07-07-UMul-ZExt.ll @@ -1,7 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s -; CHECK: llvm.umul.with.overflow define i32 @sterix(i32, i8, i64) { +; CHECK-LABEL: @sterix( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i32 [[TMP0:%.*]] to i64 +; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[TMP1:%.*]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[CONV1]], 1945964878 +; CHECK-NEXT: [[SH_PROM:%.*]] = trunc i64 [[TMP2:%.*]] to i32 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[MUL]], [[SH_PROM]] +; CHECK-NEXT: [[CONV2:%.*]] = zext i32 [[SHR]] to i64 +; CHECK-NEXT: [[MUL3:%.*]] = mul nuw nsw i64 [[CONV]], [[CONV2]] +; CHECK-NEXT: [[CONV6:%.*]] = and i64 [[MUL3]], 4294967295 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[CONV6]], [[MUL3]] +; CHECK-NEXT: br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]] +; CHECK: lor.rhs: +; CHECK-NEXT: [[AND:%.*]] = and i64 [[MUL3]], [[TMP2]] +; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[AND]] to i32 +; CHECK-NEXT: [[TOBOOL7:%.*]] = icmp eq i32 [[CONV4]], 0 +; CHECK-NEXT: [[PHITMP:%.*]] = zext i1 [[TOBOOL7]] to i32 +; CHECK-NEXT: br label [[LOR_END]] +; CHECK: lor.end: +; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHITMP]], [[LOR_RHS]] ] +; CHECK-NEXT: ret i32 [[TMP3]] +; entry: %conv = zext i32 %0 to i64 %conv1 = sext i8 %1 to i32 Index: test/Transforms/InstCombine/pr33765.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/pr33765.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S %s -instcombine | FileCheck %s + +@glob = external global i16 + +define void @patatino(i8 %beth) { +; CHECK-LABEL: @patatino( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[BETH:%.*]] to i32 +; CHECK-NEXT: br i1 undef, label [[IF_THEN9:%.*]], label [[IF_THEN9]] +; CHECK: if.then9: +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV]] +; CHECK-NEXT: [[TINKY:%.*]] = load i16, i16* @glob, align 2 +; CHECK-NEXT: [[CONV131:%.*]] = zext i16 [[TINKY]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[MUL]], [[CONV131]] +; CHECK-NEXT: [[CONV14:%.*]] = trunc i32 [[AND]] to i16 +; CHECK-NEXT: store i16 [[CONV14]], i16* @glob, align 2 +; CHECK-NEXT: ret void +; + %conv = zext i8 %beth to i32 + %mul = mul nuw nsw i32 %conv, %conv + %conv3 = and i32 %mul, 255 + %tobool8 = icmp ne i32 %mul, %conv3 + br i1 %tobool8, label %if.then9, label %if.then9 + +if.then9: + %tinky = load i16, i16* @glob + %conv13 = sext i16 %tinky to i32 + %and = and i32 %mul, %conv13 + %conv14 = trunc i32 %and to i16 + store i16 %conv14, i16* @glob + ret void +}