OpenASIP  2.0
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"
53 #include "LLVMTCECmdLineOptions.hh"
54 #include "Exception.hh"
55 
56 using 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  */
91 const MCPhysReg*
92 TCERegisterInfo::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  */
104 BitVector
105 TCERegisterInfo::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 
130  MachineBasicBlock::iterator II, int SPAdj,
131  unsigned FIOperandNum,
132  RegScavenger *RS) const {
133 
134  MachineInstr &MI = *II;
135  const TCETargetMachine& tm =
136  dynamic_cast<const TCETargetMachine&>(
137  MI.getParent()->getParent()->getTarget());
138  // Attempt to catch stack accesses using unsupported operation.
139  auto osalOpName = tm.operationName(MI.getOpcode());
140  if (!tm.validStackAccessOperation(osalOpName)
141  && osalOpName.find("MOVE") == std::string::npos) {
143  "Error: Stack address space is not reachable with operation '"
144  + tm.operationName(MI.getOpcode()) + "'.\n"
145  + "Forgot to add the operation to the stack LSU?");
146  }
147  static int lastBypassReg = 0;
148  const TCEInstrInfo &TII = dynamic_cast<const TCEInstrInfo&>(tii_);
149  assert(SPAdj == 0 && "Unexpected");
150 
151  DebugLoc dl = MI.getDebugLoc();
152  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
153  // Addressable stack objects are accessed using neg. offsets from %fp
154  // NO THEY ARE NOT! apwards from SP!
155  MachineFunction &MF = *MI.getParent()->getParent();
156 
157  auto& frameinfo = MF.getFrameInfo();
158 
159  if (frameinfo.isSpillSlotObjectIndex(FrameIndex)) {
160  for (MachineInstr::mmo_iterator i = MI.memoperands_begin();
161  i != MI.memoperands_end(); i++) {
162  const PseudoSourceValue* psv = (*i)->getPseudoValue();
163  if (psv == NULL) {
164  #ifdef LLVM_OLDER_THAN_15
165  (*i)->setValue(new FixedStackPseudoSourceValue(FrameIndex, TII));
166  #else
167  (*i)->setValue(new FixedStackPseudoSourceValue(FrameIndex, tm));
168  #endif
169  }
170  }
171  if (MI.memoperands_begin() == MI.memoperands_end()) {
172  // TODO: operation and size
173  auto flags = static_cast<MachineMemOperand::Flags>(
174  MI.mayLoad() * MachineMemOperand::MOLoad
175  | MI.mayStore() * MachineMemOperand::MOStore);
176  auto mmo = new MachineMemOperand(
177  MachinePointerInfo(), flags, 0, Align(tfi_->stackAlignment()));
178  #ifdef LLVM_OLDER_THAN_15
179  mmo->setValue(new FixedStackPseudoSourceValue(FrameIndex, TII));
180  #else
181  mmo->setValue(new FixedStackPseudoSourceValue(FrameIndex, tm));
182  #endif
183  MI.addMemOperand(MF, mmo);
184  }
185  }
186 
187  if (tfi_->hasFP(MF)) {
188  int Offset = frameinfo.getObjectOffset(FrameIndex);
189  int stackAlign = tfi_->stackAlignment();
190  // FP storage space increases offset by stackAlign.
191  Offset+= stackAlign;
192  // RA storage space increases offset of incoming vars
193  if (FrameIndex < 0 && frameinfo.hasCalls()
194  && tfi_->containsCall(MF)) {
195  Offset+= stackAlign;
196  }
197 
198  if (Offset != 0) {
199  // try to use a combined add+ld/st operation
200  // (a base+offset load/store), if available
201  // TODO: check that an offset port width is big enough for the
202  // offset immediate.
203 
204 
205  TCEString baseOffsetOp = "";
206  TCEString originalOp = tm.operationName(MI.getOpcode());
207 
208  // TODO: are these the same for LE? ALD8 etc.?
209  if (originalOp == "LDW" || originalOp == "LDHU" ||
210  originalOp == "LDH" || originalOp == "LDQU" ||
211  originalOp == "LDQ" || originalOp == "STW" ||
212  originalOp == "STH" || originalOp == "STQ" ||
213  originalOp == "LD32" || originalOp == "LDU16" ||
214  originalOp == "LD16" || originalOp == "LDU8" ||
215  originalOp == "LD8" || originalOp == "ST32" ||
216  originalOp == "ST16" || originalOp == "ST8") {
217  baseOffsetOp = TCEString("A") + originalOp;
218  }
219  if (baseOffsetOp != "" && tm.hasOperation(baseOffsetOp)) {
220  const bool isStore = MI.getDesc().mayStore();
221  unsigned storeDataReg = 0;
222  uint64_t storeDataImm = 0;
223 
224  // the address should be always the 1st operand for the
225  // base memory ops
226  if (isStore) {
227  // operands: FI, 0, DATA
228  int storeDataOp = FIOperandNum + 2;
229  if (MI.getOperand(storeDataOp).isReg()) {
230  storeDataReg = MI.getOperand(storeDataOp).getReg();
231  } else {
232  assert(MI.getOperand(storeDataOp).isImm());
233  storeDataImm = MI.getOperand(storeDataOp).getImm();
234  }
235  }
236 
237  MI.setDesc(TII.get(tm.opcode(baseOffsetOp)));
238  // now it should be safe to overwrite the 2nd operand
239  // with the stack offset
240  MI.getOperand(FIOperandNum).ChangeToRegister(TCE::FP, false);
241  MI.getOperand(FIOperandNum + 1).setImm(Offset);
242 
243  if (isStore) {
244  // need to fix the 3rd input operand (the written data)
245  // for stores
246  if (storeDataReg) {
247  MI.getOperand(FIOperandNum + 2).ChangeToRegister(
248  storeDataReg, false);
249  } else {
250  MI.getOperand(FIOperandNum + 2).ChangeToImmediate(
251  storeDataImm);
252  }
253  }
254  } else { // FP, no base+offset ops
255  MI.getOperand(FIOperandNum).ChangeToRegister(
256  TCE::KLUDGE_REGISTER, false, false, true/*iskill*/);
257  //TODO clean up
258  if (Offset > 0) {
259  BuildMI(
260  *MI.getParent(), II, MI.getDebugLoc(),
261  TII.get(ADDIMM), TCE::KLUDGE_REGISTER)
262  .addReg(TCE::FP).addImm(Offset);
263  } else {
264  auto spOpcAndOffset = TII.getPointerAdjustment(Offset);
265  BuildMI(
266  *MI.getParent(), II, MI.getDebugLoc(),
267  TII.get(std::get<0>(spOpcAndOffset)),
268  TCE::KLUDGE_REGISTER)
269  .addReg(TCE::FP)
270  .addImm(std::get<1>(spOpcAndOffset));
271  }
272  }
273  } else { // FP, offset 0
274  MI.getOperand(FIOperandNum).ChangeToRegister(TCE::FP, false);
275  }
276  } else { // no FP
277  int Offset = frameinfo.getObjectOffset(FrameIndex) +
278  frameinfo.getStackSize();
279 
280  if (Offset == 0) {
281  MI.getOperand(FIOperandNum).ChangeToRegister(TCE::SP, false);
282  return;
283  }
284 
285  // try to use a combined add+ld/st operation (a base+offset load/store),
286  // if available
287  // TODO: check that an offset port width is big enough for the offset
288  // immediate
289  const TCETargetMachine& tm =
290  dynamic_cast<const TCETargetMachine&>(
291  MI.getParent()->getParent()->getTarget());
292 
293 
294  TCEString baseOffsetOp = "";
295  TCEString originalOp = tm.operationName(MI.getOpcode());
296 
297  // TODO: are these the same for LE? ALD8 etc.?
298  if (originalOp == "LDW" || originalOp == "LDHU" ||
299  originalOp == "LDH" || originalOp == "LDQU" ||
300  originalOp == "LDQ" || originalOp == "STW" ||
301  originalOp == "STH" || originalOp == "STQ" ||
302  originalOp == "LD32" || originalOp == "LDU16" ||
303  originalOp == "LD16" || originalOp == "LDU8" ||
304  originalOp == "LD8" || originalOp == "ST32" ||
305  originalOp == "ST16" || originalOp == "ST8") {
306  baseOffsetOp = TCEString("A") + originalOp;
307  }
308  if (baseOffsetOp != "" && tm.hasOperation(baseOffsetOp)) {
309  const bool isStore = MI.getDesc().mayStore();
310  unsigned storeDataReg = 0;
311  uint64_t storeDataImm = 0;
312 
313  // the address should be always the 1st operand for the
314  // base memory ops
315  if (isStore) {
316  // operands: FI, 0, DATA
317  int storeDataOp = FIOperandNum + 2;
318  if (MI.getOperand(storeDataOp).isReg()) {
319  storeDataReg = MI.getOperand(storeDataOp).getReg();
320  } else {
321  assert(MI.getOperand(storeDataOp).isImm());
322  storeDataImm = MI.getOperand(storeDataOp).getImm();
323  }
324  }
325 
326  MI.setDesc(TII.get(tm.opcode(baseOffsetOp)));
327  // now it should be safe to overwrite the 2nd operand
328  // with the stack offset
329  MI.getOperand(FIOperandNum).ChangeToRegister(TCE::SP, false);
330  MI.getOperand(FIOperandNum + 1).setImm(Offset);
331 
332  if (isStore) {
333  // need to fix the 3rd input operand (the written data)
334  // for stores
335  if (storeDataReg) {
336  MI.getOperand(FIOperandNum + 2).ChangeToRegister(
337  storeDataReg, false);
338  } else {
339  MI.getOperand(FIOperandNum + 2).ChangeToImmediate(
340  storeDataImm);
341  }
342  }
343  } else {
344  // generate the sp + offset addition before the use
345  unsigned int tmp = 0;
346 
348  dynamic_cast<LLVMTCECmdLineOptions*>(
350  if (RS != NULL) {
351  tmp = RS->FindUnusedReg(&INTEGER_REG_CLASS);
352  }
353 
354  if (tmp != 0) {
355  MI.getOperand(FIOperandNum).ChangeToRegister(
356  tmp, false, false, true);
357  BuildMI(
358  *MI.getParent(), II, MI.getDebugLoc(), TII.get(ADDIMM),
359  tmp).addReg(TCE::SP).addImm(Offset);
360  } else {
361  MI.getOperand(FIOperandNum).ChangeToRegister(
362  TCE::KLUDGE_REGISTER, false);
363  BuildMI(
364  *MI.getParent(), II, MI.getDebugLoc(), TII.get(ADDIMM),
365  TCE::KLUDGE_REGISTER).addReg(TCE::SP).addImm(Offset);
366  }
367  }
368  }
369 }
370 
371 
372 /**
373  * Re-issue the specified 'original' instruction at the specific location
374  * targeting a new destination register.
375  *
376  * @param mbb Machine basic block of the new instruction.
377  * @param i Position of the new instruction in the basic block.
378  * @param destReg New destination register.
379  * @param orig Original instruction.
380 
381 void
382 TCERegisterInfo::reMaterialize(
383  MachineBasicBlock& mbb,
384  MachineBasicBlock::iterator i,
385  unsigned destReg,
386  const MachineInstr* orig) const {
387  assert(false && "It really was used");
388  MachineInstr* mi = mbb.getParent()->CloneMachineInstr(orig);
389  mi->getOperand(0).setReg(destReg);
390  mbb.insert(i, mi);
391 }
392 */
393 
394 /**
395  * Not implemented: When is this method even called?
396  */
397 unsigned
399  assert(false && "Remove this assert if this is really called.");
400  return TCE::RA;
401 }
402 
403 Register
404 TCERegisterInfo::getFrameRegister(const MachineFunction& mf) const {
405  if (hasFP(mf)) {
406  return TCE::FP;
407  } else {
408  return 0;
409  }
410 }
411 
412 bool
413 TCERegisterInfo::hasFP(const MachineFunction &MF) const {
414  return tfi_->hasFP(MF);
415 }
416 
417 bool
418 TCERegisterInfo::requiresRegisterScavenging(const MachineFunction&) const {
419  return false;
420 }
421 
422 
llvm
Definition: InlineAsmParser.hh:49
llvm::TCEFrameLowering::containsCall
bool containsCall(const MachineFunction &mf) const
Definition: TCEFrameInfo.cc:146
llvm::TCERegisterInfo::requiresRegisterScavenging
bool requiresRegisterScavenging(const MachineFunction &) const override
Definition: TCERegisterInfo.cc:418
Exception.hh
llvm::TCEInstrInfo
Definition: TCEInstrInfo.hh:57
BitVector
Definition: BitVector.hh:44
llvm::TCETargetMachine::validStackAccessOperation
bool validStackAccessOperation(const std::string &opName) const
Definition: TCETargetMachine.hh:196
INTEGER_REG_CLASS
#define INTEGER_REG_CLASS
Definition: TCERegisterInfo.cc:72
llvm::TCEFrameLowering::hasFP
bool hasFP(const MachineFunction &MF) const override
Definition: TCEFrameInfo.cc:138
llvm::TCERegisterInfo::TCERegisterInfo
TCERegisterInfo(const TargetInstrInfo &tii)
Definition: TCERegisterInfo.cc:82
CompileError
Definition: Exception.hh:1019
llvm::TCEFrameLowering::stackAlignment
int stackAlignment() const
Definition: TCEFrameInfo.hh:95
ADDIMM
#define ADDIMM
Definition: TCERegisterInfo.cc:70
llvm::TCERegisterInfo::getFrameRegister
Register getFrameRegister(const MachineFunction &mf) const override
Definition: TCERegisterInfo.cc:404
TCERegisterInfo.hh
llvm::TCERegisterInfo::getCalleeSavedRegs
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF=0) const override
Definition: TCERegisterInfo.cc:92
TCEString.hh
llvm::TCETargetMachine::hasOperation
bool hasOperation(TCEString operationName) const
Definition: TCETargetMachine.hh:200
assert
#define assert(condition)
Definition: Application.hh:86
llvm::TCERegisterInfo::hasFP
bool hasFP(const MachineFunction &MF) const
Definition: TCERegisterInfo.cc:413
THROW_EXCEPTION
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition: Exception.hh:39
LLVMTCECmdLineOptions.hh
TCETargetMachine.hh
Application.hh
Application::cmdLineOptions
static CmdLineOptions * cmdLineOptions()
Definition: Application.cc:397
TCEFrameInfo.hh
llvm::TCERegisterInfo::getReservedRegs
BitVector getReservedRegs(const MachineFunction &MF) const override
Definition: TCERegisterInfo.cc:105
LLVMTCECmdLineOptions
Definition: LLVMTCECmdLineOptions.hh:48
options
static MachInfoCmdLineOptions options
Definition: MachInfo.cc:46
RA
#define RA()
Definition: POMGenMacros.hh:393
TCEPlugin.hh
TCEString
Definition: TCEString.hh:53
llvm::TCERegisterInfo::setReservedVectorRegs
void setReservedVectorRegs(llvm::BitVector &reserved) const
llvm::TCEInstrInfo::getPointerAdjustment
std::tuple< int, int > getPointerAdjustment(int offset) const
Definition: TCEInstrInfo.cc:721
llvm::TCERegisterInfo::tii_
const TargetInstrInfo & tii_
Definition: TCERegisterInfo.hh:84
llvm::TCETargetMachine
Definition: TCETargetMachine.hh:106
llvm::TCETargetMachine::opcode
unsigned opcode(TCEString operationName) const
Definition: TCETargetMachine.hh:241
llvm::TCETargetMachine::operationName
std::string operationName(unsigned opc) const
Definition: TCETargetMachine.hh:188
llvm::TCERegisterInfo::getRARegister
unsigned getRARegister() const
Definition: TCERegisterInfo.cc:398
TCEInstrInfo.hh
llvm::TCERegisterInfo::eliminateFrameIndex
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=NULL) const override
Definition: TCERegisterInfo.cc:129
llvm::TCERegisterInfo::tfi_
const TCEFrameLowering * tfi_
Definition: TCERegisterInfo.hh:85