LLVM  14.0.0git
FixIrreducible.cpp
Go to the documentation of this file.
1 //===- FixIrreducible.cpp - Convert irreducible control-flow into loops ---===//
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 // An irreducible SCC is one which has multiple "header" blocks, i.e., blocks
10 // with control-flow edges incident from outside the SCC. This pass converts a
11 // irreducible SCC into a natural loop by applying the following transformation:
12 //
13 // 1. Collect the set of headers H of the SCC.
14 // 2. Collect the set of predecessors P of these headers. These may be inside as
15 // well as outside the SCC.
16 // 3. Create block N and redirect every edge from set P to set H through N.
17 //
18 // This converts the SCC into a natural loop with N as the header: N is the only
19 // block with edges incident from outside the SCC, and all backedges in the SCC
20 // are incident on N, i.e., for every backedge, the head now dominates the tail.
21 //
22 // INPUT CFG: The blocks A and B form an irreducible loop with two headers.
23 //
24 // Entry
25 // / \
26 // v v
27 // A ----> B
28 // ^ /|
29 // `----' |
30 // v
31 // Exit
32 //
33 // OUTPUT CFG: Edges incident on A and B are now redirected through a
34 // new block N, forming a natural loop consisting of N, A and B.
35 //
36 // Entry
37 // |
38 // v
39 // .---> N <---.
40 // / / \ \
41 // | / \ |
42 // \ v v /
43 // `-- A B --'
44 // |
45 // v
46 // Exit
47 //
48 // The transformation is applied to every maximal SCC that is not already
49 // recognized as a loop. The pass operates on all maximal SCCs found in the
50 // function body outside of any loop, as well as those found inside each loop,
51 // including inside any newly created loops. This ensures that any SCC hidden
52 // inside a maximal SCC is also transformed.
53 //
54 // The actual transformation is handled by function CreateControlFlowHub, which
55 // takes a set of incoming blocks (the predecessors) and outgoing blocks (the
56 // headers). The function also moves every PHINode in an outgoing block to the
57 // hub. Since the hub dominates all the outgoing blocks, each such PHINode
58 // continues to dominate its uses. Since every header in an SCC has at least two
59 // predecessors, every value used in the header (or later) but defined in a
60 // predecessor (or earlier) is represented by a PHINode in a header. Hence the
61 // above handling of PHINodes is sufficient and no further processing is
62 // required to restore SSA.
63 //
64 // Limitation: The pass cannot handle switch statements and indirect
65 // branches. Both must be lowered to plain branches first.
66 //
67 //===----------------------------------------------------------------------===//
68 
70 #include "llvm/ADT/SCCIterator.h"
72 #include "llvm/InitializePasses.h"
73 #include "llvm/Pass.h"
74 #include "llvm/Transforms/Utils.h"
76 
77 #define DEBUG_TYPE "fix-irreducible"
78 
79 using namespace llvm;
80 
81 namespace {
82 struct FixIrreducible : public FunctionPass {
83  static char ID;
84  FixIrreducible() : FunctionPass(ID) {
86  }
87 
88  void getAnalysisUsage(AnalysisUsage &AU) const override {
95  }
96 
97  bool runOnFunction(Function &F) override;
98 };
99 } // namespace
100 
101 char FixIrreducible::ID = 0;
102 
103 FunctionPass *llvm::createFixIrreduciblePass() { return new FixIrreducible(); }
104 
105 INITIALIZE_PASS_BEGIN(FixIrreducible, "fix-irreducible",
106  "Convert irreducible control-flow into natural loops",
107  false /* Only looks at CFG */, false /* Analysis Pass */)
108 INITIALIZE_PASS_DEPENDENCY(LowerSwitchLegacyPass)
112  "Convert irreducible control-flow into natural loops",
113  false /* Only looks at CFG */, false /* Analysis Pass */)
114 
115 // When a new loop is created, existing children of the parent loop may now be
116 // fully inside the new loop. Reconnect these as children of the new loop.
117 static void reconnectChildLoops(LoopInfo &LI, Loop *ParentLoop, Loop *NewLoop,
118  SetVector<BasicBlock *> &Blocks,
119  SetVector<BasicBlock *> &Headers) {
120  auto &CandidateLoops = ParentLoop ? ParentLoop->getSubLoopsVector()
121  : LI.getTopLevelLoopsVector();
122  // The new loop cannot be its own child, and any candidate is a
123  // child iff its header is owned by the new loop. Move all the
124  // children to a new vector.
125  auto FirstChild = std::partition(
126  CandidateLoops.begin(), CandidateLoops.end(), [&](Loop *L) {
127  return L == NewLoop || !Blocks.contains(L->getHeader());
128  });
129  SmallVector<Loop *, 8> ChildLoops(FirstChild, CandidateLoops.end());
130  CandidateLoops.erase(FirstChild, CandidateLoops.end());
131 
132  for (Loop *Child : ChildLoops) {
133  LLVM_DEBUG(dbgs() << "child loop: " << Child->getHeader()->getName()
134  << "\n");
135  // TODO: A child loop whose header is also a header in the current
136  // SCC gets destroyed since its backedges are removed. That may
137  // not be necessary if we can retain such backedges.
138  if (Headers.count(Child->getHeader())) {
139  for (auto BB : Child->blocks()) {
140  LI.changeLoopFor(BB, NewLoop);
141  LLVM_DEBUG(dbgs() << "moved block from child: " << BB->getName()
142  << "\n");
143  }
144  LI.destroy(Child);
145  LLVM_DEBUG(dbgs() << "subsumed child loop (common header)\n");
146  continue;
147  }
148 
149  Child->setParentLoop(nullptr);
150  NewLoop->addChildLoop(Child);
151  LLVM_DEBUG(dbgs() << "added child loop to new loop\n");
152  }
153 }
154 
155 // Given a set of blocks and headers in an irreducible SCC, convert it into a
156 // natural loop. Also insert this new loop at its appropriate place in the
157 // hierarchy of loops.
159  Loop *ParentLoop,
160  SetVector<BasicBlock *> &Blocks,
161  SetVector<BasicBlock *> &Headers) {
162 #ifndef NDEBUG
163  // All headers are part of the SCC
164  for (auto H : Headers) {
165  assert(Blocks.count(H));
166  }
167 #endif
168 
169  SetVector<BasicBlock *> Predecessors;
170  for (auto H : Headers) {
171  for (auto P : predecessors(H)) {
172  Predecessors.insert(P);
173  }
174  }
175 
176  LLVM_DEBUG(
177  dbgs() << "Found predecessors:";
178  for (auto P : Predecessors) {
179  dbgs() << " " << P->getName();
180  }
181  dbgs() << "\n");
182 
183  // Redirect all the backedges through a "hub" consisting of a series
184  // of guard blocks that manage the flow of control from the
185  // predecessors to the headers.
186  SmallVector<BasicBlock *, 8> GuardBlocks;
188  CreateControlFlowHub(&DTU, GuardBlocks, Predecessors, Headers, "irr");
189 #if defined(EXPENSIVE_CHECKS)
191 #else
193 #endif
194 
195  // Create a new loop from the now-transformed cycle
196  auto NewLoop = LI.AllocateLoop();
197  if (ParentLoop) {
198  ParentLoop->addChildLoop(NewLoop);
199  } else {
200  LI.addTopLevelLoop(NewLoop);
201  }
202 
203  // Add the guard blocks to the new loop. The first guard block is
204  // the head of all the backedges, and it is the first to be inserted
205  // in the loop. This ensures that it is recognized as the
206  // header. Since the new loop is already in LoopInfo, the new blocks
207  // are also propagated up the chain of parent loops.
208  for (auto G : GuardBlocks) {
209  LLVM_DEBUG(dbgs() << "added guard block: " << G->getName() << "\n");
210  NewLoop->addBasicBlockToLoop(G, LI);
211  }
212 
213  // Add the SCC blocks to the new loop.
214  for (auto BB : Blocks) {
215  NewLoop->addBlockEntry(BB);
216  if (LI.getLoopFor(BB) == ParentLoop) {
217  LLVM_DEBUG(dbgs() << "moved block from parent: " << BB->getName()
218  << "\n");
219  LI.changeLoopFor(BB, NewLoop);
220  } else {
221  LLVM_DEBUG(dbgs() << "added block from child: " << BB->getName() << "\n");
222  }
223  }
224  LLVM_DEBUG(dbgs() << "header for new loop: "
225  << NewLoop->getHeader()->getName() << "\n");
226 
227  reconnectChildLoops(LI, ParentLoop, NewLoop, Blocks, Headers);
228 
229  NewLoop->verifyLoop();
230  if (ParentLoop) {
231  ParentLoop->verifyLoop();
232  }
233 #if defined(EXPENSIVE_CHECKS)
234  LI.verify(DT);
235 #endif // EXPENSIVE_CHECKS
236 }
237 
238 namespace llvm {
239 // Enable the graph traits required for traversing a Loop body.
240 template <> struct GraphTraits<Loop> : LoopBodyTraits {};
241 } // namespace llvm
242 
243 // Overloaded wrappers to go with the function template below.
244 static BasicBlock *unwrapBlock(BasicBlock *B) { return B; }
245 static BasicBlock *unwrapBlock(LoopBodyTraits::NodeRef &N) { return N.second; }
246 
248  SetVector<BasicBlock *> &Blocks,
249  SetVector<BasicBlock *> &Headers) {
250  createNaturalLoopInternal(LI, DT, nullptr, Blocks, Headers);
251 }
252 
253 static void createNaturalLoop(LoopInfo &LI, DominatorTree &DT, Loop &L,
254  SetVector<BasicBlock *> &Blocks,
255  SetVector<BasicBlock *> &Headers) {
256  createNaturalLoopInternal(LI, DT, &L, Blocks, Headers);
257 }
258 
259 // Convert irreducible SCCs; Graph G may be a Function* or a Loop&.
260 template <class Graph>
261 static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G) {
262  bool Changed = false;
263  for (auto Scc = scc_begin(G); !Scc.isAtEnd(); ++Scc) {
264  if (Scc->size() < 2)
265  continue;
267  LLVM_DEBUG(dbgs() << "Found SCC:");
268  for (auto N : *Scc) {
269  auto BB = unwrapBlock(N);
270  LLVM_DEBUG(dbgs() << " " << BB->getName());
271  Blocks.insert(BB);
272  }
273  LLVM_DEBUG(dbgs() << "\n");
274 
275  // Minor optimization: The SCC blocks are usually discovered in an order
276  // that is the opposite of the order in which these blocks appear as branch
277  // targets. This results in a lot of condition inversions in the control
278  // flow out of the new ControlFlowHub, which can be mitigated if the orders
279  // match. So we discover the headers using the reverse of the block order.
280  SetVector<BasicBlock *> Headers;
281  LLVM_DEBUG(dbgs() << "Found headers:");
282  for (auto BB : reverse(Blocks)) {
283  for (const auto P : predecessors(BB)) {
284  // Skip unreachable predecessors.
285  if (!DT.isReachableFromEntry(P))
286  continue;
287  if (!Blocks.count(P)) {
288  LLVM_DEBUG(dbgs() << " " << BB->getName());
289  Headers.insert(BB);
290  break;
291  }
292  }
293  }
294  LLVM_DEBUG(dbgs() << "\n");
295 
296  if (Headers.size() == 1) {
297  assert(LI.isLoopHeader(Headers.front()));
298  LLVM_DEBUG(dbgs() << "Natural loop with a single header: skipped\n");
299  continue;
300  }
301  createNaturalLoop(LI, DT, G, Blocks, Headers);
302  Changed = true;
303  }
304  return Changed;
305 }
306 
308  LLVM_DEBUG(dbgs() << "===== Fix irreducible control-flow in function: "
309  << F.getName() << "\n");
310 
311  bool Changed = false;
312  SmallVector<Loop *, 8> WorkList;
313 
314  LLVM_DEBUG(dbgs() << "visiting top-level\n");
315  Changed |= makeReducible(LI, DT, &F);
316 
317  // Any SCCs reduced are now already in the list of top-level loops, so simply
318  // add them all to the worklist.
319  append_range(WorkList, LI);
320 
321  while (!WorkList.empty()) {
322  auto L = WorkList.pop_back_val();
323  LLVM_DEBUG(dbgs() << "visiting loop with header "
324  << L->getHeader()->getName() << "\n");
325  Changed |= makeReducible(LI, DT, *L);
326  // Any SCCs reduced are now already in the list of child loops, so simply
327  // add them all to the worklist.
328  WorkList.append(L->begin(), L->end());
329  }
330 
331  return Changed;
332 }
333 
335  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
336  auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
337  return FixIrreducibleImpl(F, LI, DT);
338 }
339 
342  auto &LI = AM.getResult<LoopAnalysis>(F);
343  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
344  if (!FixIrreducibleImpl(F, LI, DT))
345  return PreservedAnalyses::all();
347  PA.preserve<LoopAnalysis>();
349  return PA;
350 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm::predecessors
pred_range predecessors(BasicBlock *BB)
Definition: CFG.h:127
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
SCCIterator.h
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:783
llvm::Function
Definition: Function.h:62
llvm::Loop
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:530
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
fix
arm execution domain fix
Definition: ARMTargetMachine.cpp:391
Pass.h
llvm::SetVector::size
size_type size() const
Determine the number of elements in the SetVector.
Definition: SetVector.h:77
llvm::createFixIrreduciblePass
FunctionPass * createFixIrreduciblePass()
Definition: FixIrreducible.cpp:103
llvm::SmallVector< Loop *, 8 >
llvm::LoopInfoBase::verify
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
Definition: LoopInfoImpl.h:690
llvm::FixIrreduciblePass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: FixIrreducible.cpp:340
llvm::LoopInfoBase::changeLoopFor
void changeLoopFor(BlockT *BB, LoopT *L)
Change the top-level loop that contains BB to the specified loop.
Definition: LoopInfo.h:1005
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:151
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:359
llvm::LoopInfoWrapperPass
The legacy pass manager's analysis pass to compute loop information.
Definition: LoopInfo.h:1268
irreducible
fix irreducible
Definition: FixIrreducible.cpp:111
reconnectChildLoops
fix Convert irreducible control flow into natural static false void reconnectChildLoops(LoopInfo &LI, Loop *ParentLoop, Loop *NewLoop, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
Definition: FixIrreducible.cpp:117
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(FixIrreducible, "fix-irreducible", "Convert irreducible control-flow into natural loops", false, false) INITIALIZE_PASS_END(FixIrreducible
FixIrreducible.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:635
llvm::Sched::Fast
@ Fast
Definition: TargetLowering.h:105
llvm::JumpTable::Full
@ Full
Definition: TargetOptions.h:50
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::LoopBodyTraits::NodeRef
std::pair< const Loop *, BasicBlock * > NodeRef
Definition: LoopIterator.h:41
unwrapBlock
static BasicBlock * unwrapBlock(BasicBlock *B)
Definition: FixIrreducible.cpp:244
llvm::SmallVectorImpl::append
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:648
llvm::CreateControlFlowHub
BasicBlock * CreateControlFlowHub(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const SetVector< BasicBlock * > &Predecessors, const SetVector< BasicBlock * > &Successors, const StringRef Prefix)
Given a set of incoming and outgoing blocks, create a "hub" such that every edge from an incoming blo...
llvm::LoopBase::addChildLoop
void addChildLoop(LoopT *NewChild)
Add the specified loop to be a child of this loop.
Definition: LoopInfo.h:395
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::LoopInfoBase::addTopLevelLoop
void addTopLevelLoop(LoopT *New)
This adds the specified loop to the collection of top-level loops.
Definition: LoopInfo.h:1024
false
Definition: StackSlotColoring.cpp:142
makeReducible
static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G)
Definition: FixIrreducible.cpp:261
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::LoopBase::verifyLoop
void verifyLoop() const
Verify loop structure.
Definition: LoopInfoImpl.h:286
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:287
llvm::initializeFixIrreduciblePass
void initializeFixIrreduciblePass(PassRegistry &)
llvm::DomTreeUpdater
Definition: DomTreeUpdater.h:28
Utils.h
LoopIterator.h
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::LoopInfoBase::AllocateLoop
LoopT * AllocateLoop(ArgsTy &&... Args)
Definition: LoopInfo.h:931
llvm::scc_begin
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
Definition: SCCIterator.h:228
into
Clang compiles this into
Definition: README.txt:504
createNaturalLoop
static void createNaturalLoop(LoopInfo &LI, DominatorTree &DT, Function *F, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
Definition: FixIrreducible.cpp:247
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::LoopBodyTraits
Definition: LoopIterator.h:40
llvm::PreservedAnalyses::preserve
void preserve()
Mark an analysis as preserved.
Definition: PassManager.h:176
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::LoopInfoBase::getLoopFor
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Definition: LoopInfo.h:967
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::DominatorTree::isReachableFromEntry
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
Definition: Dominators.cpp:328
llvm::SetVector::insert
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:141
llvm::LoopInfo
Definition: LoopInfo.h:1083
llvm::AnalysisUsage::addPreservedID
AnalysisUsage & addPreservedID(const void *ID)
Definition: PassAnalysisSupport.h:88
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1778
llvm::DomTreeUpdater::UpdateStrategy::Eager
@ Eager
llvm::partition
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1685
llvm::LowerSwitchID
char & LowerSwitchID
Definition: LowerSwitch.cpp:570
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::LoopInfoBase::isLoopHeader
bool isLoopHeader(const BlockT *BB) const
Definition: LoopInfo.h:980
H
#define H(x, y, z)
Definition: MD5.cpp:58
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::SetVector::count
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition: SetVector.h:215
llvm::SetVector::front
const T & front() const
Return the first element of the SetVector.
Definition: SetVector.h:122
FixIrreducibleImpl
static bool FixIrreducibleImpl(Function &F, LoopInfo &LI, DominatorTree &DT)
Definition: FixIrreducible.cpp:307
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:252
N
#define N
llvm::DominatorTreeBase::verify
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Definition: GenericDomTree.h:802
createNaturalLoopInternal
static void createNaturalLoopInternal(LoopInfo &LI, DominatorTree &DT, Loop *ParentLoop, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
Definition: FixIrreducible.cpp:158
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::AnalysisUsage::addRequiredID
AnalysisUsage & addRequiredID(const void *ID)
Definition: Pass.cpp:267
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::GraphTraits
Definition: GraphTraits.h:35
loops
fix Convert irreducible control flow into natural loops
Definition: FixIrreducible.cpp:112
llvm::SetVector
A vector that has set insertion semantics.
Definition: SetVector.h:40
BasicBlockUtils.h
InitializePasses.h
llvm::LoopAnalysis
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:1243
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38