10b57cec5SDimitry Andric //===- HexagonGenMux.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric // During instruction selection, MUX instructions are generated for
100b57cec5SDimitry Andric // conditional assignments. Since such assignments often present an
110b57cec5SDimitry Andric // opportunity to predicate instructions, HexagonExpandCondsets
120b57cec5SDimitry Andric // expands MUXes into pairs of conditional transfers, and then proceeds
130b57cec5SDimitry Andric // with predication of the producers/consumers of the registers involved.
140b57cec5SDimitry Andric // This happens after exiting from the SSA form, but before the machine
150b57cec5SDimitry Andric // instruction scheduler. After the scheduler and after the register
160b57cec5SDimitry Andric // allocation there can be cases of pairs of conditional transfers
170b57cec5SDimitry Andric // resulting from a MUX where neither of them was further predicated. If
180b57cec5SDimitry Andric // these transfers are now placed far enough from the instruction defining
190b57cec5SDimitry Andric // the predicate register, they cannot use the .new form. In such cases it
200b57cec5SDimitry Andric // is better to collapse them back to a single MUX instruction.
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
230b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
240b57cec5SDimitry Andric #include "HexagonSubtarget.h"
250b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
260b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
270b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
280b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
360b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
390b57cec5SDimitry Andric #include "llvm/Pass.h"
400b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
410b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
420b57cec5SDimitry Andric #include <algorithm>
430b57cec5SDimitry Andric #include <cassert>
440b57cec5SDimitry Andric #include <iterator>
450b57cec5SDimitry Andric #include <limits>
460b57cec5SDimitry Andric #include <utility>
470b57cec5SDimitry Andric
48fe6060f1SDimitry Andric #define DEBUG_TYPE "hexmux"
49fe6060f1SDimitry Andric
500b57cec5SDimitry Andric using namespace llvm;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric namespace llvm {
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric FunctionPass *createHexagonGenMux();
550b57cec5SDimitry Andric void initializeHexagonGenMuxPass(PassRegistry& Registry);
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric } // end namespace llvm
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric // Initialize this to 0 to always prefer generating mux by default.
600b57cec5SDimitry Andric static cl::opt<unsigned> MinPredDist("hexagon-gen-mux-threshold", cl::Hidden,
610b57cec5SDimitry Andric cl::init(0), cl::desc("Minimum distance between predicate definition and "
620b57cec5SDimitry Andric "farther of the two predicated uses"));
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric namespace {
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric class HexagonGenMux : public MachineFunctionPass {
670b57cec5SDimitry Andric public:
680b57cec5SDimitry Andric static char ID;
690b57cec5SDimitry Andric
HexagonGenMux()700b57cec5SDimitry Andric HexagonGenMux() : MachineFunctionPass(ID) {}
710b57cec5SDimitry Andric
getPassName() const720b57cec5SDimitry Andric StringRef getPassName() const override {
730b57cec5SDimitry Andric return "Hexagon generate mux instructions";
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const760b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
770b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
810b57cec5SDimitry Andric
getRequiredProperties() const820b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
830b57cec5SDimitry Andric return MachineFunctionProperties().set(
840b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric private:
880b57cec5SDimitry Andric const HexagonInstrInfo *HII = nullptr;
890b57cec5SDimitry Andric const HexagonRegisterInfo *HRI = nullptr;
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric struct CondsetInfo {
920b57cec5SDimitry Andric unsigned PredR = 0;
930b57cec5SDimitry Andric unsigned TrueX = std::numeric_limits<unsigned>::max();
940b57cec5SDimitry Andric unsigned FalseX = std::numeric_limits<unsigned>::max();
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric CondsetInfo() = default;
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric struct DefUseInfo {
1000b57cec5SDimitry Andric BitVector Defs, Uses;
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric DefUseInfo() = default;
DefUseInfo__anonbc17b4c50111::HexagonGenMux::DefUseInfo1030b57cec5SDimitry Andric DefUseInfo(const BitVector &D, const BitVector &U) : Defs(D), Uses(U) {}
1040b57cec5SDimitry Andric };
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric struct MuxInfo {
1070b57cec5SDimitry Andric MachineBasicBlock::iterator At;
1080b57cec5SDimitry Andric unsigned DefR, PredR;
1090b57cec5SDimitry Andric MachineOperand *SrcT, *SrcF;
1100b57cec5SDimitry Andric MachineInstr *Def1, *Def2;
1110b57cec5SDimitry Andric
MuxInfo__anonbc17b4c50111::HexagonGenMux::MuxInfo1120b57cec5SDimitry Andric MuxInfo(MachineBasicBlock::iterator It, unsigned DR, unsigned PR,
1130b57cec5SDimitry Andric MachineOperand *TOp, MachineOperand *FOp, MachineInstr &D1,
1140b57cec5SDimitry Andric MachineInstr &D2)
1150b57cec5SDimitry Andric : At(It), DefR(DR), PredR(PR), SrcT(TOp), SrcF(FOp), Def1(&D1),
1160b57cec5SDimitry Andric Def2(&D2) {}
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric using InstrIndexMap = DenseMap<MachineInstr *, unsigned>;
1200b57cec5SDimitry Andric using DefUseInfoMap = DenseMap<unsigned, DefUseInfo>;
1210b57cec5SDimitry Andric using MuxInfoList = SmallVector<MuxInfo, 4>;
1220b57cec5SDimitry Andric
isRegPair(unsigned Reg) const1230b57cec5SDimitry Andric bool isRegPair(unsigned Reg) const {
1240b57cec5SDimitry Andric return Hexagon::DoubleRegsRegClass.contains(Reg);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric void getSubRegs(unsigned Reg, BitVector &SRs) const;
1280b57cec5SDimitry Andric void expandReg(unsigned Reg, BitVector &Set) const;
1290b57cec5SDimitry Andric void getDefsUses(const MachineInstr *MI, BitVector &Defs,
1300b57cec5SDimitry Andric BitVector &Uses) const;
1310b57cec5SDimitry Andric void buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,
1320b57cec5SDimitry Andric DefUseInfoMap &DUM);
1330b57cec5SDimitry Andric bool isCondTransfer(unsigned Opc) const;
1340b57cec5SDimitry Andric unsigned getMuxOpcode(const MachineOperand &Src1,
1350b57cec5SDimitry Andric const MachineOperand &Src2) const;
1360b57cec5SDimitry Andric bool genMuxInBlock(MachineBasicBlock &B);
1370b57cec5SDimitry Andric };
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric } // end anonymous namespace
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric char HexagonGenMux::ID = 0;
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric INITIALIZE_PASS(HexagonGenMux, "hexagon-gen-mux",
1440b57cec5SDimitry Andric "Hexagon generate mux instructions", false, false)
1450b57cec5SDimitry Andric
getSubRegs(unsigned Reg,BitVector & SRs) const1460b57cec5SDimitry Andric void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const {
14706c3fb27SDimitry Andric for (MCPhysReg I : HRI->subregs(Reg))
14806c3fb27SDimitry Andric SRs[I] = true;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
expandReg(unsigned Reg,BitVector & Set) const1510b57cec5SDimitry Andric void HexagonGenMux::expandReg(unsigned Reg, BitVector &Set) const {
1520b57cec5SDimitry Andric if (isRegPair(Reg))
1530b57cec5SDimitry Andric getSubRegs(Reg, Set);
1540b57cec5SDimitry Andric else
1550b57cec5SDimitry Andric Set[Reg] = true;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric
getDefsUses(const MachineInstr * MI,BitVector & Defs,BitVector & Uses) const1580b57cec5SDimitry Andric void HexagonGenMux::getDefsUses(const MachineInstr *MI, BitVector &Defs,
1590b57cec5SDimitry Andric BitVector &Uses) const {
1600b57cec5SDimitry Andric // First, get the implicit defs and uses for this instruction.
1610b57cec5SDimitry Andric unsigned Opc = MI->getOpcode();
1620b57cec5SDimitry Andric const MCInstrDesc &D = HII->get(Opc);
163bdd1243dSDimitry Andric for (MCPhysReg R : D.implicit_defs())
164bdd1243dSDimitry Andric expandReg(R, Defs);
165bdd1243dSDimitry Andric for (MCPhysReg R : D.implicit_uses())
166bdd1243dSDimitry Andric expandReg(R, Uses);
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric // Look over all operands, and collect explicit defs and uses.
1690b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
1700b57cec5SDimitry Andric if (!MO.isReg() || MO.isImplicit())
1710b57cec5SDimitry Andric continue;
1728bcb0991SDimitry Andric Register R = MO.getReg();
1730b57cec5SDimitry Andric BitVector &Set = MO.isDef() ? Defs : Uses;
1740b57cec5SDimitry Andric expandReg(R, Set);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
buildMaps(MachineBasicBlock & B,InstrIndexMap & I2X,DefUseInfoMap & DUM)1780b57cec5SDimitry Andric void HexagonGenMux::buildMaps(MachineBasicBlock &B, InstrIndexMap &I2X,
1790b57cec5SDimitry Andric DefUseInfoMap &DUM) {
1800b57cec5SDimitry Andric unsigned Index = 0;
1810b57cec5SDimitry Andric unsigned NR = HRI->getNumRegs();
1820b57cec5SDimitry Andric BitVector Defs(NR), Uses(NR);
1830b57cec5SDimitry Andric
184349cc55cSDimitry Andric for (MachineInstr &MI : B) {
185349cc55cSDimitry Andric I2X.insert(std::make_pair(&MI, Index));
1860b57cec5SDimitry Andric Defs.reset();
1870b57cec5SDimitry Andric Uses.reset();
188349cc55cSDimitry Andric getDefsUses(&MI, Defs, Uses);
1890b57cec5SDimitry Andric DUM.insert(std::make_pair(Index, DefUseInfo(Defs, Uses)));
1900b57cec5SDimitry Andric Index++;
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
isCondTransfer(unsigned Opc) const1940b57cec5SDimitry Andric bool HexagonGenMux::isCondTransfer(unsigned Opc) const {
1950b57cec5SDimitry Andric switch (Opc) {
1960b57cec5SDimitry Andric case Hexagon::A2_tfrt:
1970b57cec5SDimitry Andric case Hexagon::A2_tfrf:
1980b57cec5SDimitry Andric case Hexagon::C2_cmoveit:
1990b57cec5SDimitry Andric case Hexagon::C2_cmoveif:
2000b57cec5SDimitry Andric return true;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric return false;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
getMuxOpcode(const MachineOperand & Src1,const MachineOperand & Src2) const2050b57cec5SDimitry Andric unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1,
2060b57cec5SDimitry Andric const MachineOperand &Src2) const {
2070b57cec5SDimitry Andric bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg();
2080b57cec5SDimitry Andric if (IsReg1)
2090b57cec5SDimitry Andric return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir;
2100b57cec5SDimitry Andric if (IsReg2)
2110b57cec5SDimitry Andric return Hexagon::C2_muxri;
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric // Neither is a register. The first source is extendable, but the second
2140b57cec5SDimitry Andric // is not (s8).
2150b57cec5SDimitry Andric if (Src2.isImm() && isInt<8>(Src2.getImm()))
2160b57cec5SDimitry Andric return Hexagon::C2_muxii;
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric return 0;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
genMuxInBlock(MachineBasicBlock & B)2210b57cec5SDimitry Andric bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
2220b57cec5SDimitry Andric bool Changed = false;
2230b57cec5SDimitry Andric InstrIndexMap I2X;
2240b57cec5SDimitry Andric DefUseInfoMap DUM;
2250b57cec5SDimitry Andric buildMaps(B, I2X, DUM);
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric using CondsetMap = DenseMap<unsigned, CondsetInfo>;
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric CondsetMap CM;
2300b57cec5SDimitry Andric MuxInfoList ML;
2310b57cec5SDimitry Andric
232349cc55cSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(B)) {
233349cc55cSDimitry Andric unsigned Opc = MI.getOpcode();
2340b57cec5SDimitry Andric if (!isCondTransfer(Opc))
2350b57cec5SDimitry Andric continue;
236349cc55cSDimitry Andric Register DR = MI.getOperand(0).getReg();
2370b57cec5SDimitry Andric if (isRegPair(DR))
2380b57cec5SDimitry Andric continue;
239349cc55cSDimitry Andric MachineOperand &PredOp = MI.getOperand(1);
2400b57cec5SDimitry Andric if (PredOp.isUndef())
2410b57cec5SDimitry Andric continue;
2420b57cec5SDimitry Andric
2438bcb0991SDimitry Andric Register PR = PredOp.getReg();
244349cc55cSDimitry Andric unsigned Idx = I2X.lookup(&MI);
2450b57cec5SDimitry Andric CondsetMap::iterator F = CM.find(DR);
2460b57cec5SDimitry Andric bool IfTrue = HII->isPredicatedTrue(Opc);
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric // If there is no record of a conditional transfer for this register,
2490b57cec5SDimitry Andric // or the predicate register differs, create a new record for it.
2500b57cec5SDimitry Andric if (F != CM.end() && F->second.PredR != PR) {
2510b57cec5SDimitry Andric CM.erase(F);
2520b57cec5SDimitry Andric F = CM.end();
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric if (F == CM.end()) {
2550b57cec5SDimitry Andric auto It = CM.insert(std::make_pair(DR, CondsetInfo()));
2560b57cec5SDimitry Andric F = It.first;
2570b57cec5SDimitry Andric F->second.PredR = PR;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric CondsetInfo &CI = F->second;
2600b57cec5SDimitry Andric if (IfTrue)
2610b57cec5SDimitry Andric CI.TrueX = Idx;
2620b57cec5SDimitry Andric else
2630b57cec5SDimitry Andric CI.FalseX = Idx;
2640b57cec5SDimitry Andric if (CI.TrueX == std::numeric_limits<unsigned>::max() ||
2650b57cec5SDimitry Andric CI.FalseX == std::numeric_limits<unsigned>::max())
2660b57cec5SDimitry Andric continue;
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric // There is now a complete definition of DR, i.e. we have the predicate
2690b57cec5SDimitry Andric // register, the definition if-true, and definition if-false.
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric // First, check if the definitions are far enough from the definition
2720b57cec5SDimitry Andric // of the predicate register.
2730b57cec5SDimitry Andric unsigned MinX = std::min(CI.TrueX, CI.FalseX);
2740b57cec5SDimitry Andric unsigned MaxX = std::max(CI.TrueX, CI.FalseX);
2750b57cec5SDimitry Andric // Specifically, check if the predicate definition is within a prescribed
2760b57cec5SDimitry Andric // distance from the farther of the two predicated instructions.
2770b57cec5SDimitry Andric unsigned SearchX = (MaxX >= MinPredDist) ? MaxX-MinPredDist : 0;
2780b57cec5SDimitry Andric bool NearDef = false;
2790b57cec5SDimitry Andric for (unsigned X = SearchX; X < MaxX; ++X) {
2800b57cec5SDimitry Andric const DefUseInfo &DU = DUM.lookup(X);
2810b57cec5SDimitry Andric if (!DU.Defs[PR])
2820b57cec5SDimitry Andric continue;
2830b57cec5SDimitry Andric NearDef = true;
2840b57cec5SDimitry Andric break;
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric if (NearDef)
2870b57cec5SDimitry Andric continue;
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric // The predicate register is not defined in the last few instructions.
2900b57cec5SDimitry Andric // Check if the conversion to MUX is possible (either "up", i.e. at the
2910b57cec5SDimitry Andric // place of the earlier partial definition, or "down", where the later
2920b57cec5SDimitry Andric // definition is located). Examine all defs and uses between these two
2930b57cec5SDimitry Andric // definitions.
2940b57cec5SDimitry Andric // SR1, SR2 - source registers from the first and the second definition.
2950b57cec5SDimitry Andric MachineBasicBlock::iterator It1 = B.begin(), It2 = B.begin();
2960b57cec5SDimitry Andric std::advance(It1, MinX);
2970b57cec5SDimitry Andric std::advance(It2, MaxX);
2980b57cec5SDimitry Andric MachineInstr &Def1 = *It1, &Def2 = *It2;
2990b57cec5SDimitry Andric MachineOperand *Src1 = &Def1.getOperand(2), *Src2 = &Def2.getOperand(2);
3000b57cec5SDimitry Andric Register SR1 = Src1->isReg() ? Src1->getReg() : Register();
3010b57cec5SDimitry Andric Register SR2 = Src2->isReg() ? Src2->getReg() : Register();
3020b57cec5SDimitry Andric bool Failure = false, CanUp = true, CanDown = true;
3030b57cec5SDimitry Andric for (unsigned X = MinX+1; X < MaxX; X++) {
3040b57cec5SDimitry Andric const DefUseInfo &DU = DUM.lookup(X);
3050b57cec5SDimitry Andric if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {
3060b57cec5SDimitry Andric Failure = true;
3070b57cec5SDimitry Andric break;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric if (CanDown && DU.Defs[SR1])
3100b57cec5SDimitry Andric CanDown = false;
3110b57cec5SDimitry Andric if (CanUp && DU.Defs[SR2])
3120b57cec5SDimitry Andric CanUp = false;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric if (Failure || (!CanUp && !CanDown))
3150b57cec5SDimitry Andric continue;
3160b57cec5SDimitry Andric
3170b57cec5SDimitry Andric MachineOperand *SrcT = (MinX == CI.TrueX) ? Src1 : Src2;
3180b57cec5SDimitry Andric MachineOperand *SrcF = (MinX == CI.FalseX) ? Src1 : Src2;
3190b57cec5SDimitry Andric // Prefer "down", since this will move the MUX farther away from the
3200b57cec5SDimitry Andric // predicate definition.
3210b57cec5SDimitry Andric MachineBasicBlock::iterator At = CanDown ? Def2 : Def1;
3220b57cec5SDimitry Andric ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric
3250b57cec5SDimitry Andric for (MuxInfo &MX : ML) {
3260b57cec5SDimitry Andric unsigned MxOpc = getMuxOpcode(*MX.SrcT, *MX.SrcF);
3270b57cec5SDimitry Andric if (!MxOpc)
3280b57cec5SDimitry Andric continue;
3294824e7fdSDimitry Andric // Basic correctness check: since we are deleting instructions, validate the
330480093f4SDimitry Andric // iterators. There is a possibility that one of Def1 or Def2 is translated
331480093f4SDimitry Andric // to "mux" and being considered for other "mux" instructions.
332480093f4SDimitry Andric if (!MX.At->getParent() || !MX.Def1->getParent() || !MX.Def2->getParent())
333480093f4SDimitry Andric continue;
334480093f4SDimitry Andric
3350b57cec5SDimitry Andric MachineBasicBlock &B = *MX.At->getParent();
3360b57cec5SDimitry Andric const DebugLoc &DL = B.findDebugLoc(MX.At);
3370b57cec5SDimitry Andric auto NewMux = BuildMI(B, MX.At, DL, HII->get(MxOpc), MX.DefR)
3380b57cec5SDimitry Andric .addReg(MX.PredR)
3390b57cec5SDimitry Andric .add(*MX.SrcT)
3400b57cec5SDimitry Andric .add(*MX.SrcF);
3410b57cec5SDimitry Andric NewMux->clearKillInfo();
342480093f4SDimitry Andric B.remove(MX.Def1);
343480093f4SDimitry Andric B.remove(MX.Def2);
3440b57cec5SDimitry Andric Changed = true;
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric // Fix up kill flags.
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric LivePhysRegs LPR(*HRI);
3500b57cec5SDimitry Andric LPR.addLiveOuts(B);
3510b57cec5SDimitry Andric auto IsLive = [&LPR, this](unsigned Reg) -> bool {
35206c3fb27SDimitry Andric for (MCPhysReg S : HRI->subregs_inclusive(Reg))
35306c3fb27SDimitry Andric if (LPR.contains(S))
3540b57cec5SDimitry Andric return true;
3550b57cec5SDimitry Andric return false;
3560b57cec5SDimitry Andric };
357349cc55cSDimitry Andric for (MachineInstr &I : llvm::reverse(B)) {
358349cc55cSDimitry Andric if (I.isDebugInstr())
3590b57cec5SDimitry Andric continue;
3600b57cec5SDimitry Andric // This isn't 100% accurate, but it's safe.
3610b57cec5SDimitry Andric // It won't detect (as a kill) a case like this
3620b57cec5SDimitry Andric // r0 = add r0, 1 <-- r0 should be "killed"
3630b57cec5SDimitry Andric // ... = r0
364349cc55cSDimitry Andric for (MachineOperand &Op : I.operands()) {
3650b57cec5SDimitry Andric if (!Op.isReg() || !Op.isUse())
3660b57cec5SDimitry Andric continue;
3670b57cec5SDimitry Andric assert(Op.getSubReg() == 0 && "Should have physical registers only");
3680b57cec5SDimitry Andric bool Live = IsLive(Op.getReg());
3690b57cec5SDimitry Andric Op.setIsKill(!Live);
3700b57cec5SDimitry Andric }
371349cc55cSDimitry Andric LPR.stepBackward(I);
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric return Changed;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)3770b57cec5SDimitry Andric bool HexagonGenMux::runOnMachineFunction(MachineFunction &MF) {
3780b57cec5SDimitry Andric if (skipFunction(MF.getFunction()))
3790b57cec5SDimitry Andric return false;
3800b57cec5SDimitry Andric HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
3810b57cec5SDimitry Andric HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
3820b57cec5SDimitry Andric bool Changed = false;
3830b57cec5SDimitry Andric for (auto &I : MF)
3840b57cec5SDimitry Andric Changed |= genMuxInBlock(I);
3850b57cec5SDimitry Andric return Changed;
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric
createHexagonGenMux()3880b57cec5SDimitry Andric FunctionPass *llvm::createHexagonGenMux() {
3890b57cec5SDimitry Andric return new HexagonGenMux();
3900b57cec5SDimitry Andric }
391