LLVM: lib/Target/SPIRV/SPIRVPostLegalizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

19#include "llvm/IR/IntrinsicsSPIRV.h"

21#include

22

23#define DEBUG_TYPE "spirv-postlegalizer"

24

25using namespace llvm;

26

27namespace {

29public:

30 static char ID;

33};

34}

35

36namespace llvm {

37

44}

45

52

56 Register SrcReg = I->getOperand(I->getNumOperands() - 1).getReg();

59 assert(DefType->getOpcode() == SPIRV::OpTypeVector);

61 }

62

63 if (!ScalarType) {

64

65

66 for (unsigned i = 0; i < I->getNumDefs() && !ScalarType; ++i) {

67 for (const auto &Use :

68 MRI.use_nodbg_instructions(I->getOperand(i).getReg())) {

69 assert(Use.getOpcode() == TargetOpcode::G_BUILD_VECTOR &&

70 "Expected use of G_UNMERGE_VALUES to be a G_BUILD_VECTOR");

71 if (auto *VecType =

74 break;

75 }

76 }

77 }

78 }

79

80 if (!ScalarType)

81 return false;

82

83 for (unsigned i = 0; i < I->getNumDefs(); ++i) {

84 Register DefReg = I->getOperand(i).getReg();

86 continue;

87

88 LLT DefLLT = MRI.getType(DefReg);

94 : ScalarType;

96 }

97 return true;

98}

99

103 unsigned OpIdx) {

107 Register ResVReg = I->getOperand(0).getReg();

111 MIB, false);

112 return CompType;

113 }

114 }

115 return nullptr;

116}

117

121 unsigned StartOp, unsigned EndOp) {

123 for (unsigned i = StartOp; i < EndOp; ++i) {

125#ifdef EXPENSIVE_CHECKS

126 assert(!ResType || Type == ResType && "Conflicting type from operands.");

127 ResType = Type;

128#else

130#endif

131 }

132 }

133 return ResType;

134}

135

141 if (!MO.isReg())

142 continue;

149 return CompType;

150 }

151 }

152 }

153 return nullptr;

154}

155

162 switch (Use.getOpcode()) {

163 case TargetOpcode::G_BUILD_VECTOR:

164 case TargetOpcode::G_EXTRACT_VECTOR_ELT:

165 case TargetOpcode::G_UNMERGE_VALUES:

168 break;

169 }

170 if (ResType)

171 return ResType;

172 }

173 return nullptr;

174}

175

179 Register ResVReg = I->getOperand(0).getReg();

180 switch (I->getOpcode()) {

181 case TargetOpcode::G_CONSTANT:

182 case TargetOpcode::G_ANYEXT:

184 case TargetOpcode::G_BUILD_VECTOR:

186 case TargetOpcode::G_SHUFFLE_VECTOR:

188 default:

189 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&

190 I->getOperand(1).isReg())

192 return nullptr;

193 }

194}

195

199 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);

201 Register ResVReg = I->getOperand(0).getReg();

202

203

204

205

206 if (I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)

208

209 LLVM_DEBUG(dbgs() << "Inferring type from operands\n");

211 if (!ResType) {

214 }

215

216 if (!ResType)

217 return false;

218

219 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);

221

222 if (MRI.getRegClassOrNull(ResVReg)) {

223 LLVM_DEBUG(dbgs() << "Updating the register class.\n");

225 }

226 return true;

227}

228

231 LLVM_DEBUG(dbgs() << "Checking if instruction requires a SPIR-V type: "

232 << I;);

233 if (I.getNumDefs() == 0) {

234 LLVM_DEBUG(dbgs() << "Instruction does not have a definition.\n");

235 return false;

236 }

237

238 if (I.isPreISelOpcode()) {

239 LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");

240 return false;

241 }

242

243 Register ResultRegister = I.defs().begin()->getReg();

245 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");

246 if (MRI.getRegClassOrNull(ResultRegister)) {

247 LLVM_DEBUG(dbgs() << "Updating the register class.\n");

250 }

251 return false;

252 }

253

254 return true;

255}

256

265 }

266 }

267 }

268

269 if (Worklist.empty()) {

270 LLVM_DEBUG(dbgs() << "Initial worklist is empty.\n");

271 return;

272 }

273

275 for (auto *I : Worklist) { I->dump(); });

276

278 do {

281

286 } else {

288 }

289 }

290 Worklist = std::move(NextWorklist);

291 LLVM_DEBUG(dbgs() << "Worklist size: " << Worklist.size() << "\n");

293

294 if (Worklist.empty())

295 return;

296

297 for (auto *I : Worklist) {

299 Register ResVReg = I->getOperand(0).getReg();

300 const LLT &ResLLT = MRI.getType(ResVReg);

307 } else {

309 }

310 LLVM_DEBUG(dbgs() << "Could not determine type for " << *I

311 << ", defaulting to " << *ResType << "\n");

313 }

314}

315

318 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {

319 return true;

320 }

321 }

322 return false;

323}

324

328 LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "

329 << printReg(ResultRegister, MRI.getTargetRegisterInfo())

330 << " with type: " << *ResultType);

332 updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);

333

334

335

336

338 MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));

339 const auto *RegClass = GR->getRegClass(ResultType);

340 MRI.setRegClass(NewReg, RegClass);

341 MRI.setRegClass(ResultRegister, RegClass);

342

344

345

347

348

349 const uint32_t Flags = MI.getFlags();

351 .addDef(ResultRegister)

355 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {

357 if (MO.getReg() == ResultRegister) {

359 break;

360 }

361 }

362}

363

366 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "

367 << MF.getName() << "\n");

372 continue;

373

375

376 Register ResultRegister = MI.defs().begin()->getReg();

378 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");

379 continue;

380 }

381

385 }

386 }

387}

388

389

390

393 std::stack<MachineBasicBlock *> ToVisit;

395

396 ToVisit.push(&Start);

397 Seen.insert(ToVisit.top());

398 while (ToVisit.size() != 0) {

400 ToVisit.pop();

401

403

404 for (auto Succ : MBB->successors()) {

406 continue;

407 ToVisit.push(Succ);

409 }

410 }

411}

412

413

414

418

419bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {

420

421 const SPIRVSubtarget &ST = MF.getSubtarget();

422 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();

423 GR->setCurrentFunc(MF);

426 return true;

427}

428

430 false)

431

432char SPIRVPostLegalizer::ID = 0;

433

435 return new SPIRVPostLegalizer();

436}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

MachineInstr unsigned OpIdx

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

static bool deduceAndAssignSpirvType(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)

Definition SPIRVPostLegalizer.cpp:196

static SPIRVType * deduceIntTypeFromResult(Register ResVReg, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR)

Definition SPIRVPostLegalizer.cpp:46

void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)

Definition SPIRVPostLegalizer.cpp:391

static void registerSpirvTypeForNewInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)

Definition SPIRVPostLegalizer.cpp:257

static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI)

Definition SPIRVPostLegalizer.cpp:316

static SPIRVType * deduceResultTypeFromOperands(MachineInstr *I, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)

Definition SPIRVPostLegalizer.cpp:176

static SPIRVType * deduceTypeFromOperandRange(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned StartOp, unsigned EndOp)

Definition SPIRVPostLegalizer.cpp:118

static SPIRVType * deduceTypeFromUses(Register Reg, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)

Definition SPIRVPostLegalizer.cpp:156

static SPIRVType * deduceTypeForResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)

Definition SPIRVPostLegalizer.cpp:136

static void generateAssignType(MachineInstr &MI, Register ResultRegister, SPIRVType *ResultType, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)

Definition SPIRVPostLegalizer.cpp:325

static bool deduceAndAssignTypeForGUnmerge(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR)

Definition SPIRVPostLegalizer.cpp:53

static void ensureAssignTypeForTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR)

Definition SPIRVPostLegalizer.cpp:364

static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)

Definition SPIRVPostLegalizer.cpp:229

static SPIRVType * deduceTypeFromSingleOperand(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned OpIdx)

Definition SPIRVPostLegalizer.cpp:100

constexpr uint16_t getNumElements() const

Returns the number of elements in a vector LLT.

constexpr bool isVector() const

constexpr TypeSize getSizeInBits() const

Returns the total size of the type. Must only be called on sized types.

constexpr LLT getElementType() const

Returns the vector's element type. Only valid for vector types.

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Helper class to build MachineInstr.

MachineInstrBuilder buildInstr(unsigned Opcode)

Build and insert = Opcode .

MachineFunction & getMF()

Getter for the function we currently build.

MachineRegisterInfo * getMRI()

Getter for MRI.

const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register use operand.

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

Representation of each machine instruction.

MachineOperand class - Representation of each machine instruction operand.

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

Register getReg() const

getReg - Returns the register number.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

LLT getType(Register Reg) const

Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.

Wrapper class representing virtual and physical registers.

SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const

void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)

Register getSPIRVTypeID(const SPIRVType *SpirvType) const

SPIRVType * getScalarOrVectorComponentType(Register VReg) const

const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const

SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)

SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)

const SPIRVInstrInfo * getInstrInfo() const override

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

bool contains(ConstPtrType Ptr) const

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

The instances of the Type class are immutable: once they are created, they are never changed.

A Use represents the edge between a Value definition and its users.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

This is an optimization pass for GlobalISel generic memory operations.

bool isTypeFoldingSupported(unsigned Opcode)

void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)

Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...

void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVType *KnownResType)

FunctionPass * createSPIRVPostLegalizerPass()

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)

const MachineInstr SPIRVType

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.