llvm_unreachable("not yet handled");
}
+static Type *getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty) {
+
+ if (!Ty.isScalar())
+ return nullptr;
+
+ switch (Ty.getSizeInBits()) {
+ case 16:
+ return Type::getHalfTy(Ctx);
+ case 32:
+ return Type::getFloatTy(Ctx);
+ case 64:
+ return Type::getDoubleTy(Ctx);
+ case 128:
+ return Type::getFP128Ty(Ctx);
+ default:
+ return nullptr;
+ }
+}
+
LegalizerHelper::LegalizerHelper(MachineFunction &MF,
GISelChangeObserver &Observer,
MachineIRBuilder &Builder)
case TargetOpcode::G_FEXP2:
case TargetOpcode::G_FCEIL:
case TargetOpcode::G_FFLOOR: {
- if (Size > 64) {
- LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
+ Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
+ if (!HLTy || (Size != 32 && Size != 64)) {
+ LLVM_DEBUG(dbgs() << "No libcall available for size " << Size << ".\n");
return UnableToLegalize;
}
- Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
if (Status != Legalized)
return Status;
break;
}
- case TargetOpcode::G_FPEXT: {
- // FIXME: Support other floating point types (half, fp128 etc)
- unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
- unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
- if (ToSize != 64 || FromSize != 32)
- return UnableToLegalize;
- LegalizeResult Status = conversionLibcall(
- MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
- if (Status != Legalized)
- return Status;
- break;
- }
+ case TargetOpcode::G_FPEXT:
case TargetOpcode::G_FPTRUNC: {
- // FIXME: Support other floating point types (half, fp128 etc)
- unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
- unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
- if (ToSize != 32 || FromSize != 64)
+ Type *FromTy = getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(1).getReg()));
+ Type *ToTy = getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(0).getReg()));
+ if (!FromTy || !ToTy)
return UnableToLegalize;
- LegalizeResult Status = conversionLibcall(
- MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
+ LegalizeResult Status = conversionLibcall(MI, MIRBuilder, ToTy, FromTy );
if (Status != Legalized)
return Status;
break;
if (Ty.isVector())
return UnableToLegalize;
Register Res = MI.getOperand(0).getReg();
- Type *ZeroTy;
LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
- switch (Ty.getSizeInBits()) {
- case 16:
- ZeroTy = Type::getHalfTy(Ctx);
- break;
- case 32:
- ZeroTy = Type::getFloatTy(Ctx);
- break;
- case 64:
- ZeroTy = Type::getDoubleTy(Ctx);
- break;
- case 128:
- ZeroTy = Type::getFP128Ty(Ctx);
- break;
- default:
- llvm_unreachable("unexpected floating-point type");
- }
+ Type *ZeroTy = getFloatTypeForLLT(Ctx, Ty);
+ if (!ZeroTy)
+ return UnableToLegalize;
ConstantFP &ZeroForNegation =
*cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
// Check
ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
}
+
+TEST_F(GISelMITest, LibcallFPExt) {
+ setUp();
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(A, {
+ getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}});
+ });
+
+ LLT S16{LLT::scalar(16)};
+ LLT S32{LLT::scalar(32)};
+ LLT S128{LLT::scalar(128)};
+ auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
+ auto MIBFPExt1 =
+ B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc});
+
+ auto MIBFPExt2 =
+ B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
+ AInfo Info(MF->getSubtarget());
+ DummyGISelObserver Observer;
+ LegalizerHelper Helper(*MF, Info, Observer, B);
+ EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
+ Helper.libcall(*MIBFPExt1));
+
+ EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
+ Helper.libcall(*MIBFPExt2));
+ auto CheckStr = R"(
+ CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC
+ CHECK: $h0 = COPY [[TRUNC]]
+ CHECK: BL &__gnu_h2f_ieee
+ CHECK: $d0 = COPY
+ CHECK: BL &__extenddftf2
+ )";
+
+ // Check
+ EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
+}
+
+TEST_F(GISelMITest, LibcallFPTrunc) {
+ setUp();
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(A, {
+ getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}});
+ });
+
+ LLT S16{LLT::scalar(16)};
+ LLT S32{LLT::scalar(32)};
+ LLT S64{LLT::scalar(64)};
+ LLT S128{LLT::scalar(128)};
+ auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
+ auto MIBFPTrunc1 =
+ B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc});
+
+ auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]});
+
+ auto MIBFPTrunc2 =
+ B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge});
+ AInfo Info(MF->getSubtarget());
+ DummyGISelObserver Observer;
+ LegalizerHelper Helper(*MF, Info, Observer, B);
+ EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
+ Helper.libcall(*MIBFPTrunc1));
+
+ EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
+ Helper.libcall(*MIBFPTrunc2));
+ auto CheckStr = R"(
+ CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
+ CHECK: $s0 = COPY [[TRUNC]]
+ CHECK: BL &__gnu_f2h_ieee
+ CHECK: $q0 = COPY
+ CHECK: BL &__trunctfdf2
+ )";
+
+ // Check
+ EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
+}
+
+TEST_F(GISelMITest, LibcallSimple) {
+ setUp();
+ if (!TM)
+ return;
+
+ // Declare your legalization info
+ DefineLegalizerInfo(A, {
+ getActionDefinitionsBuilder(G_FADD).libcallFor({s16});
+ });
+
+ LLT S16{LLT::scalar(16)};
+ auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
+ auto MIBFADD =
+ B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc});
+
+ AInfo Info(MF->getSubtarget());
+ DummyGISelObserver Observer;
+ LegalizerHelper Helper(*MF, Info, Observer, B);
+ // Make sure we do not crash anymore
+ EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
+ Helper.libcall(*MIBFADD));
+}
} // namespace