diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4136,6 +4136,21 @@ m_Neg(m_Intrinsic(m_Specific(CmpLHS)))) && match(FalseVal, m_Intrinsic(m_Specific(CmpLHS)))) return FalseVal; + + // X == 0 ? 0 : X * X2 --> X * freeze(X2) + // X2 == 0 ? 0 : X * X2 --> freeze(X) * X2 + Value *X2; + if (match(TrueVal, m_Zero()) && + match(FalseVal, m_Mul(m_Value(X), m_Value(X2)))) { + unsigned OperandIndex = 0; + if (X == CmpLHS) { + X = X2; + OperandIndex = 1; + } + auto *I = cast(FalseVal); + I->setOperand(OperandIndex, new FreezeInst(X, X->getName() + ".fr", I)); + return FalseVal; + } } // Check for other compares that behave like bit test. diff --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll --- a/llvm/test/Transforms/InstSimplify/select.ll +++ b/llvm/test/Transforms/InstSimplify/select.ll @@ -1066,3 +1066,27 @@ %v = select <2 x i1> %cond, <2 x i32> %x, <2 x i32> poison ret <2 x i32> %v } + +define i32 @mul_by_zero(i32 %x, i32 %y) { +; CHECK-LABEL: @mul_by_zero( +; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze i32 [[Y:%.*]] +; CHECK-NEXT: [[M:%.*]] = mul i32 [[X:%.*]], [[Y_FROZEN]] +; CHECK-NEXT: ret i32 [[M]] +; + %c = icmp eq i32 %x, 0 + %m = mul i32 %x, %y + %r = select i1 %c, i32 0, i32 %m + ret i32 %r +} + +define i32 @mul_by_zero1(i32 %x, i32 %y) { +; CHECK-LABEL: @mul_by_zero1( +; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X:%.*]] +; CHECK-NEXT: [[M:%.*]] = mul i32 [[X_FROZEN]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[M]] +; + %c = icmp eq i32 %y, 0 + %m = mul i32 %x, %y + %r = select i1 %c, i32 0, i32 %m + ret i32 %r +}