LLVM: lib/Target/Hexagon/HexagonGenMux.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

42#include

43#include

44#include

45#include

46

47#define DEBUG_TYPE "hexmux"

48

49using namespace llvm;

50

51

53 cl::init(0), cl::desc("Minimum distance between predicate definition and "

54 "farther of the two predicated uses"));

55

56namespace {

57

59 public:

60 static char ID;

61

63

64 StringRef getPassName() const override {

65 return "Hexagon generate mux instructions";

66 }

67

68 void getAnalysisUsage(AnalysisUsage &AU) const override {

70 }

71

72 bool runOnMachineFunction(MachineFunction &MF) override;

73

74 MachineFunctionProperties getRequiredProperties() const override {

75 return MachineFunctionProperties().setNoVRegs();

76 }

77

78 private:

79 const HexagonInstrInfo *HII = nullptr;

80 const HexagonRegisterInfo *HRI = nullptr;

81

82 struct CondsetInfo {

83 unsigned PredR = 0;

84 unsigned TrueX = std::numeric_limits::max();

85 unsigned FalseX = std::numeric_limits::max();

86

87 CondsetInfo() = default;

88 };

89

90 struct DefUseInfo {

91 BitVector Defs, Uses;

92

93 DefUseInfo() = default;

94 DefUseInfo(const BitVector &D, const BitVector &U) : Defs(D), Uses(U) {}

95 };

96

97 struct MuxInfo {

99 unsigned DefR, PredR;

100 MachineOperand *SrcT, *SrcF;

101 MachineInstr *Def1, *Def2;

102

104 MachineOperand *TOp, MachineOperand *FOp, MachineInstr &D1,

105 MachineInstr &D2)

106 : At(It), DefR(DR), PredR(PR), SrcT(TOp), SrcF(FOp), Def1(&D1),

107 Def2(&D2) {}

108 };

109

110 using InstrIndexMap = DenseMap<MachineInstr *, unsigned>;

111 using DefUseInfoMap = DenseMap<unsigned, DefUseInfo>;

112 using MuxInfoList = SmallVector<MuxInfo, 4>;

113

114 bool isRegPair(unsigned Reg) const {

115 return Hexagon::DoubleRegsRegClass.contains(Reg);

116 }

117

118 void getSubRegs(unsigned Reg, BitVector &SRs) const;

119 void expandReg(unsigned Reg, BitVector &Set) const;

120 void getDefsUses(const MachineInstr *MI, BitVector &Defs,

121 BitVector &Uses) const;

122 void buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,

123 DefUseInfoMap &DUM);

124 bool isCondTransfer(unsigned Opc) const;

125 unsigned getMuxOpcode(const MachineOperand &Src1,

126 const MachineOperand &Src2) const;

127 bool genMuxInBlock(MachineBasicBlock &B);

128 };

129

130}

131

132char HexagonGenMux::ID = 0;

133

135 "Hexagon generate mux instructions", false, false)

136

137void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const {

139 SRs[I] = true;

140}

141

142void HexagonGenMux::expandReg(unsigned Reg, BitVector &Set) const {

143 if (isRegPair(Reg))

144 getSubRegs(Reg, Set);

145 else

147}

148

149void HexagonGenMux::getDefsUses(const MachineInstr *MI, BitVector &Defs,

150 BitVector &Uses) const {

151

152 unsigned Opc = MI->getOpcode();

153 const MCInstrDesc &D = HII->get(Opc);

154 for (MCPhysReg R : D.implicit_defs())

155 expandReg(R, Defs);

156 for (MCPhysReg R : D.implicit_uses())

157 expandReg(R, Uses);

158

159

160 for (const MachineOperand &MO : MI->operands()) {

161 if (!MO.isReg() || MO.isImplicit())

162 continue;

164 BitVector &Set = MO.isDef() ? Defs : Uses;

165 expandReg(R, Set);

166 }

167}

168

169void HexagonGenMux::buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,

170 DefUseInfoMap &DUM) {

171 unsigned Index = 0;

172 unsigned NR = HRI->getNumRegs();

173 BitVector Defs(NR), Uses(NR);

174

175 for (MachineInstr &MI : B) {

176 I2X.insert(std::make_pair(&MI, Index));

179 getDefsUses(&MI, Defs, Uses);

180 DUM.insert(std::make_pair(Index, DefUseInfo(Defs, Uses)));

182 }

183}

184

185bool HexagonGenMux::isCondTransfer(unsigned Opc) const {

186 switch (Opc) {

187 case Hexagon::A2_tfrt:

188 case Hexagon::A2_tfrf:

189 case Hexagon::C2_cmoveit:

190 case Hexagon::C2_cmoveif:

191 return true;

192 }

193 return false;

194}

195

196unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1,

197 const MachineOperand &Src2) const {

198 bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg();

199 if (IsReg1)

200 return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir;

201 if (IsReg2)

202 return Hexagon::C2_muxri;

203

204

205

207 return Hexagon::C2_muxii;

208

209 return 0;

210}

211

212bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {

214 InstrIndexMap I2X;

215 DefUseInfoMap DUM;

216 buildMaps(B, I2X, DUM);

217

218 using CondsetMap = DenseMap<unsigned, CondsetInfo>;

219

220 CondsetMap CM;

221 MuxInfoList ML;

222

224 unsigned Opc = MI.getOpcode();

225 if (!isCondTransfer(Opc))

226 continue;

227 Register DR = MI.getOperand(0).getReg();

228 if (isRegPair(DR))

229 continue;

230 MachineOperand &PredOp = MI.getOperand(1);

232 continue;

233

235 unsigned Idx = I2X.lookup(&MI);

236 CondsetMap::iterator F = CM.find(DR);

238

239

240

241 if (F != CM.end() && F->second.PredR != PR) {

242 CM.erase(F);

243 F = CM.end();

244 }

245 if (F == CM.end()) {

246 F = CM.try_emplace(DR).first;

247 F->second.PredR = PR;

248 }

249 CondsetInfo &CI = F->second;

250 if (IfTrue)

251 CI.TrueX = Idx;

252 else

253 CI.FalseX = Idx;

254 if (CI.TrueX == std::numeric_limits::max() ||

255 CI.FalseX == std::numeric_limits::max())

256 continue;

257

258

259

260

261

262

263 unsigned MinX = std::min(CI.TrueX, CI.FalseX);

264 unsigned MaxX = std::max(CI.TrueX, CI.FalseX);

265

266

268 bool NearDef = false;

269 for (unsigned X = SearchX; X < MaxX; ++X) {

270 const DefUseInfo &DU = DUM.lookup(X);

271 if (!DU.Defs[PR])

272 continue;

273 NearDef = true;

274 break;

275 }

276 if (NearDef)

277 continue;

278

279

280

281

282

283

284

286 std::advance(It1, MinX);

287 std::advance(It2, MaxX);

288 MachineInstr &Def1 = *It1, &Def2 = *It2;

289 MachineOperand *Src1 = &Def1.getOperand(2), *Src2 = &Def2.getOperand(2);

292 bool Failure = false, CanUp = true, CanDown = true;

293 for (unsigned X = MinX+1; X < MaxX; X++) {

294 const DefUseInfo &DU = DUM.lookup(X);

295 if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {

297 break;

298 }

299 if (CanDown && DU.Defs[SR1])

300 CanDown = false;

301 if (CanUp && DU.Defs[SR2])

302 CanUp = false;

303 }

304 if (Failure || (!CanUp && !CanDown))

305 continue;

306

307 MachineOperand *SrcT = (MinX == CI.TrueX) ? Src1 : Src2;

308 MachineOperand *SrcF = (MinX == CI.FalseX) ? Src1 : Src2;

309

310

312 ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));

313 }

314

315 for (MuxInfo &MX : ML) {

316 unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF);

317 if (!MxOpc)

318 continue;

319

320

321

322 if (!MX.At->getParent() || !MX.Def1->getParent() || !MX.Def2->getParent())

323 continue;

324

325 MachineBasicBlock &B = *MX.At->getParent();

327 auto NewMux = BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)

329 .add(*MX.SrcT)

330 .add(*MX.SrcF);

332 B.remove(MX.Def1);

333 B.remove(MX.Def2);

335 }

336

337

338

339 LiveRegUnits LPR(*HRI);

340 LPR.addLiveOuts(B);

342 if (I.isDebugInstr())

343 continue;

344

345

346

347

348 for (MachineOperand &Op : I.operands()) {

349 if (Op.isReg() || Op.isUse())

350 continue;

351 assert(Op.getSubReg() == 0 && "Should have physical registers only");

352 bool Live = !LPR.available(Op.getReg());

353 Op.setIsKill(!Live);

354 }

355 LPR.stepBackward(I);

356 }

357

359}

360

361bool HexagonGenMux::runOnMachineFunction(MachineFunction &MF) {

363 return false;

364 HII = MF.getSubtarget().getInstrInfo();

365 HRI = MF.getSubtarget().getRegisterInfo();

367 for (auto &I : MF)

370}

371

373 return new HexagonGenMux();

374}

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file implements the BitVector class.

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file defines the DenseMap class.

static cl::opt< unsigned > MinPredDist("hexagon-gen-mux-threshold", cl::Hidden, cl::init(0), cl::desc("Minimum distance between predicate definition and " "farther of the two predicated uses"))

Promote Memory to Register

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

Remove Loads Into Fake Uses

This file defines the SmallVector class.

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

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

bool isPredicatedTrue(const MachineInstr &MI) const

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...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineOperand & getOperand(unsigned i) const

LLVM_ABI void clearKillInfo()

Clears kill flags on all operands.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

Register getReg() const

getReg - Returns the register number.

unsigned ID

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

initializer< Ty > init(const Ty &Val)

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.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

auto reverse(ContainerTy &&C)

FunctionPass * createHexagonGenMux()

Definition HexagonGenMux.cpp:372

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

DWARFExpression::Operation Op