Skip to content

Commit 7a8a829

Browse files
s-perronkcloudy0717
authored andcommitted
[SPIR-V] Move ASSIGN_TYPE generation to PostLegalizer (llvm#169696)
Moves the insertion of SPIRV::ASSIGN_TYPE for type-folded instructions from the PreLegalizer to the PostLegalizer. This allows the legalizer to do more because the ASSIGN_TYPE instructions do not get in the way.
1 parent b300746 commit 7a8a829

File tree

4 files changed

+94
-120
lines changed

4 files changed

+94
-120
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -533,14 +533,11 @@ static Register buildBuiltinVariableLoad(
533533
return LoadedRegister;
534534
}
535535

536-
/// Helper external function for inserting ASSIGN_TYPE instuction between \p Reg
537-
/// and its definition, set the new register as a destination of the definition,
538-
/// assign SPIRVType to both registers. If SpirvTy is provided, use it as
539-
/// SPIRVType in ASSIGN_TYPE, otherwise create it from \p Ty. Defined in
540-
/// SPIRVPreLegalizer.cpp.
541-
extern void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
542-
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
543-
MachineRegisterInfo &MRI);
536+
/// Helper external function for assigning SPIRVType to a register, ensuring the
537+
/// register class and type are set in MRI. Defined in SPIRVPreLegalizer.cpp.
538+
extern void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy,
539+
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
540+
MachineRegisterInfo &MRI);
544541

545542
// TODO: Move to TableGen.
546543
static SPIRV::MemorySemantics::MemorySemantics
@@ -860,8 +857,8 @@ static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode,
860857
MIRBuilder.buildInstr(TargetOpcode::G_FNEG)
861858
.addDef(NegValueReg)
862859
.addUse(ValueReg);
863-
insertAssignInstr(NegValueReg, nullptr, Call->ReturnType, GR, MIRBuilder,
864-
MIRBuilder.getMF().getRegInfo());
860+
updateRegType(NegValueReg, nullptr, Call->ReturnType, GR, MIRBuilder,
861+
MIRBuilder.getMF().getRegInfo());
865862
ValueReg = NegValueReg;
866863
}
867864
}
@@ -1285,8 +1282,8 @@ static bool generateGroupInst(const SPIRV::IncomingCall *Call,
12851282
MIRBuilder.buildICmp(
12861283
CmpInst::ICMP_NE, Arg0, BoolReg,
12871284
GR->buildConstantInt(0, MIRBuilder, BoolRegType, true));
1288-
insertAssignInstr(Arg0, nullptr, BoolType, GR, MIRBuilder,
1289-
MIRBuilder.getMF().getRegInfo());
1285+
updateRegType(Arg0, nullptr, BoolType, GR, MIRBuilder,
1286+
MIRBuilder.getMF().getRegInfo());
12901287
} else if (BoolRegType->getOpcode() != SPIRV::OpTypeBool) {
12911288
report_fatal_error("Expect a boolean argument");
12921289
}
@@ -1337,8 +1334,8 @@ static bool generateGroupInst(const SPIRV::IncomingCall *Call,
13371334
MIB.addUse(Call->Arguments[i]);
13381335
setRegClassIfNull(Call->Arguments[i], MRI, GR);
13391336
}
1340-
insertAssignInstr(VecReg, nullptr, VecType, GR, MIRBuilder,
1341-
MIRBuilder.getMF().getRegInfo());
1337+
updateRegType(VecReg, nullptr, VecType, GR, MIRBuilder,
1338+
MIRBuilder.getMF().getRegInfo());
13421339
}
13431340

13441341
// Build work/sub group instruction.
@@ -1603,8 +1600,7 @@ static bool genWorkgroupQuery(const SPIRV::IncomingCall *Call,
16031600

16041601
// If the index is dynamic, need check if it's < 3, and then use a select.
16051602
if (!IsConstantIndex) {
1606-
insertAssignInstr(Extracted, nullptr, PointerSizeType, GR, MIRBuilder,
1607-
*MRI);
1603+
updateRegType(Extracted, nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
16081604

16091605
auto IndexType = GR->getSPIRVTypeForVReg(IndexRegister);
16101606
auto BoolType = GR->getOrCreateSPIRVBoolType(MIRBuilder, true);
@@ -1992,8 +1988,8 @@ static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call,
19921988
.addUse(QueryResult)
19931989
.addImm(ExtractedComposite);
19941990
if (NewType != nullptr)
1995-
insertAssignInstr(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,
1996-
MIRBuilder.getMF().getRegInfo());
1991+
updateRegType(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,
1992+
MIRBuilder.getMF().getRegInfo());
19971993
} else {
19981994
// More than 1 component is expected, fill a new vector.
19991995
auto MIB = MIRBuilder.buildInstr(SPIRV::OpVectorShuffle)
@@ -2766,8 +2762,8 @@ static bool generateAsyncCopy(const SPIRV::IncomingCall *Call,
27662762
: buildConstantIntReg32(1, MIRBuilder, GR))
27672763
.addUse(EventReg);
27682764
if (NewType != nullptr)
2769-
insertAssignInstr(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,
2770-
MIRBuilder.getMF().getRegInfo());
2765+
updateRegType(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,
2766+
MIRBuilder.getMF().getRegInfo());
27712767
return Res;
27722768
}
27732769
case SPIRV::OpGroupWaitEvents:

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
276276
}
277277

278278
// Get or create a SPIR-V type corresponding the given LLVM IR type,
279-
// and map it to the given VReg by creating an ASSIGN_TYPE instruction.
279+
// and map it to the given VReg.
280280
SPIRVType *assignTypeToVReg(const Type *Type, Register VReg,
281281
MachineIRBuilder &MIRBuilder,
282282
SPIRV::AccessQualifier::AccessQualifier AQ,
@@ -290,7 +290,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
290290
const SPIRVInstrInfo &TII);
291291

292292
// In cases where the SPIR-V type is already known, this function can be
293-
// used to map it to the given VReg via an ASSIGN_TYPE instruction.
293+
// used to map it to the given VReg.
294294
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg,
295295
const MachineFunction &MF);
296296

llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
//===-- SPIRVPostLegalizer.cpp - ammend info after legalization -*- C++ -*-===//
2-
//
3-
// which may appear after the legalizer pass
1+
//===-- SPIRVPostLegalizer.cpp - amend info after legalization -*- C++ -*-===//
42
//
53
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
64
// See https://llvm.org/LICENSE.txt for license information.
75
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
86
//
97
//===----------------------------------------------------------------------===//
108
//
11-
// The pass partially apply pre-legalization logic to new instructions inserted
12-
// as a result of legalization:
9+
// The pass partially applies pre-legalization logic to new instructions
10+
// inserted as a result of legalization:
1311
// - assigns SPIR-V types to registers for new instructions.
12+
// - inserts ASSIGN_TYPE pseudo-instructions required for type folding.
1413
//
1514
//===----------------------------------------------------------------------===//
1615

@@ -36,9 +35,9 @@ class SPIRVPostLegalizer : public MachineFunctionPass {
3635

3736
namespace llvm {
3837
// Defined in SPIRVPreLegalizer.cpp.
39-
extern void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
40-
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
41-
MachineRegisterInfo &MRI);
38+
extern void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy,
39+
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
40+
MachineRegisterInfo &MRI);
4241
extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
4342
MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR,
4443
SPIRVType *KnownResType);
@@ -314,6 +313,54 @@ static void registerSpirvTypeForNewInstructions(MachineFunction &MF,
314313
}
315314
}
316315

316+
static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI) {
317+
for (MachineInstr &UseInstr : MRI.use_nodbg_instructions(Reg)) {
318+
if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
319+
return true;
320+
}
321+
}
322+
return false;
323+
}
324+
325+
static void generateAssignType(MachineInstr &MI, Register ResultRegister,
326+
SPIRVType *ResultType, SPIRVGlobalRegistry *GR,
327+
MachineRegisterInfo &MRI) {
328+
LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
329+
<< printReg(ResultRegister, MRI.getTargetRegisterInfo())
330+
<< " with type: " << *ResultType);
331+
MachineIRBuilder MIB(MI);
332+
updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
333+
334+
// Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
335+
// present after each auto-folded instruction to take a type reference
336+
// from.
337+
Register NewReg =
338+
MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));
339+
const auto *RegClass = GR->getRegClass(ResultType);
340+
MRI.setRegClass(NewReg, RegClass);
341+
MRI.setRegClass(ResultRegister, RegClass);
342+
343+
GR->assignSPIRVTypeToVReg(ResultType, ResultRegister, MIB.getMF());
344+
// This is to make it convenient for Legalizer to get the SPIRVType
345+
// when processing the actual MI (i.e. not pseudo one).
346+
GR->assignSPIRVTypeToVReg(ResultType, NewReg, MIB.getMF());
347+
// Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to
348+
// keep the flags after instruction selection.
349+
const uint32_t Flags = MI.getFlags();
350+
MIB.buildInstr(SPIRV::ASSIGN_TYPE)
351+
.addDef(ResultRegister)
352+
.addUse(NewReg)
353+
.addUse(GR->getSPIRVTypeID(ResultType))
354+
.setMIFlags(Flags);
355+
for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
356+
MachineOperand &MO = MI.getOperand(I);
357+
if (MO.getReg() == ResultRegister) {
358+
MO.setReg(NewReg);
359+
break;
360+
}
361+
}
362+
}
363+
317364
static void ensureAssignTypeForTypeFolding(MachineFunction &MF,
318365
SPIRVGlobalRegistry *GR) {
319366
LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
@@ -323,35 +370,18 @@ static void ensureAssignTypeForTypeFolding(MachineFunction &MF,
323370
for (MachineInstr &MI : MBB) {
324371
if (!isTypeFoldingSupported(MI.getOpcode()))
325372
continue;
326-
if (MI.getNumOperands() == 1 || !MI.getOperand(1).isReg())
327-
continue;
328373

329374
LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
330375

331-
// Check uses of MI to see if it already has an use in SPIRV::ASSIGN_TYPE
332-
bool HasAssignType = false;
333376
Register ResultRegister = MI.defs().begin()->getReg();
334-
// All uses of Result register
335-
for (MachineInstr &UseInstr :
336-
MRI.use_nodbg_instructions(ResultRegister)) {
337-
if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
338-
HasAssignType = true;
339-
LLVM_DEBUG(dbgs() << " Instruction already has an ASSIGN_TYPE use: "
340-
<< UseInstr);
341-
break;
342-
}
377+
if (hasAssignType(ResultRegister, MRI)) {
378+
LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
379+
continue;
343380
}
344381

345-
if (!HasAssignType) {
346-
Register ResultRegister = MI.defs().begin()->getReg();
347-
SPIRVType *ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
348-
LLVM_DEBUG(
349-
dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
350-
<< printReg(ResultRegister, MRI.getTargetRegisterInfo())
351-
<< " with type: " << *ResultType);
352-
MachineIRBuilder MIB(MI);
353-
insertAssignInstr(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
354-
}
382+
SPIRVType *ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
383+
assert(ResultType);
384+
generateAssignType(MI, ResultRegister, ResultType, GR, MRI);
355385
}
356386
}
357387
}

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 15 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -425,52 +425,20 @@ static void setInsertPtAfterDef(MachineIRBuilder &MIB, MachineInstr *Def) {
425425
}
426426

427427
namespace llvm {
428-
void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
429-
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
430-
MachineRegisterInfo &MRI) {
428+
void updateRegType(Register Reg, Type *Ty, SPIRVType *SpvType,
429+
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
430+
MachineRegisterInfo &MRI) {
431431
assert((Ty || SpvType) && "Either LLVM or SPIRV type is expected.");
432432
MachineInstr *Def = MRI.getVRegDef(Reg);
433433
setInsertPtAfterDef(MIB, Def);
434434
if (!SpvType)
435435
SpvType = GR->getOrCreateSPIRVType(Ty, MIB,
436436
SPIRV::AccessQualifier::ReadWrite, true);
437-
438-
if (!isTypeFoldingSupported(Def->getOpcode())) {
439-
// No need to generate SPIRV::ASSIGN_TYPE pseudo-instruction
440-
if (!MRI.getRegClassOrNull(Reg))
441-
MRI.setRegClass(Reg, GR->getRegClass(SpvType));
442-
if (!MRI.getType(Reg).isValid())
443-
MRI.setType(Reg, GR->getRegType(SpvType));
444-
GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
445-
return;
446-
}
447-
448-
// Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
449-
// present after each auto-folded instruction to take a type reference from.
450-
Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
451-
const auto *RegClass = GR->getRegClass(SpvType);
452-
MRI.setRegClass(NewReg, RegClass);
453-
MRI.setRegClass(Reg, RegClass);
454-
437+
if (!MRI.getRegClassOrNull(Reg))
438+
MRI.setRegClass(Reg, GR->getRegClass(SpvType));
439+
if (!MRI.getType(Reg).isValid())
440+
MRI.setType(Reg, GR->getRegType(SpvType));
455441
GR->assignSPIRVTypeToVReg(SpvType, Reg, MIB.getMF());
456-
// This is to make it convenient for Legalizer to get the SPIRVType
457-
// when processing the actual MI (i.e. not pseudo one).
458-
GR->assignSPIRVTypeToVReg(SpvType, NewReg, MIB.getMF());
459-
// Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
460-
// the flags after instruction selection.
461-
const uint32_t Flags = Def->getFlags();
462-
MIB.buildInstr(SPIRV::ASSIGN_TYPE)
463-
.addDef(Reg)
464-
.addUse(NewReg)
465-
.addUse(GR->getSPIRVTypeID(SpvType))
466-
.setMIFlags(Flags);
467-
for (unsigned I = 0, E = Def->getNumDefs(); I != E; ++I) {
468-
MachineOperand &MO = Def->getOperand(I);
469-
if (MO.getReg() == Reg) {
470-
MO.setReg(NewReg);
471-
break;
472-
}
473-
}
474442
}
475443

476444
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
@@ -543,20 +511,18 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
543511
MachineInstr *Def = MRI.getVRegDef(Reg);
544512
assert(Def && "Expecting an instruction that defines the register");
545513
// G_GLOBAL_VALUE already has type info.
546-
if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
547-
Def->getOpcode() != SPIRV::ASSIGN_TYPE)
548-
insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB,
549-
MF.getRegInfo());
514+
if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
515+
updateRegType(Reg, nullptr, AssignedPtrType, GR, MIB,
516+
MF.getRegInfo());
550517
ToErase.push_back(&MI);
551518
} else if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
552519
Register Reg = MI.getOperand(1).getReg();
553520
Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
554521
MachineInstr *Def = MRI.getVRegDef(Reg);
555522
assert(Def && "Expecting an instruction that defines the register");
556523
// G_GLOBAL_VALUE already has type info.
557-
if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE &&
558-
Def->getOpcode() != SPIRV::ASSIGN_TYPE)
559-
insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
524+
if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
525+
updateRegType(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
560526
ToErase.push_back(&MI);
561527
} else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
562528
MachineInstr *MdMI = MI.getPrevNode();
@@ -581,20 +547,9 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
581547
MIOp == TargetOpcode::G_FCONSTANT ||
582548
MIOp == TargetOpcode::G_BUILD_VECTOR) {
583549
// %rc = G_CONSTANT ty Val
584-
// ===>
585-
// %cty = OpType* ty
586-
// %rctmp = G_CONSTANT ty Val
587-
// %rc = ASSIGN_TYPE %rctmp, %cty
550+
// Ensure %rc has a valid SPIR-V type assigned in the Global Registry.
588551
Register Reg = MI.getOperand(0).getReg();
589-
bool NeedAssignType = true;
590-
if (MRI.hasOneUse(Reg)) {
591-
MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
592-
if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
593-
isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
594-
continue;
595-
if (UseMI.getOpcode() == SPIRV::ASSIGN_TYPE)
596-
NeedAssignType = false;
597-
}
552+
bool NeedAssignType = GR->getSPIRVTypeForVReg(Reg) == nullptr;
598553
Type *Ty = nullptr;
599554
if (MIOp == TargetOpcode::G_CONSTANT) {
600555
auto TargetExtIt = TargetExtConstTypes.find(&MI);
@@ -639,13 +594,6 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
639594
if (const SPIRVType *ElemSpvType =
640595
GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg(), &MF))
641596
ElemTy = const_cast<Type *>(GR->getTypeForSPIRVType(ElemSpvType));
642-
if (!ElemTy) {
643-
// There may be a case when we already know Reg's type.
644-
MachineInstr *NextMI = MI.getNextNode();
645-
if (!NextMI || NextMI->getOpcode() != SPIRV::ASSIGN_TYPE ||
646-
NextMI->getOperand(1).getReg() != Reg)
647-
llvm_unreachable("Unexpected opcode");
648-
}
649597
}
650598
if (ElemTy)
651599
Ty = VectorType::get(
@@ -655,7 +603,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
655603
NeedAssignType = false;
656604
}
657605
if (NeedAssignType)
658-
insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
606+
updateRegType(Reg, Ty, nullptr, GR, MIB, MRI);
659607
} else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) {
660608
propagateSPIRVType(&MI, GR, MRI, MIB);
661609
}

0 commit comments

Comments
 (0)