LLVM  11.0.0git
HexagonVExtract.cpp
Go to the documentation of this file.
1 //===- HexagonVExtract.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // This pass will replace multiple occurrences of V6_extractw from the same
9 // vector register with a combination of a vector store and scalar loads.
10 //===----------------------------------------------------------------------===//
11 
12 #include "Hexagon.h"
13 #include "HexagonInstrInfo.h"
15 #include "HexagonRegisterInfo.h"
16 #include "HexagonSubtarget.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Pass.h"
25 
26 #include <map>
27 
28 using namespace llvm;
29 
30 static cl::opt<unsigned> VExtractThreshold("hexagon-vextract-threshold",
32  cl::desc("Threshold for triggering vextract replacement"));
33 
34 namespace llvm {
37 }
38 
39 namespace {
40  class HexagonVExtract : public MachineFunctionPass {
41  public:
42  static char ID;
43  HexagonVExtract() : MachineFunctionPass(ID) {}
44 
45  StringRef getPassName() const override {
46  return "Hexagon optimize vextract";
47  }
48  void getAnalysisUsage(AnalysisUsage &AU) const override {
50  }
51  bool runOnMachineFunction(MachineFunction &MF) override;
52 
53  private:
54  const HexagonSubtarget *HST = nullptr;
55  const HexagonInstrInfo *HII = nullptr;
56 
57  unsigned genElemLoad(MachineInstr *ExtI, unsigned BaseR,
59  };
60 
61  char HexagonVExtract::ID = 0;
62 }
63 
64 INITIALIZE_PASS(HexagonVExtract, "hexagon-vextract",
65  "Hexagon optimize vextract", false, false)
66 
67 unsigned HexagonVExtract::genElemLoad(MachineInstr *ExtI, unsigned BaseR,
69  MachineBasicBlock &ExtB = *ExtI->getParent();
70  DebugLoc DL = ExtI->getDebugLoc();
71  Register ElemR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
72 
73  Register ExtIdxR = ExtI->getOperand(2).getReg();
74  unsigned ExtIdxS = ExtI->getOperand(2).getSubReg();
75 
76  // Simplified check for a compile-time constant value of ExtIdxR.
77  if (ExtIdxS == 0) {
78  MachineInstr *DI = MRI.getVRegDef(ExtIdxR);
79  if (DI->getOpcode() == Hexagon::A2_tfrsi) {
80  unsigned V = DI->getOperand(1).getImm();
81  V &= (HST->getVectorLength()-1) & -4u;
82 
83  BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L2_loadri_io), ElemR)
84  .addReg(BaseR)
85  .addImm(V);
86  return ElemR;
87  }
88  }
89 
90  Register IdxR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
91  BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::A2_andir), IdxR)
92  .add(ExtI->getOperand(2))
93  .addImm(-4);
94  BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L4_loadri_rr), ElemR)
95  .addReg(BaseR)
96  .addReg(IdxR)
97  .addImm(0);
98  return ElemR;
99 }
100 
101 bool HexagonVExtract::runOnMachineFunction(MachineFunction &MF) {
102  HST = &MF.getSubtarget<HexagonSubtarget>();
103  HII = HST->getInstrInfo();
104  const auto &HRI = *HST->getRegisterInfo();
106  MachineFrameInfo &MFI = MF.getFrameInfo();
107  Register AR =
108  MF.getInfo<HexagonMachineFunctionInfo>()->getStackAlignBaseVReg();
109  std::map<unsigned, SmallVector<MachineInstr*,4>> VExtractMap;
110  MaybeAlign MaxAlign;
111  bool Changed = false;
112 
113  for (MachineBasicBlock &MBB : MF) {
114  for (MachineInstr &MI : MBB) {
115  unsigned Opc = MI.getOpcode();
116  if (Opc != Hexagon::V6_extractw)
117  continue;
118  Register VecR = MI.getOperand(1).getReg();
119  VExtractMap[VecR].push_back(&MI);
120  }
121  }
122 
123  auto EmitAddr = [&] (MachineBasicBlock &BB, MachineBasicBlock::iterator At,
124  DebugLoc dl, int FI, unsigned Offset) {
125  Register AddrR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
126  unsigned FiOpc = AR != 0 ? Hexagon::PS_fia : Hexagon::PS_fi;
127  auto MIB = BuildMI(BB, At, dl, HII->get(FiOpc), AddrR);
128  if (AR)
129  MIB.addReg(AR);
130  MIB.addFrameIndex(FI).addImm(Offset);
131  return AddrR;
132  };
133 
134  for (auto &P : VExtractMap) {
135  unsigned VecR = P.first;
136  if (P.second.size() <= VExtractThreshold)
137  continue;
138 
139  const auto &VecRC = *MRI.getRegClass(VecR);
140  Align Alignment = HRI.getSpillAlign(VecRC);
141  MaxAlign = max(MaxAlign, Alignment);
142  // Make sure this is not a spill slot: spill slots cannot be aligned
143  // if there are variable-sized objects on the stack. They must be
144  // accessible via FP (which is not aligned), because SP is unknown,
145  // and AP may not be available at the location of the load/store.
146  int FI = MFI.CreateStackObject(HRI.getSpillSize(VecRC), Alignment,
147  /*isSpillSlot*/ false);
148 
149  MachineInstr *DefI = MRI.getVRegDef(VecR);
150  MachineBasicBlock::iterator At = std::next(DefI->getIterator());
151  MachineBasicBlock &DefB = *DefI->getParent();
152  unsigned StoreOpc = VecRC.getID() == Hexagon::HvxVRRegClassID
153  ? Hexagon::V6_vS32b_ai
154  : Hexagon::PS_vstorerw_ai;
155  Register AddrR = EmitAddr(DefB, At, DefI->getDebugLoc(), FI, 0);
156  BuildMI(DefB, At, DefI->getDebugLoc(), HII->get(StoreOpc))
157  .addReg(AddrR)
158  .addImm(0)
159  .addReg(VecR);
160 
161  unsigned VecSize = HRI.getRegSizeInBits(VecRC) / 8;
162 
163  for (MachineInstr *ExtI : P.second) {
164  assert(ExtI->getOpcode() == Hexagon::V6_extractw);
165  unsigned SR = ExtI->getOperand(1).getSubReg();
166  assert(ExtI->getOperand(1).getReg() == VecR);
167 
168  MachineBasicBlock &ExtB = *ExtI->getParent();
169  DebugLoc DL = ExtI->getDebugLoc();
170  Register BaseR = EmitAddr(ExtB, ExtI, ExtI->getDebugLoc(), FI,
171  SR == 0 ? 0 : VecSize/2);
172 
173  unsigned ElemR = genElemLoad(ExtI, BaseR, MRI);
174  Register ExtR = ExtI->getOperand(0).getReg();
175  MRI.replaceRegWith(ExtR, ElemR);
176  ExtB.erase(ExtI);
177  Changed = true;
178  }
179  }
180 
181  if (AR && MaxAlign) {
182  // Update the required stack alignment.
183  MachineInstr *AlignaI = MRI.getVRegDef(AR);
184  assert(AlignaI->getOpcode() == Hexagon::PS_aligna);
185  MachineOperand &Op = AlignaI->getOperand(1);
186  if (*MaxAlign > Op.getImm())
187  Op.setImm(MaxAlign->value());
188  }
189 
190  return Changed;
191 }
192 
194  return new HexagonVExtract();
195 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:409
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition: Registry.h:44
unsigned getSubReg() const
Hexagon target-specific information for each MachineFunction.
A debug info location.
Definition: DebugLoc.h:33
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
MachineBasicBlock & MBB
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:456
static cl::opt< unsigned > VExtractThreshold("hexagon-vextract-threshold", cl::Hidden, cl::ZeroOrMore, cl::init(1), cl::desc("Threshold for triggering vextract replacement"))
INITIALIZE_PASS(HexagonVExtract, "hexagon-vextract", "Hexagon optimize vextract", false, false) unsigned HexagonVExtract
void initializeHexagonVExtractPass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
Definition: Metadata.h:1172
#define P(N)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:434
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
self_iterator getIterator()
Definition: ilist_node.h:81
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
const MachineInstrBuilder & addFrameIndex(int Idx) const
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:350
This struct is a compact representation of a valid (power of two) or undefined (0) alignment...
Definition: Alignment.h:119
MachineOperand class - Representation of each machine instruction operand.
FunctionPass * createHexagonVExtract()
int64_t getImm() const
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:280
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:62
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it...
const HexagonInstrInfo * getInstrInfo() const override
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:466
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL