}
}
- // fold (fsub A, (fneg B)) -> (fadd A, B)
- if (isNegatibleForFree(N1, LegalOperations, TLI, &Options))
- return DAG.getNode(ISD::FADD, DL, VT, N0,
- GetNegatedExpression(N1, DAG, LegalOperations), Flags);
-
- if (Options.UnsafeFPMath && N1.getOpcode() == ISD::FADD) {
+ if ((Options.UnsafeFPMath ||
+ (Flags.hasAllowReassociation() && Flags.hasNoSignedZeros()))
+ && N1.getOpcode() == ISD::FADD) {
// X - (X + Y) -> -Y
if (N0 == N1->getOperand(0))
- return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(1));
+ return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(1), Flags);
// X - (Y + X) -> -Y
if (N0 == N1->getOperand(1))
- return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(0));
+ return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(0), Flags);
}
+ // fold (fsub A, (fneg B)) -> (fadd A, B)
+ if (isNegatibleForFree(N1, LegalOperations, TLI, &Options))
+ return DAG.getNode(ISD::FADD, DL, VT, N0,
+ GetNegatedExpression(N1, DAG, LegalOperations), Flags);
+
// FSUB -> FMA combines:
if (SDValue Fused = visitFSUBForFMACombine(N)) {
AddToWorklist(Fused.getNode());
}
define float @fsub_neg_y(float %x, float %y) {
-; STRICT-LABEL: fsub_neg_y:
-; STRICT: # %bb.0:
-; STRICT-NEXT: mulss {{.*}}(%rip), %xmm0
-; STRICT-NEXT: addss %xmm1, %xmm0
-; STRICT-NEXT: subss %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_neg_y:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: mulss {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: subss %xmm1, %xmm0
-; UNSAFE-NEXT: addss %xmm1, %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_neg_y:
+; ANY: # %bb.0:
+; ANY-NEXT: mulss {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%mul = fmul float %x, 5.0
%add = fadd float %mul, %y
%r = fsub nsz reassoc float %y, %add
}
define float @fsub_neg_y_commute(float %x, float %y) {
-; STRICT-LABEL: fsub_neg_y_commute:
-; STRICT: # %bb.0:
-; STRICT-NEXT: mulss {{.*}}(%rip), %xmm0
-; STRICT-NEXT: addss %xmm1, %xmm0
-; STRICT-NEXT: subss %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_neg_y_commute:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: mulss {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: subss %xmm1, %xmm0
-; UNSAFE-NEXT: addss %xmm1, %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_neg_y_commute:
+; ANY: # %bb.0:
+; ANY-NEXT: mulss {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%mul = fmul float %x, 5.0
%add = fadd float %y, %mul
%r = fsub nsz reassoc float %y, %add
; Y - (X + Y) --> -X
define float @fsub_fadd_common_op_fneg(float %x, float %y) {
-; STRICT-LABEL: fsub_fadd_common_op_fneg:
-; STRICT: # %bb.0:
-; STRICT-NEXT: addss %xmm1, %xmm0
-; STRICT-NEXT: subss %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_fadd_common_op_fneg:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_fadd_common_op_fneg:
+; ANY: # %bb.0:
+; ANY-NEXT: xorps {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%a = fadd float %x, %y
%r = fsub reassoc nsz float %y, %a
ret float %r
; Y - (X + Y) --> -X
define <4 x float> @fsub_fadd_common_op_fneg_vec(<4 x float> %x, <4 x float> %y) {
-; STRICT-LABEL: fsub_fadd_common_op_fneg_vec:
-; STRICT: # %bb.0:
-; STRICT-NEXT: addps %xmm1, %xmm0
-; STRICT-NEXT: subps %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_fadd_common_op_fneg_vec:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_fadd_common_op_fneg_vec:
+; ANY: # %bb.0:
+; ANY-NEXT: xorps {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%a = fadd <4 x float> %x, %y
%r = fsub nsz reassoc <4 x float> %y, %a
ret <4 x float> %r
; Commute operands of the 'add'.
define float @fsub_fadd_common_op_fneg_commute(float %x, float %y) {
-; STRICT-LABEL: fsub_fadd_common_op_fneg_commute:
-; STRICT: # %bb.0:
-; STRICT-NEXT: addss %xmm1, %xmm0
-; STRICT-NEXT: subss %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_fadd_common_op_fneg_commute:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_fadd_common_op_fneg_commute:
+; ANY: # %bb.0:
+; ANY-NEXT: xorps {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%a = fadd float %y, %x
%r = fsub reassoc nsz float %y, %a
ret float %r
; Y - (Y + X) --> -X
define <4 x float> @fsub_fadd_common_op_fneg_commute_vec(<4 x float> %x, <4 x float> %y) {
-; STRICT-LABEL: fsub_fadd_common_op_fneg_commute_vec:
-; STRICT: # %bb.0:
-; STRICT-NEXT: addps %xmm1, %xmm0
-; STRICT-NEXT: subps %xmm0, %xmm1
-; STRICT-NEXT: movaps %xmm1, %xmm0
-; STRICT-NEXT: retq
-;
-; UNSAFE-LABEL: fsub_fadd_common_op_fneg_commute_vec:
-; UNSAFE: # %bb.0:
-; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0
-; UNSAFE-NEXT: retq
+; ANY-LABEL: fsub_fadd_common_op_fneg_commute_vec:
+; ANY: # %bb.0:
+; ANY-NEXT: xorps {{.*}}(%rip), %xmm0
+; ANY-NEXT: retq
%a = fadd <4 x float> %y, %x
%r = fsub reassoc nsz <4 x float> %y, %a
ret <4 x float> %r