diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 05c2727b687bb..3b5d55f77a4fb 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -383,91 +383,75 @@ void LegalizerHelper::buildWidenedRemergeToDst(Register DstReg, LLT LCMTy, } static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { +#define RTLIBCASE(LibcallPrefix) \ + do { \ + switch (Size) { \ + case 32: \ + return RTLIB::LibcallPrefix##32; \ + case 64: \ + return RTLIB::LibcallPrefix##64; \ + case 128: \ + return RTLIB::LibcallPrefix##128; \ + default: \ + llvm_unreachable("unexpected size"); \ + } \ + } while (0) + + assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); + switch (Opcode) { case TargetOpcode::G_SDIV: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - switch (Size) { - case 32: - return RTLIB::SDIV_I32; - case 64: - return RTLIB::SDIV_I64; - case 128: - return RTLIB::SDIV_I128; - default: - llvm_unreachable("unexpected size"); - } + RTLIBCASE(SDIV_I); case TargetOpcode::G_UDIV: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - switch (Size) { - case 32: - return RTLIB::UDIV_I32; - case 64: - return RTLIB::UDIV_I64; - case 128: - return RTLIB::UDIV_I128; - default: - llvm_unreachable("unexpected size"); - } + RTLIBCASE(UDIV_I); case TargetOpcode::G_SREM: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32; + RTLIBCASE(SREM_I); case TargetOpcode::G_UREM: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32; + RTLIBCASE(UREM_I); case TargetOpcode::G_CTLZ_ZERO_UNDEF: - assert(Size == 32 && "Unsupported size"); - return RTLIB::CTLZ_I32; + RTLIBCASE(CTLZ_I); case TargetOpcode::G_FADD: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; + RTLIBCASE(ADD_F); case TargetOpcode::G_FSUB: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32; + RTLIBCASE(SUB_F); case TargetOpcode::G_FMUL: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32; + RTLIBCASE(MUL_F); case TargetOpcode::G_FDIV: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32; + RTLIBCASE(DIV_F); case TargetOpcode::G_FEXP: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32; + RTLIBCASE(EXP_F); case TargetOpcode::G_FEXP2: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::EXP2_F64 : RTLIB::EXP2_F32; + RTLIBCASE(EXP2_F); case TargetOpcode::G_FREM: - return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; + RTLIBCASE(REM_F); case TargetOpcode::G_FPOW: - return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; + RTLIBCASE(POW_F); case TargetOpcode::G_FMA: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32; + RTLIBCASE(FMA_F); case TargetOpcode::G_FSIN: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - return Size == 128 ? RTLIB::SIN_F128 - : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32; + RTLIBCASE(SIN_F); case TargetOpcode::G_FCOS: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - return Size == 128 ? RTLIB::COS_F128 - : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32; + RTLIBCASE(COS_F); case TargetOpcode::G_FLOG10: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - return Size == 128 ? RTLIB::LOG10_F128 - : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32; + RTLIBCASE(LOG10_F); case TargetOpcode::G_FLOG: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - return Size == 128 ? RTLIB::LOG_F128 - : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32; + RTLIBCASE(LOG_F); case TargetOpcode::G_FLOG2: - assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); - return Size == 128 ? RTLIB::LOG2_F128 - : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32; + RTLIBCASE(LOG2_F); case TargetOpcode::G_FCEIL: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::CEIL_F64 : RTLIB::CEIL_F32; + RTLIBCASE(CEIL_F); case TargetOpcode::G_FFLOOR: - assert((Size == 32 || Size == 64) && "Unsupported size"); - return Size == 64 ? RTLIB::FLOOR_F64 : RTLIB::FLOOR_F32; + RTLIBCASE(FLOOR_F); + case TargetOpcode::G_FMINNUM: + RTLIBCASE(FMIN_F); + case TargetOpcode::G_FMAXNUM: + RTLIBCASE(FMAX_F); + case TargetOpcode::G_FSQRT: + RTLIBCASE(SQRT_F); + case TargetOpcode::G_FRINT: + RTLIBCASE(RINT_F); + case TargetOpcode::G_FNEARBYINT: + RTLIBCASE(NEARBYINT_F); } llvm_unreachable("Unknown libcall function"); } @@ -668,9 +652,14 @@ LegalizerHelper::libcall(MachineInstr &MI) { case TargetOpcode::G_FEXP: case TargetOpcode::G_FEXP2: case TargetOpcode::G_FCEIL: - case TargetOpcode::G_FFLOOR: { + case TargetOpcode::G_FFLOOR: + case TargetOpcode::G_FMINNUM: + case TargetOpcode::G_FMAXNUM: + case TargetOpcode::G_FSQRT: + case TargetOpcode::G_FRINT: + case TargetOpcode::G_FNEARBYINT: { Type *HLTy = getFloatTypeForLLT(Ctx, LLTy); - if (!HLTy || (Size != 32 && Size != 64)) { + if (!HLTy || (Size != 32 && Size != 64 && Size != 128)) { LLVM_DEBUG(dbgs() << "No libcall available for size " << Size << ".\n"); return UnableToLegalize; } diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp index 5e10a574f81fc..130db7289dd67 100644 --- a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp @@ -1353,4 +1353,953 @@ TEST_F(GISelMITest, LibcallSimple) { EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize, Helper.libcall(*MIBFADD)); } + +TEST_F(GISelMITest, LibcallSRem) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_SREM).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBSRem32 = + B.buildInstr(TargetOpcode::G_SREM, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBSRem64 = + B.buildInstr(TargetOpcode::G_SREM, {S64}, {Copies[0], Copies[0]}); + auto MIBSRem128 = + B.buildInstr(TargetOpcode::G_SREM, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSRem32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSRem64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSRem128)); + + auto CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $w0 = COPY [[TRUNC]] + CHECK: $w1 = COPY [[TRUNC]] + CHECK: BL &__modsi3 + CHECK: $x0 = COPY [[COPY]] + CHECK: $x1 = COPY [[COPY]] + CHECK: BL &__moddi3 + CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] + CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] + CHECK: $x0 = COPY [[UV]] + CHECK: $x1 = COPY [[UV1]] + CHECK: $x2 = COPY [[UV2]] + CHECK: $x3 = COPY [[UV3]] + CHECK: BL &__modti3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallURem) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_UREM).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBURem32 = + B.buildInstr(TargetOpcode::G_UREM, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBURem64 = + B.buildInstr(TargetOpcode::G_UREM, {S64}, {Copies[0], Copies[0]}); + auto MIBURem128 = + B.buildInstr(TargetOpcode::G_UREM, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBURem32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBURem64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBURem128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $w0 = COPY [[TRUNC]] + CHECK: $w1 = COPY [[TRUNC]] + CHECK: BL &__umodsi3 + CHECK: $x0 = COPY [[COPY]] + CHECK: $x1 = COPY [[COPY]] + CHECK: BL &__umoddi3 + CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] + CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] + CHECK: $x0 = COPY [[UV]] + CHECK: $x1 = COPY [[UV1]] + CHECK: $x2 = COPY [[UV2]] + CHECK: $x3 = COPY [[UV3]] + CHECK: BL &__umodti3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallCtlzZeroUndef) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF) + .libcallFor({{s32, s32}, {s64, s64}, {s128, s128}}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBCtlz32 = + B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S32}, {MIBTrunc}); + auto MIBCtlz64 = + B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S64}, {Copies[0]}); + auto MIBCtlz128 = + B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCtlz32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCtlz64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCtlz128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $w0 = COPY [[TRUNC]] + CHECK: BL &__clzsi2 + CHECK: $x0 = COPY [[COPY]] + CHECK: BL &__clzdi2 + CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] + CHECK: $x0 = COPY [[UV]] + CHECK: $x1 = COPY [[UV1]] + CHECK: BL &__clzti2 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFAdd) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FADD).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBAdd32 = + B.buildInstr(TargetOpcode::G_FADD, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBAdd64 = + B.buildInstr(TargetOpcode::G_FADD, {S64}, {Copies[0], Copies[0]}); + auto MIBAdd128 = B.buildInstr(TargetOpcode::G_FADD, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBAdd32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBAdd64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBAdd128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &__addsf3 + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &__adddf3 + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &__addtf3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFSub) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FSUB).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBSub32 = + B.buildInstr(TargetOpcode::G_FSUB, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBSub64 = + B.buildInstr(TargetOpcode::G_FSUB, {S64}, {Copies[0], Copies[0]}); + auto MIBSub128 = B.buildInstr(TargetOpcode::G_FSUB, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSub32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSub64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSub128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &__subsf3 + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &__subdf3 + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &__subtf3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFMul) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FMUL).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBMul32 = + B.buildInstr(TargetOpcode::G_FMUL, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBMul64 = + B.buildInstr(TargetOpcode::G_FMUL, {S64}, {Copies[0], Copies[0]}); + auto MIBMul128 = B.buildInstr(TargetOpcode::G_FMUL, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMul32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMul64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMul128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &__mulsf3 + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &__muldf3 + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &__multf3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFDiv) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FDIV).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBDiv32 = + B.buildInstr(TargetOpcode::G_FDIV, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBDiv64 = + B.buildInstr(TargetOpcode::G_FDIV, {S64}, {Copies[0], Copies[0]}); + auto MIBDiv128 = B.buildInstr(TargetOpcode::G_FDIV, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBDiv32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBDiv64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBDiv128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &__divsf3 + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &__divdf3 + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &__divtf3 + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFExp) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FEXP).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBExp32 = B.buildInstr(TargetOpcode::G_FEXP, {S32}, {MIBTrunc}); + auto MIBExp64 = B.buildInstr(TargetOpcode::G_FEXP, {S64}, {Copies[0]}); + auto MIBExp128 = B.buildInstr(TargetOpcode::G_FEXP, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &expf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &exp + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &expl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFExp2) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FEXP2).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBExp232 = B.buildInstr(TargetOpcode::G_FEXP2, {S32}, {MIBTrunc}); + auto MIBExp264 = B.buildInstr(TargetOpcode::G_FEXP2, {S64}, {Copies[0]}); + auto MIBExp2128 = B.buildInstr(TargetOpcode::G_FEXP2, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp232)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp264)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBExp2128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &exp2f + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &exp2 + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &exp2l + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFRem) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FREM).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBFRem32 = B.buildInstr(TargetOpcode::G_FREM, {S32}, {MIBTrunc}); + auto MIBFRem64 = B.buildInstr(TargetOpcode::G_FREM, {S64}, {Copies[0]}); + auto MIBFRem128 = B.buildInstr(TargetOpcode::G_FREM, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFRem32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFRem64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFRem128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &fmodf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &fmod + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &fmodl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFPow) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FPOW).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBPow32 = B.buildInstr(TargetOpcode::G_FPOW, {S32}, {MIBTrunc}); + auto MIBPow64 = B.buildInstr(TargetOpcode::G_FPOW, {S64}, {Copies[0]}); + auto MIBPow128 = B.buildInstr(TargetOpcode::G_FPOW, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBPow32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBPow64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBPow128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &powf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &pow + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &powl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFMa) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBMa32 = B.buildInstr(TargetOpcode::G_FMA, {S32}, {MIBTrunc, MIBTrunc}); + auto MIBMa64 = + B.buildInstr(TargetOpcode::G_FMA, {S64}, {Copies[0], Copies[0]}); + auto MIBMa128 = B.buildInstr(TargetOpcode::G_FMA, {S128}, {MIBExt, MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMa32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMa64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMa128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &fmaf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &fma + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &fmal + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFCeil) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FCEIL).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBCeil32 = B.buildInstr(TargetOpcode::G_FCEIL, {S32}, {MIBTrunc}); + auto MIBCeil64 = B.buildInstr(TargetOpcode::G_FCEIL, {S64}, {Copies[0]}); + auto MIBCeil128 = B.buildInstr(TargetOpcode::G_FCEIL, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCeil32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCeil64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBCeil128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &ceilf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &ceil + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &ceill + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFFloor) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FFLOOR).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBFloor32 = B.buildInstr(TargetOpcode::G_FFLOOR, {S32}, {MIBTrunc}); + auto MIBFloor64 = B.buildInstr(TargetOpcode::G_FFLOOR, {S64}, {Copies[0]}); + auto MIBFloor128 = B.buildInstr(TargetOpcode::G_FFLOOR, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFloor32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFloor64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBFloor128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &floorf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &floor + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &floorl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFMinNum) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FMINNUM).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBMin32 = B.buildFMinNum(S32, MIBTrunc, MIBTrunc); + auto MIBMin64 = B.buildFMinNum(S64, Copies[0], Copies[0]); + auto MIBMin128 = B.buildFMinNum(S128, MIBExt, MIBExt); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMin32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMin64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMin128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &fminf + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &fmin + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &fminl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFMaxNum) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FMAXNUM).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBMax32 = B.buildFMaxNum(S32, MIBTrunc, MIBTrunc); + auto MIBMax64 = B.buildFMaxNum(S64, Copies[0], Copies[0]); + auto MIBMax128 = B.buildFMaxNum(S128, MIBExt, MIBExt); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMax32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMax64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBMax128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: $s1 = COPY [[TRUNC]] + CHECK: BL &fmaxf + CHECK: $d0 = COPY [[COPY]] + CHECK: $d1 = COPY [[COPY]] + CHECK: BL &fmax + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: $q1 = COPY [[ANYEXT]] + CHECK: BL &fmaxl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFSqrt) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FSQRT).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBSqrt32 = B.buildInstr(TargetOpcode::G_FSQRT, {S32}, {MIBTrunc}); + auto MIBSqrt64 = B.buildInstr(TargetOpcode::G_FSQRT, {S64}, {Copies[0]}); + auto MIBSqrt128 = B.buildInstr(TargetOpcode::G_FSQRT, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSqrt32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSqrt64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBSqrt128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &sqrtf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &sqrt + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &sqrtl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFRint) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FRINT).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBRint32 = B.buildInstr(TargetOpcode::G_FRINT, {S32}, {MIBTrunc}); + auto MIBRint64 = B.buildInstr(TargetOpcode::G_FRINT, {S64}, {Copies[0]}); + auto MIBRint128 = B.buildInstr(TargetOpcode::G_FRINT, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBRint32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBRint64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBRint128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &rintf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &rint + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &rintl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(GISelMITest, LibcallFNearbyInt) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_FNEARBYINT).libcallFor({s32, s64, s128}); + }); + + LLT S32{LLT::scalar(32)}; + LLT S64{LLT::scalar(64)}; + LLT S128{LLT::scalar(128)}; + auto MIBTrunc = B.buildTrunc(S32, Copies[0]); + auto MIBExt = B.buildAnyExt(S128, Copies[0]); + + auto MIBNearbyInt32 = + B.buildInstr(TargetOpcode::G_FNEARBYINT, {S32}, {MIBTrunc}); + auto MIBNearbyInt64 = + B.buildInstr(TargetOpcode::G_FNEARBYINT, {S64}, {Copies[0]}); + auto MIBNearbyInt128 = + B.buildInstr(TargetOpcode::G_FNEARBYINT, {S128}, {MIBExt}); + + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBNearbyInt32)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBNearbyInt64)); + EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, + Helper.libcall(*MIBNearbyInt128)); + + const auto *CheckStr = R"( + CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY + CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC + CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT + CHECK: $s0 = COPY [[TRUNC]] + CHECK: BL &nearbyintf + CHECK: $d0 = COPY [[COPY]] + CHECK: BL &nearbyint + CHECK: $q0 = COPY [[ANYEXT]] + CHECK: BL &nearbyintl + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} } // namespace