1 //===- HexagonVectorPrint.cpp - Generate vector printing instructions -----===//
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 //===----------------------------------------------------------------------===//
9 // This pass adds the capability to generate pseudo vector/predicate register
10 // printing instructions. These pseudo instructions should be used with the
11 // simulator, NEVER on hardware.
13 //===----------------------------------------------------------------------===//
15 #include "HexagonInstrInfo.h"
16 #include "HexagonSubtarget.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/TargetOpcodes.h"
25 #include "llvm/IR/DebugLoc.h"
26 #include "llvm/IR/InlineAsm.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
37 #define DEBUG_TYPE "hexagon-vector-print"
39 static cl::opt
<bool> TraceHexVectorStoresOnly("trace-hex-vector-stores-only",
40 cl::Hidden
, cl::ZeroOrMore
, cl::init(false),
41 cl::desc("Enables tracing of vector stores"));
45 FunctionPass
*createHexagonVectorPrint();
46 void initializeHexagonVectorPrintPass(PassRegistry
&);
48 } // end namespace llvm
52 class HexagonVectorPrint
: public MachineFunctionPass
{
53 const HexagonSubtarget
*QST
= nullptr;
54 const HexagonInstrInfo
*QII
= nullptr;
55 const HexagonRegisterInfo
*QRI
= nullptr;
60 HexagonVectorPrint() : MachineFunctionPass(ID
) {
61 initializeHexagonVectorPrintPass(*PassRegistry::getPassRegistry());
64 StringRef
getPassName() const override
{ return "Hexagon VectorPrint pass"; }
66 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
69 } // end anonymous namespace
71 char HexagonVectorPrint::ID
= 0;
73 static bool isVecReg(unsigned Reg
) {
74 return (Reg
>= Hexagon::V0
&& Reg
<= Hexagon::V31
)
75 || (Reg
>= Hexagon::W0
&& Reg
<= Hexagon::W15
)
76 || (Reg
>= Hexagon::Q0
&& Reg
<= Hexagon::Q3
);
79 static std::string
getStringReg(unsigned R
) {
80 if (R
>= Hexagon::V0
&& R
<= Hexagon::V31
) {
81 static const char* S
[] = { "20", "21", "22", "23", "24", "25", "26", "27",
82 "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
83 "30", "31", "32", "33", "34", "35", "36", "37",
84 "38", "39", "3a", "3b", "3c", "3d", "3e", "3f"};
85 return S
[R
-Hexagon::V0
];
87 if (R
>= Hexagon::Q0
&& R
<= Hexagon::Q3
) {
88 static const char* S
[] = { "00", "01", "02", "03"};
89 return S
[R
-Hexagon::Q0
];
92 llvm_unreachable("valid vreg");
95 static void addAsmInstr(MachineBasicBlock
*MBB
, unsigned Reg
,
96 MachineBasicBlock::instr_iterator I
,
97 const DebugLoc
&DL
, const HexagonInstrInfo
*QII
,
98 MachineFunction
&Fn
) {
99 std::string VDescStr
= ".long 0x1dffe0" + getStringReg(Reg
);
100 const char *cstr
= Fn
.createExternalSymbolName(VDescStr
);
101 unsigned ExtraInfo
= InlineAsm::Extra_HasSideEffects
;
102 BuildMI(*MBB
, I
, DL
, QII
->get(TargetOpcode::INLINEASM
))
103 .addExternalSymbol(cstr
)
107 static bool getInstrVecReg(const MachineInstr
&MI
, unsigned &Reg
) {
108 if (MI
.getNumOperands() < 1) return false;
109 // Vec load or compute.
110 if (MI
.getOperand(0).isReg() && MI
.getOperand(0).isDef()) {
111 Reg
= MI
.getOperand(0).getReg();
113 return !TraceHexVectorStoresOnly
;
116 if (MI
.mayStore() && MI
.getNumOperands() >= 3 && MI
.getOperand(2).isReg()) {
117 Reg
= MI
.getOperand(2).getReg();
121 // Vec store post increment.
122 if (MI
.mayStore() && MI
.getNumOperands() >= 4 && MI
.getOperand(3).isReg()) {
123 Reg
= MI
.getOperand(3).getReg();
130 bool HexagonVectorPrint::runOnMachineFunction(MachineFunction
&Fn
) {
131 bool Changed
= false;
132 QST
= &Fn
.getSubtarget
<HexagonSubtarget
>();
133 QRI
= QST
->getRegisterInfo();
134 QII
= QST
->getInstrInfo();
135 std::vector
<MachineInstr
*> VecPrintList
;
137 for (auto &MI
: MBB
) {
139 MachineBasicBlock::instr_iterator MII
= MI
.getIterator();
140 for (++MII
; MII
!= MBB
.instr_end() && MII
->isInsideBundle(); ++MII
) {
141 if (MII
->getNumOperands() < 1)
144 if (getInstrVecReg(*MII
, Reg
)) {
145 VecPrintList
.push_back((&*MII
));
146 LLVM_DEBUG(dbgs() << "Found vector reg inside bundle \n";
152 if (getInstrVecReg(MI
, Reg
)) {
153 VecPrintList
.push_back(&MI
);
154 LLVM_DEBUG(dbgs() << "Found vector reg \n"; MI
.dump());
159 Changed
= !VecPrintList
.empty();
163 for (auto *I
: VecPrintList
) {
164 DebugLoc DL
= I
->getDebugLoc();
165 MachineBasicBlock
*MBB
= I
->getParent();
166 LLVM_DEBUG(dbgs() << "Evaluating V MI\n"; I
->dump());
168 if (!getInstrVecReg(*I
, Reg
))
169 llvm_unreachable("Need a vector reg");
170 MachineBasicBlock::instr_iterator MII
= I
->getIterator();
171 if (I
->isInsideBundle()) {
172 LLVM_DEBUG(dbgs() << "add to end of bundle\n"; I
->dump());
173 while (MBB
->instr_end() != MII
&& MII
->isInsideBundle())
176 LLVM_DEBUG(dbgs() << "add after instruction\n"; I
->dump());
179 if (MBB
->instr_end() == MII
)
182 if (Reg
>= Hexagon::V0
&& Reg
<= Hexagon::V31
) {
183 LLVM_DEBUG(dbgs() << "adding dump for V" << Reg
- Hexagon::V0
<< '\n');
184 addAsmInstr(MBB
, Reg
, MII
, DL
, QII
, Fn
);
185 } else if (Reg
>= Hexagon::W0
&& Reg
<= Hexagon::W15
) {
186 LLVM_DEBUG(dbgs() << "adding dump for W" << Reg
- Hexagon::W0
<< '\n');
187 addAsmInstr(MBB
, Hexagon::V0
+ (Reg
- Hexagon::W0
) * 2 + 1,
189 addAsmInstr(MBB
, Hexagon::V0
+ (Reg
- Hexagon::W0
) * 2,
191 } else if (Reg
>= Hexagon::Q0
&& Reg
<= Hexagon::Q3
) {
192 LLVM_DEBUG(dbgs() << "adding dump for Q" << Reg
- Hexagon::Q0
<< '\n');
193 addAsmInstr(MBB
, Reg
, MII
, DL
, QII
, Fn
);
195 llvm_unreachable("Bad Vector reg");
200 //===----------------------------------------------------------------------===//
201 // Public Constructor Functions
202 //===----------------------------------------------------------------------===//
203 INITIALIZE_PASS(HexagonVectorPrint
, "hexagon-vector-print",
204 "Hexagon VectorPrint pass", false, false)
206 FunctionPass
*llvm::createHexagonVectorPrint() {
207 return new HexagonVectorPrint();