Skip to content

Commit bf30023

Browse files
jfuenteshliao2
authored andcommitted
In order to add support for pISA iadd, several changes are introduced
in this PR. SPIRV uses generic register named ID (32b) for all the register variables. To set the type of the register, another generic register named TYPE is used (32b). This means that SPIRV instructions such as iadd/fadd are like ``dst (ID) = opcode type (TYPE) src0 (ID) src1 (ID). An example of iadd in SPIRV can be: ``` %2 = OpTypeInt 32 0 %7 = OpIAdd %2 %4 %5 ``` To transition to pISA iadd with operands being virtual registers with bit-width, the following changes are introduced: - TableGen: - Add multiclass definition for iadd for the cases of having the patterns ``iadd.XXb reg reg`` and ``iadd.XXb reg imm`` where XX={16, 32, 64}. Note that imm is not yet supported since SPIRV treats them as constant and stores them in register variable. - Redefinition of ``OpFunctionParameter`` to support different register classes. This opcode will be eventually removed once we incorporate pISA calling convention changes. - SPIRV uses a special opcode ASSIGN_TYPE to assign type to instructions. For example, in pre-legalizer pass we can see the following GMIR code ``` %1:type(s32) = OpTypeInt 32, 0 %10:id(s32) = G_ADD %11:id, %12:id %6:anyid(s32) = ASSIGN_TYPE %10:id(s32), %1:type(s32) ``` This PR removes ASSIGN_TYPE, and type is assigned directly to the opcode based on operand size coming from input LLVM IR. Resulting GMIR code after pre-legalizer is now: ``` %10:reg32b(s32) = G_ADD %11:reg32b, %12:reg32b ``` - Other changes/cleanup included in this PR: - Update register bank info. Although register bank selection is disabled, instruction selection requires that register classes have register banks associated. - Update pISA Inst info. - Add LIT test for checking iadd codegen.
1 parent b7667da commit bf30023

22 files changed

+499
-371
lines changed

llvm/lib/Target/pISA/MCTargetDesc/pISAInstPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ void pISAInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
261261
if (OpNo < MI->getNumOperands()) {
262262
const MCOperand &Op = MI->getOperand(OpNo);
263263
if (Op.isReg())
264-
O << '%' << (Register::virtReg2Index(Op.getReg()) + 1);
264+
O << "%r" << (Register::virtReg2Index(Op.getReg()) + 1);
265265
else if (Op.isImm())
266266
O << formatImm((int64_t)Op.getImm());
267267
else if (Op.isDFPImm())

llvm/lib/Target/pISA/MCTargetDesc/pISAMCCodeEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ static bool hasType(const MCInst &MI, const MCInstrInfo &MII) {
6767
// Check if we define an ID, and take a type as operand 1.
6868
auto &DefOpInfo = MCDesc.operands()[0];
6969
auto &FirstArgOpInfo = MCDesc.operands()[1];
70-
return (DefOpInfo.RegClass == pISA::IDRegClassID ||
71-
DefOpInfo.RegClass == pISA::ANYIDRegClassID) &&
70+
return (DefOpInfo.RegClass == pISA::Reg32bRegClassID ||
71+
DefOpInfo.RegClass == pISA::ANYREGRegClassID) &&
7272
FirstArgOpInfo.RegClass == pISA::TYPERegClassID;
7373
}
7474
return false;

llvm/lib/Target/pISA/pISAAsmPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ void pISAAsmPrinter::emitFunctionBodyStart() {
159159
unsigned int ParamNo = 0;
160160
for (auto &MBB : *MF) {
161161
for (auto &MI : MBB) {
162-
// TODO: Change OpFunctionParameter to PISA equivalent
163-
if (MI.getOpcode() != pISA::OpFunctionParameter) {
162+
MI.getDesc();
163+
if (!TII->isFunctionParamInstr(MI)) {
164164
if (ParamNo)
165165
return;
166166
continue;
@@ -305,7 +305,7 @@ bool pISAAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
305305
static bool isFuncOrHeaderInstr(const MachineInstr *MI,
306306
const pISAInstrInfo *TII) {
307307
return TII->isHeaderInstr(*MI) || MI->getOpcode() == pISA::OpFunction ||
308-
MI->getOpcode() == pISA::OpFunctionParameter;
308+
TII->isFunctionParamInstr(*MI);
309309
}
310310

311311
void pISAAsmPrinter::outputMCInst(MCInst &Inst) {

llvm/lib/Target/pISA/pISABuiltins.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static Register buildLoadInst(pISAType *BaseType, Register PtrRegister,
324324
Register DestinationReg = Register(0)) {
325325
MachineRegisterInfo *MRI = MIRBuilder.getMRI();
326326
if (!DestinationReg.isValid()) {
327-
DestinationReg = MRI->createVirtualRegister(&pISA::IDRegClass);
327+
DestinationReg = MRI->createVirtualRegister(&pISA::Reg32bRegClass);
328328
MRI->setType(DestinationReg, LLT::scalar(32));
329329
GR->assignpISATypeToVReg(BaseType, DestinationReg, MIRBuilder.getMF());
330330
}
@@ -344,7 +344,7 @@ static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder,
344344
LLT LLType,
345345
Register Reg = Register(0)) {
346346
Register NewRegister =
347-
MIRBuilder.getMRI()->createVirtualRegister(&pISA::IDRegClass);
347+
MIRBuilder.getMRI()->createVirtualRegister(&pISA::Reg32bRegClass);
348348
MIRBuilder.getMRI()->setType(NewRegister,
349349
LLT::pointer(0, GR->getPointerSize()));
350350
pISAType *PtrType = GR->getOrCreatepISAPointerType(
@@ -1255,7 +1255,7 @@ static bool generateReadImageInst(const StringRef DemangledCall,
12551255
pISAType *ImageType = GR->getpISATypeForVReg(Image);
12561256
pISAType *SampledImageType =
12571257
GR->getOrCreateOpTypeSampledImage(ImageType, MIRBuilder);
1258-
Register SampledImage = MRI->createVirtualRegister(&pISA::IDRegClass);
1258+
Register SampledImage = MRI->createVirtualRegister(&pISA::Reg32bRegClass);
12591259

12601260
MIRBuilder.buildInstr(pISA::OpSampledImage)
12611261
.addDef(SampledImage)
@@ -1340,7 +1340,7 @@ static bool generateSampleImageInst(const StringRef DemangledCall,
13401340
Register SampledImage =
13411341
Call->ReturnRegister.isValid()
13421342
? Call->ReturnRegister
1343-
: MIRBuilder.getMRI()->createVirtualRegister(&pISA::IDRegClass);
1343+
: MIRBuilder.getMRI()->createVirtualRegister(&pISA::Reg32bRegClass);
13441344
MIRBuilder.buildInstr(pISA::OpSampledImage)
13451345
.addDef(SampledImage)
13461346
.addUse(GR->getpISATypeID(SampledImageType))
@@ -1539,7 +1539,7 @@ static bool buildEnqueueKernel(const pISA::IncomingCall *Call,
15391539
Int32Ty, MIRBuilder, pISA::StorageClass::Function);
15401540
for (unsigned I = 0; I < LocalSizeNum; ++I) {
15411541
Register Reg =
1542-
MIRBuilder.getMRI()->createVirtualRegister(&pISA::IDRegClass);
1542+
MIRBuilder.getMRI()->createVirtualRegister(&pISA::Reg32bRegClass);
15431543
MIRBuilder.getMRI()->setType(Reg, LLType);
15441544
GR->assignpISATypeToVReg(PointerSizeTy, Reg, MIRBuilder.getMF());
15451545
auto GEPInst = MIRBuilder.buildIntrinsic(Intrinsic::pisa_gep,
@@ -1632,7 +1632,7 @@ static bool generateEnqueueInst(const pISA::IncomingCall *Call,
16321632
PtrType->getOperand(2).isReg());
16331633
Register TypeReg = PtrType->getOperand(2).getReg();
16341634
pISAType *StructType = GR->getpISATypeForVReg(TypeReg);
1635-
Register TmpReg = MRI->createVirtualRegister(&pISA::IDRegClass);
1635+
Register TmpReg = MRI->createVirtualRegister(&pISA::Reg32bRegClass);
16361636
GR->assignpISATypeToVReg(StructType, TmpReg, MIRBuilder.getMF());
16371637
// Skip the first arg, it's the destination pointer. OpBuildNDRange takes
16381638
// three other arguments, so pass zero constant on absence.
@@ -1657,7 +1657,7 @@ static bool generateEnqueueInst(const pISA::IncomingCall *Call,
16571657
MIRBuilder.getMF().getFunction().getContext(), BitWidth);
16581658
Type *FieldTy = ArrayType::get(BaseTy, Size);
16591659
pISAType *pISAFieldTy = GR->getOrCreatepISAType(FieldTy, MIRBuilder);
1660-
GlobalWorkSize = MRI->createVirtualRegister(&pISA::IDRegClass);
1660+
GlobalWorkSize = MRI->createVirtualRegister(&pISA::Reg32bRegClass);
16611661
GR->assignpISATypeToVReg(pISAFieldTy, GlobalWorkSize,
16621662
MIRBuilder.getMF());
16631663
MIRBuilder.buildInstr(pISA::OpLoad)
@@ -1846,7 +1846,7 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
18461846
if (OrigRetTy && !OrigRetTy->isVoidTy()) {
18471847
ReturnType = GR->assignTypeToVReg(OrigRetTy, OrigRet, MIRBuilder);
18481848
} else if (OrigRetTy && OrigRetTy->isVoidTy()) {
1849-
ReturnRegister = MIRBuilder.getMRI()->createVirtualRegister(&IDRegClass);
1849+
ReturnRegister = MIRBuilder.getMRI()->createVirtualRegister(&Reg32bRegClass);
18501850
MIRBuilder.getMRI()->setType(ReturnRegister, LLT::scalar(32));
18511851
ReturnType = GR->assignTypeToVReg(OrigRetTy, ReturnRegister, MIRBuilder);
18521852
}

llvm/lib/Target/pISA/pISABuiltins.td

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,10 @@ defm : DemangledExtendedBuiltin<"NClamp", GLSL_std_450, 81>;
433433
// set specifies which external instruction set the builtin belongs to.
434434
// opcode specifies the pISA operation code of the generated instruction.
435435
//===----------------------------------------------------------------------===//
436-
class NativeBuiltin<string name, InstructionSet set, Op operation> {
436+
class NativeBuiltin<string name, InstructionSet set, pISAInst operation> {
437437
string Name = name;
438438
InstructionSet Set = set;
439-
Op Opcode = operation;
439+
pISAInst Opcode = operation;
440440
}
441441

442442
// Table gathering all the native builtins.
@@ -454,7 +454,7 @@ def lookupNativeBuiltin : SearchIndex {
454454

455455
// Multiclass used to define at the same time both an incoming builtin record
456456
// and a corresponding native builtin record.
457-
multiclass DemangledNativeBuiltin<string name, InstructionSet set, BuiltinGroup group, bits<8> minNumArgs, bits<8> maxNumArgs, Op operation> {
457+
multiclass DemangledNativeBuiltin<string name, InstructionSet set, BuiltinGroup group, bits<8> minNumArgs, bits<8> maxNumArgs, pISAInst operation> {
458458
def : DemangledBuiltin<name, set, group, minNumArgs, maxNumArgs>;
459459
def : NativeBuiltin<name, set, operation>;
460460
}
@@ -572,9 +572,9 @@ defm : DemangledNativeBuiltin<"__pISA_Store", OpenCL_std, LoadStore, 2, 4, OpSto
572572
// name is the demangled name of the given builtin.
573573
// opcode specifies the pISA operation code of the generated instruction.
574574
//===----------------------------------------------------------------------===//
575-
class GroupBuiltin<string name, Op operation> {
575+
class GroupBuiltin<string name, pISAInst operation> {
576576
string Name = name;
577-
Op Opcode = operation;
577+
pISAInst Opcode = operation;
578578
bits<32> GroupOperation = !cond(!not(!eq(!find(name, "group_reduce"), -1)) : Reduce.Value,
579579
!not(!eq(!find(name, "group_scan_inclusive"), -1)) : InclusiveScan.Value,
580580
!not(!eq(!find(name, "group_scan_exclusive"), -1)) : ExclusiveScan.Value,
@@ -634,7 +634,7 @@ def lookupGroupBuiltin : SearchIndex {
634634
// Multiclass used to define at the same time both incoming builtin records
635635
// and corresponding work/sub group builtin records.
636636
defvar OnlyWork = 0; defvar OnlySub = 1; defvar WorkOrSub = 2;
637-
multiclass DemangledGroupBuiltin<string name, int level /* OnlyWork/OnlySub/... */, Op operation> {
637+
multiclass DemangledGroupBuiltin<string name, int level /* OnlyWork/OnlySub/... */, pISAInst operation> {
638638
assert !and(!ge(level, 0), !le(level, 2)), "group level is invalid: " # level;
639639

640640
if !or(!eq(level, OnlyWork), !eq(level, WorkOrSub)) then {
@@ -1107,9 +1107,9 @@ foreach i = ["", "2", "3", "4", "8", "16"] in {
11071107
// name is the demangled name of the given builtin.
11081108
// operation specifies the pISA opcode the StructType should be lowered to.
11091109
//===----------------------------------------------------------------------===//
1110-
class DemangledType<string name, Op operation> {
1110+
class DemangledType<string name, pISAInst operation> {
11111111
string Name = name;
1112-
Op Opcode = operation;
1112+
pISAInst Opcode = operation;
11131113
}
11141114

11151115
// Table gathering all the demangled type records.

llvm/lib/Target/pISA/pISACallLowering.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ bool pISACallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
303303
// Generate a pISA type for the function.
304304
auto MRI = MIRBuilder.getMRI();
305305
Register FuncVReg = MRI->createGenericVirtualRegister(LLT::scalar(32));
306-
MRI->setRegClass(FuncVReg, &pISA::IDRegClass);
306+
MRI->setRegClass(FuncVReg, &pISA::Reg32bRegClass);
307307
if (F.isDeclaration())
308308
GR->add(&F, &MIRBuilder.getMF(), FuncVReg);
309309
pISAType *RetTy = GR->getOrCreatepISAType(FTy->getReturnType(), MIRBuilder);
@@ -319,14 +319,35 @@ bool pISACallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
319319
.addImm(FuncControl)
320320
.addUse(GR->getpISATypeID(FuncTy));
321321

322-
// Add OpFunctionParameters.
322+
// FIXME: Currently only 16b/32b/64b register types are supported.
323+
// Support for lowering pISA vector types must be added.
324+
// See llvm/test/CodeGen/pISA/function-args.ll
323325
int i = 0;
324326
for (const auto &Arg : F.args()) {
325327
assert(VRegs[i].size() == 1 && "Formal arg has multiple vregs");
326-
MRI->setRegClass(VRegs[i][0], &pISA::IDRegClass);
327-
MIRBuilder.buildInstr(pISA::OpFunctionParameter)
328-
.addDef(VRegs[i][0])
329-
.addUse(GR->getpISATypeID(ArgTypeVRegs[i]));
328+
auto bitSize = Arg.getType()->getScalarSizeInBits();
329+
switch (bitSize) {
330+
case 16:
331+
MRI->setRegClass(VRegs[i][0], &pISA::Reg16bRegClass);
332+
MIRBuilder.buildInstr(pISA::OpFunctionParameter16b)
333+
.addDef(VRegs[i][0])
334+
.addUse(VRegs[i][0]);
335+
break;
336+
case 32:
337+
MRI->setRegClass(VRegs[i][0], &pISA::Reg32bRegClass);
338+
MIRBuilder.buildInstr(pISA::OpFunctionParameter32b)
339+
.addDef(VRegs[i][0])
340+
.addUse(VRegs[i][0]);
341+
break;
342+
case 64:
343+
MRI->setRegClass(VRegs[i][0], &pISA::Reg64bRegClass);
344+
MIRBuilder.buildInstr(pISA::OpFunctionParameter64b)
345+
.addDef(VRegs[i][0])
346+
.addUse(VRegs[i][0]);
347+
break;
348+
default:
349+
assert(false && "Bit size for call arg not supported");
350+
}
330351
if (F.isDeclaration())
331352
GR->add(&Arg, &MIRBuilder.getMF(), VRegs[i][0]);
332353
i++;
@@ -421,7 +442,7 @@ bool pISACallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
421442

422443
// Make sure there's a valid return reg, even for functions returning void.
423444
if (!ResVReg.isValid())
424-
ResVReg = MIRBuilder.getMRI()->createVirtualRegister(&pISA::IDRegClass);
445+
ResVReg = MIRBuilder.getMRI()->createVirtualRegister(&pISA::Reg32bRegClass);
425446
pISAType *RetType =
426447
GR->assignTypeToVReg(FTy->getReturnType(), ResVReg, MIRBuilder);
427448

llvm/lib/Target/pISA/pISADuplicatesTracker.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ void pISAGeneralDuplicatesTracker::buildDepsGraph(
6464
if (E->getIsFunc()) {
6565
MachineInstr *Next = MI->getNextNode();
6666
if (Next && (Next->getOpcode() == pISA::OpFunction ||
67-
Next->getOpcode() == pISA::OpFunctionParameter)) {
67+
Next->getOpcode() == pISA::OpFunctionParameter16b ||
68+
Next->getOpcode() == pISA::OpFunctionParameter32b ||
69+
Next->getOpcode() == pISA::OpFunctionParameter64b)) {
6870
E->addDep(Reg2Entry[&Next->getOperand(0)]);
6971
}
7072
}

llvm/lib/Target/pISA/pISAEmitIntrinsics.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,6 @@ bool pISAEmitIntrinsics::runOnFunction(Function &Func) {
458458
for (auto &I : instructions(Func))
459459
Worklist.push_back(&I);
460460

461-
for (auto &I : Worklist)
462-
insertAssignTypeIntrs(I);
463-
464461
for (auto *I : Worklist) {
465462
TrackConstants = true;
466463
if (!I->getType()->isVoidTy() || isa<StoreInst>(I))

llvm/lib/Target/pISA/pISAGlobalRegistry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ Register pISAGlobalRegistry::buildConstantSampler(
422422
auto Sampler =
423423
ResReg.isValid()
424424
? ResReg
425-
: MIRBuilder.getMRI()->createVirtualRegister(&pISA::IDRegClass);
425+
: MIRBuilder.getMRI()->createVirtualRegister(&pISA::Reg32bRegClass);
426426
auto Res = MIRBuilder.buildInstr(pISA::OpConstantSampler)
427427
.addDef(Sampler)
428428
.addUse(getpISATypeID(SampTy))

llvm/lib/Target/pISA/pISAInstrFormats.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def StringImm: Operand<i32>{
1010
let PrintMethod="printStringImm";
1111
}
1212

13-
class Op<bits<16> Opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
13+
class pISAInst<bits<16> Opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
1414
: Instruction {
1515
field bits<16> Inst;
1616

@@ -26,7 +26,7 @@ class Op<bits<16> Opcode, dag outs, dag ins, string asmstr, list<dag> pattern =
2626
}
2727

2828
// Pseudo instructions
29-
class Pseudo<dag outs, dag ins> : Op<0, outs, ins, ""> {
29+
class Pseudo<dag outs, dag ins> : pISAInst<0, outs, ins, ""> {
3030
let isPseudo = 1;
3131
let hasSideEffects = 0;
3232
}

llvm/lib/Target/pISA/pISAInstrInfo.cpp

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -110,36 +110,18 @@ bool pISAInstrInfo::canUseFastMathFlags(const MachineInstr &MI) const {
110110
}
111111
}
112112

113-
bool pISAInstrInfo::canUseNSW(const MachineInstr &MI) const {
113+
// FIXME: Update this function when incorporating calling convention changes
114+
bool pISAInstrInfo::isFunctionParamInstr(const MachineInstr &MI) const {
114115
switch (MI.getOpcode()) {
115-
case pISA::OpIAddS:
116-
case pISA::OpIAddV:
117-
case pISA::OpISubS:
118-
case pISA::OpISubV:
119-
case pISA::OpIMulS:
120-
case pISA::OpIMulV:
121-
case pISA::OpShiftLeftLogicalS:
122-
case pISA::OpShiftLeftLogicalV:
123-
case pISA::OpSNegate:
116+
case pISA::OpFunctionParameter16b:
117+
case pISA::OpFunctionParameter32b:
118+
case pISA::OpFunctionParameter64b:
124119
return true;
125120
default:
126121
return false;
127122
}
128-
}
123+
}
129124

130-
bool pISAInstrInfo::canUseNUW(const MachineInstr &MI) const {
131-
switch (MI.getOpcode()) {
132-
case pISA::OpIAddS:
133-
case pISA::OpIAddV:
134-
case pISA::OpISubS:
135-
case pISA::OpISubV:
136-
case pISA::OpIMulS:
137-
case pISA::OpIMulV:
138-
return true;
139-
default:
140-
return false;
141-
}
142-
}
143125

144126
// Analyze the branching code at the end of MBB, returning
145127
// true if it cannot be understood (e.g. it's a switch dispatch or isn't
@@ -245,7 +227,9 @@ void pISAInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
245227
}
246228

247229
bool pISAInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
248-
if (MI.getOpcode() == pISA::GET_ID || MI.getOpcode() == pISA::GET_fID ||
230+
if (MI.getOpcode() == pISA::GET_Reg16b ||
231+
MI.getOpcode() == pISA::GET_Reg32b ||
232+
MI.getOpcode() == pISA::GET_Reg64b || MI.getOpcode() == pISA::GET_fID ||
249233
MI.getOpcode() == pISA::GET_pID || MI.getOpcode() == pISA::GET_vfID ||
250234
MI.getOpcode() == pISA::GET_vID) {
251235
auto &MRI = MI.getMF()->getRegInfo();

llvm/lib/Target/pISA/pISAInstrInfo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ class pISAInstrInfo : public pISAGenInstrInfo {
3232
bool isConstantInstr(const MachineInstr &MI) const;
3333
bool isTypeDeclInstr(const MachineInstr &MI) const;
3434
bool isDecorationInstr(const MachineInstr &MI) const;
35+
bool isFunctionParamInstr(const MachineInstr &MI) const;
3536
bool canUseFastMathFlags(const MachineInstr &MI) const;
36-
bool canUseNSW(const MachineInstr &MI) const;
37-
bool canUseNUW(const MachineInstr &MI) const;
3837

3938
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
4039
MachineBasicBlock *&FBB,

0 commit comments

Comments
 (0)