diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5987,6 +5987,11 @@ SDLoc DL(Op); + // Because getNegatedExpression can delete nodes we need a handle to keep + // temporary nodes alive in case the recursion manages to create an identical + // node. + std::list Handles; + switch (Opcode) { case ISD::ConstantFP: { // Don't invert constant FP values after legalization unless the target says @@ -6055,11 +6060,18 @@ NegatibleCost CostX = NegatibleCost::Expensive; SDValue NegX = getNegatedExpression(X, DAG, LegalOps, OptForSize, CostX, Depth); + // Prevent this node from being deleted by the next call. + if (NegX) + Handles.emplace_back(NegX); + // fold (fneg (fadd X, Y)) -> (fsub (fneg Y), X) NegatibleCost CostY = NegatibleCost::Expensive; SDValue NegY = getNegatedExpression(Y, DAG, LegalOps, OptForSize, CostY, Depth); + // We're done with the handles. + Handles.clear(); + // Negate the X if its cost is less or equal than Y. if (NegX && (CostX <= CostY)) { Cost = CostX; @@ -6104,11 +6116,18 @@ NegatibleCost CostX = NegatibleCost::Expensive; SDValue NegX = getNegatedExpression(X, DAG, LegalOps, OptForSize, CostX, Depth); + // Prevent this node from being deleted by the next call. + if (NegX) + Handles.emplace_back(NegX); + // fold (fneg (fmul X, Y)) -> (fmul X, (fneg Y)) NegatibleCost CostY = NegatibleCost::Expensive; SDValue NegY = getNegatedExpression(Y, DAG, LegalOps, OptForSize, CostY, Depth); + // We're done with the handles. + Handles.clear(); + // Negate the X if its cost is less or equal than Y. if (NegX && (CostX <= CostY)) { Cost = CostX; @@ -6146,15 +6165,25 @@ if (!NegZ) break; + // Prevent this node from being deleted by the next two calls. + Handles.emplace_back(NegZ); + // fold (fneg (fma X, Y, Z)) -> (fma (fneg X), Y, (fneg Z)) NegatibleCost CostX = NegatibleCost::Expensive; SDValue NegX = getNegatedExpression(X, DAG, LegalOps, OptForSize, CostX, Depth); + // Prevent this node from being deleted by the next call. + if (NegX) + Handles.emplace_back(NegX); + // fold (fneg (fma X, Y, Z)) -> (fma X, (fneg Y), (fneg Z)) NegatibleCost CostY = NegatibleCost::Expensive; SDValue NegY = getNegatedExpression(Y, DAG, LegalOps, OptForSize, CostY, Depth); + // We're done with the handles. + Handles.clear(); + // Negate the X if its cost is less or equal than Y. if (NegX && (CostX <= CostY)) { Cost = std::min(CostX, CostZ); diff --git a/llvm/test/CodeGen/X86/pr49393.ll b/llvm/test/CodeGen/X86/pr49393.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr49393.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +define void @f() { +; CHECK-LABEL: f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: .p2align 4, 0x90 +; CHECK-NEXT: .LBB0_1: # %for.cond +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: imull %eax, %eax +; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; CHECK-NEXT: movapd %xmm0, %xmm1 +; CHECK-NEXT: mulsd %xmm0, %xmm1 +; CHECK-NEXT: subsd %xmm0, %xmm1 +; CHECK-NEXT: cwtl +; CHECK-NEXT: xorps %xmm2, %xmm2 +; CHECK-NEXT: cvtsi2sd %eax, %xmm2 +; CHECK-NEXT: mulsd %xmm0, %xmm2 +; CHECK-NEXT: mulsd %xmm0, %xmm2 +; CHECK-NEXT: movapd %xmm2, %xmm3 +; CHECK-NEXT: mulsd %xmm1, %xmm3 +; CHECK-NEXT: mulsd %xmm0, %xmm2 +; CHECK-NEXT: subsd %xmm3, %xmm1 +; CHECK-NEXT: addsd %xmm2, %xmm1 +; CHECK-NEXT: cvttsd2si %xmm1, %eax +; CHECK-NEXT: jmp .LBB0_1 +entry: + br label %for.cond + +for.cond: ; preds = %for.cond, %entry + %b.0 = phi i16 [ 0, %entry ], [ %conv77, %for.cond ] + %mul18 = mul i16 %b.0, %b.0 + %arrayidx.real = load double, double* undef, align 1 + %arrayidx.imag = load double, double* undef, align 1 + %mul_ac = fmul fast double %arrayidx.real, %arrayidx.real + %0 = fadd fast double 0.000000e+00, %arrayidx.real + %sub.r = fsub fast double %mul_ac, %0 + %sub.i = fsub fast double 0.000000e+00, %arrayidx.imag + %conv28 = sitofp i16 %mul18 to double + %mul_bc32 = fmul fast double %arrayidx.imag, %conv28 + %mul_bd46 = fmul fast double %mul_bc32, %arrayidx.imag + %mul_r49 = fsub fast double 0.000000e+00, %mul_bd46 + %mul_ac59 = fmul fast double %mul_r49, %sub.r + %mul_bc48 = fmul fast double %mul_bc32, %arrayidx.real + %mul_i50 = fadd fast double 0.000000e+00, %mul_bc48 + %1 = fmul fast double %mul_i50, %sub.i + %.neg = fneg fast double %0 + %.neg19 = fmul fast double %1, -1.000000e+00 + %.neg20 = fadd fast double %.neg, %mul_ac + %2 = fadd fast double %.neg20, %mul_ac59 + %sub.r75 = fadd fast double %2, %.neg19 + %conv77 = fptosi double %sub.r75 to i16 + br label %for.cond +}