LLVM  14.0.0git
MIRCanonicalizerPass.cpp
Go to the documentation of this file.
1 //===-------------- MIRCanonicalizer.cpp - MIR Canonicalizer --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The purpose of this pass is to employ a canonical code transformation so
10 // that code compiled with slightly different IR passes can be diffed more
11 // effectively than otherwise. This is done by renaming vregs in a given
12 // LiveRange in a canonical way. This pass also does a pseudo-scheduling to
13 // move defs closer to their use inorder to reduce diffs caused by slightly
14 // different schedules.
15 //
16 // Basic Usage:
17 //
18 // llc -o - -run-pass mir-canonicalizer example.mir
19 //
20 // Reorders instructions canonically.
21 // Renames virtual register operands canonically.
22 // Strips certain MIR artifacts (optionally).
23 //
24 //===----------------------------------------------------------------------===//
25 
26 #include "MIRVRegNamerUtils.h"
28 #include "llvm/ADT/STLExtras.h"
32 #include "llvm/CodeGen/Passes.h"
33 #include "llvm/InitializePasses.h"
34 #include "llvm/Support/Debug.h"
36 
37 #include <queue>
38 
39 using namespace llvm;
40 
41 #define DEBUG_TYPE "mir-canonicalizer"
42 
43 static cl::opt<unsigned>
44  CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden, cl::init(~0u),
45  cl::value_desc("N"),
46  cl::desc("Function number to canonicalize."));
47 
48 namespace {
49 
50 class MIRCanonicalizer : public MachineFunctionPass {
51 public:
52  static char ID;
53  MIRCanonicalizer() : MachineFunctionPass(ID) {}
54 
55  StringRef getPassName() const override {
56  return "Rename register operands in a canonical ordering.";
57  }
58 
59  void getAnalysisUsage(AnalysisUsage &AU) const override {
60  AU.setPreservesCFG();
62  }
63 
64  bool runOnMachineFunction(MachineFunction &MF) override;
65 };
66 
67 } // end anonymous namespace
68 
70 
72 
73 INITIALIZE_PASS_BEGIN(MIRCanonicalizer, "mir-canonicalizer",
74  "Rename Register Operands Canonically", false, false)
75 
76 INITIALIZE_PASS_END(MIRCanonicalizer, "mir-canonicalizer",
78 
80  if (MF.empty())
81  return {};
83  std::vector<MachineBasicBlock *> RPOList;
84  append_range(RPOList, RPOT);
85 
86  return RPOList;
87 }
88 
89 static bool
90 rescheduleLexographically(std::vector<MachineInstr *> instructions,
93 
94  bool Changed = false;
95  using StringInstrPair = std::pair<std::string, MachineInstr *>;
96  std::vector<StringInstrPair> StringInstrMap;
97 
98  for (auto *II : instructions) {
99  std::string S;
100  raw_string_ostream OS(S);
101  II->print(OS);
102  OS.flush();
103 
104  // Trim the assignment, or start from the beginning in the case of a store.
105  const size_t i = S.find('=');
106  StringInstrMap.push_back({(i == std::string::npos) ? S : S.substr(i), II});
107  }
108 
109  llvm::sort(StringInstrMap,
110  [](const StringInstrPair &a, const StringInstrPair &b) -> bool {
111  return (a.first < b.first);
112  });
113 
114  for (auto &II : StringInstrMap) {
115 
116  LLVM_DEBUG({
117  dbgs() << "Splicing ";
118  II.second->dump();
119  dbgs() << " right before: ";
120  getPos()->dump();
121  });
122 
123  Changed = true;
124  MBB->splice(getPos(), MBB, II.second);
125  }
126 
127  return Changed;
128 }
129 
130 static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount,
132 
133  bool Changed = false;
134 
135  // Calculates the distance of MI from the beginning of its parent BB.
136  auto getInstrIdx = [](const MachineInstr &MI) {
137  unsigned i = 0;
138  for (auto &CurMI : *MI.getParent()) {
139  if (&CurMI == &MI)
140  return i;
141  i++;
142  }
143  return ~0U;
144  };
145 
146  // Pre-Populate vector of instructions to reschedule so that we don't
147  // clobber the iterator.
148  std::vector<MachineInstr *> Instructions;
149  for (auto &MI : *MBB) {
150  Instructions.push_back(&MI);
151  }
152 
153  std::map<MachineInstr *, std::vector<MachineInstr *>> MultiUsers;
154  std::map<unsigned, MachineInstr *> MultiUserLookup;
155  unsigned UseToBringDefCloserToCount = 0;
156  std::vector<MachineInstr *> PseudoIdempotentInstructions;
157  std::vector<unsigned> PhysRegDefs;
158  for (auto *II : Instructions) {
159  for (unsigned i = 1; i < II->getNumOperands(); i++) {
160  MachineOperand &MO = II->getOperand(i);
161  if (!MO.isReg())
162  continue;
163 
165  continue;
166 
167  if (!MO.isDef())
168  continue;
169 
170  PhysRegDefs.push_back(MO.getReg());
171  }
172  }
173 
174  for (auto *II : Instructions) {
175  if (II->getNumOperands() == 0)
176  continue;
177  if (II->mayLoadOrStore())
178  continue;
179 
180  MachineOperand &MO = II->getOperand(0);
181  if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg()))
182  continue;
183  if (!MO.isDef())
184  continue;
185 
186  bool IsPseudoIdempotent = true;
187  for (unsigned i = 1; i < II->getNumOperands(); i++) {
188 
189  if (II->getOperand(i).isImm()) {
190  continue;
191  }
192 
193  if (II->getOperand(i).isReg()) {
194  if (!Register::isVirtualRegister(II->getOperand(i).getReg()))
195  if (!llvm::is_contained(PhysRegDefs, II->getOperand(i).getReg())) {
196  continue;
197  }
198  }
199 
200  IsPseudoIdempotent = false;
201  break;
202  }
203 
204  if (IsPseudoIdempotent) {
205  PseudoIdempotentInstructions.push_back(II);
206  continue;
207  }
208 
209  LLVM_DEBUG(dbgs() << "Operand " << 0 << " of "; II->dump(); MO.dump(););
210 
211  MachineInstr *Def = II;
212  unsigned Distance = ~0U;
213  MachineInstr *UseToBringDefCloserTo = nullptr;
215  for (auto &UO : MRI->use_nodbg_operands(MO.getReg())) {
216  MachineInstr *UseInst = UO.getParent();
217 
218  const unsigned DefLoc = getInstrIdx(*Def);
219  const unsigned UseLoc = getInstrIdx(*UseInst);
220  const unsigned Delta = (UseLoc - DefLoc);
221 
222  if (UseInst->getParent() != Def->getParent())
223  continue;
224  if (DefLoc >= UseLoc)
225  continue;
226 
227  if (Delta < Distance) {
228  Distance = Delta;
229  UseToBringDefCloserTo = UseInst;
230  MultiUserLookup[UseToBringDefCloserToCount++] = UseToBringDefCloserTo;
231  }
232  }
233 
234  const auto BBE = MBB->instr_end();
235  MachineBasicBlock::iterator DefI = BBE;
236  MachineBasicBlock::iterator UseI = BBE;
237 
238  for (auto BBI = MBB->instr_begin(); BBI != BBE; ++BBI) {
239 
240  if (DefI != BBE && UseI != BBE)
241  break;
242 
243  if (&*BBI == Def) {
244  DefI = BBI;
245  continue;
246  }
247 
248  if (&*BBI == UseToBringDefCloserTo) {
249  UseI = BBI;
250  continue;
251  }
252  }
253 
254  if (DefI == BBE || UseI == BBE)
255  continue;
256 
257  LLVM_DEBUG({
258  dbgs() << "Splicing ";
259  DefI->dump();
260  dbgs() << " right before: ";
261  UseI->dump();
262  });
263 
264  MultiUsers[UseToBringDefCloserTo].push_back(Def);
265  Changed = true;
266  MBB->splice(UseI, MBB, DefI);
267  }
268 
269  // Sort the defs for users of multiple defs lexographically.
270  for (const auto &E : MultiUserLookup) {
271 
272  auto UseI = llvm::find_if(MBB->instrs(), [&](MachineInstr &MI) -> bool {
273  return &MI == E.second;
274  });
275 
276  if (UseI == MBB->instr_end())
277  continue;
278 
279  LLVM_DEBUG(
280  dbgs() << "Rescheduling Multi-Use Instructions Lexographically.";);
281  Changed |= rescheduleLexographically(
282  MultiUsers[E.second], MBB,
283  [&]() -> MachineBasicBlock::iterator { return UseI; });
284  }
285 
286  PseudoIdempotentInstCount = PseudoIdempotentInstructions.size();
287  LLVM_DEBUG(
288  dbgs() << "Rescheduling Idempotent Instructions Lexographically.";);
289  Changed |= rescheduleLexographically(
290  PseudoIdempotentInstructions, MBB,
291  [&]() -> MachineBasicBlock::iterator { return MBB->begin(); });
292 
293  return Changed;
294 }
295 
297  bool Changed = false;
299 
300  std::vector<MachineInstr *> Copies;
301  for (MachineInstr &MI : MBB->instrs()) {
302  if (MI.isCopy())
303  Copies.push_back(&MI);
304  }
305 
306  for (MachineInstr *MI : Copies) {
307 
308  if (!MI->getOperand(0).isReg())
309  continue;
310  if (!MI->getOperand(1).isReg())
311  continue;
312 
313  const Register Dst = MI->getOperand(0).getReg();
314  const Register Src = MI->getOperand(1).getReg();
315 
316  if (!Register::isVirtualRegister(Dst))
317  continue;
318  if (!Register::isVirtualRegister(Src))
319  continue;
320  // Not folding COPY instructions if regbankselect has not set the RCs.
321  // Why are we only considering Register Classes? Because the verifier
322  // sometimes gets upset if the register classes don't match even if the
323  // types do. A future patch might add COPY folding for matching types in
324  // pre-registerbankselect code.
325  if (!MRI.getRegClassOrNull(Dst))
326  continue;
327  if (MRI.getRegClass(Dst) != MRI.getRegClass(Src))
328  continue;
329 
330  std::vector<MachineOperand *> Uses;
331  for (auto UI = MRI.use_begin(Dst); UI != MRI.use_end(); ++UI)
332  Uses.push_back(&*UI);
333  for (auto *MO : Uses)
334  MO->setReg(Src);
335 
336  Changed = true;
337  MI->eraseFromParent();
338  }
339 
340  return Changed;
341 }
342 
344  bool Changed = false;
345 
346  for (auto &MI : *MBB) {
347  for (auto &MO : MI.operands()) {
348  if (!MO.isReg())
349  continue;
350  if (!MO.isDef() && MO.isKill()) {
351  Changed = true;
352  MO.setIsKill(false);
353  }
354 
355  if (MO.isDef() && MO.isDead()) {
356  Changed = true;
357  MO.setIsDead(false);
358  }
359  }
360  }
361 
362  return Changed;
363 }
364 
366  unsigned BasicBlockNum, VRegRenamer &Renamer) {
367  LLVM_DEBUG({
368  dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << " \n\n";
369  dbgs() << "\n\n================================================\n\n";
370  });
371 
372  bool Changed = false;
373 
374  LLVM_DEBUG(dbgs() << "\n\n NEW BASIC BLOCK: " << MBB->getName() << "\n\n";);
375 
376  LLVM_DEBUG(dbgs() << "MBB Before Canonical Copy Propagation:\n";
377  MBB->dump(););
378  Changed |= propagateLocalCopies(MBB);
379  LLVM_DEBUG(dbgs() << "MBB After Canonical Copy Propagation:\n"; MBB->dump(););
380 
381  LLVM_DEBUG(dbgs() << "MBB Before Scheduling:\n"; MBB->dump(););
382  unsigned IdempotentInstCount = 0;
383  Changed |= rescheduleCanonically(IdempotentInstCount, MBB);
384  LLVM_DEBUG(dbgs() << "MBB After Scheduling:\n"; MBB->dump(););
385 
386  Changed |= Renamer.renameVRegs(MBB, BasicBlockNum);
387 
388  // TODO: Consider dropping this. Dropping kill defs is probably not
389  // semantically sound.
390  Changed |= doDefKillClear(MBB);
391 
392  LLVM_DEBUG(dbgs() << "Updated MachineBasicBlock:\n"; MBB->dump();
393  dbgs() << "\n";);
394  LLVM_DEBUG(
395  dbgs() << "\n\n================================================\n\n");
396  return Changed;
397 }
398 
399 bool MIRCanonicalizer::runOnMachineFunction(MachineFunction &MF) {
400 
401  static unsigned functionNum = 0;
402  if (CanonicalizeFunctionNumber != ~0U) {
403  if (CanonicalizeFunctionNumber != functionNum++)
404  return false;
405  LLVM_DEBUG(dbgs() << "\n Canonicalizing Function " << MF.getName()
406  << "\n";);
407  }
408 
409  // we need a valid vreg to create a vreg type for skipping all those
410  // stray vreg numbers so reach alignment/canonical vreg values.
411  std::vector<MachineBasicBlock *> RPOList = GetRPOList(MF);
412 
413  LLVM_DEBUG(
414  dbgs() << "\n\n NEW MACHINE FUNCTION: " << MF.getName() << " \n\n";
415  dbgs() << "\n\n================================================\n\n";
416  dbgs() << "Total Basic Blocks: " << RPOList.size() << "\n";
417  for (auto MBB
418  : RPOList) { dbgs() << MBB->getName() << "\n"; } dbgs()
419  << "\n\n================================================\n\n";);
420 
421  unsigned BBNum = 0;
422  bool Changed = false;
424  VRegRenamer Renamer(MRI);
425  for (auto MBB : RPOList)
426  Changed |= runOnBasicBlock(MBB, BBNum++, Renamer);
427 
428  return Changed;
429 }
i
i
Definition: README.txt:29
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:103
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
runOnBasicBlock
static bool runOnBasicBlock(MachineBasicBlock *MBB, unsigned BasicBlockNum, VRegRenamer &Renamer)
Definition: MIRCanonicalizerPass.cpp:365
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:52
llvm::MachineBasicBlock::instrs
instr_range instrs()
Definition: MachineBasicBlock.h:263
canonicalizer
mir canonicalizer
Definition: MIRCanonicalizerPass.cpp:76
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
MIRVRegNamerUtils.h
propagateLocalCopies
static bool propagateLocalCopies(MachineBasicBlock *MBB)
Definition: MIRCanonicalizerPass.cpp:296
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
Canonically
mir Rename Register Operands Canonically
Definition: MIRCanonicalizerPass.cpp:77
rescheduleCanonically
static bool rescheduleCanonically(unsigned &PseudoIdempotentInstCount, MachineBasicBlock *MBB)
Definition: MIRCanonicalizerPass.cpp:130
Instructions
Code Generation Notes for reduce the size of the ISel and reduce repetition in the implementation In a small number of this can cause even when no optimisation has taken place Instructions
Definition: MSA.txt:11
STLExtras.h
llvm::MachineOperand::dump
void dump() const
Definition: MachineOperand.cpp:969
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::MIRCanonicalizerID
char & MIRCanonicalizerID
MIRCanonicalizer - This pass canonicalizes MIR by renaming vregs according to the semantics of the in...
Definition: MIRCanonicalizerPass.cpp:71
MachineRegisterInfo.h
Uses
SmallPtrSet< MachineInstr *, 2 > Uses
Definition: ARMLowOverheadLoops.cpp:588
a
=0.0 ? 0.0 :(a > 0.0 ? 1.0 :-1.0) a
Definition: README.txt:489
llvm::MachineBasicBlock::dump
void dump() const
Definition: MachineBasicBlock.cpp:295
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:636
llvm::MachineRegisterInfo::use_nodbg_operands
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
Definition: MachineRegisterInfo.h:526
llvm::VRegRenamer::renameVRegs
bool renameVRegs(MachineBasicBlock *MBB, unsigned BBNum)
Same as the above, but sets a BBNum depending on BB traversal that will be used as prefix for the vre...
Definition: MIRVRegNamerUtils.h:89
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
false
Definition: StackSlotColoring.cpp:142
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:186
Copies
SI Lower i1 Copies
Definition: SILowerI1Copies.cpp:406
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:78
llvm::MachineRegisterInfo::getRegClass
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Definition: MachineRegisterInfo.h:634
Passes.h
llvm::cl::opt
Definition: CommandLine.h:1434
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:321
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1616
MachineFunctionPass.h
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(MIRCanonicalizer, "mir-canonicalizer", "Rename Register Operands Canonically", false, false) INITIALIZE_PASS_END(MIRCanonicalizer
llvm::Register::isVirtualRegister
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
llvm::MachineRegisterInfo::getRegClassOrNull
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
Definition: MachineRegisterInfo.h:651
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:541
llvm::MachineBasicBlock::getParent
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Definition: MachineBasicBlock.h:225
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:83
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::MachineBasicBlock::instr_begin
instr_iterator instr_begin()
Definition: MachineBasicBlock.h:252
llvm::MachineBasicBlock::instr_end
instr_iterator instr_end()
Definition: MachineBasicBlock.h:254
llvm::MachineFunction
Definition: MachineFunction.h:230
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MachineBasicBlock::splice
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Definition: MachineBasicBlock.h:950
llvm::MachineRegisterInfo::use_begin
use_iterator use_begin(Register RegNo) const
Definition: MachineRegisterInfo.h:464
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1748
rescheduleLexographically
static bool rescheduleLexographically(std::vector< MachineInstr * > instructions, MachineBasicBlock *MBB, std::function< MachineBasicBlock::iterator()> getPos)
Definition: MIRCanonicalizerPass.cpp:90
llvm::MachineOperand::isDef
bool isDef() const
Definition: MachineOperand.h:375
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::MachineInstr::getParent
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:286
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::find_if
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1578
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
std
Definition: BitVector.h:838
doDefKillClear
static bool doDefKillClear(MachineBasicBlock *MBB)
Definition: MIRCanonicalizerPass.cpp:343
GetRPOList
mir Rename Register Operands static false std::vector< MachineBasicBlock * > GetRPOList(MachineFunction &MF)
Definition: MIRCanonicalizerPass.cpp:79
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1492
llvm::VRegRenamer
VRegRenamer - This class is used for renaming vregs in a machine basic block according to semantics o...
Definition: MIRVRegNamerUtils.h:34
llvm::cl::value_desc
Definition: CommandLine.h:424
llvm::ReversePostOrderTraversal
Definition: PostOrderIterator.h:290
llvm::MachineRegisterInfo::use_end
static use_iterator use_end()
Definition: MachineRegisterInfo.h:467
PostOrderIterator.h
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:268
MachineInstrBuilder.h
llvm::cl::desc
Definition: CommandLine.h:414
raw_ostream.h
llvm::MachineInstrBundleIterator< MachineInstr >
InitializePasses.h
llvm::MachineBasicBlock::getName
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
Definition: MachineBasicBlock.cpp:314
Debug.h
CanonicalizeFunctionNumber
static cl::opt< unsigned > CanonicalizeFunctionNumber("canon-nth-function", cl::Hidden, cl::init(~0u), cl::value_desc("N"), cl::desc("Function number to canonicalize."))
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37