LLVM: lib/Target/AMDGPU/R600EmitClauseMarkers.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

21

22using namespace llvm;

23

24namespace {

25

27private:

28 const R600InstrInfo *TII = nullptr;

29 int Address = 0;

30

31 unsigned OccupiedDwords(MachineInstr &MI) const {

32 switch (MI.getOpcode()) {

33 case R600::INTERP_PAIR_XY:

34 case R600::INTERP_PAIR_ZW:

35 case R600::INTERP_VEC_LOAD:

36 case R600::DOT_4:

37 return 4;

38 case R600::KILL:

39 return 0;

40 default:

41 break;

42 }

43

44

45

46 if (TII->isLDSRetInstr(MI.getOpcode()))

47 return 2;

48

49 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()) ||

50 TII->isReductionOp(MI.getOpcode()))

51 return 4;

52

53 unsigned NumLiteral = 0;

55 E = MI.operands_end();

56 It != E; ++It) {

57 MachineOperand &MO = *It;

58 if (MO.isReg() && MO.getReg() == R600::ALU_LITERAL_X)

59 ++NumLiteral;

60 }

61 return 1 + NumLiteral;

62 }

63

64 bool isALU(const MachineInstr &MI) const {

65 if (TII->isALUInstr(MI.getOpcode()))

66 return true;

67 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()))

68 return true;

69 switch (MI.getOpcode()) {

70 case R600::PRED_X:

71 case R600::INTERP_PAIR_XY:

72 case R600::INTERP_PAIR_ZW:

73 case R600::INTERP_VEC_LOAD:

74 case R600::COPY:

75 case R600::DOT_4:

76 return true;

77 default:

78 return false;

79 }

80 }

81

82 bool IsTrivialInst(MachineInstr &MI) const {

83 switch (MI.getOpcode()) {

84 case R600::KILL:

85 case R600::RETURN:

86 case R600::IMPLICIT_DEF:

87 return true;

88 default:

89 return false;

90 }

91 }

92

93 std::pair<unsigned, unsigned> getAccessedBankLine(unsigned Sel) const {

94

95

96

97 return std::pair<unsigned, unsigned>(

98 ((Sel >> 2) - 512) >> 12,

99

100

101

102

103

104 ((((Sel >> 2) - 512) & 4095) >> 5) << 1);

105 }

106

107 bool

108 SubstituteKCacheBank(MachineInstr &MI,

109 std::vector<std::pair<unsigned, unsigned>> &CachedConsts,

110 bool UpdateInstr = true) const {

111 std::vector<std::pair<unsigned, unsigned>> UsedKCache;

112

113 if (!TII->isALUInstr(MI.getOpcode()) && MI.getOpcode() != R600::DOT_4)

114 return true;

115

116 const SmallVectorImpl<std::pair<MachineOperand *, int64_t>> &Consts =

117 TII->getSrcs(MI);

119 (TII->isALUInstr(MI.getOpcode()) || MI.getOpcode() == R600::DOT_4) &&

120 "Can't assign Const");

121 for (auto &[Op, Sel] : Consts) {

122 if (Op->getReg() != R600::ALU_CONST)

123 continue;

124 unsigned Chan = Sel & 3, Index = ((Sel >> 2) - 512) & 31;

125 unsigned KCacheIndex = Index * 4 + Chan;

126 const std::pair<unsigned, unsigned> &BankLine = getAccessedBankLine(Sel);

127 if (CachedConsts.empty()) {

128 CachedConsts.push_back(BankLine);

129 UsedKCache.emplace_back(0, KCacheIndex);

130 continue;

131 }

132 if (CachedConsts[0] == BankLine) {

133 UsedKCache.emplace_back(0, KCacheIndex);

134 continue;

135 }

136 if (CachedConsts.size() == 1) {

137 CachedConsts.push_back(BankLine);

138 UsedKCache.emplace_back(1, KCacheIndex);

139 continue;

140 }

141 if (CachedConsts[1] == BankLine) {

142 UsedKCache.emplace_back(1, KCacheIndex);

143 continue;

144 }

145 return false;

146 }

147

148 if (!UpdateInstr)

149 return true;

150

151 unsigned j = 0;

152 for (auto &[Op, Sel] : Consts) {

153 if (Op->getReg() != R600::ALU_CONST)

154 continue;

155 switch (UsedKCache[j].first) {

156 case 0:

157 Op->setReg(R600::R600_KC0RegClass.getRegister(UsedKCache[j].second));

158 break;

159 case 1:

160 Op->setReg(R600::R600_KC1RegClass.getRegister(UsedKCache[j].second));

161 break;

162 default:

164 }

165 j++;

166 }

167 return true;

168 }

169

170 bool canClauseLocalKillFitInClause(

171 unsigned AluInstCount,

172 std::vector<std::pair<unsigned, unsigned>> KCacheBanks,

175 const R600RegisterInfo &TRI = TII->getRegisterInfo();

176

177 for (MachineOperand &MO : Def->all_defs()) {

178 if (TRI.isPhysRegLiveAcrossClauses(MO.getReg()))

179 continue;

180

181

182

183 unsigned LastUseCount = 0;

185 AluInstCount += OccupiedDwords(*UseI);

186

187 if (!SubstituteKCacheBank(*UseI, KCacheBanks, false))

188 return false;

189

190

191

192

193 if (AluInstCount >= TII->getMaxAlusPerClause())

194 return false;

195

196

197

198

199

200

201

202 if (UseI->readsRegister(MO.getReg(), &TRI))

203 LastUseCount = AluInstCount;

204

205

206 if (UseI != Def && UseI->killsRegister(MO.getReg(), &TRI))

207 break;

208 }

209 if (LastUseCount)

210 return LastUseCount <= TII->getMaxAlusPerClause();

211 llvm_unreachable("Clause local register live at end of clause.");

212 }

213 return true;

214 }

215

219 std::vector<std::pair<unsigned, unsigned>> KCacheBanks;

220 bool PushBeforeModifier = false;

221 unsigned AluInstCount = 0;

223 if (IsTrivialInst(*I))

224 continue;

225 if (!isALU(*I))

226 break;

227 if (AluInstCount > TII->getMaxAlusPerClause())

228 break;

229 if (I->getOpcode() == R600::PRED_X) {

230

231

232

233

234

235

236 if (AluInstCount > 0)

237 break;

238 if (TII->getFlagOp(*I).getImm() & MO_FLAG_PUSH)

239 PushBeforeModifier = true;

240 AluInstCount ++;

241 continue;

242 }

243

244

245

246

247

248

249

250 if (TII->mustBeLastInClause(I->getOpcode())) {

251 I++;

252 break;

253 }

254

255

256

257 if (!canClauseLocalKillFitInClause(AluInstCount, KCacheBanks, I, E))

258 break;

259

260 if (!SubstituteKCacheBank(*I, KCacheBanks))

261 break;

262 AluInstCount += OccupiedDwords(*I);

263 }

264 unsigned Opcode = PushBeforeModifier ?

265 R600::CF_ALU_PUSH_BEFORE : R600::CF_ALU;

267

268

269

270

271 .addImm(Address++)

272 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].first)

273 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].first)

274 .addImm(KCacheBanks.empty()?0:2)

275 .addImm((KCacheBanks.size() < 2)?0:2)

276 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].second)

277 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].second)

278 .addImm(AluInstCount)

279 .addImm(1);

280 return I;

281 }

282

283public:

284 static char ID;

285

286 R600EmitClauseMarkers() : MachineFunctionPass(ID) {}

287

288 bool runOnMachineFunction(MachineFunction &MF) override {

289 const R600Subtarget &ST = MF.getSubtarget();

290 TII = ST.getInstrInfo();

291

292 for (MachineBasicBlock &MBB : MF) {

294 if (I != MBB.end() && I->getOpcode() == R600::CF_ALU)

295 continue;

297 if (isALU(*I)) {

298 auto next = MakeALUClause(MBB, I);

300 I = next;

301 } else

302 ++I;

303 }

304 }

305 return false;

306 }

307

308 StringRef getPassName() const override {

309 return "R600 Emit Clause Markers Pass";

310 }

311};

312

313char R600EmitClauseMarkers::ID = 0;

314

315}

316

318 "R600 Emit Clause Markers", false, false)

321

323 return new R600EmitClauseMarkers();

324}

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

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

Register const TargetRegisterInfo * TRI

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

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

Provides R600 specific target descriptions.

AMDGPU R600 specific subclass of TargetSubtarget.

FunctionPass class - This class is used to implement most global optimizations.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)

Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.

MachineInstrBundleIterator< MachineInstr > iterator

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.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

MachineOperand * mop_iterator

iterator/begin/end - Iterate over all operands of a machine instruction.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

Register getReg() const

getReg - Returns the register number.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

FunctionPass * createR600EmitClauseMarkers()

Definition R600EmitClauseMarkers.cpp:322

DWARFExpression::Operation Op