Index: lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- lib/Transforms/Scalar/Reassociate.cpp +++ lib/Transforms/Scalar/Reassociate.cpp @@ -183,6 +183,8 @@ Value *OptimizeMul(BinaryOperator *I, SmallVectorImpl &Ops); Value *RemoveFactorFromExpression(Value *V, Value *Factor); void EraseInst(Instruction *I); + void RecursivelyEraseDeadInsts(Instruction *, + SetVector> &); void OptimizeInst(Instruction *I); Instruction *canonicalizeNegConstExpr(Instruction *I); }; @@ -1926,6 +1928,22 @@ return nullptr; } +// Remove dead instructions and if any operands are trivially dead add them to +// Insts so they will be removed as well. +void Reassociate::RecursivelyEraseDeadInsts( + Instruction *I, SetVector> &Insts) { + assert(isInstructionTriviallyDead(I) && "Trivially dead instructions only!"); + SmallVector Ops(I->op_begin(), I->op_end()); + ValueRankMap.erase(I); + Insts.remove(I); + RedoInsts.remove(I); + I->eraseFromParent(); + for (auto Op : Ops) + if (Instruction *OpInst = dyn_cast(Op)) + if (OpInst->use_empty()) + Insts.insert(OpInst); +} + /// Zap the given instruction, adding interesting operands to the work list. void Reassociate::EraseInst(Instruction *I) { assert(isInstructionTriviallyDead(I) && "Trivially dead instructions only!"); @@ -2255,7 +2273,21 @@ ++II; } - // If this produced extra instructions to optimize, handle them now. + // Make a copy of all the instructions to be redone so we can remove dead + // instructions. + SetVector> ToRedo(RedoInsts); + // Iterate over all instructions to be reevaluated and remove trivially dead + // instructions. If any operand of the trivially dead instruction becomes + // dead mark it for deletion as well. Continue this process until all + // trivially dead instructions have been removed. + while (!ToRedo.empty()) { + Instruction *I = ToRedo.pop_back_val(); + if (isInstructionTriviallyDead(I)) + RecursivelyEraseDeadInsts(I, ToRedo); + } + + // Now that we have removed dead instructions, we can reoptimize the + // remaining instructions. while (!RedoInsts.empty()) { Instruction *I = RedoInsts.pop_back_val(); if (isInstructionTriviallyDead(I)) Index: test/Transforms/Reassociate/factorize-again.ll =================================================================== --- /dev/null +++ test/Transforms/Reassociate/factorize-again.ll @@ -0,0 +1,38 @@ +; RUN: opt -S -reassociate < %s | FileCheck %s +; ModuleID = 'bugpoint-reduced-simplified.bc' + +; CHECK: main +; CHECK: %2 = fsub +; CHECK: %3 = fsub +; CHECK: fadd fast float %3, %2 +define void @main(float, float) { +wrapper_entry: + %2 = fsub float undef, %0 + %3 = fsub float undef, %1 + %4 = call float @llvm.rsqrt.f32(float undef) + %5 = fmul fast float undef, %4 + %6 = fmul fast float %2, %4 + %7 = fmul fast float %3, %4 + %8 = fmul fast float %5, undef + %9 = fmul fast float %6, undef + %10 = fmul fast float %7, undef + %11 = fadd fast float %8, %9 + %12 = fadd fast float %11, %10 + %13 = call float @foo2(float %12, float 0.000000e+00) + %mul36 = fmul fast float %13, 1.500000e+00 + call void @foo1(i32 4, float %mul36) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @foo1(i32, float) #0 + +; Function Attrs: nounwind readnone +declare float @foo2(float, float) #1 + +; Function Attrs: nounwind readnone +declare float @llvm.rsqrt.f32(float) #1 + +attributes #0 = { argmemonly nounwind } +attributes #1 = { nounwind readnone } + Index: test/Transforms/Reassociate/secondary.ll =================================================================== --- test/Transforms/Reassociate/secondary.ll +++ test/Transforms/Reassociate/secondary.ll @@ -6,7 +6,7 @@ ; CHECK: define ; CHECK-NOT: undef -; CHECK: %factor = mul i32 %tmp3.neg, 2 +; CHECK: %factor = mul i32 %tmp3, -2 ; CHECK-NOT: undef ; CHECK: }