1 //===- HexagonVExtract.cpp ------------------------------------------------===//
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
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 //===----------------------------------------------------------------------===//
13 #include "HexagonInstrInfo.h"
14 #include "HexagonRegisterInfo.h"
15 #include "HexagonSubtarget.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/PassSupport.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/Support/CommandLine.h"
29 static cl::opt
<unsigned> VExtractThreshold("hexagon-vextract-threshold",
30 cl::Hidden
, cl::ZeroOrMore
, cl::init(1),
31 cl::desc("Threshold for triggering vextract replacement"));
34 void initializeHexagonVExtractPass(PassRegistry
& Registry
);
35 FunctionPass
*createHexagonVExtract();
39 class HexagonVExtract
: public MachineFunctionPass
{
42 HexagonVExtract() : MachineFunctionPass(ID
) {}
44 StringRef
getPassName() const override
{
45 return "Hexagon optimize vextract";
47 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
48 MachineFunctionPass::getAnalysisUsage(AU
);
50 bool runOnMachineFunction(MachineFunction
&MF
) override
;
53 const HexagonSubtarget
*HST
= nullptr;
54 const HexagonInstrInfo
*HII
= nullptr;
56 unsigned genElemLoad(MachineInstr
*ExtI
, unsigned BaseR
,
57 MachineRegisterInfo
&MRI
);
60 char HexagonVExtract::ID
= 0;
63 INITIALIZE_PASS(HexagonVExtract
, "hexagon-vextract",
64 "Hexagon optimize vextract", false, false)
66 unsigned HexagonVExtract::genElemLoad(MachineInstr
*ExtI
, unsigned BaseR
,
67 MachineRegisterInfo
&MRI
) {
68 MachineBasicBlock
&ExtB
= *ExtI
->getParent();
69 DebugLoc DL
= ExtI
->getDebugLoc();
70 Register ElemR
= MRI
.createVirtualRegister(&Hexagon::IntRegsRegClass
);
72 Register ExtIdxR
= ExtI
->getOperand(2).getReg();
73 unsigned ExtIdxS
= ExtI
->getOperand(2).getSubReg();
75 // Simplified check for a compile-time constant value of ExtIdxR.
77 MachineInstr
*DI
= MRI
.getVRegDef(ExtIdxR
);
78 if (DI
->getOpcode() == Hexagon::A2_tfrsi
) {
79 unsigned V
= DI
->getOperand(1).getImm();
80 V
&= (HST
->getVectorLength()-1) & -4u;
82 BuildMI(ExtB
, ExtI
, DL
, HII
->get(Hexagon::L2_loadri_io
), ElemR
)
89 Register IdxR
= MRI
.createVirtualRegister(&Hexagon::IntRegsRegClass
);
90 BuildMI(ExtB
, ExtI
, DL
, HII
->get(Hexagon::A2_andir
), IdxR
)
91 .add(ExtI
->getOperand(2))
93 BuildMI(ExtB
, ExtI
, DL
, HII
->get(Hexagon::L4_loadri_rr
), ElemR
)
100 bool HexagonVExtract::runOnMachineFunction(MachineFunction
&MF
) {
101 HST
= &MF
.getSubtarget
<HexagonSubtarget
>();
102 HII
= HST
->getInstrInfo();
103 const auto &HRI
= *HST
->getRegisterInfo();
104 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
105 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
106 std::map
<unsigned, SmallVector
<MachineInstr
*,4>> VExtractMap
;
107 bool Changed
= false;
109 for (MachineBasicBlock
&MBB
: MF
) {
110 for (MachineInstr
&MI
: MBB
) {
111 unsigned Opc
= MI
.getOpcode();
112 if (Opc
!= Hexagon::V6_extractw
)
114 Register VecR
= MI
.getOperand(1).getReg();
115 VExtractMap
[VecR
].push_back(&MI
);
119 for (auto &P
: VExtractMap
) {
120 unsigned VecR
= P
.first
;
121 if (P
.second
.size() <= VExtractThreshold
)
124 const auto &VecRC
= *MRI
.getRegClass(VecR
);
125 int FI
= MFI
.CreateSpillStackObject(HRI
.getSpillSize(VecRC
),
126 HRI
.getSpillAlignment(VecRC
));
127 MachineInstr
*DefI
= MRI
.getVRegDef(VecR
);
128 MachineBasicBlock::iterator At
= std::next(DefI
->getIterator());
129 MachineBasicBlock
&DefB
= *DefI
->getParent();
130 unsigned StoreOpc
= VecRC
.getID() == Hexagon::HvxVRRegClassID
131 ? Hexagon::V6_vS32b_ai
132 : Hexagon::PS_vstorerw_ai
;
133 BuildMI(DefB
, At
, DefI
->getDebugLoc(), HII
->get(StoreOpc
))
138 unsigned VecSize
= HRI
.getRegSizeInBits(VecRC
) / 8;
140 for (MachineInstr
*ExtI
: P
.second
) {
141 assert(ExtI
->getOpcode() == Hexagon::V6_extractw
);
142 unsigned SR
= ExtI
->getOperand(1).getSubReg();
143 assert(ExtI
->getOperand(1).getReg() == VecR
);
145 MachineBasicBlock
&ExtB
= *ExtI
->getParent();
146 DebugLoc DL
= ExtI
->getDebugLoc();
147 Register BaseR
= MRI
.createVirtualRegister(&Hexagon::IntRegsRegClass
);
148 BuildMI(ExtB
, ExtI
, DL
, HII
->get(Hexagon::PS_fi
), BaseR
)
150 .addImm(SR
== 0 ? 0 : VecSize
/2);
152 unsigned ElemR
= genElemLoad(ExtI
, BaseR
, MRI
);
153 Register ExtR
= ExtI
->getOperand(0).getReg();
154 MRI
.replaceRegWith(ExtR
, ElemR
);
163 FunctionPass
*llvm::createHexagonVExtract() {
164 return new HexagonVExtract();