TCE  1.21
Public Member Functions | Static Public Attributes | List of all members
ProgramPartitioner Struct Reference

#include <ProgramPartitioner.hh>

Inheritance diagram for ProgramPartitioner:
Inheritance graph
Collaboration diagram for ProgramPartitioner:
Collaboration graph

Public Member Functions

 ProgramPartitioner ()
 
virtual bool doInitialization (llvm::Module &M) override
 
virtual bool runOnMachineFunction (llvm::MachineFunction &MF) override
 
virtual bool doFinalization (llvm::Module &M) override
 
virtual bool findNodeIndex (const llvm::MachineInstr &I, hash_map< const llvm::MachineInstr *, unsigned > &partitions, llvm::MachineFunction &MF, unsigned int &index)
 
virtual llvm::StringRef getPassName () const override
 

Static Public Attributes

static char ID = 0
 

Detailed Description

Definition at line 77 of file ProgramPartitioner.hh.

Constructor & Destructor Documentation

◆ ProgramPartitioner()

ProgramPartitioner::ProgramPartitioner ( )
inline

Definition at line 79 of file ProgramPartitioner.hh.

References doFinalization(), doInitialization(), findNodeIndex(), getPassName(), and runOnMachineFunction().

79 : MachineFunctionPass(ID) {}
Here is the call graph for this function:

Member Function Documentation

◆ doFinalization()

bool ProgramPartitioner::doFinalization ( llvm::Module &  M)
overridevirtual

Definition at line 192 of file ProgramPartitioner.cc.

Referenced by ProgramPartitioner().

192  {
193  return false;
194 }

◆ doInitialization()

bool ProgramPartitioner::doInitialization ( llvm::Module &  M)
overridevirtual

Definition at line 63 of file ProgramPartitioner.cc.

Referenced by ProgramPartitioner().

63  {
64  return false;
65 }

◆ findNodeIndex()

bool ProgramPartitioner::findNodeIndex ( const llvm::MachineInstr &  mi,
hash_map< const llvm::MachineInstr *, unsigned > &  partitions,
llvm::MachineFunction &  MF,
unsigned int &  nodeIndex 
)
virtual

Attemts to find an index of lane to which the instruction belongs based on metadata or parent instruction assignment.

Parameters
miMachine instruction to analyze
paritionsmap between machine instruction and the lane indexes
MFmachine function to which the mi belongs
nodeIndexindex found

Definition at line 206 of file ProgramPartitioner.cc.

References llvm::TCETargetMachine::maxVectorSize(), llvm::TCETargetMachinePlugin::nodeRegClass(), and llvm::TCETargetMachine::targetPlugin().

Referenced by ProgramPartitioner().

210  {
211 
212  const TCETargetMachine& targetMach =
213  dynamic_cast<const TCETargetMachine&>(
214  MF.getTarget());
215 
216  const TCETargetMachinePlugin& tmPlugin =
217  dynamic_cast<const TCETargetMachinePlugin&>(
218  targetMach.targetPlugin());
219 
220  llvm::MachineRegisterInfo& MRI = MF.getRegInfo();
221 
222  if (nodeIndex != UINT_MAX) {
223 #ifdef DEBUG_PROGRAM_PARTITIONER
224  std::cerr << "[EXTRACT lane " << nodeIndex << "] " << std::endl;
225 #endif
226  }
227 
228  if (nodeIndex == UINT_MAX) {
229  /* Check if one of the parents of this instruction is already
230  partitioned.
231 
232  TODO: do it recursively until a root instruction or
233  a partitioned instruction is found. */
234  for (unsigned opr = 0; opr < mi.getNumOperands(); ++opr) {
235  const llvm::MachineOperand& operand = mi.getOperand(opr);
236  if (!operand.isReg()) continue;
237 
238  llvm::MachineRegisterInfo::def_iterator di =
239  MRI.def_begin(operand.getReg());
240  if (di.atEnd()) continue;
241 
242  const llvm::MachineInstr* parent = (*di).getParent();
243 
244  // TODO: this NULL check not needed anymore?
245  if (parent == NULL) continue;
246  if (partitions.find(parent) == partitions.end()) continue;
247  nodeIndex = partitions[parent];
248  break;
249  }
250  }
251  if (nodeIndex == UINT_MAX &&
252  mi.memoperands_begin() != mi.memoperands_end()) {
253  /* Check if one of the parents of this is a instruction for
254  which we can track the OpenCL work item id metadata. */
255  for (llvm::MachineInstr::mmo_iterator mmoIter =
256  mi.memoperands_begin();
257  mmoIter != mi.memoperands_end(); ++mmoIter) {
258 
259  llvm::MachineMemOperand* mo = *mmoIter;
260 
261  if (mo->getValue() == NULL ||
262  !llvm::isa<const llvm::Instruction>(mo->getValue()))
263  continue;
264  // The matching instruction, if known.
265  const llvm::Instruction* instruction =
266  llvm::cast<const llvm::Instruction>(mo->getValue());
267 
268  if (!instruction->getMetadata("wi")) {
269  continue;
270  }
271  MDNode *md = instruction->getMetadata("wi");
272  ConstantInt* id_x = NULL;
273  if (llvm::isa<MDNode>(md->getOperand(2))) {
274  // new wi metadata format is:
275  // operand 0 - WI_id
276  // operand 1 - MDNode with region id
277  // operand 2 - MDNode with XYZ coordinates
278  MDNode *xyz = dyn_cast<MDNode>(md->getOperand(2));
279  // New XYZ metadata format from pocl
280  // operand 0 - WI_xyz
281  // operand 1 - x coordinate
282  // operand 2 - y coordinate
283  // operand 3 - z coordinate
284  // pick X coordinate
285 #ifdef LLVM_OLDER_THAN_3_6
286  id_x = cast<llvm::ConstantInt>(xyz->getOperand(1));
287 #else
288  id_x = cast<llvm::ConstantInt>(
289  dyn_cast<llvm::ConstantAsMetadata>(
290  xyz->getOperand(1))->getValue());
291 #endif
292  } else {
293  // old metadata format was
294  // operand 0 - WI_id
295  // operand 1 - region id
296  // operand 2 - x coordinate
297  // operand 3 - y coordinate
298  // operand 4 - z coordinate
299  // operand 5 - instruction number
300 #ifdef LLVM_OLDER_THAN_3_6
301  id_x = cast<llvm::ConstantInt>(md->getOperand(2));
302 #else
303  id_x = cast<llvm::ConstantInt>(
304  dyn_cast<llvm::ConstantAsMetadata>(
305  md->getOperand(2))->getValue());
306 #endif
307  }
308  if (id_x == NULL)
309  continue;
310  nodeIndex =
311  (unsigned)id_x->getValue().getZExtValue() %
312  targetMach.maxVectorSize();
313 #ifdef DEBUG_PROGRAM_PARTITIONER
314  std::cerr << "[FOUND OCL WI METADATA: " <<
315  nodeIndex << "]" << std::endl;
316 #endif
317  }
318  }
319 #ifdef DEBUG_PROGRAM_PARTITIONER
320  if (nodeIndex != UINT_MAX) {
321  std::cerr << "[NODE INDEX " << nodeIndex << "]: ";
322  for (int pad = 0; pad < nodeIndex; ++pad)
323  for (int ws = 0; ws < 30; ++ws) std::cerr << " ";
324  } else {
325  std::cerr << "[NODE INDEX UNKNOWN]: ";
326  }
327 #endif
328  if (nodeIndex == UINT_MAX) return false;
329  partitions[&mi] = nodeIndex;
330 
331  /* TODO: Use the partition's register class instead of the super class to force
332  the instruction's regs to be allocated from the partition. */
333  for (unsigned int i = 0; i < mi.getNumOperands(); i++) {
334  if (mi.getOperand(i).isReg() &&
335  mi.getOperand(i).isDef()) {
336 
337  const llvm::MachineOperand& result = mi.getOperand(i);
338 #ifdef LLVM_OLDER_THAN_10
339  if (llvm::TargetRegisterInfo::isPhysicalRegister(
340  mi.getOperand(i).getReg())) continue;
341 #else
342  if (Register::isPhysicalRegister(
343  mi.getOperand(i).getReg())) continue;
344 #endif
345 
346  const llvm::TargetRegisterClass* nodeRegClass =
347  tmPlugin.nodeRegClass(nodeIndex, MRI.getRegClass(result.getReg()));
348 #ifdef DEBUG_PROGRAM_PARTITIONER
349  std::cerr << "[ORIGINAL REG CLASS "
350  << MRI.getRegClass(result.getReg())->getName()
351  << "]" << std::endl;
352 #endif
353  if (nodeRegClass == NULL) {
354 #ifdef DEBUG_PROGRAM_PARTITIONER
355  std::cerr << "[NO REG CLASS FOUND FOR THE NODE]" << std::endl;
356 #endif
357  } else {
358 #ifdef DEBUG_PROGRAM_PARTITIONER
359  std::cerr << "[ASSIGNED REG CLASS "
360  << nodeRegClass->getName() << "]" << std::endl;
361 #endif
362  MRI.setRegClass(result.getReg(), nodeRegClass);
363  }
364  }
365  }
366  return true;
367 }
virtual TCETargetMachinePlugin & targetPlugin() const
virtual const llvm::TargetRegisterClass * nodeRegClass(unsigned nodeId, const llvm::TargetRegisterClass *current) const =0
Here is the call graph for this function:

◆ getPassName()

virtual llvm::StringRef ProgramPartitioner::getPassName ( ) const
inlineoverridevirtual

Definition at line 92 of file ProgramPartitioner.hh.

Referenced by ProgramPartitioner().

92  {
93 #endif
94  return "TCE: program variables to register file partitioner";
95  }

◆ runOnMachineFunction()

bool ProgramPartitioner::runOnMachineFunction ( llvm::MachineFunction &  MF)
overridevirtual

Definition at line 68 of file ProgramPartitioner.cc.

References llvm::TCETargetMachinePlugin::extractElementLane(), llvm::TCETargetMachine::maxVectorSize(), PRINT_VAR, and llvm::TCETargetMachine::targetPlugin().

Referenced by ProgramPartitioner().

68  {
69 
70 #if (!(defined(LLVM_3_5)))
71 #ifdef DEBUG_PROGRAM_PARTITIONER
72  std::cerr << "### ProgramPartitioner disabled for llvm 3.6+ " << std::endl;
73 #endif
74  return true;
75 #endif
76 
77 #ifdef DEBUG_PROGRAM_PARTITIONER
78  std::cerr << "### Running ProgramPartitioner for "
79  << MF.getFunction()->getName().str() << std::endl;
80 #endif
81  const TCETargetMachine& targetMach =
82  dynamic_cast<const TCETargetMachine&>(
83  MF.getTarget());
84 
85  /* Partition only clustered machines with vector backend support for now. */
86  if (targetMach.maxVectorSize() == 0) return false;
87 
88 #ifdef DEBUG_PROGRAM_PARTITIONER
89  PRINT_VAR(targetMach.maxVectorSize());
90 #endif
91 
92  const TCETargetMachinePlugin& tmPlugin =
93  dynamic_cast<const TCETargetMachinePlugin&>(
94  targetMach.targetPlugin());
95 
96  llvm::MachineRegisterInfo& MRI = MF.getRegInfo();
97 
98  hash_map<const llvm::MachineInstr*, unsigned> partitions;
99 
100 
101  for (MachineFunction::const_iterator i = MF.begin();
102  i != MF.end(); i++) {
103  bool changedT, changedD = false;
104  // Loop through instruction in basic blocks looking for parent
105  // or metadata information about line assignment until there is
106  // no new information added.
107  do {
108  changedT = false;
109  changedD = false;
110  for (MachineBasicBlock::const_iterator j = i->begin();
111  j != i->end(); j++) {
112 
113  const llvm::MachineInstr& mi = *j;
114 
115  if (partitions.find(&mi) != partitions.end())
116  continue; /* Already partitioned. */
117  unsigned nodeIndex = tmPlugin.extractElementLane(mi);
118 
119  changedT |= findNodeIndex(mi, partitions, MF, nodeIndex);
120 
121  }
122 
123 #if 1
124  // Same as before but starting from the bottom of basic block to the
125  // top.
126 
127  for (MachineBasicBlock::const_iterator j = i->end();
128  j != i->begin();) {
129  j--;
130  const llvm::MachineInstr& mi = *j;
131 
132  if (partitions.find(&mi) != partitions.end())
133  continue; /* Already partitioned. */
134  unsigned nodeIndex = tmPlugin.extractElementLane(mi);
135 
136  changedD |= findNodeIndex(mi, partitions, MF, nodeIndex);
137 
138  }
139 #endif
140  } while (changedT || changedD);
141  }
142 #ifdef ASSIGN_UNKNOWN_TO_EXTRAS
143 #ifdef DEBUG_PROGRAM_PARTITIONER
144  std::cerr << "[setting the rest to EX]" << std::endl;
145 #endif
146  /* Force the non-partitioned instructions to the
147  extras node. This should include sequential C code and
148  multi-WI address computations, branch condition code,
149  etc. for OpenCL C code. */
150  for (MachineFunction::const_iterator i = MF.begin();
151  i != MF.end(); i++) {
152 
153  for (MachineBasicBlock::const_iterator j = i->begin();
154  j != i->end(); j++) {
155  const llvm::MachineInstr& mi = *j;
156 
157 #ifdef LLVM_OLDER_THAN_10
158  if (mi.getNumOperands() == 0 || !mi.getOperand(0).isReg() ||
159  !mi.getOperand(0).isDef() ||
160  llvm::TargetRegisterInfo::isPhysicalRegister(
161  mi.getOperand(0).getReg()))
162 #else
163  if (mi.getNumOperands() == 0 || !mi.getOperand(0).isReg() ||
164  !mi.getOperand(0).isDef() ||
165  Register::isPhysicalRegister(
166  mi.getOperand(0).getReg()))
167 #endif
168  continue;
169 
170  if (partitions.find(&mi) != partitions.end())
171  continue; /* Partitioned. */
172  const llvm::MachineOperand& result = mi.getOperand(0);
173  const llvm::TargetRegisterClass* newRegClass =
174  tmPlugin.extrasRegClass(MRI.getRegClass(result.getReg()));
175 #ifdef DEBUG_PROGRAM_PARTITIONER
176  std::cerr << "[ORIGINAL REG CLASS "
177  << MRI.getRegClass(result.getReg())->getName()
178  << "]" << std::endl;
179 #endif
180  MRI.setRegClass(result.getReg(), newRegClass);
181 #ifdef DEBUG_PROGRAM_PARTITIONER
182  std::cerr << "[ASSIGNED REG CLASS "
183  << newRegClass->getName() << "]" << std::endl;
184 #endif
185  }
186  }
187 #endif
188  return true;
189 }
virtual unsigned int extractElementLane(const MachineInstr &mi) const =0
#define PRINT_VAR(VARIABLE__)
Definition: Application.hh:110
virtual TCETargetMachinePlugin & targetPlugin() const
virtual bool findNodeIndex(const llvm::MachineInstr &I, hash_map< const llvm::MachineInstr *, unsigned > &partitions, llvm::MachineFunction &MF, unsigned int &index)
Here is the call graph for this function:

Member Data Documentation

◆ ID

POP_COMPILER_DIAGS char ProgramPartitioner::ID = 0
static

Definition at line 78 of file ProgramPartitioner.hh.


The documentation for this struct was generated from the following files: