OpenASIP 2.2
Loading...
Searching...
No Matches
LLVMTCERISCVIntrinsicsLowering.cc
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 Tampere University.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18/**
19 * @file LLVMTCERISCVIntrinsicsLowering.cc
20 *
21 * Pass for lowering RISC-V intrinsics
22 *
23 * @author Kari Hepola 2022
24 * @note rating: red
25 */
26
27#include "CompilerWarnings.hh"
28
29IGNORE_COMPILER_WARNING("-Wunused-parameter")
30
31#include <llvm/CodeGen/MachineFunction.h>
32#include "tce_config.h"
33#include <llvm/IR/Function.h>
34#include <llvm/Support/CommandLine.h>
35#include <llvm/Analysis/AliasAnalysis.h>
36
37#include <iostream>
38
40#include "Application.hh"
41#include "InterPassData.hh"
43#include "OperationPool.hh"
44#include "BEMGenerator.hh"
45#include "Exception.hh"
46
47#include "tce_config.h"
48
49#include "RISCVFields.hh"
50
51
53
54namespace llvm {
55
57
59 : MachineFunctionPass(ID) {
60 auto* option = static_cast<llvm::cl::opt<std::string>*>(
61 llvm::cl::getRegisteredOptions().lookup("adf"));
62 const std::string adf = option->getValue();
63 try {
65 } catch (const Exception& e) {
67 << "TCE: unable to load the ADF:" << std::endl
68 << e.errorMessage() << std::endl
69 << "Make sure you give the"
70 << " correct adf with the -adf switch to llc";
71 }
72 bem_ = BEMGenerator(*mach_).generate();
74}
75
76bool
78 return false;
79}
80
83 InstructionFormat* format = NULL;
84 for (int f = 0; f < bem_->instructionFormatCount(); f++) {
86 format = &bem_->instructionFormat(f);
87 break;
88 }
89 }
90 if (format == NULL) {
91 std::string msg = "BEM does not identify R format ";
92 throw InvalidData(__FILE__, __LINE__, __func__, msg);
93 }
94 return format;
95}
96
97std::string
98LLVMTCERISCVIntrinsicsLowering::findRegs(const std::string& s) const {
99 std::vector<TCEString> asmSubStrings = StringTools::chopString(s, " ");
100 std::string regs = "";
101 int foundRegs = 0;
102 for (TCEString i : asmSubStrings) {
103 std::string ss = static_cast<std::string>(i);
104 if (StringTools::containsChar(ss, '$')) {
105 regs += " " + ss;
106 foundRegs++;
107 }
108 }
109 if (foundRegs != 3) {
110 std::string msg =
111 "Invalid amount of register operands, 3 required, found " +
112 std::to_string(foundRegs);
113 throw InvalidData(__FILE__, __LINE__, __func__, msg);
114 }
115 return regs;
116}
117
118std::string
120 const std::string& s) const {
121 std::vector<TCEString> asmSubStrings = StringTools::chopString(s, " ");
122 std::string opName = "";
123 for (TCEString i : asmSubStrings) {
124 std::string ss = static_cast<std::string>(i);
125 if (StringTools::containsChar(ss, '/')) {
126 ss = StringTools::replaceAllOccurrences(ss, "//", "");
128 if (rFormat_->hasOperation(ss)) {
129 opName = ss;
130 } else {
131 std::string msg = "Machine does not have operation: " + ss;
132 throw InvalidData(__FILE__, __LINE__, __func__, msg);
133 }
134 }
135 }
136 if (opName == "") {
137 const std::string msg =
138 "Warning: Failed to find operation name from: \"" + s + "\"";
139 std::cerr << msg << std::endl;
140 //std::string msg = "Failed to find operation name from: " + s;
141 //throw InvalidData(__FILE__, __LINE__, __func__, msg);
142 }
143 return opName;
144}
145
146std::vector<int>
148 const MachineBasicBlock::iterator& it) const {
149 const unsigned OpIdx = 0;
150 std::vector<int> regIdxs;
151 const std::string asmString =
152 std::string(it->getOperand(OpIdx).getSymbolName());
153 for (unsigned o = 0; o < it->getNumOperands(); o++) {
154 const MachineOperand& mo = it->getOperand(o);
155 if (mo.isReg()) {
156 // TODO: Fix this virtual to physical reg mapping
157#ifdef LLVM_OLDER_THAN_17
158 const int magicNumber = 40;
159#else
160 const int magicNumber = 41;
161#endif
162 int idx = mo.getReg() - magicNumber;
163 regIdxs.push_back(idx);
164 if (idx < 0 && idx > 31) {
165 std::string msg =
166 "Invalid register index: " + std::to_string(idx) +
167 " in instruction: " + asmString;
168 throw InvalidData(__FILE__, __LINE__, __func__, msg);
169 };
170 }
171 }
172 if (regIdxs.size() != 3) {
173 std::string msg = "3 reg operands required, found " +
174 std::to_string(regIdxs.size()) +
175 " in instruction: " + asmString;
176 throw InvalidData(__FILE__, __LINE__, __func__, msg);
177 }
178 return regIdxs;
179}
180
181int
183 const std::string& opName, const std::vector<int>& regIdxs) const {
184 const int fu3Mask = 0b1110000000;
185 const int fu7Mask = 0b11111110000000000;
186 const int opcodeMask = 0b1111111;
187 int encoding = rFormat_->encoding(opName);
188 const int fu3Enc = ((encoding & fu3Mask) >> 7);
189 const int fu7Enc = ((encoding & fu7Mask) >> 10);
190 const int opcodeEnc = encoding & opcodeMask;
191 const int shiftedEnc = (fu7Enc << 25) + (fu3Enc << 12) + opcodeEnc;
192
193 encoding = shiftedEnc + (regIdxs.at(0) << 7) + (regIdxs.at(1) << 15) +
194 (regIdxs.at(2) << 20);
195
196 return encoding;
197}
198
199bool
201 for (MachineFunction::iterator i = MF.begin(); i != MF.end(); i++) {
202 for (MachineBasicBlock::iterator j = i->begin(); j != i->end(); j++) {
203 if (j->isInlineAsm()) {
204 const unsigned OpIdx = 0;
205 std::string asmString =
206 std::string(j->getOperand(OpIdx).getSymbolName());
207 const std::string opName = findOperationName(asmString);
208 if (opName == "") {
209 continue;
210 }
211 const std::string regs = findRegs(asmString);
212 const std::vector<int> regIdxs = findRegIndexes(j);
213
214 int encoding = constructEncoding(opName, regIdxs);
215 std::string* cName = new std::string(
216 ".long " + std::to_string(encoding) + "; #" + opName +
217 regs);
218 j->getOperand(OpIdx).ChangeToES(
219 cName->c_str(), j->getOperand(OpIdx).getTargetFlags());
220 }
221 }
222 }
223 return false;
224}
225
226FunctionPass*
227createRISCVIntrinsicsPass(const char* /*target*/) {
229}
230
231} // namespace llvm
#define __func__
#define IGNORE_COMPILER_WARNING(X)
#define POP_COMPILER_DIAGS
static std::ostream & logStream()
BinaryEncoding * generate()
int instructionFormatCount() const
InstructionFormat & instructionFormat(int index) const
std::string errorMessage() const
Definition Exception.cc:123
bool hasOperation(const std::string &op) const
int encoding(const std::string &op) const
std::string name() const
static bool containsChar(const std::string &source, char ch, bool caseSensitive=true)
static std::string stringToLower(const std::string &source)
static std::vector< TCEString > chopString(const std::string &source, const std::string &delimiters)
static std::string replaceAllOccurrences(const std::string &source, const std::string &occurrence, const std::string &newString)
static Machine * loadFromADF(const std::string &adfFileName)
Definition Machine.cc:899
std::string findRegs(const std::string &s) const
std::string findOperationName(const std::string &s) const
std::vector< int > findRegIndexes(const MachineBasicBlock::iterator &it) const
int constructEncoding(const std::string &opName, const std::vector< int > &regIdxs) const
virtual bool runOnMachineFunction(MachineFunction &MF)
const std::string RISCV_R_TYPE_NAME
FunctionPass * createRISCVIntrinsicsPass(const char *)