diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonExpandCondsets.cpp')
| -rw-r--r-- | lib/Target/Hexagon/HexagonExpandCondsets.cpp | 154 |
1 files changed, 87 insertions, 67 deletions
diff --git a/lib/Target/Hexagon/HexagonExpandCondsets.cpp b/lib/Target/Hexagon/HexagonExpandCondsets.cpp index a2f6dd68c1a1..c2feaf5737b2 100644 --- a/lib/Target/Hexagon/HexagonExpandCondsets.cpp +++ b/lib/Target/Hexagon/HexagonExpandCondsets.cpp @@ -1,4 +1,4 @@ -//===--- HexagonExpandCondsets.cpp ----------------------------------------===// +//===- HexagonExpandCondsets.cpp ------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -17,33 +17,33 @@ // // Liveness tracking aside, the main functionality of this pass is divided // into two steps. The first step is to replace an instruction -// vreg0 = C2_mux vreg1, vreg2, vreg3 +// %0 = C2_mux %1, %2, %3 // with a pair of conditional transfers -// vreg0 = A2_tfrt vreg1, vreg2 -// vreg0 = A2_tfrf vreg1, vreg3 +// %0 = A2_tfrt %1, %2 +// %0 = A2_tfrf %1, %3 // It is the intention that the execution of this pass could be terminated // after this step, and the code generated would be functionally correct. // -// If the uses of the source values vreg1 and vreg2 are kills, and their +// If the uses of the source values %1 and %2 are kills, and their // definitions are predicable, then in the second step, the conditional // transfers will then be rewritten as predicated instructions. E.g. -// vreg0 = A2_or vreg1, vreg2 -// vreg3 = A2_tfrt vreg99, vreg0<kill> +// %0 = A2_or %1, %2 +// %3 = A2_tfrt %99, killed %0 // will be rewritten as -// vreg3 = A2_port vreg99, vreg1, vreg2 +// %3 = A2_port %99, %1, %2 // // This replacement has two variants: "up" and "down". Consider this case: -// vreg0 = A2_or vreg1, vreg2 +// %0 = A2_or %1, %2 // ... [intervening instructions] ... -// vreg3 = A2_tfrt vreg99, vreg0<kill> +// %3 = A2_tfrt %99, killed %0 // variant "up": -// vreg3 = A2_port vreg99, vreg1, vreg2 -// ... [intervening instructions, vreg0->vreg3] ... +// %3 = A2_port %99, %1, %2 +// ... [intervening instructions, %0->vreg3] ... // [deleted] // variant "down": // [deleted] // ... [intervening instructions] ... -// vreg3 = A2_port vreg99, vreg1, vreg2 +// %3 = A2_port %99, %1, %2 // // Both, one or none of these variants may be valid, and checks are made // to rule out inapplicable variants. @@ -51,13 +51,13 @@ // As an additional optimization, before either of the two steps above is // executed, the pass attempts to coalesce the target register with one of // the source registers, e.g. given an instruction -// vreg3 = C2_mux vreg0, vreg1, vreg2 -// vreg3 will be coalesced with either vreg1 or vreg2. If this succeeds, +// %3 = C2_mux %0, %1, %2 +// %3 will be coalesced with either %1 or %2. If this succeeds, // the instruction would then be (for example) -// vreg3 = C2_mux vreg0, vreg3, vreg2 +// %3 = C2_mux %0, %3, %2 // and, under certain circumstances, this could result in only one predicated // instruction: -// vreg3 = A2_tfrf vreg0, vreg2 +// %3 = A2_tfrf %0, %2 // // Splitting a definition of a register into two predicated transfers @@ -65,18 +65,18 @@ // will see both instructions as actual definitions, and will mark the // first one as dead. The definition is not actually dead, and this // situation will need to be fixed. For example: -// vreg1<def,dead> = A2_tfrt ... ; marked as dead -// vreg1<def> = A2_tfrf ... +// dead %1 = A2_tfrt ... ; marked as dead +// %1 = A2_tfrf ... // // Since any of the individual predicated transfers may end up getting // removed (in case it is an identity copy), some pre-existing def may // be marked as dead after live interval recomputation: -// vreg1<def,dead> = ... ; marked as dead +// dead %1 = ... ; marked as dead // ... -// vreg1<def> = A2_tfrf ... ; if A2_tfrt is removed -// This case happens if vreg1 was used as a source in A2_tfrt, which means +// %1 = A2_tfrf ... ; if A2_tfrt is removed +// This case happens if %1 was used as a source in A2_tfrt, which means // that is it actually live at the A2_tfrf, and so the now dead definition -// of vreg1 will need to be updated to non-dead at some point. +// of %1 will need to be updated to non-dead at some point. // // This issue could be remedied by adding implicit uses to the predicated // transfers, but this will create a problem with subsequent predication, @@ -87,12 +87,13 @@ // to be added, and updating the live ranges will be more involved. #include "HexagonInstrInfo.h" +#include "HexagonRegisterInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/LiveInterval.h" -#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" @@ -102,13 +103,16 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Function.h" +#include "llvm/MC/LaneBitmask.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetRegisterInfo.h" #include <cassert> #include <iterator> #include <set> @@ -136,10 +140,7 @@ namespace { public: static char ID; - HexagonExpandCondsets() : - MachineFunctionPass(ID), HII(nullptr), TRI(nullptr), MRI(nullptr), - LIS(nullptr), CoaLimitActive(false), - TfrLimitActive(false), CoaCounter(0), TfrCounter(0) { + HexagonExpandCondsets() : MachineFunctionPass(ID) { if (OptCoaLimit.getPosition()) CoaLimitActive = true, CoaLimit = OptCoaLimit; if (OptTfrLimit.getPosition()) @@ -161,14 +162,17 @@ namespace { bool runOnMachineFunction(MachineFunction &MF) override; private: - const HexagonInstrInfo *HII; - const TargetRegisterInfo *TRI; + const HexagonInstrInfo *HII = nullptr; + const TargetRegisterInfo *TRI = nullptr; MachineDominatorTree *MDT; - MachineRegisterInfo *MRI; - LiveIntervals *LIS; - - bool CoaLimitActive, TfrLimitActive; - unsigned CoaLimit, TfrLimit, CoaCounter, TfrCounter; + MachineRegisterInfo *MRI = nullptr; + LiveIntervals *LIS = nullptr; + bool CoaLimitActive = false; + bool TfrLimitActive = false; + unsigned CoaLimit; + unsigned TfrLimit; + unsigned CoaCounter = 0; + unsigned TfrCounter = 0; struct RegisterRef { RegisterRef(const MachineOperand &Op) : Reg(Op.getReg()), @@ -186,9 +190,10 @@ namespace { unsigned Reg, Sub; }; - typedef DenseMap<unsigned,unsigned> ReferenceMap; + using ReferenceMap = DenseMap<unsigned, unsigned>; enum { Sub_Low = 0x1, Sub_High = 0x2, Sub_None = (Sub_Low | Sub_High) }; enum { Exec_Then = 0x10, Exec_Else = 0x20 }; + unsigned getMaskForSub(unsigned Sub); bool isCondset(const MachineInstr &MI); LaneBitmask getLaneMask(unsigned Reg, unsigned Sub); @@ -484,18 +489,33 @@ void HexagonExpandCondsets::updateDeadsInRange(unsigned Reg, LaneBitmask LM, if (!HII->isPredicated(*DefI)) continue; // Construct the set of all necessary implicit uses, based on the def - // operands in the instruction. - std::set<RegisterRef> ImpUses; - for (auto &Op : DefI->operands()) - if (Op.isReg() && Op.isDef() && DefRegs.count(Op)) - ImpUses.insert(Op); + // operands in the instruction. We need to tie the implicit uses to + // the corresponding defs. + std::map<RegisterRef,unsigned> ImpUses; + for (unsigned i = 0, e = DefI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = DefI->getOperand(i); + if (!Op.isReg() || !DefRegs.count(Op)) + continue; + if (Op.isDef()) { + ImpUses.insert({Op, i}); + } else { + // This function can be called for the same register with different + // lane masks. If the def in this instruction was for the whole + // register, we can get here more than once. Avoid adding multiple + // implicit uses (or adding an implicit use when an explicit one is + // present). + ImpUses.erase(Op); + } + } if (ImpUses.empty()) continue; MachineFunction &MF = *DefI->getParent()->getParent(); - for (RegisterRef R : ImpUses) + for (std::pair<RegisterRef, unsigned> P : ImpUses) { + RegisterRef R = P.first; MachineInstrBuilder(MF, DefI).addReg(R.Reg, RegState::Implicit, R.Sub); + DefI->tieOperands(P.second, DefI->getNumOperands()-1); + } } - } void HexagonExpandCondsets::updateDeadFlags(unsigned Reg) { @@ -634,7 +654,7 @@ bool HexagonExpandCondsets::split(MachineInstr &MI, return false; TfrCounter++; } - DEBUG(dbgs() << "\nsplitting BB#" << MI.getParent()->getNumber() << ": " + DEBUG(dbgs() << "\nsplitting " << printMBBReference(*MI.getParent()) << ": " << MI); MachineOperand &MD = MI.getOperand(0); // Definition MachineOperand &MP = MI.getOperand(1); // Predicate register @@ -740,8 +760,8 @@ MachineInstr *HexagonExpandCondsets::getReachingDefForPred(RegisterRef RD, if (RR.Reg != RD.Reg) continue; // If the "Reg" part agrees, there is still the subregister to check. - // If we are looking for vreg1:loreg, we can skip vreg1:hireg, but - // not vreg1 (w/o subregisters). + // If we are looking for %1:loreg, we can skip %1:hireg, but + // not %1 (w/o subregisters). if (RR.Sub == RD.Sub) return MI; if (RR.Sub == 0 || RD.Sub == 0) @@ -1051,7 +1071,7 @@ bool HexagonExpandCondsets::predicateInBlock(MachineBasicBlock &B, bool Done = predicate(*I, (Opc == Hexagon::A2_tfrt), UpdRegs); if (!Done) { // If we didn't predicate I, we may need to remove it in case it is - // an "identity" copy, e.g. vreg1 = A2_tfrt vreg2, vreg1. + // an "identity" copy, e.g. %1 = A2_tfrt %2, %1. if (RegisterRef(I->getOperand(0)) == RegisterRef(I->getOperand(2))) { for (auto &Op : I->operands()) if (Op.isReg()) @@ -1117,8 +1137,8 @@ bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef R2) { DEBUG(dbgs() << "compatible registers: (" << (Overlap ? "overlap" : "disjoint") << ")\n " - << PrintReg(R1.Reg, TRI, R1.Sub) << " " << L1 << "\n " - << PrintReg(R2.Reg, TRI, R2.Sub) << " " << L2 << "\n"); + << printReg(R1.Reg, TRI, R1.Sub) << " " << L1 << "\n " + << printReg(R2.Reg, TRI, R2.Sub) << " " << L2 << "\n"); if (R1.Sub || R2.Sub) return false; if (Overlap) @@ -1133,7 +1153,7 @@ bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef R2) { MRI->replaceRegWith(R2.Reg, R1.Reg); // Move all live segments from L2 to L1. - typedef DenseMap<VNInfo*,VNInfo*> ValueInfoMap; + using ValueInfoMap = DenseMap<VNInfo *, VNInfo *>; ValueInfoMap VM; for (LiveInterval::iterator I = L2.begin(), E = L2.end(); I != E; ++I) { VNInfo *NewVN, *OldVN = I->valno; @@ -1178,18 +1198,18 @@ bool HexagonExpandCondsets::coalesceSegments( MachineOperand &S1 = CI->getOperand(2), &S2 = CI->getOperand(3); bool Done = false; // Consider this case: - // vreg1 = instr1 ... - // vreg2 = instr2 ... - // vreg0 = C2_mux ..., vreg1, vreg2 - // If vreg0 was coalesced with vreg1, we could end up with the following + // %1 = instr1 ... + // %2 = instr2 ... + // %0 = C2_mux ..., %1, %2 + // If %0 was coalesced with %1, we could end up with the following // code: - // vreg0 = instr1 ... - // vreg2 = instr2 ... - // vreg0 = A2_tfrf ..., vreg2 + // %0 = instr1 ... + // %2 = instr2 ... + // %0 = A2_tfrf ..., %2 // which will later become: - // vreg0 = instr1 ... - // vreg0 = instr2_cNotPt ... - // i.e. there will be an unconditional definition (instr1) of vreg0 + // %0 = instr1 ... + // %0 = instr2_cNotPt ... + // i.e. there will be an unconditional definition (instr1) of %0 // followed by a conditional one. The output dependency was there before // and it unavoidable, but if instr1 is predicable, we will no longer be // able to predicate it here. @@ -1223,7 +1243,7 @@ bool HexagonExpandCondsets::coalesceSegments( } bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { - if (skipFunction(*MF.getFunction())) + if (skipFunction(MF.getFunction())) return false; HII = static_cast<const HexagonInstrInfo*>(MF.getSubtarget().getInstrInfo()); @@ -1233,7 +1253,7 @@ bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { MRI = &MF.getRegInfo(); DEBUG(LIS->print(dbgs() << "Before expand-condsets\n", - MF.getFunction()->getParent())); + MF.getFunction().getParent())); bool Changed = false; std::set<unsigned> CoalUpd, PredUpd; @@ -1261,7 +1281,7 @@ bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { KillUpd.insert(Op.getReg()); updateLiveness(KillUpd, false, true, false); DEBUG(LIS->print(dbgs() << "After coalescing\n", - MF.getFunction()->getParent())); + MF.getFunction().getParent())); // First, simply split all muxes into a pair of conditional transfers // and update the live intervals to reflect the new arrangement. The @@ -1278,7 +1298,7 @@ bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { // (because of predicated defs), so make sure they are left untouched. // Predication does not use live intervals. DEBUG(LIS->print(dbgs() << "After splitting\n", - MF.getFunction()->getParent())); + MF.getFunction().getParent())); // Traverse all blocks and collapse predicable instructions feeding // conditional transfers into predicated instructions. @@ -1287,7 +1307,7 @@ bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { for (auto &B : MF) Changed |= predicateInBlock(B, PredUpd); DEBUG(LIS->print(dbgs() << "After predicating\n", - MF.getFunction()->getParent())); + MF.getFunction().getParent())); PredUpd.insert(CoalUpd.begin(), CoalUpd.end()); updateLiveness(PredUpd, true, true, true); @@ -1295,7 +1315,7 @@ bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { DEBUG({ if (Changed) LIS->print(dbgs() << "After expand-condsets\n", - MF.getFunction()->getParent()); + MF.getFunction().getParent()); }); return Changed; |
