diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 36744de92128..37936af6d853 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -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); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 30bf7e3a4a3d..5114e979e58e 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -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 Flags = std::nullopt) { + return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1}, Flags); } /// Build and insert \p Res = G_UITOFP \p Src0 diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index ace08c2f77df..e6eec3194b71 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -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: diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 857dace8d36d..6d4e4e64280c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -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); diff --git a/llvm/test/CodeGen/AMDGPU/llvm.modf.ll b/llvm/test/CodeGen/AMDGPU/llvm.modf.ll index 19aa833dc136..fc4f6507f273 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.modf.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.modf.ll @@ -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 }