OpenASIP 2.2
Loading...
Searching...
No Matches
TCETargetMachine.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2020 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file TCETargeMachine.cpp
26 *
27 * Declaration of TCETargetMachine class.
28 *
29 * @author Veli-Pekka Jääskeläinen 2007 (vjaaskel-no.spam-cs.tut.fi)
30 * @author Mikael Lepistö 2009 (mikael.lepisto-no.spam—tut.fi)
31 * @author Pekka Jääskeläinen 2007-2015
32 */
33
34#include "CompilerWarnings.hh"
35
36IGNORE_COMPILER_WARNING("-Wunused-parameter")
37
38#include "tce_config.h"
39
40#include "llvm/IR/PassManager.h"
41#include "llvm/CodeGen/TargetRegisterInfo.h"
42#include "llvm/CodeGen/SelectionDAGNodes.h"
43#include "llvm/MC/MCContext.h"
44#include "llvm/MC/MCStreamer.h"
45#include "llvm/MC/MCInstPrinter.h"
46#include "llvm/CodeGen/MachineModuleInfo.h"
47#include "llvm/ADT/APFloat.h"
48
50#include "TCETargetMachine.hh"
51#include "TCEMCAsmInfo.hh"
52#include "LLVMPOMBuilder.hh"
53#include "PluginTools.hh"
54#include "MathTools.hh"
55#include "FileSystem.hh"
56#include "ADFSerializer.hh"
57#include "Conversion.hh"
58#include "MachineInfo.hh"
60#include "Machine.hh"
61#include "ImmediateAnalyzer.hh"
62#include "ImmInfo.hh"
63#include <llvm/Transforms/Scalar.h>
64
65
66#include <iostream>
67
69
71
72using namespace llvm;
73
74
76Pass* createLinkBitcodePass(Module& inputCode);
77Pass* createProgramPartitionerPass(std::string partitioningStrategy);
79
80class DummyInstPrinter : public MCInstPrinter {
81public:
83 const llvm::MCAsmInfo& mai, const llvm::MCInstrInfo& mii,
84 const llvm::MCRegisterInfo& mri) : llvm::MCInstPrinter(mai, mii, mri) {}
85
86 bool
87 applyTargetSpecificCLOption(StringRef Opt) override {
88 return false;
89 }
90 std::pair<const char*, uint64_t>
91 getMnemonic(const MCInst* MI) override {
92 return std::make_pair(nullptr, 0);
93 }
94
96 const MCInst*, uint64_t, StringRef,
97 const MCSubtargetInfo&, raw_ostream&) override {}
98
99 void
100 #ifdef LLVM_OLDER_THAN_16
101 printRegName(raw_ostream& OS, unsigned RegNo) const override {}
102 #else
103 printRegName(raw_ostream& OS, MCRegister Reg) const override {}
104 #endif
105};
106
107// In TCE target we don't print the MCInsts from LLVM, but
108// just want to run the codegen passes so we can get the
109// MachineInstrs in to our own finalization phases. LLVM 3.7
110// started to require MCInstPrinter to be created, a dummy
111// must be created therefore.
113 const Triple &,
114 unsigned,
115 const MCAsmInfo &MAI,
116 const MCInstrInfo &MII,
117 const MCRegisterInfo &MRI) {
118 return new DummyInstPrinter(MAI, MII, MRI);
119}
120
121extern "C" void LLVMInitializeTCETarget() {
122 RegisterTargetMachine<TCETargetMachine> Y(TheTCETarget);
123 RegisterTargetMachine<TCETargetMachine> X0(TheTCELE64Target);
124 RegisterTargetMachine<TCETargetMachine> X(TheTCELETarget);
125
126 RegisterMCAsmInfo<TCEMCAsmInfo> Z(TheTCETarget);
127 RegisterMCAsmInfo<TCEMCAsmInfo> V0(TheTCELE64Target);
128 RegisterMCAsmInfo<TCEMCAsmInfo> V(TheTCELETarget);
129 TargetRegistry::RegisterMCInstPrinter(TheTCETarget, dummyInstrPrinterCtor);
130 TargetRegistry::RegisterMCInstPrinter(
132 TargetRegistry::RegisterMCInstPrinter(
134}
135
136//
137// Data layout:
138//--------------
139// E-p:32:32:32-a0:0:64-i1:8:8-i8:8:8-i32:32:32-i64:32:64-f32:32:32-f64:32:64" (old)
140// E-p:32:32:32-a0:0:32-i1:8:8-i8:8:8-i32:32:32-i64:32:32-f32:32:32-f64:32:32" (new)
141// E = Big endian data
142// -p:32:32:32 = Pointer size 32 bits, api & preferred alignment 32 bits.
143// -i8:8:8 = 8bit integer api & preferred alignment 8 bits.
144// a0:0:32 = struct alignment (abi packed?), preferred 32 bits.
145// etc.
146//
147
149 const Target &T, const Triple& TTriple,
150 const llvm::StringRef& CPU, const llvm::StringRef& FS,
151 const TargetOptions &Options,
152 #ifdef LLVM_OLDER_THAN_16
153 Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool) :
154 #else
155 std::optional<Reloc::Model> RM, std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool) :
156 #endif
157 TCEBaseTargetMachine(T, TTriple, CPU, FS, Options,
158 RM?*RM:Reloc::Model::Static, CM?*CM:CodeModel::Small, OL),
159 // Note: Reloc::Model does not have "Default" named member. "Static" is ok?
160 // Note: CodeModel does not have "Default" named member. "Small" is ok?
161 plugin_(NULL), pluginTool_(NULL) {
162}
163
164/**
165 * The Destructor.
166 */
168 if (pluginTool_ != NULL) {
169 delete pluginTool_;
170 pluginTool_ = NULL;
171 }
172}
173
174void
177
178 setTTAMach(&target);
179 plugin_ = &plugin;
180 missingOps_.clear();
181 promotedOps_.clear();
182 MVT::SimpleValueType defType = plugin_->getDefaultType();
183 if (!plugin_->hasSDIV()) missingOps_.insert(std::make_pair(llvm::ISD::SDIV, defType));
184 if (!plugin_->hasUDIV()) missingOps_.insert(std::make_pair(llvm::ISD::UDIV, defType));
185 if (!plugin_->hasSREM()) missingOps_.insert(std::make_pair(llvm::ISD::SREM, defType));
186 if (!plugin_->hasUREM()) missingOps_.insert(std::make_pair(llvm::ISD::UREM, defType));
187 if (!plugin_->hasMUL()) missingOps_.insert(std::make_pair(llvm::ISD::MUL, defType));
188 if (!plugin_->hasROTL()) missingOps_.insert(std::make_pair(llvm::ISD::ROTL, defType));
189 if (!plugin_->hasROTR()) missingOps_.insert(std::make_pair(llvm::ISD::ROTR, defType));
190
191 if (!plugin_->hasSHL()) customLegalizedOps_.insert(std::make_pair(llvm::ISD::SHL, MVT::i32));
192 if (!plugin_->hasSHR()) customLegalizedOps_.insert(std::make_pair(llvm::ISD::SRA, MVT::i32));
193 if (!plugin_->hasSHRU()) customLegalizedOps_.insert(std::make_pair(llvm::ISD::SRL, MVT::i32));
194
195 if (!plugin_->hasSXHW()) missingOps_.insert(
196 std::make_pair(llvm::ISD::SIGN_EXTEND_INREG, MVT::i16));
197
198 if (!plugin_->hasSXQW()) missingOps_.insert(
199 std::make_pair(llvm::ISD::SIGN_EXTEND_INREG, MVT::i8));
200
201 if (!plugin_->hasSQRTF()) {
202 missingOps_.insert(std::make_pair(llvm::ISD::FSQRT, MVT::f32));
203 }
204
205 // register machine to plugin
207
208 initAsmInfo();
209
210 // Set data layout with correct stack alignment.
211 unsigned alignBits = MachineInfo::maxMemoryAlignment(target) * 8;
212 TCEString dataLayoutStr("");
213 if (plugin_->isLittleEndian()) {
214 dataLayoutStr += target.is64bit() ? "e-p:64:64:64" : "e-p:32:32:32";
215 } else {
216 dataLayoutStr += "E-p:32:32:32";
217 }
218 dataLayoutStr += "-a0:0:" + Conversion::toString(alignBits);
219 if (target.is64bit()) {
220 dataLayoutStr += "-i1:8:64";
221 dataLayoutStr += "-i8:8:64";
222 dataLayoutStr += "-i16:16:64";
223 dataLayoutStr += "-i32:32:64";
224 dataLayoutStr += "-i64:64:64";
225 dataLayoutStr += "-f16:16:64";
226 dataLayoutStr += "-f32:32:64";
227 } else {
228 dataLayoutStr += "-i1:8:8";
229 dataLayoutStr += "-i8:8:32";
230 dataLayoutStr += "-i16:16:32";
231 dataLayoutStr += "-i32:32:32";
232 dataLayoutStr += "-i64:64:64";
233 dataLayoutStr += "-f16:16:16";
234 dataLayoutStr += "-f32:32:32";
235 }
236 dataLayoutStr += "-f64:64:64";
237 dataLayoutStr += "-v64:64:64";
238 dataLayoutStr += "-v128:128:128";
239 dataLayoutStr += "-v256:256:256";
240 dataLayoutStr += "-v512:512:512";
241 dataLayoutStr += "-v1024:1024:1024";
242#if LLVM_HAS_CUSTOM_VECTOR_EXTENSION == 2
243 dataLayoutStr += "-v2048:2048:2048";
244 dataLayoutStr += "-v4096:4096:4096";
245#endif
246
247 DataLayout* dl = plugin_->getDataLayout();
248 dl->reset(dataLayoutStr.c_str());
249}
250
251/**
252 * Creates an instruction selector instance.
253 *
254 */
255bool
257{
258 addPass(plugin_->createISelPass(static_cast<TCETargetMachine*>(TM)));
259 return false;
260}
261
262/**
263 * Some extra passes needed by TCE
264 *
265 * @param pm Function pass manager to add isel pass.
266 * @param fast Not used.
267 */
268void
271
272
273bool
277 if (options != NULL && !options->disableHWLoops() &&
278 ((static_cast<TCETargetMachine*>(TM))->ttaMach_)
279 ->hasOperation("hwloop"))
280 #ifdef LLVM_OLDER_THAN_17
281 addPass(createHardwareLoopsPass());
282 #else
283 addPass(createHardwareLoopsLegacyPass());
284 #endif
285
286
287 // lower floating point stuff.. maybe could use plugin as param instead machine...
289 *((static_cast<TCETargetMachine*>(TM))->ttaMach_)));
290
291 if ((static_cast<TCETargetMachine*>(TM))->emulationModule_ != NULL) {
293 *((static_cast<TCETargetMachine*>(TM))->emulationModule_)));
294 }
295
296 CodeGenOpt::Level OptLevel = getOptLevel();
297
298 // NOTE: This must be added before Machine function analysis pass..
299 // needed by POMBuilder to prevent writing debug data to data section
300 // might be good to disable when printing out machine function code...
301 // However, it need to comment out to support debug info
302// PM.add(createStripSymbolsPass(/*bool OnlyDebugInfo=*/true));
303
304 return false;
305}
306
307/**
308 * Creates a TTAMachine::Machine object of the target architecture.
309 */
314
315 assert(options->isMachineFileDefined() && "ADF not defined");
316 assert(options->machineFile() != "" && "ADF not defined");
317 ADFSerializer serializer;
318 serializer.setSourceFile(options->machineFile());
319 return serializer.readMachine();
320}
321
322/**
323 * Returns list of llvm::ISD SelectionDAG opcodes for operations that are not
324 * supported in the target architecture.
325 *
326 * The returned operations have to be expanded to emulation function calls
327 * or emulation patterns in TCETargetLowering.
328 */
329const std::set<std::pair<unsigned, llvm::MVT::SimpleValueType> >*
333
334/**
335 * Returns list of llvm::ISD SelectionDAG opcodes for operations that are not
336 * supported in the target architecture but will be promoted.
337 *
338 * The returned operations have to be promoted to emulation function calls
339 * or emulation patterns in TCETargetLowering.
340 */
341const std::set<std::pair<unsigned, llvm::MVT::SimpleValueType> >*
345
346/**
347 * Returns list of llvm::ISD SelectionDAG opcodes for operations that are not
348 * supported in the target architecture but will be custom-selected.
349 */
350const std::set<std::pair<unsigned, llvm::MVT::SimpleValueType> >*
354
355TargetPassConfig*
357 PassManagerBase &PM) {
358 TCEPassConfig *tpc;
359 tpc = new TCEPassConfig(this, PM, plugin_);
360 // TODO: is this false by default if not set?
361 // false seems to give slightly better performance than true.
362 tpc->setEnableTailMerge(false);
363 return tpc;
364}
365
366/**
367 * Returns true if the value can be encoded as immediate to register.
368 */
369bool
370TCETargetMachine::canEncodeAsMOVI(const llvm::MVT& vt, int64_t val) const {
371 // setTargetMachinePlugin() calls calculateSupportedImmediateLimits.
372 assert(ttaMach_ && "setTargetMachinePlugin() was not called");
373 switch (vt.SimpleTy) {
374 case MVT::i1:
375 return (1 <= largestImm_);
376 case MVT::i8:
377 case MVT::i16:
378 case MVT::i32:
379 case MVT::i64:
380 return smallestImm_ == INT64_MIN || largestImm_ == UINT64_MAX ||
381 ((int64_t)smallestImm_ <= val &&
382 (val < 0 || val <= (int64_t)largestImm_));
383 default: assert(false && "Not implemented or supported.");
384 }
385 return false;
386}
387
388/**
389 * Returns true if the floating point value can be encoded as immediate to
390 * register.
391 */
392bool
393TCETargetMachine::canEncodeAsMOVF(const llvm::APFloat& fp) const {
394 int fpBitWidth = static_cast<int>(
395 llvm::APFloat::getSizeInBits(fp.getSemantics()));
396 return fpBitWidth <= SupportedFPImmWidth_;
397}
398
399void
401 using MCC = MachineConnectivityCheck;
402
403 // FIX ME: All 32 bit regs are assumed to be RF-connected.
404 std::pair<int64_t, uint64_t> moveImm{
405 std::numeric_limits<int64_t>::max(),
406 std::numeric_limits<uint64_t>::min() };
408 for (auto& rf : ttaMach_->registerFileNavigator()) {
409 if (rf->width() != 32) continue;
410
411 for (auto& bus : ttaMach_->busNavigator()) {
412 if (!MCC::busConnectedToRF(*bus, *rf)
413 || bus->immediateWidth() == 0) {
414 continue;
415 }
416
417 if (bus->immediateWidth() >= 32) {
418 moveImm.first = -(1ll << (32-1));
419 moveImm.second = (1ll << 32)-1;
420 break;
421 } else {
422 std::pair<int64_t, uint64_t> imm =
423 MathTools::bitsToIntegerRange<int64_t, uint64_t>(
424 bus->immediateWidth(),
425 bus->signExtends());
426
427 moveImm.first = std::min(moveImm.first, imm.first);
428 moveImm.second = std::max(moveImm.second, imm.second);
429 }
430 }
431 }
432
433 for (auto& iu : ttaMach_->immediateUnitNavigator()) {
434 for (auto& it : ttaMach_->instructionTemplateNavigator()) {
435 int supportedWidth = it->supportedWidth(*iu);
436 if (supportedWidth >= 32) {
437 moveImm.first = -(1ll << (32-1));
438 moveImm.second = (1ll << 32)-1;
439 break;
440 } else {
441 std::pair<int64_t, uint64_t> imm =
442 MathTools::bitsToIntegerRange<int64_t, uint64_t>(
443 supportedWidth, iu->signExtends());
444
445 moveImm.first = std::min(moveImm.first, imm.first);
446 moveImm.second = std::max(moveImm.second, imm.second);
447 }
448 }
449 }
450 smallestImm_ = moveImm.first;
451 largestImm_ = moveImm.second;
452
453 for (auto* rf : ttaMach_->registerFileNavigator()) {
454 if (!MCC::rfConnected(*rf)) continue;
455
456 SupportedFPImmWidth_ = std::max(
459 }
460}
461
462void
464 addPass(&IfConverterID);
465}
466
467int TCETargetMachine::getLoadOpcode(int asid, int align, const llvm::EVT& vt) const {
468 int laneCount = vt.getVectorElementCount().getKnownMinValue();
469
470 int laneSize = vt.getScalarSizeInBits();
471 int vecSize = laneCount * laneSize;
472 TCEString relaxedName = "LD"; relaxedName << laneSize << "X" << laneCount;
473 TCEString strictName = "LD"; strictName << vecSize;
474 bool allowStrict = vecSize <= align;
475
476 auto fuNav = ttaMach_->functionUnitNavigator();
477 bool found = false;
478 for (int i = 0; i < fuNav.count(); i++) {
479 auto fu = fuNav.item(i);
480 if (fu->hasOperation(relaxedName) && fu->hasAddressSpace()) {
481 auto as = fu->addressSpace();
482 if (as->hasNumericalId(asid)) {
483 found = true;
484 break;
485 }
486 }
487 if (allowStrict) {
488 if (fu->hasOperation(strictName) && fu->hasAddressSpace()) {
489 auto as = fu->addressSpace();
490 if (as->hasNumericalId(asid)) {
491 found = true;
492 break;
493 }
494 }
495 }
496 }
497 return found ? plugin_->getLoadOpcode(vt) : -1;
498}
#define assert(condition)
#define IGNORE_COMPILER_WARNING(X)
#define POP_COMPILER_DIAGS
static llvm::RegisterPass< InnerLoopFinder > X("find-innerloops-test", "Finds inner loops test.", false, true)
#define addPass(P)
Pass * createLinkBitcodePass(Module &input)
Pass * createLowerMissingInstructionsPass(const TTAMachine::Machine &mach)
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
Pass * createLinkBitcodePass(Module &inputCode)
Pass * createLowerMissingInstructionsPass(const TTAMachine::Machine &mach)
Pass * createInstructionPatternAnalyzer()
Pass * createProgramPartitionerPass(std::string partitioningStrategy)
void LLVMInitializeTCETarget()
MCInstPrinter * dummyInstrPrinterCtor(const Triple &, unsigned, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
TTAMachine::Machine * readMachine()
static CmdLineOptions * cmdLineOptions()
static std::string toString(const T &source)
void printRegName(raw_ostream &OS, MCRegister Reg) const override
void printInst(const MCInst *, uint64_t, StringRef, const MCSubtargetInfo &, raw_ostream &) override
bool applyTargetSpecificCLOption(StringRef Opt) override
DummyInstPrinter(const llvm::MCAsmInfo &mai, const llvm::MCInstrInfo &mii, const llvm::MCRegisterInfo &mri)
std::pair< const char *, uint64_t > getMnemonic(const MCInst *MI) override
static int registerImmediateLoadWidth(const TTAMachine::RegisterFile &targetRF, bool allowSignExtension=false)
Definition ImmInfo.cc:326
static int maxMemoryAlignment(const TTAMachine::Machine &mach)
Definition Model.hh:50
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
bool is64bit() const
Definition Machine.hh:260
void setSourceFile(const std::string &fileName)
const TTAMachine::Machine * ttaMach_
TCETargetMachinePlugin * plugin_
virtual void addPreSched2()
virtual bool addInstSelector()
virtual bool addPreISel()
virtual void addPreRegAlloc()
virtual bool hasUREM() const =0
virtual bool hasUDIV() const =0
virtual bool hasSDIV() const =0
virtual bool hasSHR() const =0
virtual bool hasSQRTF() const =0
virtual MVT::SimpleValueType getDefaultType() const =0
virtual void registerTargetMachine(TCETargetMachine &tm)=0
Plugin needs target machine for TragetLowering generation.
virtual const DataLayout * getDataLayout() const
virtual bool hasROTL() const =0
virtual bool hasSHRU() const =0
virtual bool hasSHL() const =0
virtual FunctionPass * createISelPass(TCETargetMachine *tm)=0
virtual bool hasSREM() const =0
virtual bool hasSXHW() const =0
virtual bool isLittleEndian() const =0
virtual bool hasROTR() const =0
virtual int getLoadOpcode(const llvm::EVT &vt) const =0
virtual bool hasSXQW() const =0
virtual bool hasMUL() const =0
const std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > * customLegalizedOperations()
const std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > * missingOperations()
virtual void setTTAMach(const TTAMachine::Machine *mach) override
TCETargetMachine(const Target &T, const Triple &TTriple, const llvm::StringRef &CPU, const llvm::StringRef &FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOpt::Level OL, bool isLittle)
virtual TargetPassConfig * createPassConfig(PassManagerBase &PM) override
TTAMachine::Machine * createMachine()
bool canEncodeAsMOVI(const llvm::MVT &vt, int64_t val) const
int getLoadOpcode(int asid, int align, const llvm::EVT &vt) const
std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > promotedOps_
bool canEncodeAsMOVF(const llvm::APFloat &fp) const
virtual void setTargetMachinePlugin(TCETargetMachinePlugin &plugin, TTAMachine::Machine &target)
std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > customLegalizedOps_
TCETargetMachinePlugin * plugin_
std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > missingOps_
llvm::ISD opcode list of operations that have to be expanded.
const std::set< std::pair< unsigned, llvm::MVT::SimpleValueType > > * promotedOperations()
Target TheTCETarget
Target TheTCELETarget
Target TheTCELE64Target