@@ -300,6 +300,72 @@ lookupBuiltin(StringRef DemangledCall,
300
300
return nullptr ;
301
301
}
302
302
303
+ static MachineInstr *getBlockStructInstr (Register ParamReg,
304
+ MachineRegisterInfo *MRI) {
305
+ // We expect the following sequence of instructions:
306
+ // %0:_(pN) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.alloca)
307
+ // or = G_GLOBAL_VALUE @block_literal_global
308
+ // %1:_(pN) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.bitcast), %0
309
+ // %2:_(p4) = G_ADDRSPACE_CAST %1:_(pN)
310
+ MachineInstr *MI = MRI->getUniqueVRegDef (ParamReg);
311
+ assert (MI->getOpcode () == TargetOpcode::G_ADDRSPACE_CAST &&
312
+ MI->getOperand (1 ).isReg ());
313
+ Register BitcastReg = MI->getOperand (1 ).getReg ();
314
+ MachineInstr *BitcastMI = MRI->getUniqueVRegDef (BitcastReg);
315
+ assert (isSpvIntrinsic (*BitcastMI, Intrinsic::spv_bitcast) &&
316
+ BitcastMI->getOperand (2 ).isReg ());
317
+ Register ValueReg = BitcastMI->getOperand (2 ).getReg ();
318
+ MachineInstr *ValueMI = MRI->getUniqueVRegDef (ValueReg);
319
+ return ValueMI;
320
+ }
321
+
322
+ // Return an integer constant corresponding to the given register and
323
+ // defined in spv_track_constant.
324
+ // TODO: maybe unify with prelegalizer pass.
325
+ static unsigned getConstFromIntrinsic (Register Reg, MachineRegisterInfo *MRI) {
326
+ MachineInstr *DefMI = MRI->getUniqueVRegDef (Reg);
327
+ assert (isSpvIntrinsic (*DefMI, Intrinsic::spv_track_constant) &&
328
+ DefMI->getOperand (2 ).isReg ());
329
+ MachineInstr *DefMI2 = MRI->getUniqueVRegDef (DefMI->getOperand (2 ).getReg ());
330
+ assert (DefMI2->getOpcode () == TargetOpcode::G_CONSTANT &&
331
+ DefMI2->getOperand (1 ).isCImm ());
332
+ return DefMI2->getOperand (1 ).getCImm ()->getValue ().getZExtValue ();
333
+ }
334
+
335
+ // Return type of the instruction result from spv_assign_type intrinsic.
336
+ // TODO: maybe unify with prelegalizer pass.
337
+ static const Type *getMachineInstrType (MachineInstr *MI) {
338
+ MachineInstr *NextMI = MI->getNextNode ();
339
+ if (!NextMI)
340
+ return nullptr ;
341
+ if (isSpvIntrinsic (*NextMI, Intrinsic::spv_assign_name))
342
+ if ((NextMI = NextMI->getNextNode ()) == nullptr )
343
+ return nullptr ;
344
+ Register ValueReg = MI->getOperand (0 ).getReg ();
345
+ if ((!isSpvIntrinsic (*NextMI, Intrinsic::spv_assign_type) &&
346
+ !isSpvIntrinsic (*NextMI, Intrinsic::spv_assign_ptr_type)) ||
347
+ NextMI->getOperand (1 ).getReg () != ValueReg)
348
+ return nullptr ;
349
+ Type *Ty = getMDOperandAsType (NextMI->getOperand (2 ).getMetadata (), 0 );
350
+ assert (Ty && " Type is expected" );
351
+ return Ty;
352
+ }
353
+
354
+ static const Type *getBlockStructType (Register ParamReg,
355
+ MachineRegisterInfo *MRI) {
356
+ // In principle, this information should be passed to us from Clang via
357
+ // an elementtype attribute. However, said attribute requires that
358
+ // the function call be an intrinsic, which is not. Instead, we rely on being
359
+ // able to trace this to the declaration of a variable: OpenCL C specification
360
+ // section 6.12.5 should guarantee that we can do this.
361
+ MachineInstr *MI = getBlockStructInstr (ParamReg, MRI);
362
+ if (MI->getOpcode () == TargetOpcode::G_GLOBAL_VALUE)
363
+ return MI->getOperand (1 ).getGlobal ()->getType ();
364
+ assert (isSpvIntrinsic (*MI, Intrinsic::spv_alloca) &&
365
+ " Blocks in OpenCL C must be traceable to allocation site" );
366
+ return getMachineInstrType (MI);
367
+ }
368
+
303
369
// ===----------------------------------------------------------------------===//
304
370
// Helper functions for building misc instructions
305
371
// ===----------------------------------------------------------------------===//
@@ -1371,6 +1437,14 @@ static bool generateBarrierInst(const SPIRV::IncomingCall *Call,
1371
1437
return buildBarrierInst (Call, Opcode, MIRBuilder, GR);
1372
1438
}
1373
1439
1440
+ static bool generateCastToPtrInst (const SPIRV::IncomingCall *Call,
1441
+ MachineIRBuilder &MIRBuilder) {
1442
+ MIRBuilder.buildInstr (TargetOpcode::G_ADDRSPACE_CAST)
1443
+ .addDef (Call->ReturnRegister )
1444
+ .addUse (Call->Arguments [0 ]);
1445
+ return true ;
1446
+ }
1447
+
1374
1448
static bool generateDotOrFMulInst (const SPIRV::IncomingCall *Call,
1375
1449
MachineIRBuilder &MIRBuilder,
1376
1450
SPIRVGlobalRegistry *GR) {
@@ -1847,68 +1921,6 @@ static bool buildNDRange(const SPIRV::IncomingCall *Call,
1847
1921
.addUse (TmpReg);
1848
1922
}
1849
1923
1850
- static MachineInstr *getBlockStructInstr (Register ParamReg,
1851
- MachineRegisterInfo *MRI) {
1852
- // We expect the following sequence of instructions:
1853
- // %0:_(pN) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.alloca)
1854
- // or = G_GLOBAL_VALUE @block_literal_global
1855
- // %1:_(pN) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.spv.bitcast), %0
1856
- // %2:_(p4) = G_ADDRSPACE_CAST %1:_(pN)
1857
- MachineInstr *MI = MRI->getUniqueVRegDef (ParamReg);
1858
- assert (MI->getOpcode () == TargetOpcode::G_ADDRSPACE_CAST &&
1859
- MI->getOperand (1 ).isReg ());
1860
- Register BitcastReg = MI->getOperand (1 ).getReg ();
1861
- MachineInstr *BitcastMI = MRI->getUniqueVRegDef (BitcastReg);
1862
- assert (isSpvIntrinsic (*BitcastMI, Intrinsic::spv_bitcast) &&
1863
- BitcastMI->getOperand (2 ).isReg ());
1864
- Register ValueReg = BitcastMI->getOperand (2 ).getReg ();
1865
- MachineInstr *ValueMI = MRI->getUniqueVRegDef (ValueReg);
1866
- return ValueMI;
1867
- }
1868
-
1869
- // Return an integer constant corresponding to the given register and
1870
- // defined in spv_track_constant.
1871
- // TODO: maybe unify with prelegalizer pass.
1872
- static unsigned getConstFromIntrinsic (Register Reg, MachineRegisterInfo *MRI) {
1873
- MachineInstr *DefMI = MRI->getUniqueVRegDef (Reg);
1874
- assert (isSpvIntrinsic (*DefMI, Intrinsic::spv_track_constant) &&
1875
- DefMI->getOperand (2 ).isReg ());
1876
- MachineInstr *DefMI2 = MRI->getUniqueVRegDef (DefMI->getOperand (2 ).getReg ());
1877
- assert (DefMI2->getOpcode () == TargetOpcode::G_CONSTANT &&
1878
- DefMI2->getOperand (1 ).isCImm ());
1879
- return DefMI2->getOperand (1 ).getCImm ()->getValue ().getZExtValue ();
1880
- }
1881
-
1882
- // Return type of the instruction result from spv_assign_type intrinsic.
1883
- // TODO: maybe unify with prelegalizer pass.
1884
- static const Type *getMachineInstrType (MachineInstr *MI) {
1885
- MachineInstr *NextMI = MI->getNextNode ();
1886
- if (isSpvIntrinsic (*NextMI, Intrinsic::spv_assign_name))
1887
- NextMI = NextMI->getNextNode ();
1888
- Register ValueReg = MI->getOperand (0 ).getReg ();
1889
- if (!isSpvIntrinsic (*NextMI, Intrinsic::spv_assign_type) ||
1890
- NextMI->getOperand (1 ).getReg () != ValueReg)
1891
- return nullptr ;
1892
- Type *Ty = getMDOperandAsType (NextMI->getOperand (2 ).getMetadata (), 0 );
1893
- assert (Ty && " Type is expected" );
1894
- return Ty;
1895
- }
1896
-
1897
- static const Type *getBlockStructType (Register ParamReg,
1898
- MachineRegisterInfo *MRI) {
1899
- // In principle, this information should be passed to us from Clang via
1900
- // an elementtype attribute. However, said attribute requires that
1901
- // the function call be an intrinsic, which is not. Instead, we rely on being
1902
- // able to trace this to the declaration of a variable: OpenCL C specification
1903
- // section 6.12.5 should guarantee that we can do this.
1904
- MachineInstr *MI = getBlockStructInstr (ParamReg, MRI);
1905
- if (MI->getOpcode () == TargetOpcode::G_GLOBAL_VALUE)
1906
- return MI->getOperand (1 ).getGlobal ()->getType ();
1907
- assert (isSpvIntrinsic (*MI, Intrinsic::spv_alloca) &&
1908
- " Blocks in OpenCL C must be traceable to allocation site" );
1909
- return getMachineInstrType (MI);
1910
- }
1911
-
1912
1924
// TODO: maybe move to the global register.
1913
1925
static SPIRVType *
1914
1926
getOrCreateSPIRVDeviceEventPointer (MachineIRBuilder &MIRBuilder,
@@ -2322,6 +2334,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
2322
2334
return generateAtomicFloatingInst (Call.get (), MIRBuilder, GR);
2323
2335
case SPIRV::Barrier:
2324
2336
return generateBarrierInst (Call.get (), MIRBuilder, GR);
2337
+ case SPIRV::CastToPtr:
2338
+ return generateCastToPtrInst (Call.get (), MIRBuilder);
2325
2339
case SPIRV::Dot:
2326
2340
return generateDotOrFMulInst (Call.get (), MIRBuilder, GR);
2327
2341
case SPIRV::Wave:
0 commit comments