Skip to content

Commit b512df6

Browse files
[SPIR-V] Improve Tablegen instruction selection and account for a pointer size of the target (#88725)
This PR resolves the issue that SPIR-V Backend uses the notion of a pointer size of the target, most notably, in legalizer code, but Tablegen instruction selection in SPIR-V Backend doesn't account for a pointer size of the target. See #88723 for a detailed description. There are 3 test cases attached to the PR that reproduced the issue, when dealing with spirv32-spirv64 differences, and are working correctly now with this PR.
1 parent 971237d commit b512df6

13 files changed

+138
-74
lines changed

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,8 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
653653
auto MRI = MIRBuilder.getMRI();
654654
assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
655655
if (Reg != ResVReg) {
656-
LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
656+
LLT RegLLTy =
657+
LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
657658
MRI->setType(Reg, RegLLTy);
658659
assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
659660
} else {

llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,10 @@ void SPIRVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
247247

248248
bool SPIRVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
249249
if (MI.getOpcode() == SPIRV::GET_ID || MI.getOpcode() == SPIRV::GET_fID ||
250-
MI.getOpcode() == SPIRV::GET_pID || MI.getOpcode() == SPIRV::GET_vfID ||
251-
MI.getOpcode() == SPIRV::GET_vID || MI.getOpcode() == SPIRV::GET_vpID) {
250+
MI.getOpcode() == SPIRV::GET_pID32 ||
251+
MI.getOpcode() == SPIRV::GET_pID64 || MI.getOpcode() == SPIRV::GET_vfID ||
252+
MI.getOpcode() == SPIRV::GET_vID || MI.getOpcode() == SPIRV::GET_vpID32 ||
253+
MI.getOpcode() == SPIRV::GET_vpID64) {
252254
auto &MRI = MI.getMF()->getRegInfo();
253255
MRI.replaceRegWith(MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
254256
MI.eraseFromParent();

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ let isCodeGenOnly=1 in {
1919
def DECL_TYPE: Pseudo<(outs ANYID:$dst_id), (ins ANYID:$src_id, TYPE:$src_ty)>;
2020
def GET_ID: Pseudo<(outs ID:$dst_id), (ins ANYID:$src)>;
2121
def GET_fID: Pseudo<(outs fID:$dst_id), (ins ANYID:$src)>;
22-
def GET_pID: Pseudo<(outs pID:$dst_id), (ins ANYID:$src)>;
22+
def GET_pID32: Pseudo<(outs pID32:$dst_id), (ins ANYID:$src)>;
23+
def GET_pID64: Pseudo<(outs pID64:$dst_id), (ins ANYID:$src)>;
2324
def GET_vID: Pseudo<(outs vID:$dst_id), (ins ANYID:$src)>;
2425
def GET_vfID: Pseudo<(outs vfID:$dst_id), (ins ANYID:$src)>;
25-
def GET_vpID: Pseudo<(outs vpID:$dst_id), (ins ANYID:$src)>;
26+
def GET_vpID32: Pseudo<(outs vpID32:$dst_id), (ins ANYID:$src)>;
27+
def GET_vpID64: Pseudo<(outs vpID64:$dst_id), (ins ANYID:$src)>;
2628
}
2729

2830
def SPVTypeBin : SDTypeProfile<1, 2, []>;
@@ -66,8 +68,10 @@ multiclass TernOpTypedGen<string name, bits<16> opCode, SDNode node, bit genP =
6668
def SIVCond: TernOpTyped<name, opCode, vID, ID, node>;
6769
}
6870
if genP then {
69-
def SPSCond: TernOpTyped<name, opCode, ID, pID, node>;
70-
def SPVCond: TernOpTyped<name, opCode, vID, pID, node>;
71+
def SPSCond32: TernOpTyped<name, opCode, ID, pID32, node>;
72+
def SPVCond32: TernOpTyped<name, opCode, vID, pID32, node>;
73+
def SPSCond64: TernOpTyped<name, opCode, ID, pID64, node>;
74+
def SPVCond64: TernOpTyped<name, opCode, vID, pID64, node>;
7175
}
7276
if genV then {
7377
if genF then {
@@ -79,8 +83,10 @@ multiclass TernOpTypedGen<string name, bits<16> opCode, SDNode node, bit genP =
7983
def VIVCond: TernOpTyped<name, opCode, vID, vID, node>;
8084
}
8185
if genP then {
82-
def VPSCond: TernOpTyped<name, opCode, ID, vpID, node>;
83-
def VPVCond: TernOpTyped<name, opCode, vID, vpID, node>;
86+
def VPSCond32: TernOpTyped<name, opCode, ID, vpID32, node>;
87+
def VPVCond32: TernOpTyped<name, opCode, vID, vpID32, node>;
88+
def VPSCond64: TernOpTyped<name, opCode, ID, vpID64, node>;
89+
def VPVCond64: TernOpTyped<name, opCode, vID, vpID64, node>;
8490
}
8591
}
8692
}

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,18 @@ bool SPIRVInstructionSelector::select(MachineInstr &I) {
290290
// If it's not a GMIR instruction, we've selected it already.
291291
if (!isPreISelGenericOpcode(Opcode)) {
292292
if (Opcode == SPIRV::ASSIGN_TYPE) { // These pseudos aren't needed any more.
293-
auto *Def = MRI->getVRegDef(I.getOperand(1).getReg());
293+
Register DstReg = I.getOperand(0).getReg();
294+
Register SrcReg = I.getOperand(1).getReg();
295+
auto *Def = MRI->getVRegDef(SrcReg);
294296
if (isTypeFoldingSupported(Def->getOpcode())) {
297+
if (MRI->getType(DstReg).isPointer())
298+
MRI->setType(DstReg, LLT::scalar(32));
295299
bool Res = selectImpl(I, *CoverageInfo);
296300
assert(Res || Def->getOpcode() == TargetOpcode::G_CONSTANT);
297301
if (Res)
298302
return Res;
299303
}
300-
MRI->replaceRegWith(I.getOperand(1).getReg(), I.getOperand(0).getReg());
304+
MRI->replaceRegWith(SrcReg, DstReg);
301305
I.removeFromParent();
302306
return true;
303307
} else if (I.getNumDefs() == 1) {

llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
5555

5656
static bool isMetaInstrGET(unsigned Opcode) {
5757
return Opcode == SPIRV::GET_ID || Opcode == SPIRV::GET_fID ||
58-
Opcode == SPIRV::GET_pID || Opcode == SPIRV::GET_vID ||
59-
Opcode == SPIRV::GET_vfID || Opcode == SPIRV::GET_vpID;
58+
Opcode == SPIRV::GET_pID32 || Opcode == SPIRV::GET_pID64 ||
59+
Opcode == SPIRV::GET_vID || Opcode == SPIRV::GET_vfID ||
60+
Opcode == SPIRV::GET_vpID32 || Opcode == SPIRV::GET_vpID64;
6061
}
6162

6263
static bool mayBeInserted(unsigned Opcode) {

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,12 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
223223
}
224224

225225
static std::pair<Register, unsigned>
226-
createNewIdReg(Register ValReg, unsigned Opcode, MachineRegisterInfo &MRI,
226+
createNewIdReg(SPIRVType *SpvType, Register SrcReg, MachineRegisterInfo &MRI,
227227
const SPIRVGlobalRegistry &GR) {
228-
LLT NewT = LLT::scalar(32);
229-
SPIRVType *SpvType = GR.getSPIRVTypeForVReg(ValReg);
228+
if (!SpvType)
229+
SpvType = GR.getSPIRVTypeForVReg(SrcReg);
230230
assert(SpvType && "VReg is expected to have SPIRV type");
231+
LLT NewT = LLT::scalar(32);
231232
bool IsFloat = SpvType->getOpcode() == SPIRV::OpTypeFloat;
232233
bool IsVectorFloat =
233234
SpvType->getOpcode() == SPIRV::OpTypeVector &&
@@ -236,14 +237,38 @@ createNewIdReg(Register ValReg, unsigned Opcode, MachineRegisterInfo &MRI,
236237
IsFloat |= IsVectorFloat;
237238
auto GetIdOp = IsFloat ? SPIRV::GET_fID : SPIRV::GET_ID;
238239
auto DstClass = IsFloat ? &SPIRV::fIDRegClass : &SPIRV::IDRegClass;
239-
if (MRI.getType(ValReg).isPointer()) {
240-
NewT = LLT::pointer(0, 32);
241-
GetIdOp = SPIRV::GET_pID;
242-
DstClass = &SPIRV::pIDRegClass;
243-
} else if (MRI.getType(ValReg).isVector()) {
240+
if (MRI.getType(SrcReg).isPointer()) {
241+
unsigned PtrSz = GR.getPointerSize();
242+
NewT = LLT::pointer(0, PtrSz);
243+
bool IsVec = MRI.getType(SrcReg).isVector();
244+
if (IsVec)
245+
NewT = LLT::fixed_vector(2, NewT);
246+
if (PtrSz == 64) {
247+
if (IsVec) {
248+
GetIdOp = SPIRV::GET_vpID64;
249+
DstClass = &SPIRV::vpID64RegClass;
250+
} else {
251+
GetIdOp = SPIRV::GET_pID64;
252+
DstClass = &SPIRV::pID64RegClass;
253+
}
254+
} else {
255+
if (IsVec) {
256+
GetIdOp = SPIRV::GET_vpID32;
257+
DstClass = &SPIRV::vpID32RegClass;
258+
} else {
259+
GetIdOp = SPIRV::GET_pID32;
260+
DstClass = &SPIRV::pID32RegClass;
261+
}
262+
}
263+
} else if (MRI.getType(SrcReg).isVector()) {
244264
NewT = LLT::fixed_vector(2, NewT);
245-
GetIdOp = IsFloat ? SPIRV::GET_vfID : SPIRV::GET_vID;
246-
DstClass = IsFloat ? &SPIRV::vfIDRegClass : &SPIRV::vIDRegClass;
265+
if (IsFloat) {
266+
GetIdOp = SPIRV::GET_vfID;
267+
DstClass = &SPIRV::vfIDRegClass;
268+
} else {
269+
GetIdOp = SPIRV::GET_vID;
270+
DstClass = &SPIRV::vIDRegClass;
271+
}
247272
}
248273
Register IdReg = MRI.createGenericVirtualRegister(NewT);
249274
MRI.setRegClass(IdReg, DstClass);
@@ -264,14 +289,14 @@ Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
264289
MIB.setInsertPt(*Def->getParent(),
265290
(Def->getNextNode() ? Def->getNextNode()->getIterator()
266291
: Def->getParent()->end()));
292+
SpirvTy = SpirvTy ? SpirvTy : GR->getOrCreateSPIRVType(Ty, MIB);
267293
Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
268294
if (auto *RC = MRI.getRegClassOrNull(Reg)) {
269295
MRI.setRegClass(NewReg, RC);
270296
} else {
271297
MRI.setRegClass(NewReg, &SPIRV::IDRegClass);
272298
MRI.setRegClass(Reg, &SPIRV::IDRegClass);
273299
}
274-
SpirvTy = SpirvTy ? SpirvTy : GR->getOrCreateSPIRVType(Ty, MIB);
275300
GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
276301
// This is to make it convenient for Legalizer to get the SPIRVType
277302
// when processing the actual MI (i.e. not pseudo one).
@@ -290,11 +315,11 @@ Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
290315

291316
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
292317
MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR) {
293-
unsigned Opc = MI.getOpcode();
294318
assert(MI.getNumDefs() > 0 && MRI.hasOneUse(MI.getOperand(0).getReg()));
295319
MachineInstr &AssignTypeInst =
296320
*(MRI.use_instr_begin(MI.getOperand(0).getReg()));
297-
auto NewReg = createNewIdReg(MI.getOperand(0).getReg(), Opc, MRI, *GR).first;
321+
auto NewReg =
322+
createNewIdReg(nullptr, MI.getOperand(0).getReg(), MRI, *GR).first;
298323
AssignTypeInst.getOperand(1).setReg(NewReg);
299324
MI.getOperand(0).setReg(NewReg);
300325
MIB.setInsertPt(*MI.getParent(),
@@ -303,7 +328,7 @@ void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
303328
for (auto &Op : MI.operands()) {
304329
if (!Op.isReg() || Op.isDef())
305330
continue;
306-
auto IdOpInfo = createNewIdReg(Op.getReg(), Opc, MRI, *GR);
331+
auto IdOpInfo = createNewIdReg(nullptr, Op.getReg(), MRI, *GR);
307332
MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(Op.getReg());
308333
Op.setReg(IdOpInfo.first);
309334
}
@@ -419,6 +444,7 @@ static void processInstrsWithTypeFolding(MachineFunction &MF,
419444
processInstr(MI, MIB, MRI, GR);
420445
}
421446
}
447+
422448
for (MachineBasicBlock &MBB : MF) {
423449
for (MachineInstr &MI : MBB) {
424450
// We need to rewrite dst types for ASSIGN_TYPE instrs to be able
@@ -431,16 +457,18 @@ static void processInstrsWithTypeFolding(MachineFunction &MF,
431457
if (!isTypeFoldingSupported(Opcode))
432458
continue;
433459
Register DstReg = MI.getOperand(0).getReg();
434-
if (MRI.getType(DstReg).isVector())
460+
bool IsDstPtr = MRI.getType(DstReg).isPointer();
461+
if (IsDstPtr || MRI.getType(DstReg).isVector())
435462
MRI.setRegClass(DstReg, &SPIRV::IDRegClass);
436463
// Don't need to reset type of register holding constant and used in
437-
// G_ADDRSPACE_CAST, since it braaks legalizer.
464+
// G_ADDRSPACE_CAST, since it breaks legalizer.
438465
if (Opcode == TargetOpcode::G_CONSTANT && MRI.hasOneUse(DstReg)) {
439466
MachineInstr &UseMI = *MRI.use_instr_begin(DstReg);
440467
if (UseMI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST)
441468
continue;
442469
}
443-
MRI.setType(DstReg, LLT::scalar(32));
470+
MRI.setType(DstReg, IsDstPtr ? LLT::pointer(0, GR->getPointerSize())
471+
: LLT::scalar(32));
444472
}
445473
}
446474
}

llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,7 @@ using namespace llvm;
2727
const RegisterBank &
2828
SPIRVRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
2929
LLT Ty) const {
30-
switch (RC.getID()) {
31-
case SPIRV::TYPERegClassID:
30+
if (RC.getID() == SPIRV::TYPERegClassID)
3231
return SPIRV::TYPERegBank;
33-
case SPIRV::pIDRegClassID:
34-
case SPIRV::IDRegClassID:
35-
return SPIRV::IDRegBank;
36-
case SPIRV::fIDRegClassID:
37-
return SPIRV::fIDRegBank;
38-
case SPIRV::vIDRegClassID:
39-
return SPIRV::vIDRegBank;
40-
case SPIRV::vfIDRegClassID:
41-
return SPIRV::vfIDRegBank;
42-
case SPIRV::vpIDRegClassID:
43-
return SPIRV::vpIDRegBank;
44-
case SPIRV::ANYIDRegClassID:
45-
case SPIRV::ANYRegClassID:
46-
return SPIRV::IDRegBank;
47-
}
48-
llvm_unreachable("Unknown register class");
32+
return SPIRV::IDRegBank;
4933
}

llvm/lib/Target/SPIRV/SPIRVRegisterBanks.td

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88

99
// Although RegisterBankSelection is disabled we need to distinct the banks
1010
// as InstructionSelector RegClass checking code relies on them
11-
def IDRegBank : RegisterBank<"IDBank", [ID]>;
12-
def fIDRegBank : RegisterBank<"fIDBank", [fID]>;
13-
def vIDRegBank : RegisterBank<"vIDBank", [vID]>;
14-
def vfIDRegBank : RegisterBank<"vfIDBank", [vfID]>;
15-
def vpIDRegBank : RegisterBank<"vpIDBank", [vpID]>;
11+
1612
def TYPERegBank : RegisterBank<"TYPEBank", [TYPE]>;
13+
def IDRegBank : RegisterBank<"IDBank", [ID, fID, pID32, pID64, vID, vfID, vpID32, vpID64]>;

llvm/lib/Target/SPIRV/SPIRVRegisterInfo.td

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,46 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
let Namespace = "SPIRV" in {
14-
def p0 : PtrValueType <i32, 0>;
15-
16-
class P0Vec<ValueType scalar>
17-
: PtrValueType <scalar, 0> {
18-
let nElem = 2;
19-
let ElementType = p0;
20-
let isInteger = false;
21-
let isFP = false;
22-
let isVector = true;
14+
// Pointer types for patterns with the GlobalISelEmitter
15+
def p32 : PtrValueType <i32, 0>;
16+
def p64 : PtrValueType <i64, 0>;
17+
18+
class VTPtrVec<int nelem, PtrValueType ptr>
19+
: VTVec<nelem, ValueType<ptr.Size, ptr.Value>, ptr.Value> {
20+
int isPointer = true;
2321
}
2422

25-
def v2p0 : P0Vec<i32>;
26-
// All registers are for 32-bit identifiers, so have a single dummy register
23+
def v2p32 : VTPtrVec<2, p32>;
24+
def v2p64 : VTPtrVec<2, p64>;
2725

28-
// Class for registers that are the result of OpTypeXXX instructions
26+
// Class for type registers
2927
def TYPE0 : Register<"TYPE0">;
3028
def TYPE : RegisterClass<"SPIRV", [i32], 32, (add TYPE0)>;
3129

32-
// Class for every other non-type ID
30+
// Class for non-type registers
3331
def ID0 : Register<"ID0">;
34-
def ID : RegisterClass<"SPIRV", [i32], 32, (add ID0)>;
3532
def fID0 : Register<"fID0">;
36-
def fID : RegisterClass<"SPIRV", [f32], 32, (add fID0)>;
37-
def pID0 : Register<"pID0">;
38-
def pID : RegisterClass<"SPIRV", [p0], 32, (add pID0)>;
33+
def pID320 : Register<"pID320">;
34+
def pID640 : Register<"pID640">;
3935
def vID0 : Register<"vID0">;
40-
def vID : RegisterClass<"SPIRV", [v2i32], 32, (add vID0)>;
4136
def vfID0 : Register<"vfID0">;
37+
def vpID320 : Register<"vpID320">;
38+
def vpID640 : Register<"vpID640">;
39+
40+
def ID : RegisterClass<"SPIRV", [i32], 32, (add ID0)>;
41+
def fID : RegisterClass<"SPIRV", [f32], 32, (add fID0)>;
42+
def pID32 : RegisterClass<"SPIRV", [p32], 32, (add pID320)>;
43+
def pID64 : RegisterClass<"SPIRV", [p64], 32, (add pID640)>;
44+
def vID : RegisterClass<"SPIRV", [v2i32], 32, (add vID0)>;
4245
def vfID : RegisterClass<"SPIRV", [v2f32], 32, (add vfID0)>;
43-
def vpID0 : Register<"vpID0">;
44-
def vpID : RegisterClass<"SPIRV", [v2p0], 32, (add vpID0)>;
46+
def vpID32 : RegisterClass<"SPIRV", [v2p32], 32, (add vpID320)>;
47+
def vpID64 : RegisterClass<"SPIRV", [v2p64], 32, (add vpID640)>;
4548

46-
def ANYID : RegisterClass<"SPIRV", [i32, f32, p0, v2i32, v2f32], 32, (add ID, fID, pID, vID, vfID)>;
49+
def ANYID : RegisterClass<
50+
"SPIRV",
51+
[i32, f32, p32, p64, v2i32, v2f32, v2p32, v2p64],
52+
32,
53+
(add ID0, fID0, pID320, pID640, vID0, vfID0, vpID320, vpID640)>;
4754

4855
// A few instructions like OpName can take ids from both type and non-type
4956
// instructions, so we need a super-class to allow for both to count as valid

llvm/test/CodeGen/SPIRV/instructions/select-phi.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
3+
24
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --translator-compatibility-mode %s -o - -filetype=obj | spirv-val %}
35
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
6+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --translator-compatibility-mode %s -o - -filetype=obj | spirv-val %}
7+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
48

59
; CHECK-DAG: %[[Char:.*]] = OpTypeInt 8 0
610
; CHECK-DAG: %[[Long:.*]] = OpTypeInt 32 0
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
5+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
6+
7+
; CHECK-SPIRV-DAG: %[[Float:.*]] = OpTypeFloat 32
8+
; CHECK-SPIRV-DAG: %[[FloatPtr:.*]] = OpTypePointer Function %[[Float]]
9+
; CHECK-SPIRV: OpInBoundsPtrAccessChain %[[FloatPtr]]
10+
; CHECK-SPIRV: OpInBoundsPtrAccessChain %[[FloatPtr]]
11+
; CHECK-SPIRV: OpSelect %[[FloatPtr]]
12+
; CHECK-SPIRV: OpLoad %[[Float]]
13+
14+
%struct = type { [3 x float] }
15+
16+
define spir_kernel void @bar(i1 %sw) {
17+
entry:
18+
%var1 = alloca %struct
19+
%var2 = alloca %struct
20+
%elem1 = getelementptr inbounds [3 x float], ptr %var1, i64 0, i64 0
21+
%elem2 = getelementptr inbounds [3 x float], ptr %var2, i64 0, i64 1
22+
%elem = select i1 %sw, ptr %elem1, ptr %elem2
23+
%res = load float, ptr %elem
24+
ret void
25+
}

llvm/test/CodeGen/SPIRV/instructions/select.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
22
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
33

4+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
5+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
6+
47
; CHECK-DAG: OpName [[SCALARi32:%.+]] "select_i32"
58
; CHECK-DAG: OpName [[SCALARPTR:%.+]] "select_ptr"
69
; CHECK-DAG: OpName [[VEC2i32:%.+]] "select_i32v2"

llvm/test/CodeGen/SPIRV/select.ll renamed to llvm/test/CodeGen/SPIRV/select-builtin.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
24

35
; CHECK-SPIRV: OpSelect
46

0 commit comments

Comments
 (0)