Skip to content

Commit 7a0eda5

Browse files
committed
Lower spv_bitcast in instruction lowering instead of prelegalization.
1 parent 50f19ff commit 7a0eda5

File tree

5 files changed

+68
-41
lines changed

5 files changed

+68
-41
lines changed

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
594594
bool HasDefs = I.getNumDefs() > 0;
595595
Register ResVReg = HasDefs ? I.getOperand(0).getReg() : Register(0);
596596
SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) : nullptr;
597+
I.dump();
597598
assert(!HasDefs || ResType || I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
598599
I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
599600
if (spvSelect(ResVReg, ResType, I)) {
@@ -3143,6 +3144,14 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
31433144
return selectInsertElt(ResVReg, ResType, I);
31443145
case Intrinsic::spv_gep:
31453146
return selectGEP(ResVReg, ResType, I);
3147+
case Intrinsic::spv_bitcast: {
3148+
Register OpReg = I.getOperand(2).getReg();
3149+
SPIRVType *OpType =
3150+
OpReg.isValid() ? GR.getSPIRVTypeForVReg(OpReg) : nullptr;
3151+
if (!GR.isBitcastCompatible(ResType, OpType))
3152+
report_fatal_error("incompatible result and operand types in a bitcast");
3153+
return selectOpWithSrcs(ResVReg, ResType, I, {OpReg}, SPIRV::OpBitcast);
3154+
}
31463155
case Intrinsic::spv_unref_global:
31473156
case Intrinsic::spv_init_global: {
31483157
MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "SPIRV.h"
1515
#include "SPIRVGlobalRegistry.h"
1616
#include "SPIRVSubtarget.h"
17+
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
1718
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1819
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1920
#include "llvm/CodeGen/MachineInstr.h"
@@ -188,7 +189,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
188189
LegalizeMutations::changeElementCountTo(
189190
0, ElementCount::getFixed(4)))
190191
.lowerIf(vectorElementCountIsGreaterThan(1, 4))
191-
.alwaysLegal();
192+
.custom();
192193
getActionDefinitionsBuilder(G_CONCAT_VECTORS)
193194
.legalFor(allShaderVectors)
194195
.lower();
@@ -415,6 +416,11 @@ bool SPIRVLegalizerInfo::legalizeCustom(
415416
default:
416417
// TODO: implement legalization for other opcodes.
417418
return true;
419+
case TargetOpcode::G_BITCAST:
420+
return legalizeBitcast(Helper, MI);
421+
case TargetOpcode::G_INTRINSIC:
422+
return legalizeIntrinsic(Helper, MI);
423+
418424
case TargetOpcode::G_IS_FPCLASS:
419425
return legalizeIsFPClass(Helper, MI, LocObserver);
420426
case TargetOpcode::G_ICMP: {
@@ -441,6 +447,41 @@ bool SPIRVLegalizerInfo::legalizeCustom(
441447
}
442448
}
443449

450+
bool SPIRVLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
451+
MachineInstr &MI) const {
452+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
453+
MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
454+
455+
auto IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
456+
if (IntrinsicID == Intrinsic::spv_bitcast) {
457+
Register DstReg = MI.getOperand(0).getReg();
458+
Register SrcReg = MI.getOperand(2).getReg();
459+
LLT DstTy = MRI.getType(DstReg);
460+
LLT SrcTy = MRI.getType(SrcReg);
461+
462+
bool isLongVector = (DstTy.isVector() && DstTy.getNumElements() > 4) ||
463+
(SrcTy.isVector() && SrcTy.getNumElements() > 4);
464+
465+
if (isLongVector) {
466+
MIRBuilder.buildBitcast(DstReg, SrcReg);
467+
MI.eraseFromParent();
468+
}
469+
return true;
470+
}
471+
return true;
472+
}
473+
474+
bool SPIRVLegalizerInfo::legalizeBitcast(LegalizerHelper &Helper,
475+
MachineInstr &MI) const {
476+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
477+
Register DstReg = MI.getOperand(0).getReg();
478+
Register SrcReg = MI.getOperand(1).getReg();
479+
SmallVector<Register, 1> DstRegs = {DstReg};
480+
MIRBuilder.buildIntrinsic(Intrinsic::spv_bitcast, DstRegs).addUse(SrcReg);
481+
MI.eraseFromParent();
482+
return true;
483+
}
484+
444485
// Note this code was copied from LegalizerHelper::lowerISFPCLASS and adjusted
445486
// to ensure that all instructions created during the lowering have SPIR-V types
446487
// assigned to them.

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@ class SPIRVLegalizerInfo : public LegalizerInfo {
2929
public:
3030
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
3131
LostDebugLocObserver &LocObserver) const override;
32+
bool legalizeIntrinsic(LegalizerHelper &Helper,
33+
MachineInstr &MI) const override;
34+
3235
SPIRVLegalizerInfo(const SPIRVSubtarget &ST);
3336

3437
private:
3538
bool legalizeIsFPClass(LegalizerHelper &Helper, MachineInstr &MI,
3639
LostDebugLocObserver &LocObserver) const;
40+
bool legalizeBitcast(LegalizerHelper &Helper, MachineInstr &MI) const;
3741
};
3842
} // namespace llvm
3943
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMACHINELEGALIZER_H

llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ static bool mayBeInserted(unsigned Opcode) {
4949
case TargetOpcode::G_CONSTANT:
5050
case TargetOpcode::G_UNMERGE_VALUES:
5151
case TargetOpcode::G_EXTRACT_VECTOR_ELT:
52-
case TargetOpcode::G_BITCAST:
52+
case TargetOpcode::G_INTRINSIC:
53+
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
5354
case TargetOpcode::G_SMAX:
5455
case TargetOpcode::G_UMAX:
5556
case TargetOpcode::G_SMIN:
@@ -201,7 +202,11 @@ static bool processInstr(MachineInstr *I, MachineFunction &MF,
201202
}
202203
break;
203204
}
204-
case TargetOpcode::G_BITCAST: {
205+
case TargetOpcode::G_INTRINSIC:
206+
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
207+
if (!isSpvIntrinsic(*I, Intrinsic::spv_bitcast))
208+
break;
209+
205210
for (const auto &Use : MRI.use_nodbg_instructions(ResVReg)) {
206211
const unsigned UseOpc = Use.getOpcode();
207212
assert(UseOpc == TargetOpcode::G_EXTRACT_VECTOR_ELT ||
@@ -326,13 +331,10 @@ bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
326331

327332
// TODO: Move this into is own function.
328333
SmallVector<MachineInstr *, 8> ExtractInstrs;
329-
SmallVector<MachineInstr *, 8> BitcastInstrs;
330334
for (MachineBasicBlock &MBB : MF) {
331335
for (MachineInstr &MI : MBB) {
332336
if (MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT) {
333337
ExtractInstrs.push_back(&MI);
334-
} else if (MI.getOpcode() == TargetOpcode::G_BITCAST) {
335-
BitcastInstrs.push_back(&MI);
336338
}
337339
}
338340
}
@@ -343,27 +345,12 @@ bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
343345
Register Vec = MI->getOperand(1).getReg();
344346
Register Idx = MI->getOperand(2).getReg();
345347

346-
auto Intr =
347-
MIB.buildIntrinsic(Intrinsic::spv_extractelt, Dst, false, false);
348+
auto Intr = MIB.buildIntrinsic(Intrinsic::spv_extractelt, Dst, true, false);
348349
Intr.addUse(Vec);
349350
Intr.addUse(Idx);
350351

351352
MI->eraseFromParent();
352353
}
353-
354-
for (MachineInstr *MI : BitcastInstrs) {
355-
MachineIRBuilder MIB(*MI);
356-
Register Dst = MI->getOperand(0).getReg();
357-
Register Src = MI->getOperand(1).getReg();
358-
SPIRVType *DstType = GR->getSPIRVTypeForVReg(Dst);
359-
assert(DstType && "Destination of G_BITCAST must have a type");
360-
MIB.buildInstr(SPIRV::OpBitcast)
361-
.addDef(Dst)
362-
.addUse(GR->getSPIRVTypeID(DstType))
363-
.addUse(Src);
364-
MI->eraseFromParent();
365-
}
366-
367354
return true;
368355
}
369356

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -216,29 +216,15 @@ static void buildOpBitcast(SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
216216
// in https://github.com/llvm/llvm-project/pull/110270 for even more context.
217217
static void selectOpBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
218218
MachineIRBuilder MIB) {
219-
// TODO: This change will still cause failures for the machine verifier.
220-
// This is done so that the G_Bitcast legalization rules can be used.
221-
// We will have to add rules to legalize the intrinsic. Note that we cannot
222-
// try to lower only bitcast the verify will complain about. You could cast
223-
// a long vector of float to a long vector of ints. That has to be legalized
224-
// but is also an invalid G_Bitcast.
225-
//
226-
// Could we use G_COPY? for cases where the LLT are the same? Then lowering
227-
// the G_COPY could be either an OpBitcast or OpCopyObject denpending on the
228-
// source and result type.
229-
230-
MachineRegisterInfo &MRI = MF.getRegInfo();
231219
SmallVector<MachineInstr *, 16> ToErase;
232220
for (MachineBasicBlock &MBB : MF) {
233221
for (MachineInstr &MI : MBB) {
234222
if (MI.getOpcode() != TargetOpcode::G_BITCAST)
235223
continue;
236-
Register DstReg = MI.getOperand(0).getReg();
237-
if (MRI.getType(DstReg).isPointer()) {
238-
MIB.setInsertPt(*MI.getParent(), MI);
239-
buildOpBitcast(GR, MIB, DstReg, MI.getOperand(1).getReg());
240-
ToErase.push_back(&MI);
241-
}
224+
MIB.setInsertPt(*MI.getParent(), MI);
225+
buildOpBitcast(GR, MIB, MI.getOperand(0).getReg(),
226+
MI.getOperand(1).getReg());
227+
ToErase.push_back(&MI);
242228
}
243229
}
244230
for (MachineInstr *MI : ToErase) {
@@ -255,7 +241,7 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
255241
SmallVector<MachineInstr *, 10> ToErase;
256242
for (MachineBasicBlock &MBB : MF) {
257243
for (MachineInstr &MI : MBB) {
258-
if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast) &&
244+
if (/* !isSpvIntrinsic(MI, Intrinsic::spv_bitcast) && */
259245
!isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
260246
continue;
261247
assert(MI.getOperand(2).isReg());

0 commit comments

Comments
 (0)