OpenASIP  2.0
ConstantTransformer.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2015 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 ConstantTransformer.cc
26  *
27  * Implementation of ConstantTransformer class.
28  *
29  * @author Pekka Jääskeläinen 2015
30  * @note reting: red
31  */
32 
33 #include "CompilerWarnings.hh"
34 
35 IGNORE_COMPILER_WARNING("-Wunused-parameter")
36 
37 #include "ConstantTransformer.hh"
38 
39 #include "MachineInfo.hh"
40 #include "TCETargetMachine.hh"
41 #include "OperationPool.hh"
42 #include "Operation.hh"
43 #include "Operand.hh"
44 
45 #include <llvm/CodeGen/MachineFunction.h>
46 #include <llvm/CodeGen/MachineBasicBlock.h>
47 #include <llvm/MC/MCInstrInfo.h>
48 #include <llvm/CodeGen/TargetInstrInfo.h>
49 #include <llvm/CodeGen/TargetSubtargetInfo.h>
50 #include <llvm/CodeGen/TargetOpcodes.h>
51 #include <llvm/CodeGen/MachineInstrBuilder.h>
52 
54 
55 #include <sstream>
56 
57 using llvm::MachineBasicBlock;
58 using llvm::MachineFunction;
59 using llvm::MachineOperand;
62 
63 #define sub "SUB"
64 
66 
67 bool
69  return false;
70 }
71 
72 /**
73  * In case the given operandId is an input operand in the
74  * MachineInstr, returns the corresponding OSAL operand id
75  * (starting from 1), 0 otherwise.
76  */
77 unsigned
79  const Operation& operation,
80  const llvm::MachineInstr& instr,
81  unsigned operandId) {
82 
83  const TCETargetMachine& tm =
84  dynamic_cast<const TCETargetMachine&>(
85  instr.getParent()->getParent()->getTarget());
86 
87  TCEString operationName = tm.operationName(instr.getDesc().getOpcode());
88  bool hasGuard = operationName[0] == '?' || operationName[0] == '!';
89 
90  unsigned osalIndex = 0;
91  for (unsigned operandI = 0; operandI < instr.getNumOperands(); ++operandI) {
92  const MachineOperand& mo = instr.getOperand(operandI);
93  if (hasGuard && operandI == 0) continue;
94  // Output or metadata.
95  if ((mo.isReg() && (mo.isDef() || mo.isImplicit())) || mo.isMetadata())
96  continue;
97  ++osalIndex;
98  if (operandI == operandId) return osalIndex;
99  // LLVM machineinstructions always present the addresses in the
100  // base + offset form, thus consume two input operands per one
101  // OSAL operand. Skip the offset operand in case the OSAL operation
102  // only the takes a single absolute address.
103  if (operation.operand(osalIndex).isAddress() &&
104  !operation.isBaseOffsetMemOperation()) {
105  ++operandI;
106  }
107  }
108 
109  return 0;
110 }
111 
112 bool
113 ConstantTransformer::runOnMachineFunction(llvm::MachineFunction& mf) {
114 
115  const TCETargetMachine& tm =
116  dynamic_cast<const TCETargetMachine&>(mf.getTarget());
117  TCETargetMachinePlugin& plugin = tm.targetPlugin();
118 
119  OperationPool osal;
120 
121  bool changed = false;
122  for (MachineFunction::iterator i = mf.begin(); i != mf.end(); i++) {
123  MachineBasicBlock& mbb = *i;
124  for (MachineBasicBlock::iterator j = mbb.begin();
125  j != mbb.end(); j++) {
126  const llvm::MachineInstr* mi = &*j;
127  unsigned opc = mi->getOpcode();
128 
129  const llvm::MCInstrDesc& opDesc = mi->getDesc();
130  if (opDesc.isReturn()) {
131  continue;
132  }
133  if (opc == llvm::TargetOpcode::DBG_VALUE
134  || opc == llvm::TargetOpcode::DBG_LABEL
135  || opc == llvm::TargetOpcode::DBG_INSTR_REF
136  || opc == llvm::TargetOpcode::DBG_VALUE_LIST
137  || opc == llvm::TargetOpcode::DBG_PHI
138  || opc == llvm::TargetOpcode::KILL) {
139  continue;
140  }
141 
142  TCEString opname = tm.operationName(opc);
143  if (opname == "") continue;
144  bool hasGuard = opname[0] == '?' || opname[0] == '!';
145  if (hasGuard) opname = opname.substr(1);
146 
147  const Operation& op = osal.operation(opname.c_str());
148  if (op.isNull() || op.isBranch() || op.isCall() ||
149  op.readsMemory()) {
150  // isNull = INLINE asm, a pseudo asm block or similar.
151  // TODO: add support for at least INLINE and MOVE.
152 
153  // In case the operation reads memory, assume the
154  // possible immediate operand is a global address
155  // we cannot fix at this point.
156  // TODO: Fix global address constants. Needs to have new type
157  // of data symbol/relocation info in case an address
158  // constant is broken down.
159 
160  continue;
161  }
162 
163  for (unsigned operandI = 0; operandI < mi->getNumOperands();
164  ++operandI) {
165 
166  const MachineOperand& mo = mi->getOperand(operandI);
167  if (!mo.isImm()) continue;
168 
169  unsigned inputIndex = osalInputIndex(op, *mi, operandI);
170  if (inputIndex == 0) continue;
171  const Operand& operand = op.operand(inputIndex);
172  if (operand.isNull() || !operand.isInput()) {
173  continue; // ignore output operands
175  << "Input " << inputIndex
176  << " not found for operation "
177  << opname << std::endl;
178  assert(false);
179  }
180  assert(operand.isInput());
181  size_t operandWidth = operand.width();
182 
184  mach_, mo.getImm(), operandWidth)) continue;
185 
186  // check if it's possible to convert C to SUB(0, -C) such
187  // that it can be encoded for the target
190  mach_, -mo.getImm()) && /* SUB is 32b */
192 
193  const llvm::MCInstrInfo* iinfo =
194  mf.getTarget().getSubtargetImpl(
195  mf.getFunction())->getInstrInfo();
196  // RV_HIGH = SUB 0 -X
197  BuildMI(
198  mbb, j, j->getDebugLoc(), iinfo->get(plugin.opcode(sub)),
199  plugin.rvHighDRegNum()).addImm(0).addImm(-mo.getImm());
200 
201  // replace the original instruction's immediate operand
202  // with the RV_HIGH
203  llvm::MachineInstrBuilder mib =
204  BuildMI(mbb, j, j->getDebugLoc(), j->getDesc());
205  for (unsigned opr = 0; opr < j->getNumOperands(); ++opr) {
206  MachineOperand& orig = j->getOperand(opr);
207  if (opr == operandI) {
208  mib.add(MachineOperand::CreateReg(
209  plugin.rvHighDRegNum(), false));
210  continue;
211  }
212  mib.add(orig);
213  orig.clearParent();
214  }
215 
216  // the original instruction can be now deleted
217  j->eraseFromParent();
218  // start scanning the MBB from the beginning due to
219  // possibly invalidated iterators from adding the
220  // new instructions
221  j = mbb.begin();
222  changed = true;
223  } else {
224  std::ostringstream errMsg;
225  errMsg << "Program uses constant '"
226  << mo.getImm() << "'";
227  if (Application::verboseLevel() > 0) {
228  errMsg << " -> " << opname
229  << " (llvm opc = " << opc << ")";
230  }
231  errMsg << " that cannot be encoded "
232  << "for the machine by the current compiler.";
233  throw CompileError(
234  __FILE__, __LINE__, __func__, errMsg.str());
235  }
236  }
237  }
238 
239  }
240  return changed;
241 }
242 
243 bool
245  return false;
246 }
Operand
Definition: Operand.hh:52
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
MachineInfo::supportsOperation
static bool supportsOperation(const TTAMachine::Machine &mach, TCEString operation)
Definition: MachineInfo.cc:382
ConstantTransformer::doInitialization
bool doInitialization(llvm::Module &M)
Definition: ConstantTransformer.cc:68
Operand::width
virtual int width() const
Definition: Operand.cc:318
MachineInfo.hh
CompileError
Definition: Exception.hh:1019
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
Operand::isNull
virtual bool isNull() const
Definition: Operand.hh:130
assert
#define assert(condition)
Definition: Application.hh:86
osalInputIndex
unsigned osalInputIndex(const Operation &operation, const llvm::MachineInstr &instr, unsigned operandId)
Definition: ConstantTransformer.cc:78
ConstantTransformer::doFinalization
bool doFinalization(llvm::Module &M)
Definition: ConstantTransformer.cc:244
TCETargetMachine.hh
llvm::TCETargetMachinePlugin::opcode
virtual unsigned opcode(TCEString operationName) const =0
Returns the opcode for the given osal operation, undefined if not found.
__func__
#define __func__
Definition: Application.hh:67
Operation.hh
Operation::readsMemory
virtual bool readsMemory() const
Definition: Operation.cc:242
Operation::isBaseOffsetMemOperation
virtual bool isBaseOffsetMemOperation() const
Definition: Operation.cc:323
Operation
Definition: Operation.hh:59
Operand.hh
llvm::TCETargetMachinePlugin
Definition: TCETargetMachinePlugin.hh:109
Operation::operand
virtual Operand & operand(int id) const
Definition: Operation.cc:541
llvm::TCETargetMachinePlugin::rvHighDRegNum
virtual unsigned rvHighDRegNum()=0
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
Application::errorStream
static std::ostream & errorStream()
Definition: Application.cc:171
Operation::isNull
bool isNull() const
ConstantTransformer::runOnMachineFunction
bool runOnMachineFunction(llvm::MachineFunction &mf)
Definition: ConstantTransformer.cc:113
TCEString
Definition: TCEString.hh:53
sub
#define sub
Definition: ConstantTransformer.cc:63
POP_COMPILER_DIAGS
#define POP_COMPILER_DIAGS
Definition: CompilerWarnings.hh:68
ConstantTransformer::mach_
const TTAMachine::Machine & mach_
Definition: ConstantTransformer.hh:56
ConstantTransformer::ID
static char ID
Definition: ConstantTransformer.hh:45
llvm::TCETargetMachine
Definition: TCETargetMachine.hh:106
Operand::isAddress
virtual bool isAddress() const
Definition: Operand.cc:328
Operation::isCall
virtual bool isCall() const
Definition: Operation.cc:318
OperationPool
Definition: OperationPool.hh:52
Operand::isInput
virtual bool isInput() const
Definition: Operand.cc:145
llvm::TCETargetMachine::operationName
std::string operationName(unsigned opc) const
Definition: TCETargetMachine.hh:188
OperationPool.hh
Operation::isBranch
virtual bool isBranch() const
Definition: Operation.cc:306
CompilerWarnings.hh
MachineInfo::canEncodeImmediateInteger
static bool canEncodeImmediateInteger(const TTAMachine::Machine &mach, int64_t imm, unsigned destWidth=UINT_MAX)
Definition: MachineInfo.cc:444
llvm::TCETargetMachine::targetPlugin
virtual TCETargetMachinePlugin & targetPlugin() const
Definition: TCETargetMachine.hh:120