10b57cec5SDimitry Andric //===- HexagonExpandCondsets.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 // Replace mux instructions with the corresponding legal instructions.
100b57cec5SDimitry Andric // It is meant to work post-SSA, but still on virtual registers. It was
110b57cec5SDimitry Andric // originally placed between register coalescing and machine instruction
120b57cec5SDimitry Andric // scheduler.
130b57cec5SDimitry Andric // In this place in the optimization sequence, live interval analysis had
140b57cec5SDimitry Andric // been performed, and the live intervals should be preserved. A large part
150b57cec5SDimitry Andric // of the code deals with preserving the liveness information.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric // Liveness tracking aside, the main functionality of this pass is divided
180b57cec5SDimitry Andric // into two steps. The first step is to replace an instruction
190b57cec5SDimitry Andric // %0 = C2_mux %1, %2, %3
200b57cec5SDimitry Andric // with a pair of conditional transfers
210b57cec5SDimitry Andric // %0 = A2_tfrt %1, %2
220b57cec5SDimitry Andric // %0 = A2_tfrf %1, %3
230b57cec5SDimitry Andric // It is the intention that the execution of this pass could be terminated
240b57cec5SDimitry Andric // after this step, and the code generated would be functionally correct.
250b57cec5SDimitry Andric //
260b57cec5SDimitry Andric // If the uses of the source values %1 and %2 are kills, and their
270b57cec5SDimitry Andric // definitions are predicable, then in the second step, the conditional
280b57cec5SDimitry Andric // transfers will then be rewritten as predicated instructions. E.g.
290b57cec5SDimitry Andric // %0 = A2_or %1, %2
300b57cec5SDimitry Andric // %3 = A2_tfrt %99, killed %0
310b57cec5SDimitry Andric // will be rewritten as
320b57cec5SDimitry Andric // %3 = A2_port %99, %1, %2
330b57cec5SDimitry Andric //
340b57cec5SDimitry Andric // This replacement has two variants: "up" and "down". Consider this case:
350b57cec5SDimitry Andric // %0 = A2_or %1, %2
360b57cec5SDimitry Andric // ... [intervening instructions] ...
370b57cec5SDimitry Andric // %3 = A2_tfrt %99, killed %0
380b57cec5SDimitry Andric // variant "up":
390b57cec5SDimitry Andric // %3 = A2_port %99, %1, %2
400b57cec5SDimitry Andric // ... [intervening instructions, %0->vreg3] ...
410b57cec5SDimitry Andric // [deleted]
420b57cec5SDimitry Andric // variant "down":
430b57cec5SDimitry Andric // [deleted]
440b57cec5SDimitry Andric // ... [intervening instructions] ...
450b57cec5SDimitry Andric // %3 = A2_port %99, %1, %2
460b57cec5SDimitry Andric //
470b57cec5SDimitry Andric // Both, one or none of these variants may be valid, and checks are made
480b57cec5SDimitry Andric // to rule out inapplicable variants.
490b57cec5SDimitry Andric //
500b57cec5SDimitry Andric // As an additional optimization, before either of the two steps above is
510b57cec5SDimitry Andric // executed, the pass attempts to coalesce the target register with one of
520b57cec5SDimitry Andric // the source registers, e.g. given an instruction
530b57cec5SDimitry Andric // %3 = C2_mux %0, %1, %2
540b57cec5SDimitry Andric // %3 will be coalesced with either %1 or %2. If this succeeds,
550b57cec5SDimitry Andric // the instruction would then be (for example)
560b57cec5SDimitry Andric // %3 = C2_mux %0, %3, %2
570b57cec5SDimitry Andric // and, under certain circumstances, this could result in only one predicated
580b57cec5SDimitry Andric // instruction:
590b57cec5SDimitry Andric // %3 = A2_tfrf %0, %2
600b57cec5SDimitry Andric //
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric // Splitting a definition of a register into two predicated transfers
630b57cec5SDimitry Andric // creates a complication in liveness tracking. Live interval computation
640b57cec5SDimitry Andric // will see both instructions as actual definitions, and will mark the
650b57cec5SDimitry Andric // first one as dead. The definition is not actually dead, and this
660b57cec5SDimitry Andric // situation will need to be fixed. For example:
670b57cec5SDimitry Andric // dead %1 = A2_tfrt ... ; marked as dead
680b57cec5SDimitry Andric // %1 = A2_tfrf ...
690b57cec5SDimitry Andric //
700b57cec5SDimitry Andric // Since any of the individual predicated transfers may end up getting
710b57cec5SDimitry Andric // removed (in case it is an identity copy), some pre-existing def may
720b57cec5SDimitry Andric // be marked as dead after live interval recomputation:
730b57cec5SDimitry Andric // dead %1 = ... ; marked as dead
740b57cec5SDimitry Andric // ...
750b57cec5SDimitry Andric // %1 = A2_tfrf ... ; if A2_tfrt is removed
760b57cec5SDimitry Andric // This case happens if %1 was used as a source in A2_tfrt, which means
770b57cec5SDimitry Andric // that is it actually live at the A2_tfrf, and so the now dead definition
780b57cec5SDimitry Andric // of %1 will need to be updated to non-dead at some point.
790b57cec5SDimitry Andric //
800b57cec5SDimitry Andric // This issue could be remedied by adding implicit uses to the predicated
810b57cec5SDimitry Andric // transfers, but this will create a problem with subsequent predication,
820b57cec5SDimitry Andric // since the transfers will no longer be possible to reorder. To avoid
830b57cec5SDimitry Andric // that, the initial splitting will not add any implicit uses. These
840b57cec5SDimitry Andric // implicit uses will be added later, after predication. The extra price,
850b57cec5SDimitry Andric // however, is that finding the locations where the implicit uses need
860b57cec5SDimitry Andric // to be added, and updating the live ranges will be more involved.
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
890b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
900b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
910b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
920b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
930b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
940b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
950b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
960b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
970b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
980b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
990b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
1000b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
1010b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
1020b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
1030b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
1040b57cec5SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
1050b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
1060b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
1070b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
1080b57cec5SDimitry Andric #include "llvm/IR/Function.h"
109480093f4SDimitry Andric #include "llvm/InitializePasses.h"
1100b57cec5SDimitry Andric #include "llvm/MC/LaneBitmask.h"
1110b57cec5SDimitry Andric #include "llvm/Pass.h"
1120b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
1130b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
1140b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1150b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
1160b57cec5SDimitry Andric #include <cassert>
1170b57cec5SDimitry Andric #include <iterator>
1185f757f3fSDimitry Andric #include <map>
1190b57cec5SDimitry Andric #include <set>
1200b57cec5SDimitry Andric #include <utility>
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric #define DEBUG_TYPE "expand-condsets"
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric using namespace llvm;
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric static cl::opt<unsigned> OptTfrLimit("expand-condsets-tfr-limit",
1270b57cec5SDimitry Andric cl::init(~0U), cl::Hidden, cl::desc("Max number of mux expansions"));
1280b57cec5SDimitry Andric static cl::opt<unsigned> OptCoaLimit("expand-condsets-coa-limit",
1290b57cec5SDimitry Andric cl::init(~0U), cl::Hidden, cl::desc("Max number of segment coalescings"));
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric namespace llvm {
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric void initializeHexagonExpandCondsetsPass(PassRegistry&);
1340b57cec5SDimitry Andric FunctionPass *createHexagonExpandCondsets();
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric } // end namespace llvm
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric namespace {
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric class HexagonExpandCondsets : public MachineFunctionPass {
1410b57cec5SDimitry Andric public:
1420b57cec5SDimitry Andric static char ID;
1430b57cec5SDimitry Andric
HexagonExpandCondsets()1440b57cec5SDimitry Andric HexagonExpandCondsets() : MachineFunctionPass(ID) {
1450b57cec5SDimitry Andric if (OptCoaLimit.getPosition())
1460b57cec5SDimitry Andric CoaLimitActive = true, CoaLimit = OptCoaLimit;
1470b57cec5SDimitry Andric if (OptTfrLimit.getPosition())
1480b57cec5SDimitry Andric TfrLimitActive = true, TfrLimit = OptTfrLimit;
1490b57cec5SDimitry Andric initializeHexagonExpandCondsetsPass(*PassRegistry::getPassRegistry());
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
getPassName() const1520b57cec5SDimitry Andric StringRef getPassName() const override { return "Hexagon Expand Condsets"; }
1530b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1540b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
155*0fca6ea1SDimitry Andric AU.addRequired<LiveIntervalsWrapperPass>();
156*0fca6ea1SDimitry Andric AU.addPreserved<LiveIntervalsWrapperPass>();
157*0fca6ea1SDimitry Andric AU.addPreserved<SlotIndexesWrapperPass>();
158*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>();
159*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>();
1600b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric private:
1660b57cec5SDimitry Andric const HexagonInstrInfo *HII = nullptr;
1670b57cec5SDimitry Andric const TargetRegisterInfo *TRI = nullptr;
1680b57cec5SDimitry Andric MachineDominatorTree *MDT;
1690b57cec5SDimitry Andric MachineRegisterInfo *MRI = nullptr;
1700b57cec5SDimitry Andric LiveIntervals *LIS = nullptr;
1710b57cec5SDimitry Andric bool CoaLimitActive = false;
1720b57cec5SDimitry Andric bool TfrLimitActive = false;
1730b57cec5SDimitry Andric unsigned CoaLimit;
1740b57cec5SDimitry Andric unsigned TfrLimit;
1750b57cec5SDimitry Andric unsigned CoaCounter = 0;
1760b57cec5SDimitry Andric unsigned TfrCounter = 0;
1770b57cec5SDimitry Andric
178e8d8bef9SDimitry Andric // FIXME: Consolidate duplicate definitions of RegisterRef
1790b57cec5SDimitry Andric struct RegisterRef {
RegisterRef__anondf36eb6c0111::HexagonExpandCondsets::RegisterRef1800b57cec5SDimitry Andric RegisterRef(const MachineOperand &Op) : Reg(Op.getReg()),
1810b57cec5SDimitry Andric Sub(Op.getSubReg()) {}
RegisterRef__anondf36eb6c0111::HexagonExpandCondsets::RegisterRef1820b57cec5SDimitry Andric RegisterRef(unsigned R = 0, unsigned S = 0) : Reg(R), Sub(S) {}
1830b57cec5SDimitry Andric
operator ==__anondf36eb6c0111::HexagonExpandCondsets::RegisterRef1840b57cec5SDimitry Andric bool operator== (RegisterRef RR) const {
1850b57cec5SDimitry Andric return Reg == RR.Reg && Sub == RR.Sub;
1860b57cec5SDimitry Andric }
operator !=__anondf36eb6c0111::HexagonExpandCondsets::RegisterRef1870b57cec5SDimitry Andric bool operator!= (RegisterRef RR) const { return !operator==(RR); }
operator <__anondf36eb6c0111::HexagonExpandCondsets::RegisterRef1880b57cec5SDimitry Andric bool operator< (RegisterRef RR) const {
1890b57cec5SDimitry Andric return Reg < RR.Reg || (Reg == RR.Reg && Sub < RR.Sub);
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
192e8d8bef9SDimitry Andric Register Reg;
193e8d8bef9SDimitry Andric unsigned Sub;
1940b57cec5SDimitry Andric };
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric using ReferenceMap = DenseMap<unsigned, unsigned>;
1970b57cec5SDimitry Andric enum { Sub_Low = 0x1, Sub_High = 0x2, Sub_None = (Sub_Low | Sub_High) };
1980b57cec5SDimitry Andric enum { Exec_Then = 0x10, Exec_Else = 0x20 };
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric unsigned getMaskForSub(unsigned Sub);
2010b57cec5SDimitry Andric bool isCondset(const MachineInstr &MI);
202e8d8bef9SDimitry Andric LaneBitmask getLaneMask(Register Reg, unsigned Sub);
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric void addRefToMap(RegisterRef RR, ReferenceMap &Map, unsigned Exec);
2050b57cec5SDimitry Andric bool isRefInMap(RegisterRef, ReferenceMap &Map, unsigned Exec);
2060b57cec5SDimitry Andric
207e8d8bef9SDimitry Andric void updateDeadsInRange(Register Reg, LaneBitmask LM, LiveRange &Range);
208e8d8bef9SDimitry Andric void updateKillFlags(Register Reg);
209e8d8bef9SDimitry Andric void updateDeadFlags(Register Reg);
210e8d8bef9SDimitry Andric void recalculateLiveInterval(Register Reg);
2110b57cec5SDimitry Andric void removeInstr(MachineInstr &MI);
212bdd1243dSDimitry Andric void updateLiveness(const std::set<Register> &RegSet, bool Recalc,
2130b57cec5SDimitry Andric bool UpdateKills, bool UpdateDeads);
214bdd1243dSDimitry Andric void distributeLiveIntervals(const std::set<Register> &Regs);
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric unsigned getCondTfrOpcode(const MachineOperand &SO, bool Cond);
2170b57cec5SDimitry Andric MachineInstr *genCondTfrFor(MachineOperand &SrcOp,
2180b57cec5SDimitry Andric MachineBasicBlock::iterator At, unsigned DstR,
2190b57cec5SDimitry Andric unsigned DstSR, const MachineOperand &PredOp, bool PredSense,
2200b57cec5SDimitry Andric bool ReadUndef, bool ImpUse);
221e8d8bef9SDimitry Andric bool split(MachineInstr &MI, std::set<Register> &UpdRegs);
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric bool isPredicable(MachineInstr *MI);
2240b57cec5SDimitry Andric MachineInstr *getReachingDefForPred(RegisterRef RD,
2250b57cec5SDimitry Andric MachineBasicBlock::iterator UseIt, unsigned PredR, bool Cond);
2260b57cec5SDimitry Andric bool canMoveOver(MachineInstr &MI, ReferenceMap &Defs, ReferenceMap &Uses);
2270b57cec5SDimitry Andric bool canMoveMemTo(MachineInstr &MI, MachineInstr &ToI, bool IsDown);
2280b57cec5SDimitry Andric void predicateAt(const MachineOperand &DefOp, MachineInstr &MI,
2290b57cec5SDimitry Andric MachineBasicBlock::iterator Where,
2300b57cec5SDimitry Andric const MachineOperand &PredOp, bool Cond,
231e8d8bef9SDimitry Andric std::set<Register> &UpdRegs);
2320b57cec5SDimitry Andric void renameInRange(RegisterRef RO, RegisterRef RN, unsigned PredR,
2330b57cec5SDimitry Andric bool Cond, MachineBasicBlock::iterator First,
2340b57cec5SDimitry Andric MachineBasicBlock::iterator Last);
235e8d8bef9SDimitry Andric bool predicate(MachineInstr &TfrI, bool Cond, std::set<Register> &UpdRegs);
236e8d8bef9SDimitry Andric bool predicateInBlock(MachineBasicBlock &B, std::set<Register> &UpdRegs);
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric bool isIntReg(RegisterRef RR, unsigned &BW);
2390b57cec5SDimitry Andric bool isIntraBlocks(LiveInterval &LI);
2400b57cec5SDimitry Andric bool coalesceRegisters(RegisterRef R1, RegisterRef R2);
2410b57cec5SDimitry Andric bool coalesceSegments(const SmallVectorImpl<MachineInstr *> &Condsets,
242e8d8bef9SDimitry Andric std::set<Register> &UpdRegs);
2430b57cec5SDimitry Andric };
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric } // end anonymous namespace
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric char HexagonExpandCondsets::ID = 0;
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric namespace llvm {
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric char &HexagonExpandCondsetsID = HexagonExpandCondsets::ID;
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric } // end namespace llvm
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonExpandCondsets, "expand-condsets",
2560b57cec5SDimitry Andric "Hexagon Expand Condsets", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)257*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
258*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
259*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
2600b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonExpandCondsets, "expand-condsets",
2610b57cec5SDimitry Andric "Hexagon Expand Condsets", false, false)
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric unsigned HexagonExpandCondsets::getMaskForSub(unsigned Sub) {
2640b57cec5SDimitry Andric switch (Sub) {
2650b57cec5SDimitry Andric case Hexagon::isub_lo:
2660b57cec5SDimitry Andric case Hexagon::vsub_lo:
2670b57cec5SDimitry Andric return Sub_Low;
2680b57cec5SDimitry Andric case Hexagon::isub_hi:
2690b57cec5SDimitry Andric case Hexagon::vsub_hi:
2700b57cec5SDimitry Andric return Sub_High;
2710b57cec5SDimitry Andric case Hexagon::NoSubRegister:
2720b57cec5SDimitry Andric return Sub_None;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric llvm_unreachable("Invalid subregister");
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric
isCondset(const MachineInstr & MI)2770b57cec5SDimitry Andric bool HexagonExpandCondsets::isCondset(const MachineInstr &MI) {
2780b57cec5SDimitry Andric unsigned Opc = MI.getOpcode();
2790b57cec5SDimitry Andric switch (Opc) {
2800b57cec5SDimitry Andric case Hexagon::C2_mux:
2810b57cec5SDimitry Andric case Hexagon::C2_muxii:
2820b57cec5SDimitry Andric case Hexagon::C2_muxir:
2830b57cec5SDimitry Andric case Hexagon::C2_muxri:
2840b57cec5SDimitry Andric case Hexagon::PS_pselect:
2850b57cec5SDimitry Andric return true;
2860b57cec5SDimitry Andric break;
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric return false;
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric
getLaneMask(Register Reg,unsigned Sub)291e8d8bef9SDimitry Andric LaneBitmask HexagonExpandCondsets::getLaneMask(Register Reg, unsigned Sub) {
292e8d8bef9SDimitry Andric assert(Reg.isVirtual());
2930b57cec5SDimitry Andric return Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub)
2940b57cec5SDimitry Andric : MRI->getMaxLaneMaskForVReg(Reg);
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
addRefToMap(RegisterRef RR,ReferenceMap & Map,unsigned Exec)2970b57cec5SDimitry Andric void HexagonExpandCondsets::addRefToMap(RegisterRef RR, ReferenceMap &Map,
2980b57cec5SDimitry Andric unsigned Exec) {
2990b57cec5SDimitry Andric unsigned Mask = getMaskForSub(RR.Sub) | Exec;
3000b57cec5SDimitry Andric ReferenceMap::iterator F = Map.find(RR.Reg);
3010b57cec5SDimitry Andric if (F == Map.end())
3020b57cec5SDimitry Andric Map.insert(std::make_pair(RR.Reg, Mask));
3030b57cec5SDimitry Andric else
3040b57cec5SDimitry Andric F->second |= Mask;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
isRefInMap(RegisterRef RR,ReferenceMap & Map,unsigned Exec)3070b57cec5SDimitry Andric bool HexagonExpandCondsets::isRefInMap(RegisterRef RR, ReferenceMap &Map,
3080b57cec5SDimitry Andric unsigned Exec) {
3090b57cec5SDimitry Andric ReferenceMap::iterator F = Map.find(RR.Reg);
3100b57cec5SDimitry Andric if (F == Map.end())
3110b57cec5SDimitry Andric return false;
3120b57cec5SDimitry Andric unsigned Mask = getMaskForSub(RR.Sub) | Exec;
3130b57cec5SDimitry Andric if (Mask & F->second)
3140b57cec5SDimitry Andric return true;
3150b57cec5SDimitry Andric return false;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric
updateKillFlags(Register Reg)318e8d8bef9SDimitry Andric void HexagonExpandCondsets::updateKillFlags(Register Reg) {
3190b57cec5SDimitry Andric auto KillAt = [this,Reg] (SlotIndex K, LaneBitmask LM) -> void {
3200b57cec5SDimitry Andric // Set the <kill> flag on a use of Reg whose lane mask is contained in LM.
3210b57cec5SDimitry Andric MachineInstr *MI = LIS->getInstructionFromIndex(K);
3220b57cec5SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
3230b57cec5SDimitry Andric MachineOperand &Op = MI->getOperand(i);
3240b57cec5SDimitry Andric if (!Op.isReg() || !Op.isUse() || Op.getReg() != Reg ||
3250b57cec5SDimitry Andric MI->isRegTiedToDefOperand(i))
3260b57cec5SDimitry Andric continue;
3270b57cec5SDimitry Andric LaneBitmask SLM = getLaneMask(Reg, Op.getSubReg());
3280b57cec5SDimitry Andric if ((SLM & LM) == SLM) {
3290b57cec5SDimitry Andric // Only set the kill flag on the first encountered use of Reg in this
3300b57cec5SDimitry Andric // instruction.
3310b57cec5SDimitry Andric Op.setIsKill(true);
3320b57cec5SDimitry Andric break;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric };
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric LiveInterval &LI = LIS->getInterval(Reg);
3380b57cec5SDimitry Andric for (auto I = LI.begin(), E = LI.end(); I != E; ++I) {
3390b57cec5SDimitry Andric if (!I->end.isRegister())
3400b57cec5SDimitry Andric continue;
3410b57cec5SDimitry Andric // Do not mark the end of the segment as <kill>, if the next segment
3420b57cec5SDimitry Andric // starts with a predicated instruction.
3430b57cec5SDimitry Andric auto NextI = std::next(I);
3440b57cec5SDimitry Andric if (NextI != E && NextI->start.isRegister()) {
3450b57cec5SDimitry Andric MachineInstr *DefI = LIS->getInstructionFromIndex(NextI->start);
3460b57cec5SDimitry Andric if (HII->isPredicated(*DefI))
3470b57cec5SDimitry Andric continue;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric bool WholeReg = true;
3500b57cec5SDimitry Andric if (LI.hasSubRanges()) {
3510b57cec5SDimitry Andric auto EndsAtI = [I] (LiveInterval::SubRange &S) -> bool {
3520b57cec5SDimitry Andric LiveRange::iterator F = S.find(I->end);
3530b57cec5SDimitry Andric return F != S.end() && I->end == F->end;
3540b57cec5SDimitry Andric };
3550b57cec5SDimitry Andric // Check if all subranges end at I->end. If so, make sure to kill
3560b57cec5SDimitry Andric // the whole register.
3570b57cec5SDimitry Andric for (LiveInterval::SubRange &S : LI.subranges()) {
3580b57cec5SDimitry Andric if (EndsAtI(S))
3590b57cec5SDimitry Andric KillAt(I->end, S.LaneMask);
3600b57cec5SDimitry Andric else
3610b57cec5SDimitry Andric WholeReg = false;
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric if (WholeReg)
3650b57cec5SDimitry Andric KillAt(I->end, MRI->getMaxLaneMaskForVReg(Reg));
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
updateDeadsInRange(Register Reg,LaneBitmask LM,LiveRange & Range)369e8d8bef9SDimitry Andric void HexagonExpandCondsets::updateDeadsInRange(Register Reg, LaneBitmask LM,
3700b57cec5SDimitry Andric LiveRange &Range) {
371e8d8bef9SDimitry Andric assert(Reg.isVirtual());
3720b57cec5SDimitry Andric if (Range.empty())
3730b57cec5SDimitry Andric return;
3740b57cec5SDimitry Andric
3750b57cec5SDimitry Andric // Return two booleans: { def-modifes-reg, def-covers-reg }.
3760b57cec5SDimitry Andric auto IsRegDef = [this,Reg,LM] (MachineOperand &Op) -> std::pair<bool,bool> {
3770b57cec5SDimitry Andric if (!Op.isReg() || !Op.isDef())
3780b57cec5SDimitry Andric return { false, false };
3798bcb0991SDimitry Andric Register DR = Op.getReg(), DSR = Op.getSubReg();
380e8d8bef9SDimitry Andric if (!DR.isVirtual() || DR != Reg)
3810b57cec5SDimitry Andric return { false, false };
3820b57cec5SDimitry Andric LaneBitmask SLM = getLaneMask(DR, DSR);
3830b57cec5SDimitry Andric LaneBitmask A = SLM & LM;
3840b57cec5SDimitry Andric return { A.any(), A == SLM };
3850b57cec5SDimitry Andric };
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric // The splitting step will create pairs of predicated definitions without
3880b57cec5SDimitry Andric // any implicit uses (since implicit uses would interfere with predication).
3890b57cec5SDimitry Andric // This can cause the reaching defs to become dead after live range
3900b57cec5SDimitry Andric // recomputation, even though they are not really dead.
3910b57cec5SDimitry Andric // We need to identify predicated defs that need implicit uses, and
3920b57cec5SDimitry Andric // dead defs that are not really dead, and correct both problems.
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric auto Dominate = [this] (SetVector<MachineBasicBlock*> &Defs,
3950b57cec5SDimitry Andric MachineBasicBlock *Dest) -> bool {
396bdd1243dSDimitry Andric for (MachineBasicBlock *D : Defs) {
3970b57cec5SDimitry Andric if (D != Dest && MDT->dominates(D, Dest))
3980b57cec5SDimitry Andric return true;
399bdd1243dSDimitry Andric }
4000b57cec5SDimitry Andric MachineBasicBlock *Entry = &Dest->getParent()->front();
4010b57cec5SDimitry Andric SetVector<MachineBasicBlock*> Work(Dest->pred_begin(), Dest->pred_end());
4020b57cec5SDimitry Andric for (unsigned i = 0; i < Work.size(); ++i) {
4030b57cec5SDimitry Andric MachineBasicBlock *B = Work[i];
4040b57cec5SDimitry Andric if (Defs.count(B))
4050b57cec5SDimitry Andric continue;
4060b57cec5SDimitry Andric if (B == Entry)
4070b57cec5SDimitry Andric return false;
4080b57cec5SDimitry Andric for (auto *P : B->predecessors())
4090b57cec5SDimitry Andric Work.insert(P);
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric return true;
4120b57cec5SDimitry Andric };
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric // First, try to extend live range within individual basic blocks. This
4150b57cec5SDimitry Andric // will leave us only with dead defs that do not reach any predicated
4160b57cec5SDimitry Andric // defs in the same block.
4170b57cec5SDimitry Andric SetVector<MachineBasicBlock*> Defs;
4180b57cec5SDimitry Andric SmallVector<SlotIndex,4> PredDefs;
4190b57cec5SDimitry Andric for (auto &Seg : Range) {
4200b57cec5SDimitry Andric if (!Seg.start.isRegister())
4210b57cec5SDimitry Andric continue;
4220b57cec5SDimitry Andric MachineInstr *DefI = LIS->getInstructionFromIndex(Seg.start);
4230b57cec5SDimitry Andric Defs.insert(DefI->getParent());
4240b57cec5SDimitry Andric if (HII->isPredicated(*DefI))
4250b57cec5SDimitry Andric PredDefs.push_back(Seg.start);
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric SmallVector<SlotIndex,8> Undefs;
4290b57cec5SDimitry Andric LiveInterval &LI = LIS->getInterval(Reg);
4300b57cec5SDimitry Andric LI.computeSubRangeUndefs(Undefs, LM, *MRI, *LIS->getSlotIndexes());
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric for (auto &SI : PredDefs) {
4330b57cec5SDimitry Andric MachineBasicBlock *BB = LIS->getMBBFromIndex(SI);
4340b57cec5SDimitry Andric auto P = Range.extendInBlock(Undefs, LIS->getMBBStartIdx(BB), SI);
4350b57cec5SDimitry Andric if (P.first != nullptr || P.second)
4360b57cec5SDimitry Andric SI = SlotIndex();
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric // Calculate reachability for those predicated defs that were not handled
4400b57cec5SDimitry Andric // by the in-block extension.
4410b57cec5SDimitry Andric SmallVector<SlotIndex,4> ExtTo;
4420b57cec5SDimitry Andric for (auto &SI : PredDefs) {
4430b57cec5SDimitry Andric if (!SI.isValid())
4440b57cec5SDimitry Andric continue;
4450b57cec5SDimitry Andric MachineBasicBlock *BB = LIS->getMBBFromIndex(SI);
4460b57cec5SDimitry Andric if (BB->pred_empty())
4470b57cec5SDimitry Andric continue;
4480b57cec5SDimitry Andric // If the defs from this range reach SI via all predecessors, it is live.
4490b57cec5SDimitry Andric // It can happen that SI is reached by the defs through some paths, but
4500b57cec5SDimitry Andric // not all. In the IR coming into this optimization, SI would not be
4510b57cec5SDimitry Andric // considered live, since the defs would then not jointly dominate SI.
4520b57cec5SDimitry Andric // That means that SI is an overwriting def, and no implicit use is
4530b57cec5SDimitry Andric // needed at this point. Do not add SI to the extension points, since
4540b57cec5SDimitry Andric // extendToIndices will abort if there is no joint dominance.
4550b57cec5SDimitry Andric // If the abort was avoided by adding extra undefs added to Undefs,
4560b57cec5SDimitry Andric // extendToIndices could actually indicate that SI is live, contrary
4570b57cec5SDimitry Andric // to the original IR.
4580b57cec5SDimitry Andric if (Dominate(Defs, BB))
4590b57cec5SDimitry Andric ExtTo.push_back(SI);
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric if (!ExtTo.empty())
4630b57cec5SDimitry Andric LIS->extendToIndices(Range, ExtTo, Undefs);
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric // Remove <dead> flags from all defs that are not dead after live range
4660b57cec5SDimitry Andric // extension, and collect all def operands. They will be used to generate
4670b57cec5SDimitry Andric // the necessary implicit uses.
4680b57cec5SDimitry Andric // At the same time, add <dead> flag to all defs that are actually dead.
4690b57cec5SDimitry Andric // This can happen, for example, when a mux with identical inputs is
4700b57cec5SDimitry Andric // replaced with a COPY: the use of the predicate register disappears and
4710b57cec5SDimitry Andric // the dead can become dead.
4720b57cec5SDimitry Andric std::set<RegisterRef> DefRegs;
4730b57cec5SDimitry Andric for (auto &Seg : Range) {
4740b57cec5SDimitry Andric if (!Seg.start.isRegister())
4750b57cec5SDimitry Andric continue;
4760b57cec5SDimitry Andric MachineInstr *DefI = LIS->getInstructionFromIndex(Seg.start);
4770b57cec5SDimitry Andric for (auto &Op : DefI->operands()) {
4780b57cec5SDimitry Andric auto P = IsRegDef(Op);
4790b57cec5SDimitry Andric if (P.second && Seg.end.isDead()) {
4800b57cec5SDimitry Andric Op.setIsDead(true);
4810b57cec5SDimitry Andric } else if (P.first) {
4820b57cec5SDimitry Andric DefRegs.insert(Op);
4830b57cec5SDimitry Andric Op.setIsDead(false);
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andric // Now, add implicit uses to each predicated def that is reached
4890b57cec5SDimitry Andric // by other defs.
4900b57cec5SDimitry Andric for (auto &Seg : Range) {
4910b57cec5SDimitry Andric if (!Seg.start.isRegister() || !Range.liveAt(Seg.start.getPrevSlot()))
4920b57cec5SDimitry Andric continue;
4930b57cec5SDimitry Andric MachineInstr *DefI = LIS->getInstructionFromIndex(Seg.start);
4940b57cec5SDimitry Andric if (!HII->isPredicated(*DefI))
4950b57cec5SDimitry Andric continue;
4960b57cec5SDimitry Andric // Construct the set of all necessary implicit uses, based on the def
4970b57cec5SDimitry Andric // operands in the instruction. We need to tie the implicit uses to
4980b57cec5SDimitry Andric // the corresponding defs.
4990b57cec5SDimitry Andric std::map<RegisterRef,unsigned> ImpUses;
5000b57cec5SDimitry Andric for (unsigned i = 0, e = DefI->getNumOperands(); i != e; ++i) {
5010b57cec5SDimitry Andric MachineOperand &Op = DefI->getOperand(i);
5020b57cec5SDimitry Andric if (!Op.isReg() || !DefRegs.count(Op))
5030b57cec5SDimitry Andric continue;
5040b57cec5SDimitry Andric if (Op.isDef()) {
5050b57cec5SDimitry Andric // Tied defs will always have corresponding uses, so no extra
5060b57cec5SDimitry Andric // implicit uses are needed.
5070b57cec5SDimitry Andric if (!Op.isTied())
5080b57cec5SDimitry Andric ImpUses.insert({Op, i});
5090b57cec5SDimitry Andric } else {
5100b57cec5SDimitry Andric // This function can be called for the same register with different
5110b57cec5SDimitry Andric // lane masks. If the def in this instruction was for the whole
5120b57cec5SDimitry Andric // register, we can get here more than once. Avoid adding multiple
5130b57cec5SDimitry Andric // implicit uses (or adding an implicit use when an explicit one is
5140b57cec5SDimitry Andric // present).
5150b57cec5SDimitry Andric if (Op.isTied())
5160b57cec5SDimitry Andric ImpUses.erase(Op);
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric if (ImpUses.empty())
5200b57cec5SDimitry Andric continue;
5210b57cec5SDimitry Andric MachineFunction &MF = *DefI->getParent()->getParent();
522bdd1243dSDimitry Andric for (auto [R, DefIdx] : ImpUses) {
5230b57cec5SDimitry Andric MachineInstrBuilder(MF, DefI).addReg(R.Reg, RegState::Implicit, R.Sub);
524bdd1243dSDimitry Andric DefI->tieOperands(DefIdx, DefI->getNumOperands()-1);
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
updateDeadFlags(Register Reg)529e8d8bef9SDimitry Andric void HexagonExpandCondsets::updateDeadFlags(Register Reg) {
5300b57cec5SDimitry Andric LiveInterval &LI = LIS->getInterval(Reg);
5310b57cec5SDimitry Andric if (LI.hasSubRanges()) {
5320b57cec5SDimitry Andric for (LiveInterval::SubRange &S : LI.subranges()) {
5330b57cec5SDimitry Andric updateDeadsInRange(Reg, S.LaneMask, S);
5340b57cec5SDimitry Andric LIS->shrinkToUses(S, Reg);
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric LI.clear();
5370b57cec5SDimitry Andric LIS->constructMainRangeFromSubranges(LI);
5380b57cec5SDimitry Andric } else {
5390b57cec5SDimitry Andric updateDeadsInRange(Reg, MRI->getMaxLaneMaskForVReg(Reg), LI);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric
recalculateLiveInterval(Register Reg)543e8d8bef9SDimitry Andric void HexagonExpandCondsets::recalculateLiveInterval(Register Reg) {
5440b57cec5SDimitry Andric LIS->removeInterval(Reg);
5450b57cec5SDimitry Andric LIS->createAndComputeVirtRegInterval(Reg);
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
removeInstr(MachineInstr & MI)5480b57cec5SDimitry Andric void HexagonExpandCondsets::removeInstr(MachineInstr &MI) {
5490b57cec5SDimitry Andric LIS->RemoveMachineInstrFromMaps(MI);
5500b57cec5SDimitry Andric MI.eraseFromParent();
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
updateLiveness(const std::set<Register> & RegSet,bool Recalc,bool UpdateKills,bool UpdateDeads)553bdd1243dSDimitry Andric void HexagonExpandCondsets::updateLiveness(const std::set<Register> &RegSet,
554e8d8bef9SDimitry Andric bool Recalc, bool UpdateKills,
555e8d8bef9SDimitry Andric bool UpdateDeads) {
5560b57cec5SDimitry Andric UpdateKills |= UpdateDeads;
557e8d8bef9SDimitry Andric for (Register R : RegSet) {
558e8d8bef9SDimitry Andric if (!R.isVirtual()) {
559e8d8bef9SDimitry Andric assert(R.isPhysical());
5600b57cec5SDimitry Andric // There shouldn't be any physical registers as operands, except
5610b57cec5SDimitry Andric // possibly reserved registers.
5620b57cec5SDimitry Andric assert(MRI->isReserved(R));
5630b57cec5SDimitry Andric continue;
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric if (Recalc)
5660b57cec5SDimitry Andric recalculateLiveInterval(R);
5670b57cec5SDimitry Andric if (UpdateKills)
5680b57cec5SDimitry Andric MRI->clearKillFlags(R);
5690b57cec5SDimitry Andric if (UpdateDeads)
5700b57cec5SDimitry Andric updateDeadFlags(R);
5710b57cec5SDimitry Andric // Fixing <dead> flags may extend live ranges, so reset <kill> flags
5720b57cec5SDimitry Andric // after that.
5730b57cec5SDimitry Andric if (UpdateKills)
5740b57cec5SDimitry Andric updateKillFlags(R);
5750b57cec5SDimitry Andric LIS->getInterval(R).verify();
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric
distributeLiveIntervals(const std::set<Register> & Regs)579bdd1243dSDimitry Andric void HexagonExpandCondsets::distributeLiveIntervals(
580bdd1243dSDimitry Andric const std::set<Register> &Regs) {
581bdd1243dSDimitry Andric ConnectedVNInfoEqClasses EQC(*LIS);
582bdd1243dSDimitry Andric for (Register R : Regs) {
583bdd1243dSDimitry Andric if (!R.isVirtual())
584bdd1243dSDimitry Andric continue;
585bdd1243dSDimitry Andric LiveInterval &LI = LIS->getInterval(R);
586bdd1243dSDimitry Andric unsigned NumComp = EQC.Classify(LI);
587bdd1243dSDimitry Andric if (NumComp == 1)
588bdd1243dSDimitry Andric continue;
589bdd1243dSDimitry Andric
590bdd1243dSDimitry Andric SmallVector<LiveInterval*> NewLIs;
591bdd1243dSDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(LI.reg());
592bdd1243dSDimitry Andric for (unsigned I = 1; I < NumComp; ++I) {
593bdd1243dSDimitry Andric Register NewR = MRI->createVirtualRegister(RC);
594bdd1243dSDimitry Andric NewLIs.push_back(&LIS->createEmptyInterval(NewR));
595bdd1243dSDimitry Andric }
596bdd1243dSDimitry Andric EQC.Distribute(LI, NewLIs.begin(), *MRI);
597bdd1243dSDimitry Andric }
598bdd1243dSDimitry Andric }
599bdd1243dSDimitry Andric
6000b57cec5SDimitry Andric /// Get the opcode for a conditional transfer of the value in SO (source
6010b57cec5SDimitry Andric /// operand). The condition (true/false) is given in Cond.
getCondTfrOpcode(const MachineOperand & SO,bool IfTrue)6020b57cec5SDimitry Andric unsigned HexagonExpandCondsets::getCondTfrOpcode(const MachineOperand &SO,
6030b57cec5SDimitry Andric bool IfTrue) {
6040b57cec5SDimitry Andric if (SO.isReg()) {
605e8d8bef9SDimitry Andric MCRegister PhysR;
6060b57cec5SDimitry Andric RegisterRef RS = SO;
607e8d8bef9SDimitry Andric if (RS.Reg.isVirtual()) {
6080b57cec5SDimitry Andric const TargetRegisterClass *VC = MRI->getRegClass(RS.Reg);
6090b57cec5SDimitry Andric assert(VC->begin() != VC->end() && "Empty register class");
6100b57cec5SDimitry Andric PhysR = *VC->begin();
6110b57cec5SDimitry Andric } else {
6120b57cec5SDimitry Andric PhysR = RS.Reg;
6130b57cec5SDimitry Andric }
614e8d8bef9SDimitry Andric MCRegister PhysS = (RS.Sub == 0) ? PhysR : TRI->getSubReg(PhysR, RS.Sub);
6150b57cec5SDimitry Andric const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(PhysS);
6160b57cec5SDimitry Andric switch (TRI->getRegSizeInBits(*RC)) {
6170b57cec5SDimitry Andric case 32:
618bdd1243dSDimitry Andric return IfTrue ? Hexagon::A2_tfrt : Hexagon::A2_tfrf;
6190b57cec5SDimitry Andric case 64:
620bdd1243dSDimitry Andric return IfTrue ? Hexagon::A2_tfrpt : Hexagon::A2_tfrpf;
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric llvm_unreachable("Invalid register operand");
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric switch (SO.getType()) {
6250b57cec5SDimitry Andric case MachineOperand::MO_Immediate:
6260b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate:
6270b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
6280b57cec5SDimitry Andric case MachineOperand::MO_TargetIndex:
6290b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex:
6300b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol:
6310b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress:
6320b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress:
633bdd1243dSDimitry Andric return IfTrue ? Hexagon::C2_cmoveit : Hexagon::C2_cmoveif;
6340b57cec5SDimitry Andric default:
6350b57cec5SDimitry Andric break;
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric llvm_unreachable("Unexpected source operand");
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andric /// Generate a conditional transfer, copying the value SrcOp to the
6410b57cec5SDimitry Andric /// destination register DstR:DstSR, and using the predicate register from
6420b57cec5SDimitry Andric /// PredOp. The Cond argument specifies whether the predicate is to be
6430b57cec5SDimitry Andric /// if(PredOp), or if(!PredOp).
genCondTfrFor(MachineOperand & SrcOp,MachineBasicBlock::iterator At,unsigned DstR,unsigned DstSR,const MachineOperand & PredOp,bool PredSense,bool ReadUndef,bool ImpUse)6440b57cec5SDimitry Andric MachineInstr *HexagonExpandCondsets::genCondTfrFor(MachineOperand &SrcOp,
6450b57cec5SDimitry Andric MachineBasicBlock::iterator At,
6460b57cec5SDimitry Andric unsigned DstR, unsigned DstSR, const MachineOperand &PredOp,
6470b57cec5SDimitry Andric bool PredSense, bool ReadUndef, bool ImpUse) {
6480b57cec5SDimitry Andric MachineInstr *MI = SrcOp.getParent();
6490b57cec5SDimitry Andric MachineBasicBlock &B = *At->getParent();
6500b57cec5SDimitry Andric const DebugLoc &DL = MI->getDebugLoc();
6510b57cec5SDimitry Andric
6520b57cec5SDimitry Andric // Don't avoid identity copies here (i.e. if the source and the destination
6530b57cec5SDimitry Andric // are the same registers). It is actually better to generate them here,
6540b57cec5SDimitry Andric // since this would cause the copy to potentially be predicated in the next
6550b57cec5SDimitry Andric // step. The predication will remove such a copy if it is unable to
6560b57cec5SDimitry Andric /// predicate.
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric unsigned Opc = getCondTfrOpcode(SrcOp, PredSense);
6590b57cec5SDimitry Andric unsigned DstState = RegState::Define | (ReadUndef ? RegState::Undef : 0);
6600b57cec5SDimitry Andric unsigned PredState = getRegState(PredOp) & ~RegState::Kill;
6610b57cec5SDimitry Andric MachineInstrBuilder MIB;
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric if (SrcOp.isReg()) {
6640b57cec5SDimitry Andric unsigned SrcState = getRegState(SrcOp);
6650b57cec5SDimitry Andric if (RegisterRef(SrcOp) == RegisterRef(DstR, DstSR))
6660b57cec5SDimitry Andric SrcState &= ~RegState::Kill;
6670b57cec5SDimitry Andric MIB = BuildMI(B, At, DL, HII->get(Opc))
6680b57cec5SDimitry Andric .addReg(DstR, DstState, DstSR)
6690b57cec5SDimitry Andric .addReg(PredOp.getReg(), PredState, PredOp.getSubReg())
6700b57cec5SDimitry Andric .addReg(SrcOp.getReg(), SrcState, SrcOp.getSubReg());
6710b57cec5SDimitry Andric } else {
6720b57cec5SDimitry Andric MIB = BuildMI(B, At, DL, HII->get(Opc))
6730b57cec5SDimitry Andric .addReg(DstR, DstState, DstSR)
6740b57cec5SDimitry Andric .addReg(PredOp.getReg(), PredState, PredOp.getSubReg())
6750b57cec5SDimitry Andric .add(SrcOp);
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric
6780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "created an initial copy: " << *MIB);
6790b57cec5SDimitry Andric return &*MIB;
6800b57cec5SDimitry Andric }
6810b57cec5SDimitry Andric
6820b57cec5SDimitry Andric /// Replace a MUX instruction MI with a pair A2_tfrt/A2_tfrf. This function
6830b57cec5SDimitry Andric /// performs all necessary changes to complete the replacement.
split(MachineInstr & MI,std::set<Register> & UpdRegs)6840b57cec5SDimitry Andric bool HexagonExpandCondsets::split(MachineInstr &MI,
685e8d8bef9SDimitry Andric std::set<Register> &UpdRegs) {
6860b57cec5SDimitry Andric if (TfrLimitActive) {
6870b57cec5SDimitry Andric if (TfrCounter >= TfrLimit)
6880b57cec5SDimitry Andric return false;
6890b57cec5SDimitry Andric TfrCounter++;
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nsplitting " << printMBBReference(*MI.getParent())
6920b57cec5SDimitry Andric << ": " << MI);
6930b57cec5SDimitry Andric MachineOperand &MD = MI.getOperand(0); // Definition
6940b57cec5SDimitry Andric MachineOperand &MP = MI.getOperand(1); // Predicate register
6950b57cec5SDimitry Andric assert(MD.isDef());
6968bcb0991SDimitry Andric Register DR = MD.getReg(), DSR = MD.getSubReg();
6970b57cec5SDimitry Andric bool ReadUndef = MD.isUndef();
6980b57cec5SDimitry Andric MachineBasicBlock::iterator At = MI;
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric auto updateRegs = [&UpdRegs] (const MachineInstr &MI) -> void {
701bdd1243dSDimitry Andric for (auto &Op : MI.operands()) {
7020b57cec5SDimitry Andric if (Op.isReg())
7030b57cec5SDimitry Andric UpdRegs.insert(Op.getReg());
704bdd1243dSDimitry Andric }
7050b57cec5SDimitry Andric };
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric // If this is a mux of the same register, just replace it with COPY.
7080b57cec5SDimitry Andric // Ideally, this would happen earlier, so that register coalescing would
7090b57cec5SDimitry Andric // see it.
7100b57cec5SDimitry Andric MachineOperand &ST = MI.getOperand(2);
7110b57cec5SDimitry Andric MachineOperand &SF = MI.getOperand(3);
7120b57cec5SDimitry Andric if (ST.isReg() && SF.isReg()) {
7130b57cec5SDimitry Andric RegisterRef RT(ST);
7140b57cec5SDimitry Andric if (RT == RegisterRef(SF)) {
7150b57cec5SDimitry Andric // Copy regs to update first.
7160b57cec5SDimitry Andric updateRegs(MI);
7170b57cec5SDimitry Andric MI.setDesc(HII->get(TargetOpcode::COPY));
7180b57cec5SDimitry Andric unsigned S = getRegState(ST);
7190b57cec5SDimitry Andric while (MI.getNumOperands() > 1)
72081ad6265SDimitry Andric MI.removeOperand(MI.getNumOperands()-1);
7210b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent();
7220b57cec5SDimitry Andric MachineInstrBuilder(MF, MI).addReg(RT.Reg, S, RT.Sub);
7230b57cec5SDimitry Andric return true;
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric // First, create the two invididual conditional transfers, and add each
7280b57cec5SDimitry Andric // of them to the live intervals information. Do that first and then remove
7290b57cec5SDimitry Andric // the old instruction from live intervals.
7300b57cec5SDimitry Andric MachineInstr *TfrT =
7310b57cec5SDimitry Andric genCondTfrFor(ST, At, DR, DSR, MP, true, ReadUndef, false);
7320b57cec5SDimitry Andric MachineInstr *TfrF =
7330b57cec5SDimitry Andric genCondTfrFor(SF, At, DR, DSR, MP, false, ReadUndef, true);
7340b57cec5SDimitry Andric LIS->InsertMachineInstrInMaps(*TfrT);
7350b57cec5SDimitry Andric LIS->InsertMachineInstrInMaps(*TfrF);
7360b57cec5SDimitry Andric
7370b57cec5SDimitry Andric // Will need to recalculate live intervals for all registers in MI.
7380b57cec5SDimitry Andric updateRegs(MI);
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric removeInstr(MI);
7410b57cec5SDimitry Andric return true;
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric
isPredicable(MachineInstr * MI)7440b57cec5SDimitry Andric bool HexagonExpandCondsets::isPredicable(MachineInstr *MI) {
7450b57cec5SDimitry Andric if (HII->isPredicated(*MI) || !HII->isPredicable(*MI))
7460b57cec5SDimitry Andric return false;
7470b57cec5SDimitry Andric if (MI->hasUnmodeledSideEffects() || MI->mayStore())
7480b57cec5SDimitry Andric return false;
7490b57cec5SDimitry Andric // Reject instructions with multiple defs (e.g. post-increment loads).
7500b57cec5SDimitry Andric bool HasDef = false;
7510b57cec5SDimitry Andric for (auto &Op : MI->operands()) {
7520b57cec5SDimitry Andric if (!Op.isReg() || !Op.isDef())
7530b57cec5SDimitry Andric continue;
7540b57cec5SDimitry Andric if (HasDef)
7550b57cec5SDimitry Andric return false;
7560b57cec5SDimitry Andric HasDef = true;
7570b57cec5SDimitry Andric }
758bdd1243dSDimitry Andric for (auto &Mo : MI->memoperands()) {
7590b57cec5SDimitry Andric if (Mo->isVolatile() || Mo->isAtomic())
7600b57cec5SDimitry Andric return false;
761bdd1243dSDimitry Andric }
7620b57cec5SDimitry Andric return true;
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric
7650b57cec5SDimitry Andric /// Find the reaching definition for a predicated use of RD. The RD is used
7660b57cec5SDimitry Andric /// under the conditions given by PredR and Cond, and this function will ignore
7670b57cec5SDimitry Andric /// definitions that set RD under the opposite conditions.
getReachingDefForPred(RegisterRef RD,MachineBasicBlock::iterator UseIt,unsigned PredR,bool Cond)7680b57cec5SDimitry Andric MachineInstr *HexagonExpandCondsets::getReachingDefForPred(RegisterRef RD,
7690b57cec5SDimitry Andric MachineBasicBlock::iterator UseIt, unsigned PredR, bool Cond) {
7700b57cec5SDimitry Andric MachineBasicBlock &B = *UseIt->getParent();
7710b57cec5SDimitry Andric MachineBasicBlock::iterator I = UseIt, S = B.begin();
7720b57cec5SDimitry Andric if (I == S)
7730b57cec5SDimitry Andric return nullptr;
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andric bool PredValid = true;
7760b57cec5SDimitry Andric do {
7770b57cec5SDimitry Andric --I;
7780b57cec5SDimitry Andric MachineInstr *MI = &*I;
7790b57cec5SDimitry Andric // Check if this instruction can be ignored, i.e. if it is predicated
7800b57cec5SDimitry Andric // on the complementary condition.
7810b57cec5SDimitry Andric if (PredValid && HII->isPredicated(*MI)) {
782*0fca6ea1SDimitry Andric if (MI->readsRegister(PredR, /*TRI=*/nullptr) &&
783*0fca6ea1SDimitry Andric (Cond != HII->isPredicatedTrue(*MI)))
7840b57cec5SDimitry Andric continue;
7850b57cec5SDimitry Andric }
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric // Check the defs. If the PredR is defined, invalidate it. If RD is
7880b57cec5SDimitry Andric // defined, return the instruction or 0, depending on the circumstances.
7890b57cec5SDimitry Andric for (auto &Op : MI->operands()) {
7900b57cec5SDimitry Andric if (!Op.isReg() || !Op.isDef())
7910b57cec5SDimitry Andric continue;
7920b57cec5SDimitry Andric RegisterRef RR = Op;
7930b57cec5SDimitry Andric if (RR.Reg == PredR) {
7940b57cec5SDimitry Andric PredValid = false;
7950b57cec5SDimitry Andric continue;
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric if (RR.Reg != RD.Reg)
7980b57cec5SDimitry Andric continue;
7990b57cec5SDimitry Andric // If the "Reg" part agrees, there is still the subregister to check.
8000b57cec5SDimitry Andric // If we are looking for %1:loreg, we can skip %1:hireg, but
8010b57cec5SDimitry Andric // not %1 (w/o subregisters).
8020b57cec5SDimitry Andric if (RR.Sub == RD.Sub)
8030b57cec5SDimitry Andric return MI;
8040b57cec5SDimitry Andric if (RR.Sub == 0 || RD.Sub == 0)
8050b57cec5SDimitry Andric return nullptr;
8060b57cec5SDimitry Andric // We have different subregisters, so we can continue looking.
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric } while (I != S);
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric return nullptr;
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric
8130b57cec5SDimitry Andric /// Check if the instruction MI can be safely moved over a set of instructions
8140b57cec5SDimitry Andric /// whose side-effects (in terms of register defs and uses) are expressed in
8150b57cec5SDimitry Andric /// the maps Defs and Uses. These maps reflect the conditional defs and uses
8160b57cec5SDimitry Andric /// that depend on the same predicate register to allow moving instructions
8170b57cec5SDimitry Andric /// over instructions predicated on the opposite condition.
canMoveOver(MachineInstr & MI,ReferenceMap & Defs,ReferenceMap & Uses)8180b57cec5SDimitry Andric bool HexagonExpandCondsets::canMoveOver(MachineInstr &MI, ReferenceMap &Defs,
8190b57cec5SDimitry Andric ReferenceMap &Uses) {
8200b57cec5SDimitry Andric // In order to be able to safely move MI over instructions that define
8210b57cec5SDimitry Andric // "Defs" and use "Uses", no def operand from MI can be defined or used
8220b57cec5SDimitry Andric // and no use operand can be defined.
8230b57cec5SDimitry Andric for (auto &Op : MI.operands()) {
8240b57cec5SDimitry Andric if (!Op.isReg())
8250b57cec5SDimitry Andric continue;
8260b57cec5SDimitry Andric RegisterRef RR = Op;
8270b57cec5SDimitry Andric // For physical register we would need to check register aliases, etc.
8280b57cec5SDimitry Andric // and we don't want to bother with that. It would be of little value
8290b57cec5SDimitry Andric // before the actual register rewriting (from virtual to physical).
830e8d8bef9SDimitry Andric if (!RR.Reg.isVirtual())
8310b57cec5SDimitry Andric return false;
8320b57cec5SDimitry Andric // No redefs for any operand.
8330b57cec5SDimitry Andric if (isRefInMap(RR, Defs, Exec_Then))
8340b57cec5SDimitry Andric return false;
8350b57cec5SDimitry Andric // For defs, there cannot be uses.
8360b57cec5SDimitry Andric if (Op.isDef() && isRefInMap(RR, Uses, Exec_Then))
8370b57cec5SDimitry Andric return false;
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric return true;
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric /// Check if the instruction accessing memory (TheI) can be moved to the
8430b57cec5SDimitry Andric /// location ToI.
canMoveMemTo(MachineInstr & TheI,MachineInstr & ToI,bool IsDown)8440b57cec5SDimitry Andric bool HexagonExpandCondsets::canMoveMemTo(MachineInstr &TheI, MachineInstr &ToI,
8450b57cec5SDimitry Andric bool IsDown) {
8460b57cec5SDimitry Andric bool IsLoad = TheI.mayLoad(), IsStore = TheI.mayStore();
8470b57cec5SDimitry Andric if (!IsLoad && !IsStore)
8480b57cec5SDimitry Andric return true;
8490b57cec5SDimitry Andric if (HII->areMemAccessesTriviallyDisjoint(TheI, ToI))
8500b57cec5SDimitry Andric return true;
8510b57cec5SDimitry Andric if (TheI.hasUnmodeledSideEffects())
8520b57cec5SDimitry Andric return false;
8530b57cec5SDimitry Andric
8540b57cec5SDimitry Andric MachineBasicBlock::iterator StartI = IsDown ? TheI : ToI;
8550b57cec5SDimitry Andric MachineBasicBlock::iterator EndI = IsDown ? ToI : TheI;
8560b57cec5SDimitry Andric bool Ordered = TheI.hasOrderedMemoryRef();
8570b57cec5SDimitry Andric
8580b57cec5SDimitry Andric // Search for aliased memory reference in (StartI, EndI).
859bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_range(std::next(StartI), EndI)) {
860bdd1243dSDimitry Andric if (MI.hasUnmodeledSideEffects())
8610b57cec5SDimitry Andric return false;
862bdd1243dSDimitry Andric bool L = MI.mayLoad(), S = MI.mayStore();
8630b57cec5SDimitry Andric if (!L && !S)
8640b57cec5SDimitry Andric continue;
865bdd1243dSDimitry Andric if (Ordered && MI.hasOrderedMemoryRef())
8660b57cec5SDimitry Andric return false;
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric bool Conflict = (L && IsStore) || S;
8690b57cec5SDimitry Andric if (Conflict)
8700b57cec5SDimitry Andric return false;
8710b57cec5SDimitry Andric }
8720b57cec5SDimitry Andric return true;
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric
8750b57cec5SDimitry Andric /// Generate a predicated version of MI (where the condition is given via
8760b57cec5SDimitry Andric /// PredR and Cond) at the point indicated by Where.
predicateAt(const MachineOperand & DefOp,MachineInstr & MI,MachineBasicBlock::iterator Where,const MachineOperand & PredOp,bool Cond,std::set<Register> & UpdRegs)8770b57cec5SDimitry Andric void HexagonExpandCondsets::predicateAt(const MachineOperand &DefOp,
8780b57cec5SDimitry Andric MachineInstr &MI,
8790b57cec5SDimitry Andric MachineBasicBlock::iterator Where,
8800b57cec5SDimitry Andric const MachineOperand &PredOp, bool Cond,
881e8d8bef9SDimitry Andric std::set<Register> &UpdRegs) {
8820b57cec5SDimitry Andric // The problem with updating live intervals is that we can move one def
8830b57cec5SDimitry Andric // past another def. In particular, this can happen when moving an A2_tfrt
8840b57cec5SDimitry Andric // over an A2_tfrf defining the same register. From the point of view of
8850b57cec5SDimitry Andric // live intervals, these two instructions are two separate definitions,
8860b57cec5SDimitry Andric // and each one starts another live segment. LiveIntervals's "handleMove"
8870b57cec5SDimitry Andric // does not allow such moves, so we need to handle it ourselves. To avoid
8880b57cec5SDimitry Andric // invalidating liveness data while we are using it, the move will be
8890b57cec5SDimitry Andric // implemented in 4 steps: (1) add a clone of the instruction MI at the
8900b57cec5SDimitry Andric // target location, (2) update liveness, (3) delete the old instruction,
8910b57cec5SDimitry Andric // and (4) update liveness again.
8920b57cec5SDimitry Andric
8930b57cec5SDimitry Andric MachineBasicBlock &B = *MI.getParent();
8940b57cec5SDimitry Andric DebugLoc DL = Where->getDebugLoc(); // "Where" points to an instruction.
8950b57cec5SDimitry Andric unsigned Opc = MI.getOpcode();
8960b57cec5SDimitry Andric unsigned PredOpc = HII->getCondOpcode(Opc, !Cond);
8970b57cec5SDimitry Andric MachineInstrBuilder MB = BuildMI(B, Where, DL, HII->get(PredOpc));
8980b57cec5SDimitry Andric unsigned Ox = 0, NP = MI.getNumOperands();
8990b57cec5SDimitry Andric // Skip all defs from MI first.
9000b57cec5SDimitry Andric while (Ox < NP) {
9010b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(Ox);
9020b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef())
9030b57cec5SDimitry Andric break;
9040b57cec5SDimitry Andric Ox++;
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric // Add the new def, then the predicate register, then the rest of the
9070b57cec5SDimitry Andric // operands.
9080b57cec5SDimitry Andric MB.addReg(DefOp.getReg(), getRegState(DefOp), DefOp.getSubReg());
9090b57cec5SDimitry Andric MB.addReg(PredOp.getReg(), PredOp.isUndef() ? RegState::Undef : 0,
9100b57cec5SDimitry Andric PredOp.getSubReg());
9110b57cec5SDimitry Andric while (Ox < NP) {
9120b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(Ox);
9130b57cec5SDimitry Andric if (!MO.isReg() || !MO.isImplicit())
9140b57cec5SDimitry Andric MB.add(MO);
9150b57cec5SDimitry Andric Ox++;
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric MB.cloneMemRefs(MI);
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric MachineInstr *NewI = MB;
9200b57cec5SDimitry Andric NewI->clearKillInfo();
9210b57cec5SDimitry Andric LIS->InsertMachineInstrInMaps(*NewI);
9220b57cec5SDimitry Andric
923bdd1243dSDimitry Andric for (auto &Op : NewI->operands()) {
9240b57cec5SDimitry Andric if (Op.isReg())
9250b57cec5SDimitry Andric UpdRegs.insert(Op.getReg());
9260b57cec5SDimitry Andric }
927bdd1243dSDimitry Andric }
9280b57cec5SDimitry Andric
9290b57cec5SDimitry Andric /// In the range [First, Last], rename all references to the "old" register RO
9300b57cec5SDimitry Andric /// to the "new" register RN, but only in instructions predicated on the given
9310b57cec5SDimitry Andric /// condition.
renameInRange(RegisterRef RO,RegisterRef RN,unsigned PredR,bool Cond,MachineBasicBlock::iterator First,MachineBasicBlock::iterator Last)9320b57cec5SDimitry Andric void HexagonExpandCondsets::renameInRange(RegisterRef RO, RegisterRef RN,
9330b57cec5SDimitry Andric unsigned PredR, bool Cond, MachineBasicBlock::iterator First,
9340b57cec5SDimitry Andric MachineBasicBlock::iterator Last) {
9350b57cec5SDimitry Andric MachineBasicBlock::iterator End = std::next(Last);
936bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_range(First, End)) {
9370b57cec5SDimitry Andric // Do not touch instructions that are not predicated, or are predicated
9380b57cec5SDimitry Andric // on the opposite condition.
939bdd1243dSDimitry Andric if (!HII->isPredicated(MI))
9400b57cec5SDimitry Andric continue;
941*0fca6ea1SDimitry Andric if (!MI.readsRegister(PredR, /*TRI=*/nullptr) ||
942*0fca6ea1SDimitry Andric (Cond != HII->isPredicatedTrue(MI)))
9430b57cec5SDimitry Andric continue;
9440b57cec5SDimitry Andric
945bdd1243dSDimitry Andric for (auto &Op : MI.operands()) {
9460b57cec5SDimitry Andric if (!Op.isReg() || RO != RegisterRef(Op))
9470b57cec5SDimitry Andric continue;
9480b57cec5SDimitry Andric Op.setReg(RN.Reg);
9490b57cec5SDimitry Andric Op.setSubReg(RN.Sub);
9500b57cec5SDimitry Andric // In practice, this isn't supposed to see any defs.
9510b57cec5SDimitry Andric assert(!Op.isDef() && "Not expecting a def");
9520b57cec5SDimitry Andric }
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric
9560b57cec5SDimitry Andric /// For a given conditional copy, predicate the definition of the source of
9570b57cec5SDimitry Andric /// the copy under the given condition (using the same predicate register as
9580b57cec5SDimitry Andric /// the copy).
predicate(MachineInstr & TfrI,bool Cond,std::set<Register> & UpdRegs)9590b57cec5SDimitry Andric bool HexagonExpandCondsets::predicate(MachineInstr &TfrI, bool Cond,
960e8d8bef9SDimitry Andric std::set<Register> &UpdRegs) {
9610b57cec5SDimitry Andric // TfrI - A2_tfr[tf] Instruction (not A2_tfrsi).
9620b57cec5SDimitry Andric unsigned Opc = TfrI.getOpcode();
9630b57cec5SDimitry Andric (void)Opc;
9640b57cec5SDimitry Andric assert(Opc == Hexagon::A2_tfrt || Opc == Hexagon::A2_tfrf);
9650b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nattempt to predicate if-" << (Cond ? "true" : "false")
9660b57cec5SDimitry Andric << ": " << TfrI);
9670b57cec5SDimitry Andric
9680b57cec5SDimitry Andric MachineOperand &MD = TfrI.getOperand(0);
9690b57cec5SDimitry Andric MachineOperand &MP = TfrI.getOperand(1);
9700b57cec5SDimitry Andric MachineOperand &MS = TfrI.getOperand(2);
9710b57cec5SDimitry Andric // The source operand should be a <kill>. This is not strictly necessary,
9720b57cec5SDimitry Andric // but it makes things a lot simpler. Otherwise, we would need to rename
9730b57cec5SDimitry Andric // some registers, which would complicate the transformation considerably.
9740b57cec5SDimitry Andric if (!MS.isKill())
9750b57cec5SDimitry Andric return false;
9760b57cec5SDimitry Andric // Avoid predicating instructions that define a subregister if subregister
9770b57cec5SDimitry Andric // liveness tracking is not enabled.
9780b57cec5SDimitry Andric if (MD.getSubReg() && !MRI->shouldTrackSubRegLiveness(MD.getReg()))
9790b57cec5SDimitry Andric return false;
9800b57cec5SDimitry Andric
9810b57cec5SDimitry Andric RegisterRef RT(MS);
9828bcb0991SDimitry Andric Register PredR = MP.getReg();
9830b57cec5SDimitry Andric MachineInstr *DefI = getReachingDefForPred(RT, TfrI, PredR, Cond);
9840b57cec5SDimitry Andric if (!DefI || !isPredicable(DefI))
9850b57cec5SDimitry Andric return false;
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Source def: " << *DefI);
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andric // Collect the information about registers defined and used between the
9900b57cec5SDimitry Andric // DefI and the TfrI.
9910b57cec5SDimitry Andric // Map: reg -> bitmask of subregs
9920b57cec5SDimitry Andric ReferenceMap Uses, Defs;
9930b57cec5SDimitry Andric MachineBasicBlock::iterator DefIt = DefI, TfrIt = TfrI;
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andric // Check if the predicate register is valid between DefI and TfrI.
9960b57cec5SDimitry Andric // If it is, we can then ignore instructions predicated on the negated
9970b57cec5SDimitry Andric // conditions when collecting def and use information.
9980b57cec5SDimitry Andric bool PredValid = true;
999bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_range(std::next(DefIt), TfrIt)) {
1000bdd1243dSDimitry Andric if (!MI.modifiesRegister(PredR, nullptr))
10010b57cec5SDimitry Andric continue;
10020b57cec5SDimitry Andric PredValid = false;
10030b57cec5SDimitry Andric break;
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric
1006bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_range(std::next(DefIt), TfrIt)) {
10070b57cec5SDimitry Andric // If this instruction is predicated on the same register, it could
10080b57cec5SDimitry Andric // potentially be ignored.
10090b57cec5SDimitry Andric // By default assume that the instruction executes on the same condition
10100b57cec5SDimitry Andric // as TfrI (Exec_Then), and also on the opposite one (Exec_Else).
10110b57cec5SDimitry Andric unsigned Exec = Exec_Then | Exec_Else;
1012*0fca6ea1SDimitry Andric if (PredValid && HII->isPredicated(MI) &&
1013*0fca6ea1SDimitry Andric MI.readsRegister(PredR, /*TRI=*/nullptr))
1014bdd1243dSDimitry Andric Exec = (Cond == HII->isPredicatedTrue(MI)) ? Exec_Then : Exec_Else;
10150b57cec5SDimitry Andric
1016bdd1243dSDimitry Andric for (auto &Op : MI.operands()) {
10170b57cec5SDimitry Andric if (!Op.isReg())
10180b57cec5SDimitry Andric continue;
10190b57cec5SDimitry Andric // We don't want to deal with physical registers. The reason is that
10200b57cec5SDimitry Andric // they can be aliased with other physical registers. Aliased virtual
10210b57cec5SDimitry Andric // registers must share the same register number, and can only differ
10220b57cec5SDimitry Andric // in the subregisters, which we are keeping track of. Physical
10230b57cec5SDimitry Andric // registers ters no longer have subregisters---their super- and
10240b57cec5SDimitry Andric // subregisters are other physical registers, and we are not checking
10250b57cec5SDimitry Andric // that.
10260b57cec5SDimitry Andric RegisterRef RR = Op;
1027e8d8bef9SDimitry Andric if (!RR.Reg.isVirtual())
10280b57cec5SDimitry Andric return false;
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric ReferenceMap &Map = Op.isDef() ? Defs : Uses;
10310b57cec5SDimitry Andric if (Op.isDef() && Op.isUndef()) {
10320b57cec5SDimitry Andric assert(RR.Sub && "Expecting a subregister on <def,read-undef>");
10330b57cec5SDimitry Andric // If this is a <def,read-undef>, then it invalidates the non-written
10340b57cec5SDimitry Andric // part of the register. For the purpose of checking the validity of
10350b57cec5SDimitry Andric // the move, assume that it modifies the whole register.
10360b57cec5SDimitry Andric RR.Sub = 0;
10370b57cec5SDimitry Andric }
10380b57cec5SDimitry Andric addRefToMap(RR, Map, Exec);
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric
10420b57cec5SDimitry Andric // The situation:
10430b57cec5SDimitry Andric // RT = DefI
10440b57cec5SDimitry Andric // ...
10450b57cec5SDimitry Andric // RD = TfrI ..., RT
10460b57cec5SDimitry Andric
10470b57cec5SDimitry Andric // If the register-in-the-middle (RT) is used or redefined between
10480b57cec5SDimitry Andric // DefI and TfrI, we may not be able proceed with this transformation.
10490b57cec5SDimitry Andric // We can ignore a def that will not execute together with TfrI, and a
10500b57cec5SDimitry Andric // use that will. If there is such a use (that does execute together with
10510b57cec5SDimitry Andric // TfrI), we will not be able to move DefI down. If there is a use that
10520b57cec5SDimitry Andric // executed if TfrI's condition is false, then RT must be available
10530b57cec5SDimitry Andric // unconditionally (cannot be predicated).
10540b57cec5SDimitry Andric // Essentially, we need to be able to rename RT to RD in this segment.
10550b57cec5SDimitry Andric if (isRefInMap(RT, Defs, Exec_Then) || isRefInMap(RT, Uses, Exec_Else))
10560b57cec5SDimitry Andric return false;
10570b57cec5SDimitry Andric RegisterRef RD = MD;
10580b57cec5SDimitry Andric // If the predicate register is defined between DefI and TfrI, the only
10590b57cec5SDimitry Andric // potential thing to do would be to move the DefI down to TfrI, and then
10600b57cec5SDimitry Andric // predicate. The reaching def (DefI) must be movable down to the location
10610b57cec5SDimitry Andric // of the TfrI.
10620b57cec5SDimitry Andric // If the target register of the TfrI (RD) is not used or defined between
10630b57cec5SDimitry Andric // DefI and TfrI, consider moving TfrI up to DefI.
10640b57cec5SDimitry Andric bool CanUp = canMoveOver(TfrI, Defs, Uses);
10650b57cec5SDimitry Andric bool CanDown = canMoveOver(*DefI, Defs, Uses);
10660b57cec5SDimitry Andric // The TfrI does not access memory, but DefI could. Check if it's safe
10670b57cec5SDimitry Andric // to move DefI down to TfrI.
1068bdd1243dSDimitry Andric if (DefI->mayLoadOrStore()) {
10690b57cec5SDimitry Andric if (!canMoveMemTo(*DefI, TfrI, true))
10700b57cec5SDimitry Andric CanDown = false;
1071bdd1243dSDimitry Andric }
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can move up: " << (CanUp ? "yes" : "no")
10740b57cec5SDimitry Andric << ", can move down: " << (CanDown ? "yes\n" : "no\n"));
10750b57cec5SDimitry Andric MachineBasicBlock::iterator PastDefIt = std::next(DefIt);
10760b57cec5SDimitry Andric if (CanUp)
10770b57cec5SDimitry Andric predicateAt(MD, *DefI, PastDefIt, MP, Cond, UpdRegs);
10780b57cec5SDimitry Andric else if (CanDown)
10790b57cec5SDimitry Andric predicateAt(MD, *DefI, TfrIt, MP, Cond, UpdRegs);
10800b57cec5SDimitry Andric else
10810b57cec5SDimitry Andric return false;
10820b57cec5SDimitry Andric
10830b57cec5SDimitry Andric if (RT != RD) {
10840b57cec5SDimitry Andric renameInRange(RT, RD, PredR, Cond, PastDefIt, TfrIt);
10850b57cec5SDimitry Andric UpdRegs.insert(RT.Reg);
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric removeInstr(TfrI);
10890b57cec5SDimitry Andric removeInstr(*DefI);
10900b57cec5SDimitry Andric return true;
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric
10930b57cec5SDimitry Andric /// Predicate all cases of conditional copies in the specified block.
predicateInBlock(MachineBasicBlock & B,std::set<Register> & UpdRegs)10940b57cec5SDimitry Andric bool HexagonExpandCondsets::predicateInBlock(MachineBasicBlock &B,
1095e8d8bef9SDimitry Andric std::set<Register> &UpdRegs) {
10960b57cec5SDimitry Andric bool Changed = false;
1097349cc55cSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(B)) {
1098349cc55cSDimitry Andric unsigned Opc = MI.getOpcode();
10990b57cec5SDimitry Andric if (Opc == Hexagon::A2_tfrt || Opc == Hexagon::A2_tfrf) {
1100349cc55cSDimitry Andric bool Done = predicate(MI, (Opc == Hexagon::A2_tfrt), UpdRegs);
11010b57cec5SDimitry Andric if (!Done) {
11020b57cec5SDimitry Andric // If we didn't predicate I, we may need to remove it in case it is
11030b57cec5SDimitry Andric // an "identity" copy, e.g. %1 = A2_tfrt %2, %1.
1104349cc55cSDimitry Andric if (RegisterRef(MI.getOperand(0)) == RegisterRef(MI.getOperand(2))) {
1105bdd1243dSDimitry Andric for (auto &Op : MI.operands()) {
11060b57cec5SDimitry Andric if (Op.isReg())
11070b57cec5SDimitry Andric UpdRegs.insert(Op.getReg());
1108bdd1243dSDimitry Andric }
1109349cc55cSDimitry Andric removeInstr(MI);
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric }
11120b57cec5SDimitry Andric Changed |= Done;
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric return Changed;
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric
isIntReg(RegisterRef RR,unsigned & BW)11180b57cec5SDimitry Andric bool HexagonExpandCondsets::isIntReg(RegisterRef RR, unsigned &BW) {
1119e8d8bef9SDimitry Andric if (!RR.Reg.isVirtual())
11200b57cec5SDimitry Andric return false;
11210b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(RR.Reg);
11220b57cec5SDimitry Andric if (RC == &Hexagon::IntRegsRegClass) {
11230b57cec5SDimitry Andric BW = 32;
11240b57cec5SDimitry Andric return true;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric if (RC == &Hexagon::DoubleRegsRegClass) {
11270b57cec5SDimitry Andric BW = (RR.Sub != 0) ? 32 : 64;
11280b57cec5SDimitry Andric return true;
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric return false;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric
isIntraBlocks(LiveInterval & LI)11330b57cec5SDimitry Andric bool HexagonExpandCondsets::isIntraBlocks(LiveInterval &LI) {
113404eeddc0SDimitry Andric for (LiveRange::Segment &LR : LI) {
11350b57cec5SDimitry Andric // Range must start at a register...
11360b57cec5SDimitry Andric if (!LR.start.isRegister())
11370b57cec5SDimitry Andric return false;
11380b57cec5SDimitry Andric // ...and end in a register or in a dead slot.
11390b57cec5SDimitry Andric if (!LR.end.isRegister() && !LR.end.isDead())
11400b57cec5SDimitry Andric return false;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric return true;
11430b57cec5SDimitry Andric }
11440b57cec5SDimitry Andric
coalesceRegisters(RegisterRef R1,RegisterRef R2)11450b57cec5SDimitry Andric bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef R2) {
11460b57cec5SDimitry Andric if (CoaLimitActive) {
11470b57cec5SDimitry Andric if (CoaCounter >= CoaLimit)
11480b57cec5SDimitry Andric return false;
11490b57cec5SDimitry Andric CoaCounter++;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric unsigned BW1, BW2;
11520b57cec5SDimitry Andric if (!isIntReg(R1, BW1) || !isIntReg(R2, BW2) || BW1 != BW2)
11530b57cec5SDimitry Andric return false;
11540b57cec5SDimitry Andric if (MRI->isLiveIn(R1.Reg))
11550b57cec5SDimitry Andric return false;
11560b57cec5SDimitry Andric if (MRI->isLiveIn(R2.Reg))
11570b57cec5SDimitry Andric return false;
11580b57cec5SDimitry Andric
11590b57cec5SDimitry Andric LiveInterval &L1 = LIS->getInterval(R1.Reg);
11600b57cec5SDimitry Andric LiveInterval &L2 = LIS->getInterval(R2.Reg);
11610b57cec5SDimitry Andric if (L2.empty())
11620b57cec5SDimitry Andric return false;
11630b57cec5SDimitry Andric if (L1.hasSubRanges() || L2.hasSubRanges())
11640b57cec5SDimitry Andric return false;
11650b57cec5SDimitry Andric bool Overlap = L1.overlaps(L2);
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "compatible registers: ("
11680b57cec5SDimitry Andric << (Overlap ? "overlap" : "disjoint") << ")\n "
11690b57cec5SDimitry Andric << printReg(R1.Reg, TRI, R1.Sub) << " " << L1 << "\n "
11700b57cec5SDimitry Andric << printReg(R2.Reg, TRI, R2.Sub) << " " << L2 << "\n");
11710b57cec5SDimitry Andric if (R1.Sub || R2.Sub)
11720b57cec5SDimitry Andric return false;
11730b57cec5SDimitry Andric if (Overlap)
11740b57cec5SDimitry Andric return false;
11750b57cec5SDimitry Andric
11760b57cec5SDimitry Andric // Coalescing could have a negative impact on scheduling, so try to limit
11770b57cec5SDimitry Andric // to some reasonable extent. Only consider coalescing segments, when one
11780b57cec5SDimitry Andric // of them does not cross basic block boundaries.
11790b57cec5SDimitry Andric if (!isIntraBlocks(L1) && !isIntraBlocks(L2))
11800b57cec5SDimitry Andric return false;
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric MRI->replaceRegWith(R2.Reg, R1.Reg);
11830b57cec5SDimitry Andric
11840b57cec5SDimitry Andric // Move all live segments from L2 to L1.
11850b57cec5SDimitry Andric using ValueInfoMap = DenseMap<VNInfo *, VNInfo *>;
11860b57cec5SDimitry Andric ValueInfoMap VM;
118704eeddc0SDimitry Andric for (LiveRange::Segment &I : L2) {
118804eeddc0SDimitry Andric VNInfo *NewVN, *OldVN = I.valno;
11890b57cec5SDimitry Andric ValueInfoMap::iterator F = VM.find(OldVN);
11900b57cec5SDimitry Andric if (F == VM.end()) {
119104eeddc0SDimitry Andric NewVN = L1.getNextValue(I.valno->def, LIS->getVNInfoAllocator());
11920b57cec5SDimitry Andric VM.insert(std::make_pair(OldVN, NewVN));
11930b57cec5SDimitry Andric } else {
11940b57cec5SDimitry Andric NewVN = F->second;
11950b57cec5SDimitry Andric }
119604eeddc0SDimitry Andric L1.addSegment(LiveRange::Segment(I.start, I.end, NewVN));
11970b57cec5SDimitry Andric }
1198e8d8bef9SDimitry Andric while (!L2.empty())
11990b57cec5SDimitry Andric L2.removeSegment(*L2.begin());
12000b57cec5SDimitry Andric LIS->removeInterval(R2.Reg);
12010b57cec5SDimitry Andric
12020b57cec5SDimitry Andric updateKillFlags(R1.Reg);
12030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "coalesced: " << L1 << "\n");
12040b57cec5SDimitry Andric L1.verify();
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andric return true;
12070b57cec5SDimitry Andric }
12080b57cec5SDimitry Andric
12090b57cec5SDimitry Andric /// Attempt to coalesce one of the source registers to a MUX instruction with
12100b57cec5SDimitry Andric /// the destination register. This could lead to having only one predicated
12110b57cec5SDimitry Andric /// instruction in the end instead of two.
coalesceSegments(const SmallVectorImpl<MachineInstr * > & Condsets,std::set<Register> & UpdRegs)12120b57cec5SDimitry Andric bool HexagonExpandCondsets::coalesceSegments(
12130b57cec5SDimitry Andric const SmallVectorImpl<MachineInstr *> &Condsets,
1214e8d8bef9SDimitry Andric std::set<Register> &UpdRegs) {
12150b57cec5SDimitry Andric SmallVector<MachineInstr*,16> TwoRegs;
12160b57cec5SDimitry Andric for (MachineInstr *MI : Condsets) {
12170b57cec5SDimitry Andric MachineOperand &S1 = MI->getOperand(2), &S2 = MI->getOperand(3);
12180b57cec5SDimitry Andric if (!S1.isReg() && !S2.isReg())
12190b57cec5SDimitry Andric continue;
12200b57cec5SDimitry Andric TwoRegs.push_back(MI);
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric bool Changed = false;
12240b57cec5SDimitry Andric for (MachineInstr *CI : TwoRegs) {
12250b57cec5SDimitry Andric RegisterRef RD = CI->getOperand(0);
12260b57cec5SDimitry Andric RegisterRef RP = CI->getOperand(1);
12270b57cec5SDimitry Andric MachineOperand &S1 = CI->getOperand(2), &S2 = CI->getOperand(3);
12280b57cec5SDimitry Andric bool Done = false;
12290b57cec5SDimitry Andric // Consider this case:
12300b57cec5SDimitry Andric // %1 = instr1 ...
12310b57cec5SDimitry Andric // %2 = instr2 ...
12320b57cec5SDimitry Andric // %0 = C2_mux ..., %1, %2
12330b57cec5SDimitry Andric // If %0 was coalesced with %1, we could end up with the following
12340b57cec5SDimitry Andric // code:
12350b57cec5SDimitry Andric // %0 = instr1 ...
12360b57cec5SDimitry Andric // %2 = instr2 ...
12370b57cec5SDimitry Andric // %0 = A2_tfrf ..., %2
12380b57cec5SDimitry Andric // which will later become:
12390b57cec5SDimitry Andric // %0 = instr1 ...
12400b57cec5SDimitry Andric // %0 = instr2_cNotPt ...
12410b57cec5SDimitry Andric // i.e. there will be an unconditional definition (instr1) of %0
12420b57cec5SDimitry Andric // followed by a conditional one. The output dependency was there before
12430b57cec5SDimitry Andric // and it unavoidable, but if instr1 is predicable, we will no longer be
12440b57cec5SDimitry Andric // able to predicate it here.
12450b57cec5SDimitry Andric // To avoid this scenario, don't coalesce the destination register with
12460b57cec5SDimitry Andric // a source register that is defined by a predicable instruction.
12470b57cec5SDimitry Andric if (S1.isReg()) {
12480b57cec5SDimitry Andric RegisterRef RS = S1;
12490b57cec5SDimitry Andric MachineInstr *RDef = getReachingDefForPred(RS, CI, RP.Reg, true);
12500b57cec5SDimitry Andric if (!RDef || !HII->isPredicable(*RDef)) {
12510b57cec5SDimitry Andric Done = coalesceRegisters(RD, RegisterRef(S1));
12520b57cec5SDimitry Andric if (Done) {
12530b57cec5SDimitry Andric UpdRegs.insert(RD.Reg);
12540b57cec5SDimitry Andric UpdRegs.insert(S1.getReg());
12550b57cec5SDimitry Andric }
12560b57cec5SDimitry Andric }
12570b57cec5SDimitry Andric }
12580b57cec5SDimitry Andric if (!Done && S2.isReg()) {
12590b57cec5SDimitry Andric RegisterRef RS = S2;
12600b57cec5SDimitry Andric MachineInstr *RDef = getReachingDefForPred(RS, CI, RP.Reg, false);
12610b57cec5SDimitry Andric if (!RDef || !HII->isPredicable(*RDef)) {
12620b57cec5SDimitry Andric Done = coalesceRegisters(RD, RegisterRef(S2));
12630b57cec5SDimitry Andric if (Done) {
12640b57cec5SDimitry Andric UpdRegs.insert(RD.Reg);
12650b57cec5SDimitry Andric UpdRegs.insert(S2.getReg());
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric }
12690b57cec5SDimitry Andric Changed |= Done;
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric return Changed;
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)12740b57cec5SDimitry Andric bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) {
12750b57cec5SDimitry Andric if (skipFunction(MF.getFunction()))
12760b57cec5SDimitry Andric return false;
12770b57cec5SDimitry Andric
12780b57cec5SDimitry Andric HII = static_cast<const HexagonInstrInfo*>(MF.getSubtarget().getInstrInfo());
12790b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo();
1280*0fca6ea1SDimitry Andric MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1281*0fca6ea1SDimitry Andric LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
12820b57cec5SDimitry Andric MRI = &MF.getRegInfo();
12830b57cec5SDimitry Andric
1284*0fca6ea1SDimitry Andric LLVM_DEBUG(LIS->print(dbgs() << "Before expand-condsets\n"));
12850b57cec5SDimitry Andric
12860b57cec5SDimitry Andric bool Changed = false;
1287e8d8bef9SDimitry Andric std::set<Register> CoalUpd, PredUpd;
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric SmallVector<MachineInstr*,16> Condsets;
1290bdd1243dSDimitry Andric for (auto &B : MF) {
1291bdd1243dSDimitry Andric for (auto &I : B) {
12920b57cec5SDimitry Andric if (isCondset(I))
12930b57cec5SDimitry Andric Condsets.push_back(&I);
1294bdd1243dSDimitry Andric }
1295bdd1243dSDimitry Andric }
12960b57cec5SDimitry Andric
12970b57cec5SDimitry Andric // Try to coalesce the target of a mux with one of its sources.
12980b57cec5SDimitry Andric // This could eliminate a register copy in some circumstances.
12990b57cec5SDimitry Andric Changed |= coalesceSegments(Condsets, CoalUpd);
13000b57cec5SDimitry Andric
13010b57cec5SDimitry Andric // Update kill flags on all source operands. This is done here because
13020b57cec5SDimitry Andric // at this moment (when expand-condsets runs), there are no kill flags
13030b57cec5SDimitry Andric // in the IR (they have been removed by live range analysis).
13040b57cec5SDimitry Andric // Updating them right before we split is the easiest, because splitting
13050b57cec5SDimitry Andric // adds definitions which would interfere with updating kills afterwards.
1306e8d8bef9SDimitry Andric std::set<Register> KillUpd;
1307bdd1243dSDimitry Andric for (MachineInstr *MI : Condsets) {
1308bdd1243dSDimitry Andric for (MachineOperand &Op : MI->operands()) {
1309bdd1243dSDimitry Andric if (Op.isReg() && Op.isUse()) {
13100b57cec5SDimitry Andric if (!CoalUpd.count(Op.getReg()))
13110b57cec5SDimitry Andric KillUpd.insert(Op.getReg());
1312bdd1243dSDimitry Andric }
1313bdd1243dSDimitry Andric }
1314bdd1243dSDimitry Andric }
13150b57cec5SDimitry Andric updateLiveness(KillUpd, false, true, false);
1316*0fca6ea1SDimitry Andric LLVM_DEBUG(LIS->print(dbgs() << "After coalescing\n"));
13170b57cec5SDimitry Andric
13180b57cec5SDimitry Andric // First, simply split all muxes into a pair of conditional transfers
13190b57cec5SDimitry Andric // and update the live intervals to reflect the new arrangement. The
13200b57cec5SDimitry Andric // goal is to update the kill flags, since predication will rely on
13210b57cec5SDimitry Andric // them.
13220b57cec5SDimitry Andric for (MachineInstr *MI : Condsets)
13230b57cec5SDimitry Andric Changed |= split(*MI, PredUpd);
13240b57cec5SDimitry Andric Condsets.clear(); // The contents of Condsets are invalid here anyway.
13250b57cec5SDimitry Andric
13260b57cec5SDimitry Andric // Do not update live ranges after splitting. Recalculation of live
13270b57cec5SDimitry Andric // intervals removes kill flags, which were preserved by splitting on
13280b57cec5SDimitry Andric // the source operands of condsets. These kill flags are needed by
13290b57cec5SDimitry Andric // predication, and after splitting they are difficult to recalculate
13300b57cec5SDimitry Andric // (because of predicated defs), so make sure they are left untouched.
13310b57cec5SDimitry Andric // Predication does not use live intervals.
1332*0fca6ea1SDimitry Andric LLVM_DEBUG(LIS->print(dbgs() << "After splitting\n"));
13330b57cec5SDimitry Andric
13340b57cec5SDimitry Andric // Traverse all blocks and collapse predicable instructions feeding
13350b57cec5SDimitry Andric // conditional transfers into predicated instructions.
13360b57cec5SDimitry Andric // Walk over all the instructions again, so we may catch pre-existing
13370b57cec5SDimitry Andric // cases that were not created in the previous step.
13380b57cec5SDimitry Andric for (auto &B : MF)
13390b57cec5SDimitry Andric Changed |= predicateInBlock(B, PredUpd);
1340*0fca6ea1SDimitry Andric LLVM_DEBUG(LIS->print(dbgs() << "After predicating\n"));
13410b57cec5SDimitry Andric
13420b57cec5SDimitry Andric PredUpd.insert(CoalUpd.begin(), CoalUpd.end());
13430b57cec5SDimitry Andric updateLiveness(PredUpd, true, true, true);
13440b57cec5SDimitry Andric
1345bdd1243dSDimitry Andric if (Changed)
1346bdd1243dSDimitry Andric distributeLiveIntervals(PredUpd);
1347bdd1243dSDimitry Andric
13480b57cec5SDimitry Andric LLVM_DEBUG({
13490b57cec5SDimitry Andric if (Changed)
1350*0fca6ea1SDimitry Andric LIS->print(dbgs() << "After expand-condsets\n");
13510b57cec5SDimitry Andric });
13520b57cec5SDimitry Andric
13530b57cec5SDimitry Andric return Changed;
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13570b57cec5SDimitry Andric // Public Constructor Functions
13580b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
createHexagonExpandCondsets()13590b57cec5SDimitry Andric FunctionPass *llvm::createHexagonExpandCondsets() {
13600b57cec5SDimitry Andric return new HexagonExpandCondsets();
13610b57cec5SDimitry Andric }
1362