xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonGenMux.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- HexagonGenMux.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // During instruction selection, MUX instructions are generated for
10 // conditional assignments. Since such assignments often present an
11 // opportunity to predicate instructions, HexagonExpandCondsets
12 // expands MUXes into pairs of conditional transfers, and then proceeds
13 // with predication of the producers/consumers of the registers involved.
14 // This happens after exiting from the SSA form, but before the machine
15 // instruction scheduler. After the scheduler and after the register
16 // allocation there can be cases of pairs of conditional transfers
17 // resulting from a MUX where neither of them was further predicated. If
18 // these transfers are now placed far enough from the instruction defining
19 // the predicate register, they cannot use the .new form. In such cases it
20 // is better to collapse them back to a single MUX instruction.
21 
22 #include "Hexagon.h"
23 #include "HexagonInstrInfo.h"
24 #include "HexagonRegisterInfo.h"
25 #include "HexagonSubtarget.h"
26 #include "llvm/ADT/BitVector.h"
27 #include "llvm/ADT/DenseMap.h"
28 #include "llvm/ADT/SmallVector.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/CodeGen/LiveRegUnits.h"
31 #include "llvm/CodeGen/MachineBasicBlock.h"
32 #include "llvm/CodeGen/MachineFunction.h"
33 #include "llvm/CodeGen/MachineFunctionPass.h"
34 #include "llvm/CodeGen/MachineInstr.h"
35 #include "llvm/CodeGen/MachineInstrBuilder.h"
36 #include "llvm/CodeGen/MachineOperand.h"
37 #include "llvm/IR/DebugLoc.h"
38 #include "llvm/MC/MCInstrDesc.h"
39 #include "llvm/Pass.h"
40 #include "llvm/Support/CommandLine.h"
41 #include "llvm/Support/MathExtras.h"
42 #include <algorithm>
43 #include <cassert>
44 #include <iterator>
45 #include <limits>
46 #include <utility>
47 
48 #define DEBUG_TYPE "hexmux"
49 
50 using namespace llvm;
51 
52 // Initialize this to 0 to always prefer generating mux by default.
53 static cl::opt<unsigned> MinPredDist("hexagon-gen-mux-threshold", cl::Hidden,
54   cl::init(0), cl::desc("Minimum distance between predicate definition and "
55   "farther of the two predicated uses"));
56 
57 namespace {
58 
59   class HexagonGenMux : public MachineFunctionPass {
60   public:
61     static char ID;
62 
HexagonGenMux()63     HexagonGenMux() : MachineFunctionPass(ID) {}
64 
getPassName() const65     StringRef getPassName() const override {
66       return "Hexagon generate mux instructions";
67     }
68 
getAnalysisUsage(AnalysisUsage & AU) const69     void getAnalysisUsage(AnalysisUsage &AU) const override {
70       MachineFunctionPass::getAnalysisUsage(AU);
71     }
72 
73     bool runOnMachineFunction(MachineFunction &MF) override;
74 
getRequiredProperties() const75     MachineFunctionProperties getRequiredProperties() const override {
76       return MachineFunctionProperties().setNoVRegs();
77     }
78 
79   private:
80     const HexagonInstrInfo *HII = nullptr;
81     const HexagonRegisterInfo *HRI = nullptr;
82 
83     struct CondsetInfo {
84       unsigned PredR = 0;
85       unsigned TrueX = std::numeric_limits<unsigned>::max();
86       unsigned FalseX = std::numeric_limits<unsigned>::max();
87 
88       CondsetInfo() = default;
89     };
90 
91     struct DefUseInfo {
92       BitVector Defs, Uses;
93 
94       DefUseInfo() = default;
DefUseInfo__anoncf1483fd0111::HexagonGenMux::DefUseInfo95       DefUseInfo(const BitVector &D, const BitVector &U) : Defs(D), Uses(U) {}
96     };
97 
98     struct MuxInfo {
99       MachineBasicBlock::iterator At;
100       unsigned DefR, PredR;
101       MachineOperand *SrcT, *SrcF;
102       MachineInstr *Def1, *Def2;
103 
MuxInfo__anoncf1483fd0111::HexagonGenMux::MuxInfo104       MuxInfo(MachineBasicBlock::iterator It, unsigned DR, unsigned PR,
105               MachineOperand *TOp, MachineOperand *FOp, MachineInstr &D1,
106               MachineInstr &D2)
107           : At(It), DefR(DR), PredR(PR), SrcT(TOp), SrcF(FOp), Def1(&D1),
108             Def2(&D2) {}
109     };
110 
111     using InstrIndexMap = DenseMap<MachineInstr *, unsigned>;
112     using DefUseInfoMap = DenseMap<unsigned, DefUseInfo>;
113     using MuxInfoList = SmallVector<MuxInfo, 4>;
114 
isRegPair(unsigned Reg) const115     bool isRegPair(unsigned Reg) const {
116       return Hexagon::DoubleRegsRegClass.contains(Reg);
117     }
118 
119     void getSubRegs(unsigned Reg, BitVector &SRs) const;
120     void expandReg(unsigned Reg, BitVector &Set) const;
121     void getDefsUses(const MachineInstr *MI, BitVector &Defs,
122           BitVector &Uses) const;
123     void buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,
124           DefUseInfoMap &DUM);
125     bool isCondTransfer(unsigned Opc) const;
126     unsigned getMuxOpcode(const MachineOperand &Src1,
127           const MachineOperand &Src2) const;
128     bool genMuxInBlock(MachineBasicBlock &B);
129   };
130 
131 } // end anonymous namespace
132 
133 char HexagonGenMux::ID = 0;
134 
135 INITIALIZE_PASS(HexagonGenMux, "hexagon-gen-mux",
136   "Hexagon generate mux instructions", false, false)
137 
getSubRegs(unsigned Reg,BitVector & SRs) const138 void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const {
139   for (MCPhysReg I : HRI->subregs(Reg))
140     SRs[I] = true;
141 }
142 
expandReg(unsigned Reg,BitVector & Set) const143 void HexagonGenMux::expandReg(unsigned Reg, BitVector &Set) const {
144   if (isRegPair(Reg))
145     getSubRegs(Reg, Set);
146   else
147     Set[Reg] = true;
148 }
149 
getDefsUses(const MachineInstr * MI,BitVector & Defs,BitVector & Uses) const150 void HexagonGenMux::getDefsUses(const MachineInstr *MI, BitVector &Defs,
151       BitVector &Uses) const {
152   // First, get the implicit defs and uses for this instruction.
153   unsigned Opc = MI->getOpcode();
154   const MCInstrDesc &D = HII->get(Opc);
155   for (MCPhysReg R : D.implicit_defs())
156     expandReg(R, Defs);
157   for (MCPhysReg R : D.implicit_uses())
158     expandReg(R, Uses);
159 
160   // Look over all operands, and collect explicit defs and uses.
161   for (const MachineOperand &MO : MI->operands()) {
162     if (!MO.isReg() || MO.isImplicit())
163       continue;
164     Register R = MO.getReg();
165     BitVector &Set = MO.isDef() ? Defs : Uses;
166     expandReg(R, Set);
167   }
168 }
169 
buildMaps(MachineBasicBlock & B,InstrIndexMap & I2X,DefUseInfoMap & DUM)170 void HexagonGenMux::buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,
171       DefUseInfoMap &DUM) {
172   unsigned Index = 0;
173   unsigned NR = HRI->getNumRegs();
174   BitVector Defs(NR), Uses(NR);
175 
176   for (MachineInstr &MI : B) {
177     I2X.insert(std::make_pair(&MI, Index));
178     Defs.reset();
179     Uses.reset();
180     getDefsUses(&MI, Defs, Uses);
181     DUM.insert(std::make_pair(Index, DefUseInfo(Defs, Uses)));
182     Index++;
183   }
184 }
185 
isCondTransfer(unsigned Opc) const186 bool HexagonGenMux::isCondTransfer(unsigned Opc) const {
187   switch (Opc) {
188     case Hexagon::A2_tfrt:
189     case Hexagon::A2_tfrf:
190     case Hexagon::C2_cmoveit:
191     case Hexagon::C2_cmoveif:
192       return true;
193   }
194   return false;
195 }
196 
getMuxOpcode(const MachineOperand & Src1,const MachineOperand & Src2) const197 unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1,
198       const MachineOperand &Src2) const {
199   bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg();
200   if (IsReg1)
201     return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir;
202   if (IsReg2)
203     return Hexagon::C2_muxri;
204 
205   // Neither is a register. The first source is extendable, but the second
206   // is not (s8).
207   if (Src2.isImm() && isInt<8>(Src2.getImm()))
208     return Hexagon::C2_muxii;
209 
210   return 0;
211 }
212 
genMuxInBlock(MachineBasicBlock & B)213 bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
214   bool Changed = false;
215   InstrIndexMap I2X;
216   DefUseInfoMap DUM;
217   buildMaps(B, I2X, DUM);
218 
219   using CondsetMap = DenseMap<unsigned, CondsetInfo>;
220 
221   CondsetMap CM;
222   MuxInfoList ML;
223 
224   for (MachineInstr &MI : llvm::make_early_inc_range(B)) {
225     unsigned Opc = MI.getOpcode();
226     if (!isCondTransfer(Opc))
227       continue;
228     Register DR = MI.getOperand(0).getReg();
229     if (isRegPair(DR))
230       continue;
231     MachineOperand &PredOp = MI.getOperand(1);
232     if (PredOp.isUndef())
233       continue;
234 
235     Register PR = PredOp.getReg();
236     unsigned Idx = I2X.lookup(&MI);
237     CondsetMap::iterator F = CM.find(DR);
238     bool IfTrue = HII->isPredicatedTrue(Opc);
239 
240     // If there is no record of a conditional transfer for this register,
241     // or the predicate register differs, create a new record for it.
242     if (F != CM.end() && F->second.PredR != PR) {
243       CM.erase(F);
244       F = CM.end();
245     }
246     if (F == CM.end()) {
247       F = CM.try_emplace(DR).first;
248       F->second.PredR = PR;
249     }
250     CondsetInfo &CI = F->second;
251     if (IfTrue)
252       CI.TrueX = Idx;
253     else
254       CI.FalseX = Idx;
255     if (CI.TrueX == std::numeric_limits<unsigned>::max() ||
256         CI.FalseX == std::numeric_limits<unsigned>::max())
257       continue;
258 
259     // There is now a complete definition of DR, i.e. we have the predicate
260     // register, the definition if-true, and definition if-false.
261 
262     // First, check if the definitions are far enough from the definition
263     // of the predicate register.
264     unsigned MinX = std::min(CI.TrueX, CI.FalseX);
265     unsigned MaxX = std::max(CI.TrueX, CI.FalseX);
266     // Specifically, check if the predicate definition is within a prescribed
267     // distance from the farther of the two predicated instructions.
268     unsigned SearchX = (MaxX >= MinPredDist) ? MaxX-MinPredDist : 0;
269     bool NearDef = false;
270     for (unsigned X = SearchX; X < MaxX; ++X) {
271       const DefUseInfo &DU = DUM.lookup(X);
272       if (!DU.Defs[PR])
273         continue;
274       NearDef = true;
275       break;
276     }
277     if (NearDef)
278       continue;
279 
280     // The predicate register is not defined in the last few instructions.
281     // Check if the conversion to MUX is possible (either "up", i.e. at the
282     // place of the earlier partial definition, or "down", where the later
283     // definition is located). Examine all defs and uses between these two
284     // definitions.
285     // SR1, SR2 - source registers from the first and the second definition.
286     MachineBasicBlock::iterator It1 = B.begin(), It2 = B.begin();
287     std::advance(It1, MinX);
288     std::advance(It2, MaxX);
289     MachineInstr &Def1 = *It1, &Def2 = *It2;
290     MachineOperand *Src1 = &Def1.getOperand(2), *Src2 = &Def2.getOperand(2);
291     Register SR1 = Src1->isReg() ? Src1->getReg() : Register();
292     Register SR2 = Src2->isReg() ? Src2->getReg() : Register();
293     bool Failure = false, CanUp = true, CanDown = true;
294     for (unsigned X = MinX+1; X < MaxX; X++) {
295       const DefUseInfo &DU = DUM.lookup(X);
296       if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {
297         Failure = true;
298         break;
299       }
300       if (CanDown && DU.Defs[SR1])
301         CanDown = false;
302       if (CanUp && DU.Defs[SR2])
303         CanUp = false;
304     }
305     if (Failure || (!CanUp && !CanDown))
306       continue;
307 
308     MachineOperand *SrcT = (MinX == CI.TrueX) ? Src1 : Src2;
309     MachineOperand *SrcF = (MinX == CI.FalseX) ? Src1 : Src2;
310     // Prefer "down", since this will move the MUX farther away from the
311     // predicate definition.
312     MachineBasicBlock::iterator At = CanDown ? Def2 : Def1;
313     ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));
314   }
315 
316   for (MuxInfo &MX : ML) {
317     unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF);
318     if (!MxOpc)
319       continue;
320     // Basic correctness check: since we are deleting instructions, validate the
321     // iterators. There is a possibility that one of Def1 or Def2 is translated
322     // to "mux" and being considered for other "mux" instructions.
323     if (!MX.At->getParent() || !MX.Def1->getParent() || !MX.Def2->getParent())
324       continue;
325 
326     MachineBasicBlock &B = *MX.At->getParent();
327     const DebugLoc &DL = B.findDebugLoc(MX.At);
328     auto NewMux = BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)
329                       .addReg(MX.PredR)
330                       .add(*MX.SrcT)
331                       .add(*MX.SrcF);
332     NewMux->clearKillInfo();
333     B.remove(MX.Def1);
334     B.remove(MX.Def2);
335     Changed = true;
336   }
337 
338   // Fix up kill flags.
339 
340   LiveRegUnits LPR(*HRI);
341   LPR.addLiveOuts(B);
342   for (MachineInstr &I : llvm::reverse(B)) {
343     if (I.isDebugInstr())
344       continue;
345     // This isn't 100% accurate, but it's safe.
346     // It won't detect (as a kill) a case like this
347     //   r0 = add r0, 1    <-- r0 should be "killed"
348     //   ... = r0
349     for (MachineOperand &Op : I.operands()) {
350       if (!Op.isReg() || !Op.isUse())
351         continue;
352       assert(Op.getSubReg() == 0 && "Should have physical registers only");
353       bool Live = !LPR.available(Op.getReg());
354       Op.setIsKill(!Live);
355     }
356     LPR.stepBackward(I);
357   }
358 
359   return Changed;
360 }
361 
runOnMachineFunction(MachineFunction & MF)362 bool HexagonGenMux::runOnMachineFunction(MachineFunction &MF) {
363   if (skipFunction(MF.getFunction()))
364     return false;
365   HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
366   HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
367   bool Changed = false;
368   for (auto &I : MF)
369     Changed |= genMuxInBlock(I);
370   return Changed;
371 }
372 
createHexagonGenMux()373 FunctionPass *llvm::createHexagonGenMux() {
374   return new HexagonGenMux();
375 }
376