Skip to content

Commit eb803df

Browse files
[AArch64][GlobalISel] Add G_FMODF instruction (#160061)
This commit adds the intrinsic `G_FMODF` to GMIR & enables its translation, legalization and instruction selection in AArch64.
1 parent 04c01ff commit eb803df

File tree

16 files changed

+826
-229
lines changed

16 files changed

+826
-229
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ class LegalizerHelper {
300300
Type *OpType,
301301
LostDebugLocObserver &LocObserver);
302302

303+
LegalizeResult emitModfLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
304+
unsigned Size, Type *OpType,
305+
LostDebugLocObserver &LocObserver);
306+
303307
public:
304308
/// Return the alignment to use for a stack temporary object with the given
305309
/// type.

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,13 @@ class LLVM_ABI MachineIRBuilder {
21842184
return buildInstr(TargetOpcode::G_FSINCOS, {Sin, Cos}, {Src}, Flags);
21852185
}
21862186

2187+
/// Build and insert \p Fract, \p Int = G_FMODF \p Src
2188+
MachineInstrBuilder buildModf(const DstOp &Fract, const DstOp &Int,
2189+
const SrcOp &Src,
2190+
std::optional<unsigned> Flags = std::nullopt) {
2191+
return buildInstr(TargetOpcode::G_FMODF, {Fract, Int}, {Src}, Flags);
2192+
}
2193+
21872194
/// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1
21882195
MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0,
21892196
const SrcOp &Src1) {

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ HANDLE_TARGET_OPCODE(G_FDIV)
650650
/// Generic FP remainder.
651651
HANDLE_TARGET_OPCODE(G_FREM)
652652

653+
/// Generic FP modf
654+
HANDLE_TARGET_OPCODE(G_FMODF)
655+
653656
/// Generic FP exponentiation.
654657
HANDLE_TARGET_OPCODE(G_FPOW)
655658

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,13 @@ def G_FREM : GenericInstruction {
981981
let hasSideEffects = false;
982982
}
983983

984+
/// Generic FP modf
985+
def G_FMODF : GenericInstruction {
986+
let OutOperandList = (outs type0:$dst1, type0:$dst2);
987+
let InOperandList = (ins type0:$src1);
988+
let hasSideEffects = false;
989+
}
990+
984991
// Floating point exponentiation.
985992
def G_FPOW : GenericInstruction {
986993
let OutOperandList = (outs type0:$dst);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,6 +2362,13 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
23622362
MachineInstr::copyFlagsFromInstruction(CI));
23632363
return true;
23642364
}
2365+
case Intrinsic::modf: {
2366+
ArrayRef<Register> VRegs = getOrCreateVRegs(CI);
2367+
MIRBuilder.buildModf(VRegs[0], VRegs[1],
2368+
getOrCreateVReg(*CI.getArgOperand(0)),
2369+
MachineInstr::copyFlagsFromInstruction(CI));
2370+
return true;
2371+
}
23652372
case Intrinsic::sincos: {
23662373
ArrayRef<Register> VRegs = getOrCreateVRegs(CI);
23672374
MIRBuilder.buildFSincos(VRegs[0], VRegs[1],

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
471471
RTLIBCASE(TANH_F);
472472
case TargetOpcode::G_FSINCOS:
473473
RTLIBCASE(SINCOS_F);
474+
case TargetOpcode::G_FMODF:
475+
RTLIBCASE(MODF_F);
474476
case TargetOpcode::G_FLOG10:
475477
RTLIBCASE(LOG10_F);
476478
case TargetOpcode::G_FLOG:
@@ -702,6 +704,46 @@ LegalizerHelper::LegalizeResult LegalizerHelper::emitSincosLibcall(
702704
return LegalizerHelper::Legalized;
703705
}
704706

707+
LegalizerHelper::LegalizeResult
708+
LegalizerHelper::emitModfLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
709+
unsigned Size, Type *OpType,
710+
LostDebugLocObserver &LocObserver) {
711+
MachineFunction &MF = MIRBuilder.getMF();
712+
MachineRegisterInfo &MRI = MF.getRegInfo();
713+
714+
Register DstFrac = MI.getOperand(0).getReg();
715+
Register DstInt = MI.getOperand(1).getReg();
716+
Register Src = MI.getOperand(2).getReg();
717+
LLT DstTy = MRI.getType(DstFrac);
718+
719+
int MemSize = DstTy.getSizeInBytes();
720+
Align Alignment = getStackTemporaryAlignment(DstTy);
721+
const DataLayout &DL = MIRBuilder.getDataLayout();
722+
unsigned AddrSpace = DL.getAllocaAddrSpace();
723+
MachinePointerInfo PtrInfo;
724+
725+
Register StackPtrInt =
726+
createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo)
727+
.getReg(0);
728+
729+
auto &Ctx = MF.getFunction().getContext();
730+
auto LibcallResult = createLibcall(
731+
MIRBuilder, getRTLibDesc(MI.getOpcode(), Size), {DstFrac, OpType, 0},
732+
{{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
733+
LocObserver, &MI);
734+
735+
if (LibcallResult != LegalizeResult::Legalized)
736+
return LegalizerHelper::UnableToLegalize;
737+
738+
MachineMemOperand *LoadMMOInt = MF.getMachineMemOperand(
739+
PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment);
740+
741+
MIRBuilder.buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
742+
MI.eraseFromParent();
743+
744+
return LegalizerHelper::Legalized;
745+
}
746+
705747
LegalizerHelper::LegalizeResult
706748
llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
707749
MachineInstr &MI, LostDebugLocObserver &LocObserver) {
@@ -1341,6 +1383,16 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
13411383
}
13421384
return emitSincosLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
13431385
}
1386+
case TargetOpcode::G_FMODF: {
1387+
LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
1388+
unsigned Size = LLTy.getSizeInBits();
1389+
Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
1390+
if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
1391+
LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
1392+
return UnableToLegalize;
1393+
}
1394+
return emitModfLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
1395+
}
13441396
case TargetOpcode::G_LROUND:
13451397
case TargetOpcode::G_LLROUND:
13461398
case TargetOpcode::G_INTRINSIC_LRINT:
@@ -3333,6 +3385,16 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
33333385
widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
33343386
Observer.changedInstr(MI);
33353387
return Legalized;
3388+
case TargetOpcode::G_FMODF: {
3389+
Observer.changingInstr(MI);
3390+
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
3391+
3392+
widenScalarDst(MI, WideTy, 1, TargetOpcode::G_FPTRUNC);
3393+
MIRBuilder.setInsertPt(MIRBuilder.getMBB(), --MIRBuilder.getInsertPt());
3394+
widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
3395+
Observer.changedInstr(MI);
3396+
return Legalized;
3397+
}
33363398
case TargetOpcode::G_FPOWI:
33373399
case TargetOpcode::G_FLDEXP:
33383400
case TargetOpcode::G_STRICT_FLDEXP: {
@@ -5472,6 +5534,7 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
54725534
case G_LROUND:
54735535
case G_LLROUND:
54745536
case G_INTRINSIC_TRUNC:
5537+
case G_FMODF:
54755538
case G_FCOS:
54765539
case G_FSIN:
54775540
case G_FTAN:

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
438438
getActionDefinitionsBuilder({G_FCOS, G_FSIN, G_FPOW, G_FLOG, G_FLOG2,
439439
G_FLOG10, G_FTAN, G_FEXP, G_FEXP2, G_FEXP10,
440440
G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH,
441-
G_FSINH, G_FTANH})
441+
G_FSINH, G_FTANH, G_FMODF})
442442
// We need a call for these, so we always need to scalarize.
443443
.scalarize(0)
444444
// Regardless of FP16 support, widen 16-bit elements to 32-bits.

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
752752
return selectExtInst(ResVReg, ResType, I, CL::exp, GL::Exp);
753753
case TargetOpcode::G_FEXP2:
754754
return selectExtInst(ResVReg, ResType, I, CL::exp2, GL::Exp2);
755+
case TargetOpcode::G_FMODF:
756+
return selectModf(ResVReg, ResType, I);
755757

756758
case TargetOpcode::G_FLOG:
757759
return selectExtInst(ResVReg, ResType, I, CL::log, GL::Log);
@@ -3453,9 +3455,6 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
34533455
case Intrinsic::spv_discard: {
34543456
return selectDiscard(ResVReg, ResType, I);
34553457
}
3456-
case Intrinsic::modf: {
3457-
return selectModf(ResVReg, ResType, I);
3458-
}
34593458
default: {
34603459
std::string DiagMsg;
34613460
raw_string_ostream OS(DiagMsg);
@@ -4268,6 +4267,7 @@ bool SPIRVInstructionSelector::selectModf(Register ResVReg,
42684267
PtrTyReg,
42694268
LLT::pointer(storageClassToAddressSpace(SPIRV::StorageClass::Function),
42704269
GR.getPointerSize()));
4270+
42714271
// Assign SPIR-V type of the pointer type of the alloca variable to the
42724272
// new register.
42734273
GR.assignSPIRVTypeToVReg(PtrType, PtrTyReg, MIRBuilder.getMF());
@@ -4280,10 +4280,7 @@ bool SPIRVInstructionSelector::selectModf(Register ResVReg,
42804280
.addUse(GR.getSPIRVTypeID(PtrType))
42814281
.addImm(static_cast<uint32_t>(SPIRV::StorageClass::Function));
42824282
Register Variable = AllocaMIB->getOperand(0).getReg();
4283-
// Modf must have 4 operands, the first two are the 2 parts of the result,
4284-
// the third is the operand, and the last one is the floating point value.
4285-
assert(I.getNumOperands() == 4 &&
4286-
"Expected 4 operands for modf instruction");
4283+
42874284
MachineBasicBlock &BB = *I.getParent();
42884285
// Create the OpenCLLIB::modf instruction.
42894286
auto MIB =
@@ -4293,8 +4290,8 @@ bool SPIRVInstructionSelector::selectModf(Register ResVReg,
42934290
.addImm(static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
42944291
.addImm(CL::modf)
42954292
.setMIFlags(I.getFlags())
4296-
.add(I.getOperand(3)) // Floating point value.
4297-
.addUse(Variable); // Pointer to integral part.
4293+
.add(I.getOperand(I.getNumExplicitDefs())) // Floating point value.
4294+
.addUse(Variable); // Pointer to integral part.
42984295
// Assign the integral part stored in the ptr to the second element of the
42994296
// result.
43004297
Register IntegralPartReg = I.getOperand(1).getReg();

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
300300
getActionDefinitionsBuilder({G_STRICT_FSQRT,
301301
G_FPOW,
302302
G_FEXP,
303+
G_FMODF,
303304
G_FEXP2,
304305
G_FLOG,
305306
G_FLOG2,

0 commit comments

Comments
 (0)