[llvm] 3b80d02 - DAG: Look through fneg when trying to create unsafe minnum/maxnum
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 23 02:07:29 PST 2023
Author: Matt Arsenault
Date: 2023-01-23T06:07:22-04:00
New Revision: 3b80d02992892c34c5d0860efb764d8f11352dec
URL: https://github.com/llvm/llvm-project/commit/3b80d02992892c34c5d0860efb764d8f11352dec
DIFF: https://github.com/llvm/llvm-project/commit/3b80d02992892c34c5d0860efb764d8f11352dec.diff
LOG: DAG: Look through fneg when trying to create unsafe minnum/maxnum
This makes most sense for isFNegFree targets, but shouldn't make
things worse without it. This avoids AMDGPU test regressions in a
future patch.
For some reason APFloat::compareAbsoluteValue is private, so compute
the neg of the constants.
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 42f6221e402f..8c87fc4acd3a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10346,14 +10346,11 @@ static bool isLegalToCombineMinNumMaxNum(SelectionDAG &DAG, SDValue LHS,
DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS);
}
-/// Generate Min/Max node
-static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
- SDValue RHS, SDValue True, SDValue False,
- ISD::CondCode CC, const TargetLowering &TLI,
- SelectionDAG &DAG) {
- if (!(LHS == True && RHS == False) && !(LHS == False && RHS == True))
- return SDValue();
-
+static SDValue combineMinNumMaxNumImpl(const SDLoc &DL, EVT VT, SDValue LHS,
+ SDValue RHS, SDValue True, SDValue False,
+ ISD::CondCode CC,
+ const TargetLowering &TLI,
+ SelectionDAG &DAG) {
EVT TransformVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
switch (CC) {
case ISD::SETOLT:
@@ -10394,6 +10391,43 @@ static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
}
}
+/// Generate Min/Max node
+static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
+ SDValue RHS, SDValue True, SDValue False,
+ ISD::CondCode CC, const TargetLowering &TLI,
+ SelectionDAG &DAG) {
+ if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
+ return combineMinNumMaxNumImpl(DL, VT, LHS, RHS, True, False, CC, TLI, DAG);
+
+ // If we can't directly match this, try to see if we can pull an fneg out of
+ // the select.
+ if (True.getOpcode() != ISD::FNEG)
+ return SDValue();
+
+ ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
+ ConstantFPSDNode *CFalse = dyn_cast<ConstantFPSDNode>(False);
+ SDValue NegTrue = True.getOperand(0);
+
+ // Try to unfold an fneg from the select if we are comparing the negated
+ // constant.
+ //
+ // select (setcc x, K) (fneg x), -K -> fneg(minnum(x, K))
+ //
+ // TODO: Handle fabs
+ if (LHS == NegTrue && CFalse && CRHS) {
+ APFloat NegRHS = neg(CRHS->getValueAPF());
+ if (NegRHS == CFalse->getValueAPF()) {
+ SDValue Combined = combineMinNumMaxNumImpl(DL, VT, LHS, RHS, NegTrue,
+ False, CC, TLI, DAG);
+ if (Combined)
+ return DAG.getNode(ISD::FNEG, DL, VT, Combined);
+ return SDValue();
+ }
+ }
+
+ return SDValue();
+}
+
/// If a (v)select has a condition value that is a sign-bit test, try to smear
/// the condition operand sign-bit across the value width and use it as a mask.
static SDValue foldSelectOfConstantsUsingSra(SDNode *N, SelectionDAG &DAG) {
diff --git a/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll b/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
index d18295fc0132..23fdf0708470 100644
--- a/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
+++ b/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
@@ -6,12 +6,9 @@ define float @select_fneg_a_or_8_cmp_olt_a_neg8_f32(float %a, float %b) #0 {
; CHECK: @ %bb.0:
; CHECK-NEXT: vmov.f32 s0, #-8.000000e+00
; CHECK-NEXT: vmov s2, r0
-; CHECK-NEXT: vmov.f32 s4, #8.000000e+00
-; CHECK-NEXT: vneg.f32 s6, s2
-; CHECK-NEXT: vcmp.f32 s0, s2
-; CHECK-NEXT: vmrs APSR_nzcv, fpscr
-; CHECK-NEXT: vselgt.f32 s0, s6, s4
+; CHECK-NEXT: vminnm.f32 s0, s2, s0
; CHECK-NEXT: vmov r0, s0
+; CHECK-NEXT: eor r0, r0, #-2147483648
; CHECK-NEXT: mov pc, lr
%fneg.a = fneg nnan nsz float %a
%cmp.a = fcmp nnan nsz olt float %a, -8.0
@@ -22,13 +19,10 @@ define float @select_fneg_a_or_8_cmp_olt_a_neg8_f32(float %a, float %b) #0 {
define half @select_fneg_a_or_8_cmp_olt_a_neg8_f16(half %a, half %b) #0 {
; CHECK-LABEL: select_fneg_a_or_8_cmp_olt_a_neg8_f16:
; CHECK: @ %bb.0:
-; CHECK-NEXT: vmov.f16 s4, r0
; CHECK-NEXT: vmov.f16 s0, #-8.000000e+00
-; CHECK-NEXT: vcmp.f16 s0, s4
-; CHECK-NEXT: vmov.f16 s2, #8.000000e+00
-; CHECK-NEXT: vmrs APSR_nzcv, fpscr
-; CHECK-NEXT: vneg.f16 s6, s4
-; CHECK-NEXT: vselgt.f16 s0, s6, s2
+; CHECK-NEXT: vmov.f16 s2, r0
+; CHECK-NEXT: vminnm.f16 s0, s2, s0
+; CHECK-NEXT: vneg.f16 s0, s0
; CHECK-NEXT: vmov r0, s0
; CHECK-NEXT: mov pc, lr
%fneg.a = fneg nnan nsz half %a
@@ -42,12 +36,9 @@ define float @select_fneg_a_or_8_cmp_ogt_a_neg8_f32(float %a, float %b) #0 {
; CHECK: @ %bb.0:
; CHECK-NEXT: vmov.f32 s0, #-8.000000e+00
; CHECK-NEXT: vmov s2, r0
-; CHECK-NEXT: vmov.f32 s4, #8.000000e+00
-; CHECK-NEXT: vneg.f32 s6, s2
-; CHECK-NEXT: vcmp.f32 s2, s0
-; CHECK-NEXT: vmrs APSR_nzcv, fpscr
-; CHECK-NEXT: vselgt.f32 s0, s6, s4
+; CHECK-NEXT: vmaxnm.f32 s0, s2, s0
; CHECK-NEXT: vmov r0, s0
+; CHECK-NEXT: eor r0, r0, #-2147483648
; CHECK-NEXT: mov pc, lr
%fneg.a = fneg nnan nsz float %a
%cmp.a = fcmp nnan nsz ogt float %a, -8.0
@@ -58,13 +49,10 @@ define float @select_fneg_a_or_8_cmp_ogt_a_neg8_f32(float %a, float %b) #0 {
define half @select_fneg_a_or_8_cmp_ogt_a_neg8_f16(half %a, half %b) #0 {
; CHECK-LABEL: select_fneg_a_or_8_cmp_ogt_a_neg8_f16:
; CHECK: @ %bb.0:
-; CHECK-NEXT: vmov.f16 s4, r0
; CHECK-NEXT: vmov.f16 s0, #-8.000000e+00
-; CHECK-NEXT: vcmp.f16 s4, s0
-; CHECK-NEXT: vmov.f16 s2, #8.000000e+00
-; CHECK-NEXT: vmrs APSR_nzcv, fpscr
-; CHECK-NEXT: vneg.f16 s6, s4
-; CHECK-NEXT: vselgt.f16 s0, s6, s2
+; CHECK-NEXT: vmov.f16 s2, r0
+; CHECK-NEXT: vmaxnm.f16 s0, s2, s0
+; CHECK-NEXT: vneg.f16 s0, s0
; CHECK-NEXT: vmov r0, s0
; CHECK-NEXT: mov pc, lr
%fneg.a = fneg nnan nsz half %a
More information about the llvm-commits
mailing list