[AMDGPU][GlobalISel] Add lowering for G_FMODF (#180152)

Add generic expansion for G_FMODF matching the SelectionDAG
implementation.

Enable G_FMODF lowering for AMDGPU with tests.

Related: #179434
This commit is contained in:
Alex Wang 2026-02-07 10:43:55 -08:00 committed by GitHub
parent 9dd5542a34
commit a947599991
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 471 additions and 194 deletions

View File

@ -526,6 +526,7 @@ public:
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI);
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI);
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI);
LLVM_ABI LegalizeResult lowerFMODF(MachineInstr &MI);
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI);

View File

@ -2202,9 +2202,10 @@ public:
}
/// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1
MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0,
const SrcOp &Src1) {
return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1});
MachineInstrBuilder
buildFCopysign(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1,
std::optional<unsigned> Flags = std::nullopt) {
return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1}, Flags);
}
/// Build and insert \p Res = G_UITOFP \p Src0

View File

@ -4762,6 +4762,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
return lowerFPTRUNC(MI);
case G_FPOWI:
return lowerFPOWI(MI);
case G_FMODF:
return lowerFMODF(MI);
case G_SMIN:
case G_SMAX:
case G_UMIN:
@ -8719,6 +8721,35 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPOWI(MachineInstr &MI) {
return Legalized;
}
LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMODF(MachineInstr &MI) {
auto [DstFrac, DstInt, Src] = MI.getFirst3Regs();
LLT Ty = MRI.getType(Src);
auto Flags = MI.getFlags();
auto IntPart = MIRBuilder.buildIntrinsicTrunc(Ty, Src, Flags);
auto FracPart = MIRBuilder.buildFSub(Ty, Src, IntPart, Flags);
Register FracToUse;
if (MI.getFlag(MachineInstr::FmNoInfs)) {
FracToUse = FracPart.getReg(0);
} else {
auto Abs = MIRBuilder.buildFAbs(Ty, Src, Flags);
const fltSemantics &Semantics = getFltSemanticForLLT(Ty.getScalarType());
auto Inf = MIRBuilder.buildFConstant(Ty, APFloat::getInf(Semantics));
auto IsInf = MIRBuilder.buildFCmp(CmpInst::FCMP_OEQ,
Ty.changeElementSize(1), Abs, Inf);
auto Zero = MIRBuilder.buildFConstant(Ty, 0.0);
auto Select = MIRBuilder.buildSelect(Ty, IsInf, Zero, FracPart);
FracToUse = Select.getReg(0);
}
MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
MIRBuilder.buildCopy(DstInt, IntPart.getReg(0));
MI.eraseFromParent();
return Legalized;
}
static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
switch (Opc) {
case TargetOpcode::G_SMIN:

View File

@ -1057,6 +1057,11 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
.customFor({{S32, S32}, {S64, S32}, {S16, S16}, {S16, S32}})
.scalarize(0)
.lower();
getActionDefinitionsBuilder(G_FMODF)
.lowerFor({S16, S32, S64})
.scalarize(0)
.lower();
} else {
getActionDefinitionsBuilder(G_FSQRT)
.customFor({S32, S64, S16})
@ -1090,6 +1095,11 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
.minScalar(0, S32)
.clampScalar(1, S32, S32)
.lower();
getActionDefinitionsBuilder(G_FMODF)
.lowerFor({S32, S64})
.scalarize(0)
.lower();
}
auto &FPTruncActions = getActionDefinitionsBuilder(G_FPTRUNC);

View File

@ -1,7 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck -check-prefixes=GFX9 %s
; TODO: Add GlobalISel support
; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck -check-prefixes=GFX9,GFX9-SDAG %s
; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck -check-prefixes=GFX9,GFX9-GISEL %s
declare { half, half } @llvm.modf.f16(half)
declare { <2 x half>, <2 x half> } @llvm.modf.v2f16(<2 x half>)
@ -13,33 +12,59 @@ declare { double, double } @llvm.modf.f64(double)
declare { <2 x double>, <2 x double> } @llvm.modf.v2f64(<2 x double>)
define { half, half } @test_modf_f16(half %x) {
; GFX9-LABEL: test_modf_f16:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: s_movk_i32 s4, 0x7fff
; GFX9-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f16:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7fff
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f16:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v3, 0x7c00
; GFX9-GISEL-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f16_e64 s[4:5], |v0|, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0x7fff, v2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff8000, v0
; GFX9-GISEL-NEXT: v_or_b32_e32 v0, v2, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { half, half } @llvm.modf.f16(half %x)
ret { half, half } %result
}
define half @test_modf_f16_only_use_fract(half %x) {
; GFX9-LABEL: test_modf_f16_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-NEXT: s_movk_i32 s4, 0x7fff
; GFX9-NEXT: v_bfi_b32 v0, s4, v1, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f16_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7fff
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s4, v1, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f16_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v2, 0x7c00
; GFX9-GISEL-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f16_e64 s[4:5], |v0|, v2
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v1, v1, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x7fff, v1
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff8000, v0
; GFX9-GISEL-NEXT: v_or_b32_e32 v0, v1, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { half, half } @llvm.modf.f16(half %x)
%result.0 = extractvalue { half, half } %result, 0
ret half %result.0
@ -57,94 +82,175 @@ define half @test_modf_f16_only_use_integer(half %x) {
}
define { <2 x half>, <2 x half> } @test_modf_v2f16(<2 x half> %x) {
; GFX9-LABEL: test_modf_v2f16:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: s_movk_i32 s5, 0x7fff
; GFX9-NEXT: v_bfi_b32 v2, s5, v2, v0
; GFX9-NEXT: v_lshrrev_b32_e32 v0, 16, v0
; GFX9-NEXT: v_trunc_f16_e32 v3, v0
; GFX9-NEXT: v_sub_f16_e32 v4, v0, v3
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
; GFX9-NEXT: v_bfi_b32 v0, s5, v4, v0
; GFX9-NEXT: v_pack_b32_f16 v0, v2, v0
; GFX9-NEXT: v_pack_b32_f16 v1, v1, v3
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f16:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: s_movk_i32 s5, 0x7fff
; GFX9-SDAG-NEXT: v_bfi_b32 v2, s5, v2, v0
; GFX9-SDAG-NEXT: v_lshrrev_b32_e32 v0, 16, v0
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v3, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v4, v0, v3
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s5, v4, v0
; GFX9-SDAG-NEXT: v_pack_b32_f16 v0, v2, v0
; GFX9-SDAG-NEXT: v_pack_b32_f16 v1, v1, v3
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f16:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v3, 0x7c00
; GFX9-GISEL-NEXT: v_sub_f16_e32 v2, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f16_e64 s[4:5], |v0|, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0x7fff, v2
; GFX9-GISEL-NEXT: v_and_b32_e32 v5, 0xffff8000, v0
; GFX9-GISEL-NEXT: v_or_b32_e32 v2, v2, v5
; GFX9-GISEL-NEXT: v_trunc_f16_sdwa v5, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9-GISEL-NEXT: v_sub_f16_sdwa v6, v0, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_cmp_eq_f16_sdwa s[4:5], |v0|, v3 src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_mov_b32_e32 v4, 0xffff8000
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v3, v6, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v3, 0x7fff, v3
; GFX9-GISEL-NEXT: v_and_b32_sdwa v0, v0, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_or_b32_e32 v0, v3, v0
; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v2
; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v0, 16, v2
; GFX9-GISEL-NEXT: v_pack_b32_f16 v1, v1, v5
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x half>, <2 x half> } @llvm.modf.v2f16(<2 x half> %x)
ret { <2 x half>, <2 x half> } %result
}
define <2 x half> @test_modf_v2f16_only_use_fract(<2 x half> %x) {
; GFX9-LABEL: test_modf_v2f16_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-NEXT: s_movk_i32 s5, 0x7fff
; GFX9-NEXT: v_bfi_b32 v1, s5, v1, v0
; GFX9-NEXT: v_lshrrev_b32_e32 v0, 16, v0
; GFX9-NEXT: v_trunc_f16_e32 v2, v0
; GFX9-NEXT: v_sub_f16_e32 v2, v0, v2
; GFX9-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: v_bfi_b32 v0, s5, v2, v0
; GFX9-NEXT: v_pack_b32_f16 v0, v1, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f16_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x7c00
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-SDAG-NEXT: s_movk_i32 s5, 0x7fff
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s5, v1, v0
; GFX9-SDAG-NEXT: v_lshrrev_b32_e32 v0, 16, v0
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v2, v0
; GFX9-SDAG-NEXT: v_sub_f16_e32 v2, v0, v2
; GFX9-SDAG-NEXT: v_cmp_neq_f16_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s5, v2, v0
; GFX9-SDAG-NEXT: v_pack_b32_f16 v0, v1, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f16_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v2, 0x7c00
; GFX9-GISEL-NEXT: v_sub_f16_e32 v1, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f16_e64 s[4:5], |v0|, v2
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v1, v1, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x7fff, v1
; GFX9-GISEL-NEXT: v_and_b32_e32 v4, 0xffff8000, v0
; GFX9-GISEL-NEXT: v_or_b32_e32 v1, v1, v4
; GFX9-GISEL-NEXT: v_trunc_f16_sdwa v4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9-GISEL-NEXT: v_sub_f16_sdwa v4, v0, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_cmp_eq_f16_sdwa s[4:5], |v0|, v2 src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_mov_b32_e32 v3, 0xffff8000
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v4, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0x7fff, v2
; GFX9-GISEL-NEXT: v_and_b32_sdwa v0, v0, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
; GFX9-GISEL-NEXT: v_or_b32_e32 v0, v2, v0
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1
; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v0, 16, v1
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x half>, <2 x half> } @llvm.modf.v2f16(<2 x half> %x)
%result.0 = extractvalue { <2 x half>, <2 x half> } %result, 0
ret <2 x half> %result.0
}
define <2 x half> @test_modf_v2f16_only_use_integer(<2 x half> %x) {
; GFX9-LABEL: test_modf_v2f16_only_use_integer:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f16_sdwa v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9-NEXT: v_trunc_f16_e32 v0, v0
; GFX9-NEXT: v_pack_b32_f16 v0, v0, v1
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f16_only_use_integer:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f16_sdwa v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9-SDAG-NEXT: v_trunc_f16_e32 v0, v0
; GFX9-SDAG-NEXT: v_pack_b32_f16 v0, v0, v1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f16_only_use_integer:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f16_e32 v1, v0
; GFX9-GISEL-NEXT: v_trunc_f16_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
; GFX9-GISEL-NEXT: v_pack_b32_f16 v0, v1, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x half>, <2 x half> } @llvm.modf.v2f16(<2 x half> %x)
%result.1 = extractvalue { <2 x half>, <2 x half> } %result, 1
ret <2 x half> %result.1
}
define { float, float } @test_modf_f32(float %x) {
; GFX9-LABEL: test_modf_f32:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: s_brev_b32 s4, -2
; GFX9-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f32:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: s_brev_b32 s4, -2
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f32:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v3, 0x7f800000
; GFX9-GISEL-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v0|, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v3, -2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v0
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v2, v3, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { float, float } @llvm.modf.f32(float %x)
ret { float, float } %result
}
define float @test_modf_f32_only_use_fract(float %x) {
; GFX9-LABEL: test_modf_f32_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-NEXT: v_sub_f32_e32 v1, v0, v1
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-NEXT: s_brev_b32 s4, -2
; GFX9-NEXT: v_bfi_b32 v0, s4, v1, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f32_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f32_e32 v1, v0, v1
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc
; GFX9-SDAG-NEXT: s_brev_b32 s4, -2
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s4, v1, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f32_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v2, 0x7f800000
; GFX9-GISEL-NEXT: v_sub_f32_e32 v1, v0, v1
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v0|, v2
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v1, v1, 0, s[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v2, -2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v0
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v1, v2, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { float, float } @llvm.modf.f32(float %x)
%result.0 = extractvalue { float, float } %result, 0
ret float %result.0
@ -162,43 +268,81 @@ define float @test_modf_f32_only_use_integer(float %x) {
}
define { <2 x float>, <2 x float> } @test_modf_v2f32(<2 x float> %x) {
; GFX9-LABEL: test_modf_v2f32:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-NEXT: v_sub_f32_e32 v3, v0, v2
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
; GFX9-NEXT: s_brev_b32 s5, -2
; GFX9-NEXT: v_bfi_b32 v0, s5, v3, v0
; GFX9-NEXT: v_trunc_f32_e32 v3, v1
; GFX9-NEXT: v_sub_f32_e32 v4, v1, v3
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
; GFX9-NEXT: v_bfi_b32 v1, s5, v4, v1
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f32:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-SDAG-NEXT: v_sub_f32_e32 v3, v0, v2
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
; GFX9-SDAG-NEXT: s_brev_b32 s5, -2
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s5, v3, v0
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v3, v1
; GFX9-SDAG-NEXT: v_sub_f32_e32 v4, v1, v3
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s5, v4, v1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f32:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v4, 0x7f800000
; GFX9-GISEL-NEXT: v_sub_f32_e32 v3, v0, v2
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v0|, v4
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v5, -2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v0
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v3, v5, v0
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v3, v1
; GFX9-GISEL-NEXT: v_sub_f32_e32 v6, v1, v3
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v1|, v4
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v4, v6, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v4, v5, v1
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> %x)
ret { <2 x float>, <2 x float> } %result
}
define <2 x float> @test_modf_v2f32_only_use_fract(<2 x float> %x) {
; GFX9-LABEL: test_modf_v2f32_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-NEXT: v_sub_f32_e32 v2, v0, v2
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: s_brev_b32 s5, -2
; GFX9-NEXT: v_bfi_b32 v0, s5, v2, v0
; GFX9-NEXT: v_trunc_f32_e32 v2, v1
; GFX9-NEXT: v_sub_f32_e32 v2, v1, v2
; GFX9-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
; GFX9-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-NEXT: v_bfi_b32 v1, s5, v2, v1
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f32_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: s_mov_b32 s4, 0x7f800000
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-SDAG-NEXT: v_sub_f32_e32 v2, v0, v2
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: s_brev_b32 s5, -2
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s5, v2, v0
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v2, v1
; GFX9-SDAG-NEXT: v_sub_f32_e32 v2, v1, v2
; GFX9-SDAG-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4
; GFX9-SDAG-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s5, v2, v1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f32_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v2, v0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v3, 0x7f800000
; GFX9-GISEL-NEXT: v_sub_f32_e32 v2, v0, v2
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v0|, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v4, -2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v0
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v2, v4, v0
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v2, v1
; GFX9-GISEL-NEXT: v_sub_f32_e32 v2, v1, v2
; GFX9-GISEL-NEXT: v_cmp_eq_f32_e64 s[4:5], |v1|, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v2, v4, v1
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x float>, <2 x float> } @llvm.modf.v2f32(<2 x float> %x)
%result.0 = extractvalue { <2 x float>, <2 x float> } %result, 0
ret <2 x float> %result.0
@ -217,35 +361,67 @@ define <2 x float> @test_modf_v2f32_only_use_integer(<2 x float> %x) {
}
define { double, double } @test_modf_f64(double %x) {
; GFX9-LABEL: test_modf_f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-NEXT: s_movk_i32 s4, 0x204
; GFX9-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s4
; GFX9-NEXT: s_brev_b32 s6, -2
; GFX9-NEXT: v_add_f64 v[4:5], v[0:1], -v[2:3]
; GFX9-NEXT: v_cndmask_b32_e64 v0, v4, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v4, v5, 0, s[4:5]
; GFX9-NEXT: v_bfi_b32 v1, s6, v4, v1
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f64:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x204
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s4
; GFX9-SDAG-NEXT: s_brev_b32 s6, -2
; GFX9-SDAG-NEXT: v_add_f64 v[4:5], v[0:1], -v[2:3]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v0, v4, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v4, v5, 0, s[4:5]
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s6, v4, v1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f64:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-GISEL-NEXT: v_mov_b32_e32 v4, 0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v5, 0x7ff00000
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[4:5], |v[0:1]|, v[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v4, -2
; GFX9-GISEL-NEXT: v_add_f64 v[6:7], v[0:1], -v[2:3]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v5, v6, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v6, v7, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v0, 0, v5
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v6, v4, v1
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { double, double } @llvm.modf.f64(double %x)
ret { double, double } %result
}
define double @test_modf_f64_only_use_fract(double %x) {
; GFX9-LABEL: test_modf_f64_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-NEXT: s_movk_i32 s4, 0x204
; GFX9-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s4
; GFX9-NEXT: s_brev_b32 s6, -2
; GFX9-NEXT: v_add_f64 v[2:3], v[0:1], -v[2:3]
; GFX9-NEXT: v_cndmask_b32_e64 v0, v2, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v2, v3, 0, s[4:5]
; GFX9-NEXT: v_bfi_b32 v1, s6, v2, v1
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_f64_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-SDAG-NEXT: s_movk_i32 s4, 0x204
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s4
; GFX9-SDAG-NEXT: s_brev_b32 s6, -2
; GFX9-SDAG-NEXT: v_add_f64 v[2:3], v[0:1], -v[2:3]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v0, v2, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v2, v3, 0, s[4:5]
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s6, v2, v1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_f64_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[2:3], v[0:1]
; GFX9-GISEL-NEXT: v_mov_b32_e32 v4, 0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v5, 0x7ff00000
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[4:5], |v[0:1]|, v[4:5]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v4, -2
; GFX9-GISEL-NEXT: v_add_f64 v[2:3], v[0:1], -v[2:3]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v2, v2, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v0, 0, v2
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v3, v4, v1
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { double, double } @llvm.modf.f64(double %x)
%result.0 = extractvalue { double, double } %result, 0
ret double %result.0
@ -263,47 +439,95 @@ define double @test_modf_f64_only_use_integer(double %x) {
}
define { <2 x double>, <2 x double> } @test_modf_v2f64(<2 x double> %x) {
; GFX9-LABEL: test_modf_v2f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-NEXT: s_movk_i32 s6, 0x204
; GFX9-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s6
; GFX9-NEXT: v_cmp_class_f64_e64 s[6:7], v[2:3], s6
; GFX9-NEXT: s_brev_b32 s8, -2
; GFX9-NEXT: v_add_f64 v[8:9], v[0:1], -v[4:5]
; GFX9-NEXT: v_add_f64 v[10:11], v[2:3], -v[6:7]
; GFX9-NEXT: v_cndmask_b32_e64 v0, v8, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v8, v9, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v9, v11, 0, s[6:7]
; GFX9-NEXT: v_cndmask_b32_e64 v2, v10, 0, s[6:7]
; GFX9-NEXT: v_bfi_b32 v1, s8, v8, v1
; GFX9-NEXT: v_bfi_b32 v3, s8, v9, v3
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f64:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-SDAG-NEXT: s_movk_i32 s6, 0x204
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s6
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[6:7], v[2:3], s6
; GFX9-SDAG-NEXT: s_brev_b32 s8, -2
; GFX9-SDAG-NEXT: v_add_f64 v[8:9], v[0:1], -v[4:5]
; GFX9-SDAG-NEXT: v_add_f64 v[10:11], v[2:3], -v[6:7]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v0, v8, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v8, v9, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v9, v11, 0, s[6:7]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v2, v10, 0, s[6:7]
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s8, v8, v1
; GFX9-SDAG-NEXT: v_bfi_b32 v3, s8, v9, v3
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f64:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-GISEL-NEXT: v_mov_b32_e32 v8, 0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v9, 0x7ff00000
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[4:5], |v[0:1]|, v[8:9]
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[6:7], |v[2:3]|, v[8:9]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v8, -2
; GFX9-GISEL-NEXT: v_add_f64 v[10:11], v[0:1], -v[4:5]
; GFX9-GISEL-NEXT: v_add_f64 v[12:13], v[2:3], -v[6:7]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_and_b32_e32 v3, 0x80000000, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v9, v10, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v10, v11, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v11, v12, 0, s[6:7]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v12, v13, 0, s[6:7]
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v0, 0, v9
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v10, v8, v1
; GFX9-GISEL-NEXT: v_and_or_b32 v2, v2, 0, v11
; GFX9-GISEL-NEXT: v_and_or_b32 v3, v12, v8, v3
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x double>, <2 x double> } @llvm.modf.v2f64(<2 x double> %x)
ret { <2 x double>, <2 x double> } %result
}
define <2 x double> @test_modf_v2f64_only_use_fract(<2 x double> %x) {
; GFX9-LABEL: test_modf_v2f64_only_use_fract:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-NEXT: s_movk_i32 s6, 0x204
; GFX9-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s6
; GFX9-NEXT: v_cmp_class_f64_e64 s[6:7], v[2:3], s6
; GFX9-NEXT: s_brev_b32 s8, -2
; GFX9-NEXT: v_add_f64 v[4:5], v[0:1], -v[4:5]
; GFX9-NEXT: v_add_f64 v[6:7], v[2:3], -v[6:7]
; GFX9-NEXT: v_cndmask_b32_e64 v0, v4, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v4, v5, 0, s[4:5]
; GFX9-NEXT: v_cndmask_b32_e64 v5, v7, 0, s[6:7]
; GFX9-NEXT: v_cndmask_b32_e64 v2, v6, 0, s[6:7]
; GFX9-NEXT: v_bfi_b32 v1, s8, v4, v1
; GFX9-NEXT: v_bfi_b32 v3, s8, v5, v3
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_v2f64_only_use_fract:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-SDAG-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-SDAG-NEXT: s_movk_i32 s6, 0x204
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s6
; GFX9-SDAG-NEXT: v_cmp_class_f64_e64 s[6:7], v[2:3], s6
; GFX9-SDAG-NEXT: s_brev_b32 s8, -2
; GFX9-SDAG-NEXT: v_add_f64 v[4:5], v[0:1], -v[4:5]
; GFX9-SDAG-NEXT: v_add_f64 v[6:7], v[2:3], -v[6:7]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v0, v4, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v4, v5, 0, s[4:5]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v5, v7, 0, s[6:7]
; GFX9-SDAG-NEXT: v_cndmask_b32_e64 v2, v6, 0, s[6:7]
; GFX9-SDAG-NEXT: v_bfi_b32 v1, s8, v4, v1
; GFX9-SDAG-NEXT: v_bfi_b32 v3, s8, v5, v3
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_v2f64_only_use_fract:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[4:5], v[0:1]
; GFX9-GISEL-NEXT: v_trunc_f64_e32 v[6:7], v[2:3]
; GFX9-GISEL-NEXT: v_mov_b32_e32 v8, 0
; GFX9-GISEL-NEXT: v_mov_b32_e32 v9, 0x7ff00000
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[4:5], |v[0:1]|, v[8:9]
; GFX9-GISEL-NEXT: v_cmp_eq_f64_e64 s[6:7], |v[2:3]|, v[8:9]
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v8, -2
; GFX9-GISEL-NEXT: v_add_f64 v[4:5], v[0:1], -v[4:5]
; GFX9-GISEL-NEXT: v_add_f64 v[6:7], v[2:3], -v[6:7]
; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x80000000, v1
; GFX9-GISEL-NEXT: v_and_b32_e32 v3, 0x80000000, v3
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v4, v4, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v6, v6, 0, s[6:7]
; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v7, v7, 0, s[6:7]
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v0, 0, v4
; GFX9-GISEL-NEXT: v_and_or_b32 v1, v5, v8, v1
; GFX9-GISEL-NEXT: v_and_or_b32 v2, v2, 0, v6
; GFX9-GISEL-NEXT: v_and_or_b32 v3, v7, v8, v3
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call { <2 x double>, <2 x double> } @llvm.modf.v2f64(<2 x double> %x)
%result.0 = extractvalue { <2 x double>, <2 x double> } %result, 0
ret <2 x double> %result.0
@ -322,14 +546,24 @@ define <2 x double> @test_modf_v2f64_only_use_integer(<2 x double> %x) {
}
define { float, float } @test_modf_ninf(float %x) {
; GFX9-LABEL: test_modf_ninf:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-NEXT: s_brev_b32 s4, -2
; GFX9-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
; GFX9-SDAG-LABEL: test_modf_ninf:
; GFX9-SDAG: ; %bb.0:
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-SDAG-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-SDAG-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-SDAG-NEXT: s_brev_b32 s4, -2
; GFX9-SDAG-NEXT: v_bfi_b32 v0, s4, v2, v0
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_modf_ninf:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX9-GISEL-NEXT: v_trunc_f32_e32 v1, v0
; GFX9-GISEL-NEXT: v_sub_f32_e32 v2, v0, v1
; GFX9-GISEL-NEXT: v_bfrev_b32_e32 v3, -2
; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v0
; GFX9-GISEL-NEXT: v_and_or_b32 v0, v2, v3, v0
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
%result = call ninf { float, float } @llvm.modf.f32(float %x)
ret { float, float } %result
}