OpenASIP 2.2
Loading...
Searching...
No Matches
TCERegisterInfo.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 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 TCERegisterInfo.cpp
26 *
27 * Implementation of TCERegisterInfo 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 Heikki Kultala 2011-2016 (heikki.kultala-no.spam-tut.fi)
32 */
33
34#include <assert.h>
35#include "tce_config.h"
36#include <llvm/IR/Type.h>
37#include <llvm/IR/Function.h>
38#include <llvm/CodeGen/MachineInstrBuilder.h>
39#include <llvm/CodeGen/MachineFrameInfo.h>
40#include <llvm/CodeGen/TargetInstrInfo.h>
41#include <llvm/Target/TargetOptions.h>
42
43#include <llvm/ADT/STLExtras.h>
44#include <llvm/CodeGen/RegisterScavenging.h>
45
46#include "TCEPlugin.hh"
47#include "TCERegisterInfo.hh"
48#include "TCETargetMachine.hh"
49#include "TCEInstrInfo.hh"
50#include "TCEString.hh"
51#include "Application.hh"
52#include "tce_config.h"
54#include "Exception.hh"
55
56using namespace llvm;
57
58#define GET_REGINFO_MC_DESC
59#define GET_REGINFO_TARGET_DESC
60
61#include "TCEFrameInfo.hh"
62#include "TCEGenRegisterInfo.inc"
63#include "ArgRegs.hh"
64
65#ifdef TARGET64BIT
66#define ADDIMM TCE::ADD64ssa
67#define SUBIMM TCE::SUB64ssa
68#define INTEGER_REG_CLASS TCE::R64IRegsRegClass
69#else
70#define ADDIMM TCE::ADDrri
71#define SUBIMM TCE::SUBrri
72#define INTEGER_REG_CLASS TCE::R32IRegsRegClass
73#endif
74
75
76/**
77 * The Constructor.
78 *
79 * @param st Subtarget architecture.
80 * @param tii Target architecture instruction info.
81 */
83 const TargetInstrInfo& tii) :
84 TCEGenRegisterInfo(TCE::RA),
85 tii_(tii) {
86}
87
88/**
89 * Returns list of callee saved registers.
90 */
91const MCPhysReg*
92TCERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
93 static const uint16_t calleeSavedRegs[] = { TCE::FP, 0 };
94 if (hasFP(*MF)) {
95 return calleeSavedRegs+1; // skip first, it's reserved
96 } else {
97 return calleeSavedRegs;
98 }
99}
100
101/**
102 * Returns list of reserved registers.
103 */
105TCERegisterInfo::getReservedRegs(const MachineFunction& mf) const {
106
109
110 assert(&mf != NULL);
111 BitVector reserved(getNumRegs());
112 reserved.set(TCE::SP);
113 reserved.set(TCE::KLUDGE_REGISTER);
114 reserved.set(TCE::RA);
115 const MachineFrameInfo* mfi = &mf.getFrameInfo();
116 if (mfi->hasCalls() && tfi_->containsCall(mf)) {
117 for (int i = 0; i < argRegCount; i++) {
118 reserved.set(ArgRegs[i]);
119 }
120 setReservedVectorRegs(reserved);
121 }
122 if (hasFP(mf)) {
123 reserved.set(TCE::FP);
124 }
125
126 return reserved;
127}
128#ifdef LLVM_OLDER_THAN_16
130#else
132#endif
133 MachineBasicBlock::iterator II, int SPAdj,
134 unsigned FIOperandNum,
135 RegScavenger *RS) const {
136
137 MachineInstr &MI = *II;
138 const TCETargetMachine& tm =
139 dynamic_cast<const TCETargetMachine&>(
140 MI.getParent()->getParent()->getTarget());
141 // Attempt to catch stack accesses using unsupported operation.
142 auto osalOpName = tm.operationName(MI.getOpcode());
143 if (!tm.validStackAccessOperation(osalOpName)
144 && osalOpName.find("MOVE") == std::string::npos) {
146 "Error: Stack address space is not reachable with operation '"
147 + tm.operationName(MI.getOpcode()) + "'.\n"
148 + "Forgot to add the operation to the stack LSU?");
149 }
150 static int lastBypassReg = 0;
151 const TCEInstrInfo &TII = dynamic_cast<const TCEInstrInfo&>(tii_);
152 assert(SPAdj == 0 && "Unexpected");
153
154 DebugLoc dl = MI.getDebugLoc();
155 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
156 // Addressable stack objects are accessed using neg. offsets from %fp
157 // NO THEY ARE NOT! apwards from SP!
158 MachineFunction &MF = *MI.getParent()->getParent();
159
160 auto& frameinfo = MF.getFrameInfo();
161
162 if (frameinfo.isSpillSlotObjectIndex(FrameIndex)) {
163 for (MachineInstr::mmo_iterator i = MI.memoperands_begin();
164 i != MI.memoperands_end(); i++) {
165 const PseudoSourceValue* psv = (*i)->getPseudoValue();
166 if (psv == NULL) {
167 #ifdef LLVM_OLDER_THAN_15
168 (*i)->setValue(new FixedStackPseudoSourceValue(FrameIndex, TII));
169 #else
170 (*i)->setValue(new FixedStackPseudoSourceValue(FrameIndex, tm));
171 #endif
172 }
173 }
174 if (MI.memoperands_begin() == MI.memoperands_end()) {
175 // TODO: operation and size
176 auto flags = static_cast<MachineMemOperand::Flags>(
177 MI.mayLoad() * MachineMemOperand::MOLoad
178 | MI.mayStore() * MachineMemOperand::MOStore);
179 auto mmo = new MachineMemOperand(
180 MachinePointerInfo(), flags, 0, Align(tfi_->stackAlignment()));
181 #ifdef LLVM_OLDER_THAN_15
182 mmo->setValue(new FixedStackPseudoSourceValue(FrameIndex, TII));
183 #else
184 mmo->setValue(new FixedStackPseudoSourceValue(FrameIndex, tm));
185 #endif
186 MI.addMemOperand(MF, mmo);
187 }
188 }
189
190 if (tfi_->hasFP(MF)) {
191 int Offset = frameinfo.getObjectOffset(FrameIndex);
192 int stackAlign = tfi_->stackAlignment();
193 // FP storage space increases offset by stackAlign.
194 Offset+= stackAlign;
195 // RA storage space increases offset of incoming vars
196 if (FrameIndex < 0 && frameinfo.hasCalls()
197 && tfi_->containsCall(MF)) {
198 Offset+= stackAlign;
199 }
200
201 if (Offset != 0) {
202 // try to use a combined add+ld/st operation
203 // (a base+offset load/store), if available
204 // TODO: check that an offset port width is big enough for the
205 // offset immediate.
206
207
208 TCEString baseOffsetOp = "";
209 TCEString originalOp = tm.operationName(MI.getOpcode());
210
211 // TODO: are these the same for LE? ALD8 etc.?
212 if (originalOp == "LDW" || originalOp == "LDHU" ||
213 originalOp == "LDH" || originalOp == "LDQU" ||
214 originalOp == "LDQ" || originalOp == "STW" ||
215 originalOp == "STH" || originalOp == "STQ" ||
216 originalOp == "LD32" || originalOp == "LDU16" ||
217 originalOp == "LD16" || originalOp == "LDU8" ||
218 originalOp == "LD8" || originalOp == "ST32" ||
219 originalOp == "ST16" || originalOp == "ST8") {
220 baseOffsetOp = TCEString("A") + originalOp;
221 }
222 if (baseOffsetOp != "" && tm.hasOperation(baseOffsetOp)) {
223 const bool isStore = MI.getDesc().mayStore();
224 unsigned storeDataReg = 0;
225 uint64_t storeDataImm = 0;
226
227 // the address should be always the 1st operand for the
228 // base memory ops
229 if (isStore) {
230 // operands: FI, 0, DATA
231 int storeDataOp = FIOperandNum + 2;
232 if (MI.getOperand(storeDataOp).isReg()) {
233 storeDataReg = MI.getOperand(storeDataOp).getReg();
234 } else {
235 assert(MI.getOperand(storeDataOp).isImm());
236 storeDataImm = MI.getOperand(storeDataOp).getImm();
237 }
238 }
239
240 MI.setDesc(TII.get(tm.opcode(baseOffsetOp)));
241 // now it should be safe to overwrite the 2nd operand
242 // with the stack offset
243 MI.getOperand(FIOperandNum).ChangeToRegister(TCE::FP, false);
244 MI.getOperand(FIOperandNum + 1).setImm(Offset);
245
246 if (isStore) {
247 // need to fix the 3rd input operand (the written data)
248 // for stores
249 if (storeDataReg) {
250 MI.getOperand(FIOperandNum + 2).ChangeToRegister(
251 storeDataReg, false);
252 } else {
253 MI.getOperand(FIOperandNum + 2).ChangeToImmediate(
254 storeDataImm);
255 }
256 }
257 } else { // FP, no base+offset ops
258 MI.getOperand(FIOperandNum).ChangeToRegister(
259 TCE::KLUDGE_REGISTER, false, false, true/*iskill*/);
260 //TODO clean up
261 if (Offset > 0) {
262 BuildMI(
263 *MI.getParent(), II, MI.getDebugLoc(),
264 TII.get(ADDIMM), TCE::KLUDGE_REGISTER)
265 .addReg(TCE::FP).addImm(Offset);
266 } else {
267 auto spOpcAndOffset = TII.getPointerAdjustment(Offset);
268 BuildMI(
269 *MI.getParent(), II, MI.getDebugLoc(),
270 TII.get(std::get<0>(spOpcAndOffset)),
271 TCE::KLUDGE_REGISTER)
272 .addReg(TCE::FP)
273 .addImm(std::get<1>(spOpcAndOffset));
274 }
275 }
276 } else { // FP, offset 0
277 MI.getOperand(FIOperandNum).ChangeToRegister(TCE::FP, false);
278 }
279 } else { // no FP
280 int Offset = frameinfo.getObjectOffset(FrameIndex) +
281 frameinfo.getStackSize();
282
283 if (Offset == 0) {
284 MI.getOperand(FIOperandNum).ChangeToRegister(TCE::SP, false);
285 #ifdef LLVM_OLDER_THAN_16
286 return;
287 #else
288 return false;
289 #endif
290 }
291
292 // try to use a combined add+ld/st operation (a base+offset load/store),
293 // if available
294 // TODO: check that an offset port width is big enough for the offset
295 // immediate
296 const TCETargetMachine& tm =
297 dynamic_cast<const TCETargetMachine&>(
298 MI.getParent()->getParent()->getTarget());
299
300
301 TCEString baseOffsetOp = "";
302 TCEString originalOp = tm.operationName(MI.getOpcode());
303
304 // TODO: are these the same for LE? ALD8 etc.?
305 if (originalOp == "LDW" || originalOp == "LDHU" ||
306 originalOp == "LDH" || originalOp == "LDQU" ||
307 originalOp == "LDQ" || originalOp == "STW" ||
308 originalOp == "STH" || originalOp == "STQ" ||
309 originalOp == "LD32" || originalOp == "LDU16" ||
310 originalOp == "LD16" || originalOp == "LDU8" ||
311 originalOp == "LD8" || originalOp == "ST32" ||
312 originalOp == "ST16" || originalOp == "ST8") {
313 baseOffsetOp = TCEString("A") + originalOp;
314 }
315 if (baseOffsetOp != "" && tm.hasOperation(baseOffsetOp)) {
316 const bool isStore = MI.getDesc().mayStore();
317 unsigned storeDataReg = 0;
318 uint64_t storeDataImm = 0;
319
320 // the address should be always the 1st operand for the
321 // base memory ops
322 if (isStore) {
323 // operands: FI, 0, DATA
324 int storeDataOp = FIOperandNum + 2;
325 if (MI.getOperand(storeDataOp).isReg()) {
326 storeDataReg = MI.getOperand(storeDataOp).getReg();
327 } else {
328 assert(MI.getOperand(storeDataOp).isImm());
329 storeDataImm = MI.getOperand(storeDataOp).getImm();
330 }
331 }
332
333 MI.setDesc(TII.get(tm.opcode(baseOffsetOp)));
334 // now it should be safe to overwrite the 2nd operand
335 // with the stack offset
336 MI.getOperand(FIOperandNum).ChangeToRegister(TCE::SP, false);
337 MI.getOperand(FIOperandNum + 1).setImm(Offset);
338
339 if (isStore) {
340 // need to fix the 3rd input operand (the written data)
341 // for stores
342 if (storeDataReg) {
343 MI.getOperand(FIOperandNum + 2).ChangeToRegister(
344 storeDataReg, false);
345 } else {
346 MI.getOperand(FIOperandNum + 2).ChangeToImmediate(
347 storeDataImm);
348 }
349 }
350 } else {
351 // generate the sp + offset addition before the use
352 unsigned int tmp = 0;
353
355 dynamic_cast<LLVMTCECmdLineOptions*>(
357 if (RS != NULL) {
358 tmp = RS->FindUnusedReg(&INTEGER_REG_CLASS);
359 }
360
361 if (tmp != 0) {
362 MI.getOperand(FIOperandNum).ChangeToRegister(
363 tmp, false, false, true);
364 BuildMI(
365 *MI.getParent(), II, MI.getDebugLoc(), TII.get(ADDIMM),
366 tmp).addReg(TCE::SP).addImm(Offset);
367 } else {
368 MI.getOperand(FIOperandNum).ChangeToRegister(
369 TCE::KLUDGE_REGISTER, false);
370 BuildMI(
371 *MI.getParent(), II, MI.getDebugLoc(), TII.get(ADDIMM),
372 TCE::KLUDGE_REGISTER).addReg(TCE::SP).addImm(Offset);
373 }
374 }
375 }
376 #ifdef LLVM_OLDER_THAN_16
377 return;
378 #else
379 return false;
380 #endif
381}
382
383
384/**
385 * Re-issue the specified 'original' instruction at the specific location
386 * targeting a new destination register.
387 *
388 * @param mbb Machine basic block of the new instruction.
389 * @param i Position of the new instruction in the basic block.
390 * @param destReg New destination register.
391 * @param orig Original instruction.
392
393void
394TCERegisterInfo::reMaterialize(
395 MachineBasicBlock& mbb,
396 MachineBasicBlock::iterator i,
397 unsigned destReg,
398 const MachineInstr* orig) const {
399 assert(false && "It really was used");
400 MachineInstr* mi = mbb.getParent()->CloneMachineInstr(orig);
401 mi->getOperand(0).setReg(destReg);
402 mbb.insert(i, mi);
403}
404*/
405
406/**
407 * Not implemented: When is this method even called?
408 */
409unsigned
411 assert(false && "Remove this assert if this is really called.");
412 return TCE::RA;
413}
414
415Register
416TCERegisterInfo::getFrameRegister(const MachineFunction& mf) const {
417 if (hasFP(mf)) {
418 return TCE::FP;
419 } else {
420 return 0;
421 }
422}
423
424bool
425TCERegisterInfo::hasFP(const MachineFunction &MF) const {
426 return tfi_->hasFP(MF);
427}
428
429bool
430TCERegisterInfo::requiresRegisterScavenging(const MachineFunction&) const {
431 return false;
432}
433
434
#define assert(condition)
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
#define RA()
#define ADDIMM
#define INTEGER_REG_CLASS
static CmdLineOptions * cmdLineOptions()
bool hasFP(const MachineFunction &MF) const override
bool containsCall(const MachineFunction &mf) const
std::tuple< int, int > getPointerAdjustment(int offset) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF=0) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
const TCEFrameLowering * tfi_
void setReservedVectorRegs(llvm::BitVector &reserved) const
bool hasFP(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &mf) const override
TCERegisterInfo(const TargetInstrInfo &tii)
unsigned getRARegister() const
bool requiresRegisterScavenging(const MachineFunction &) const override
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=NULL) const override
std::string operationName(unsigned opc) const
bool validStackAccessOperation(const std::string &opName) const
bool hasOperation(TCEString operationName) const
unsigned opcode(TCEString operationName) const