Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -7006,6 +7006,17 @@ OptForSize, Cost, Depth)) return DAG.getNode(ISD::FP_ROUND, DL, VT, NegV, Op.getOperand(1)); break; + case ISD::SELECT: { + Cost = NegatibleCost::Cheaper; + SDValue LHS = Op.getOperand(1); + SDValue RHS = Op.getOperand(2); + if (LHS.getOpcode() == ISD::FNEG && RHS.getOpcode() == ISD::FNEG) { + return DAG.getNode(ISD::SELECT, DL, VT, Op.getOperand(0), + LHS.getOperand(0), RHS.getOperand(0)); + } + + break; + } } return SDValue(); Index: llvm/test/CodeGen/ARM/fadd-select-fneg-combine.ll =================================================================== --- llvm/test/CodeGen/ARM/fadd-select-fneg-combine.ll +++ llvm/test/CodeGen/ARM/fadd-select-fneg-combine.ll @@ -4,14 +4,12 @@ define float @fadd_select_fneg_fneg_f32(i32 %arg0, float %x, float %y, float %z) { ; CHECK-LABEL: fadd_select_fneg_fneg_f32: ; CHECK: @ %bb.0: -; CHECK-NEXT: eor r2, r2, #-2147483648 -; CHECK-NEXT: eor r1, r1, #-2147483648 ; CHECK-NEXT: vmov s0, r3 ; CHECK-NEXT: cmp r0, #0 ; CHECK-NEXT: vmov s2, r2 ; CHECK-NEXT: vmov s4, r1 ; CHECK-NEXT: vseleq.f32 s2, s4, s2 -; CHECK-NEXT: vadd.f32 s0, s2, s0 +; CHECK-NEXT: vsub.f32 s0, s0, s2 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: mov pc, lr %cmp = icmp eq i32 %arg0, 0 @@ -28,11 +26,9 @@ ; CHECK-NEXT: vmov.f16 s0, r2 ; CHECK-NEXT: cmp r0, #0 ; CHECK-NEXT: vmov.f16 s2, r1 -; CHECK-NEXT: vneg.f16 s0, s0 -; CHECK-NEXT: vneg.f16 s2, s2 ; CHECK-NEXT: vseleq.f16 s0, s2, s0 ; CHECK-NEXT: vmov.f16 s2, r3 -; CHECK-NEXT: vadd.f16 s0, s0, s2 +; CHECK-NEXT: vsub.f16 s0, s2, s0 ; CHECK-NEXT: vmov r0, s0 ; CHECK-NEXT: mov pc, lr %cmp = icmp eq i32 %arg0, 0