[GISel] Add new combines for G_FMINNUM/MAXNUM and G_FMINIMUM/MAXIMUM

I noticed https://reviews.llvm.org/D87415 added SDAG combines to fold
FMIN/MAX instrs with NaNs.

The patch implements the same NaN combines for GISel GMIR FMIN/MAX opcodes:
G_FMINNUM(X, NaN) -> X
G_FMAXNUM(X, NaN) -> X
G_FMINIMUM(X, NaN) -> NaN
G_FMAXIMUM(X, NaN) -> NaN

The patch adds AArch64 tests for these combines as well.

Reviewed by: arsenm

Differential revision: https://reviews.llvm.org/D125819
This commit is contained in:
Michael Kitzan 2022-05-16 17:22:50 -07:00
parent ebbc37391f
commit 29bebb0237
5 changed files with 355 additions and 1 deletions

View File

@ -734,6 +734,8 @@ public:
/// Fold boolean selects to logical operations.
bool matchSelectToLogical(MachineInstr &MI, BuildFnTy &MatchInfo);
bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info);
private:
/// Given a non-indexed load or store instruction \p MI, find an offset that
/// can be usefully and legally folded into it as a post-indexing operation.

View File

@ -891,6 +891,13 @@ def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule<
*${root}, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
def combine_minmax_nan_matchinfo: GIDefMatchData<"unsigned">;
def combine_minmax_nan: GICombineRule<
(defs root:$root, combine_minmax_nan_matchinfo:$info),
(match (wip_match_opcode G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root,
[{ return Helper.matchCombineFMinMaxNaN(*${root}, ${info}); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${info}); }])>;
// FIXME: These should use the custom predicate feature once it lands.
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
undef_to_negative_one,
@ -910,7 +917,7 @@ def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p,
overlapping_and, mulo_by_2, mulo_by_0,
addo_by_0]>;
addo_by_0, combine_minmax_nan]>;
def known_bits_simplifications : GICombineGroup<[
redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask,

View File

@ -5600,6 +5600,33 @@ bool CombinerHelper::matchSelectToLogical(MachineInstr &MI,
return false;
}
bool CombinerHelper::matchCombineFMinMaxNaN(MachineInstr &MI,
unsigned &IdxToPropagate) {
bool PropagateNaN;
switch (MI.getOpcode()) {
default:
return false;
case TargetOpcode::G_FMINNUM:
case TargetOpcode::G_FMAXNUM:
PropagateNaN = false;
break;
case TargetOpcode::G_FMINIMUM:
case TargetOpcode::G_FMAXIMUM:
PropagateNaN = true;
break;
}
auto MatchNaN = [&](unsigned Idx) {
Register MaybeNaNReg = MI.getOperand(Idx).getReg();
const ConstantFP *MaybeCst = getConstantFPVRegVal(MaybeNaNReg, MRI);
if (!MaybeCst || !MaybeCst->getValueAPF().isNaN())
return false;
IdxToPropagate = PropagateNaN ? Idx : (Idx == 1 ? 2 : 1);
return true;
};
return MatchNaN(1) || MatchNaN(2);
}
bool CombinerHelper::tryCombine(MachineInstr &MI) {
if (tryCombineCopy(MI))

View File

@ -0,0 +1,159 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
---
name: test_combine_nan_rhs_fminimum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminimum_half
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH7C01
; CHECK-NEXT: $h0 = COPY [[C]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMINIMUM %0, %1
$h0 = COPY %2
...
---
name: test_combine_nan_rhs_fminimum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminimum_float
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x7FF8000000000000
; CHECK-NEXT: $w0 = COPY [[C]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMINIMUM %0, %1
$w0 = COPY %2
...
---
name: test_combine_nan_rhs_fminimum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminimum_double
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x7FF8000000000000
; CHECK-NEXT: $x0 = COPY [[C]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMINIMUM %0, %1
$x0 = COPY %2
...
---
name: test_combine_nan_lhs_fminimum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminimum_half
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH7C01
; CHECK-NEXT: $h0 = COPY [[C]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMINIMUM %1, %0
$h0 = COPY %2
...
---
name: test_combine_nan_lhs_fminimum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminimum_float
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x7FF8000000000000
; CHECK-NEXT: $w0 = COPY [[C]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMINIMUM %1, %0
$w0 = COPY %2
...
---
name: test_combine_nan_lhs_fminimum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminimum_double
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x7FF8000000000000
; CHECK-NEXT: $x0 = COPY [[C]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMINIMUM %1, %0
$x0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaximum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaximum_half
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH7C01
; CHECK-NEXT: $h0 = COPY [[C]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMAXIMUM %0, %1
$h0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaximum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaximum_float
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x7FF8000000000000
; CHECK-NEXT: $w0 = COPY [[C]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMAXIMUM %0, %1
$w0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaximum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaximum_double
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x7FF8000000000000
; CHECK-NEXT: $x0 = COPY [[C]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMAXIMUM %0, %1
$x0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaximum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaximum_half
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH7C01
; CHECK-NEXT: $h0 = COPY [[C]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMAXIMUM %1, %0
$h0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaximum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaximum_float
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x7FF8000000000000
; CHECK-NEXT: $w0 = COPY [[C]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMAXIMUM %1, %0
$w0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaximum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaximum_double
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x7FF8000000000000
; CHECK-NEXT: $x0 = COPY [[C]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMAXIMUM %1, %0
$x0 = COPY %2
...

View File

@ -0,0 +1,159 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
---
name: test_combine_nan_rhs_fminnum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminnum_half
; CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
; CHECK-NEXT: $h0 = COPY [[COPY]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMINNUM %0, %1
$h0 = COPY %2
...
---
name: test_combine_nan_rhs_fminnum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminnum_float
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMINNUM %0, %1
$w0 = COPY %2
...
---
name: test_combine_nan_rhs_fminnum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fminnum_double
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMINNUM %0, %1
$x0 = COPY %2
...
---
name: test_combine_nan_lhs_fminnum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminnum_half
; CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
; CHECK-NEXT: $h0 = COPY [[COPY]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMINNUM %1, %0
$h0 = COPY %2
...
---
name: test_combine_nan_lhs_fminnum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminnum_float
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMINNUM %1, %0
$w0 = COPY %2
...
---
name: test_combine_nan_lhs_fminnum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fminnum_double
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMINNUM %1, %0
$x0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaxnum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaxnum_half
; CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
; CHECK-NEXT: $h0 = COPY [[COPY]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMAXNUM %0, %1
$h0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaxnum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaxnum_float
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMAXNUM %0, %1
$w0 = COPY %2
...
---
name: test_combine_nan_rhs_fmaxnum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_rhs_fmaxnum_double
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMAXNUM %0, %1
$x0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaxnum_half
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaxnum_half
; CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
; CHECK-NEXT: $h0 = COPY [[COPY]](s16)
%0:_(s16) = COPY $h0
%1:_(s16) = G_FCONSTANT half 0xH7C01
%2:_(s16) = G_FMAXNUM %1, %0
$h0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaxnum_float
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaxnum_float
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
%0:_(s32) = COPY $w0
%1:_(s32) = G_FCONSTANT float 0x7FF8000000000000
%2:_(s32) = G_FMAXNUM %1, %0
$w0 = COPY %2
...
---
name: test_combine_nan_lhs_fmaxnum_double
body: |
bb.1:
liveins:
; CHECK-LABEL: name: test_combine_nan_lhs_fmaxnum_double
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_FCONSTANT double 0x7FF8000000000000
%2:_(s64) = G_FMAXNUM %1, %0
$x0 = COPY %2
...