| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -mtriple=amdgpu9.00-amd-amdhsa -run-pass=legalizer %s -o - | FileCheck %s |
| |
| # Tests for G_PHI handling in GISelValueTracking::computeKnownFPClass. |
| # |
| # When all incoming values of a G_PHI are known to have certain FP classes, |
| # the intersection of their known classes is propagated through the PHI. |
| # This allows the legalizer to skip NaN fixup code in G_FMINIMUM/G_FMAXIMUM. |
| # |
| # Structure: |
| # bb.0 (entry): defines entry constants, jumps to bb.1 |
| # bb.1 (header): G_PHI of non-NaN constants, conditional branch to bb.2 or bb.3 |
| # bb.2 (body): defines back-edge constants, jumps back to bb.1 |
| # bb.3 (exit): uses PHI value in G_FMINIMUM |
| |
| --- |
| # Both operands of G_FMINIMUM are PHIs whose all incoming values are non-NaN |
| # constants (1.0/2.0 and 3.0/4.0). The legalizer should fully skip the NaN |
| # fixup: no G_FCMP ord + G_SELECT, just G_FMINNUM_IEEE. |
| name: test_fminimum_phi_both_nnan |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: test_fminimum_phi_both_nnan |
| ; CHECK: bb.0: |
| ; CHECK-NEXT: successors: %bb.1(0x80000000) |
| ; CHECK-NEXT: liveins: $sgpr0 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0 |
| ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00 |
| ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 3.000000e+00 |
| ; CHECK-NEXT: G_BR %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.1: |
| ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000) |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[PHI:%[0-9]+]]:_(s32) = G_PHI [[C]](s32), %bb.0, %4(s32), %bb.2 |
| ; CHECK-NEXT: [[PHI1:%[0-9]+]]:_(s32) = G_PHI [[C1]](s32), %bb.0, %6(s32), %bb.2 |
| ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32) |
| ; CHECK-NEXT: G_BRCOND [[TRUNC]](s1), %bb.3 |
| ; CHECK-NEXT: G_BR %bb.2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.2: |
| ; CHECK-NEXT: successors: %bb.1(0x80000000) |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00 |
| ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_FCONSTANT float 4.000000e+00 |
| ; CHECK-NEXT: G_BR %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.3: |
| ; CHECK-NEXT: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[PHI]], [[PHI1]] |
| ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[FMINNUM_IEEE]](s32) |
| ; CHECK-NEXT: $vgpr0 = COPY [[COPY1]](s32) |
| ; CHECK-NEXT: SI_RETURN implicit $vgpr0 |
| |
| bb.0: |
| liveins: $sgpr0 |
| |
| %0:_(s32) = COPY $sgpr0 |
| %1:_(s32) = G_FCONSTANT float 1.000000e+00 |
| %2:_(s32) = G_FCONSTANT float 3.000000e+00 |
| G_BR %bb.1 |
| |
| bb.1: |
| ; PHI merges two non-NaN constants: 1.0/2.0 and 3.0/4.0 |
| %5:_(s32) = G_PHI %1(s32), %bb.0, %3(s32), %bb.2 |
| %6:_(s32) = G_PHI %2(s32), %bb.0, %4(s32), %bb.2 |
| %7:_(s1) = G_TRUNC %0(s32) |
| G_BRCOND %7(s1), %bb.3 |
| G_BR %bb.2 |
| |
| bb.2: |
| %3:_(s32) = G_FCONSTANT float 2.000000e+00 |
| %4:_(s32) = G_FCONSTANT float 4.000000e+00 |
| G_BR %bb.1 |
| |
| bb.3: |
| ; G_FMINIMUM of two PHIs both known non-NaN. |
| ; NaN fixup entirely skipped: no G_FCMP ord + G_SELECT, just G_FMINNUM_IEEE. |
| %8:_(s32) = G_FMINIMUM %5, %6 |
| $vgpr0 = COPY %8(s32) |
| SI_RETURN implicit $vgpr0 |
| ... |
| |
| --- |
| # One operand of G_FMINIMUM is a PHI whose incoming values are all non-NaN |
| # constants; the other is an unknown COPY (potentially NaN). |
| # The NaN fixup IS emitted because the COPY may be NaN. |
| name: test_fminimum_phi_one_nnan |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: test_fminimum_phi_one_nnan |
| ; CHECK: bb.0: |
| ; CHECK-NEXT: successors: %bb.1(0x80000000) |
| ; CHECK-NEXT: liveins: $sgpr0, $vgpr0 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $sgpr0 |
| ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr0 |
| ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00 |
| ; CHECK-NEXT: G_BR %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.1: |
| ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000) |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[PHI:%[0-9]+]]:_(s32) = G_PHI [[C]](s32), %bb.0, %4(s32), %bb.2 |
| ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32) |
| ; CHECK-NEXT: G_BRCOND [[TRUNC]](s1), %bb.3 |
| ; CHECK-NEXT: G_BR %bb.2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.2: |
| ; CHECK-NEXT: successors: %bb.1(0x80000000) |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00 |
| ; CHECK-NEXT: G_BR %bb.1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: bb.3: |
| ; CHECK-NEXT: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[PHI]], [[COPY1]] |
| ; CHECK-NEXT: [[FCMP:%[0-9]+]]:_(i1) = G_FCMP floatpred(ord), [[PHI]](s32), [[COPY1]] |
| ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float +qnan |
| ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[FCMP]](i1), [[FMINNUM_IEEE]], [[C2]] |
| ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SELECT]](s32) |
| ; CHECK-NEXT: $vgpr0 = COPY [[COPY2]](s32) |
| ; CHECK-NEXT: SI_RETURN implicit $vgpr0 |
| |
| bb.0: |
| liveins: $sgpr0, $vgpr0 |
| |
| %0:_(s32) = COPY $sgpr0 |
| %9:_(s32) = COPY $vgpr0 |
| %1:_(s32) = G_FCONSTANT float 1.000000e+00 |
| G_BR %bb.1 |
| |
| bb.1: |
| %3:_(s32) = G_PHI %1(s32), %bb.0, %2(s32), %bb.2 |
| %4:_(s1) = G_TRUNC %0(s32) |
| G_BRCOND %4(s1), %bb.3 |
| G_BR %bb.2 |
| |
| bb.2: |
| %2:_(s32) = G_FCONSTANT float 2.000000e+00 |
| G_BR %bb.1 |
| |
| bb.3: |
| ; PHI is known non-NaN (1.0 or 2.0), %9 (from $vgpr0) is potentially NaN. |
| ; NaN fixup IS emitted because the other input may be NaN. |
| %6:_(s32) = G_FMINIMUM %3, %9 |
| $vgpr0 = COPY %6(s32) |
| SI_RETURN implicit $vgpr0 |
| ... |