LLVM  16.0.0git
x86_64.h
Go to the documentation of this file.
1 //===-- x86_64.h - Generic JITLink x86-64 edge kinds, utilities -*- C++ -*-===//
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 // Generic utilities for graphs representing x86-64 objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_JITLINK_X86_64_H
14 #define LLVM_EXECUTIONENGINE_JITLINK_X86_64_H
15 
18 
19 #include <limits>
20 
21 namespace llvm {
22 namespace jitlink {
23 namespace x86_64 {
24 
25 /// Represents x86-64 fixups and other x86-64-specific edge kinds.
27 
28  /// A plain 64-bit pointer value relocation.
29  ///
30  /// Fixup expression:
31  /// Fixup <- Target + Addend : uint64
32  ///
34 
35  /// A plain 32-bit pointer value relocation.
36  ///
37  /// Fixup expression:
38  /// Fixup <- Target + Addend : uint32
39  ///
40  /// Errors:
41  /// - The target must reside in the low 32-bits of the address space,
42  /// otherwise an out-of-range error will be returned.
43  ///
45 
46  /// A signed 32-bit pointer value relocation
47  ///
48  /// Fixup expression:
49  /// Fixup <- Target + Addend : int32
50  ///
51  /// Errors:
52  /// - The target must reside in the signed 32-bits([-2**31, 2**32 - 1]) of
53  /// the address space, otherwise an out-of-range error will be returned.
55 
56  /// A plain 16-bit pointer value relocation.
57  ///
58  /// Fixup expression:
59  /// Fixup <- Target + Addend : uint16
60  ///
61  /// Errors:
62  /// - The target must reside in the low 16-bits of the address space,
63  /// otherwise an out-of-range error will be returned.
64  ///
66 
67  /// A 64-bit delta.
68  ///
69  /// Delta from the fixup to the target.
70  ///
71  /// Fixup expression:
72  /// Fixup <- Target - Fixup + Addend : int64
73  ///
75 
76  /// A 32-bit delta.
77  ///
78  /// Delta from the fixup to the target.
79  ///
80  /// Fixup expression:
81  /// Fixup <- Target - Fixup + Addend : int64
82  ///
83  /// Errors:
84  /// - The result of the fixup expression must fit into an int32, otherwise
85  /// an out-of-range error will be returned.
86  ///
88 
89  /// A 64-bit negative delta.
90  ///
91  /// Delta from target back to the fixup.
92  ///
93  /// Fixup expression:
94  /// Fixup <- Fixup - Target + Addend : int64
95  ///
97 
98  /// A 32-bit negative delta.
99  ///
100  /// Delta from the target back to the fixup.
101  ///
102  /// Fixup expression:
103  /// Fixup <- Fixup - Target + Addend : int32
104  ///
105  /// Errors:
106  /// - The result of the fixup expression must fit into an int32, otherwise
107  /// an out-of-range error will be returned.
109 
110  /// A 64-bit GOT delta.
111  ///
112  /// Delta from the global offset table to the target
113  ///
114  /// Fixup expression:
115  /// Fixup <- Target - GOTSymbol + Addend : int64
116  ///
117  /// Errors:
118  /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
119  /// symbol was not been defined.
121 
122  /// A 32-bit PC-relative branch.
123  ///
124  /// Represents a PC-relative call or branch to a target. This can be used to
125  /// identify, record, and/or patch call sites.
126  ///
127  /// The fixup expression for this kind includes an implicit offset to account
128  /// for the PC (unlike the Delta edges) so that a Branch32PCRel with a target
129  /// T and addend zero is a call/branch to the start (offset zero) of T.
130  ///
131  /// Fixup expression:
132  /// Fixup <- Target - (Fixup + 4) + Addend : int32
133  ///
134  /// Errors:
135  /// - The result of the fixup expression must fit into an int32, otherwise
136  /// an out-of-range error will be returned.
137  ///
139 
140  /// A 32-bit PC-relative relocation.
141  ///
142  /// Represents a data/control flow instruction using PC-relative addressing
143  /// to a target.
144  ///
145  /// The fixup expression for this kind includes an implicit offset to account
146  /// for the PC (unlike the Delta edges) so that a PCRel32 with a target
147  /// T and addend zero is a call/branch to the start (offset zero) of T.
148  ///
149  /// Fixup expression:
150  /// Fixup <- Target - (Fixup + 4) + Addend : int32
151  ///
152  /// Errors:
153  /// - The result of the fixup expression must fit into an int32, otherwise
154  /// an out-of-range error will be returned.
155  ///
157 
158  /// A 32-bit PC-relative branch to a pointer jump stub.
159  ///
160  /// The target of this relocation should be a pointer jump stub of the form:
161  ///
162  /// \code{.s}
163  /// .text
164  /// jmpq *tgtptr(%rip)
165  /// ; ...
166  ///
167  /// .data
168  /// tgtptr:
169  /// .quad 0
170  /// \endcode
171  ///
172  /// This edge kind has the same fixup expression as BranchPCRel32, but further
173  /// identifies the call/branch as being to a pointer jump stub. For edges of
174  /// this kind the jump stub should not be bypassed (use
175  /// BranchPCRel32ToPtrJumpStubBypassable for that), but the pointer location
176  /// target may be recorded to allow manipulation at runtime.
177  ///
178  /// Fixup expression:
179  /// Fixup <- Target - Fixup + Addend - 4 : int32
180  ///
181  /// Errors:
182  /// - The result of the fixup expression must fit into an int32, otherwise
183  /// an out-of-range error will be returned.
184  ///
186 
187  /// A relaxable version of BranchPCRel32ToPtrJumpStub.
188  ///
189  /// The edge kind has the same fixup expression as BranchPCRel32ToPtrJumpStub,
190  /// but identifies the call/branch as being to a pointer jump stub that may be
191  /// bypassed with a direct jump to the ultimate target if the ultimate target
192  /// is within range of the fixup location.
193  ///
194  /// Fixup expression:
195  /// Fixup <- Target - Fixup + Addend - 4: int32
196  ///
197  /// Errors:
198  /// - The result of the fixup expression must fit into an int32, otherwise
199  /// an out-of-range error will be returned.
200  ///
202 
203  /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
204  /// entry for the original target.
205  ///
206  /// Indicates that this edge should be transformed into a Delta32 targeting
207  /// the GOT entry for the edge's current target, maintaining the same addend.
208  /// A GOT entry for the target should be created if one does not already
209  /// exist.
210  ///
211  /// Edges of this kind are usually handled by a GOT builder pass inserted by
212  /// default.
213  ///
214  /// Fixup expression:
215  /// NONE
216  ///
217  /// Errors:
218  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
219  /// phase will result in an assert/unreachable during the fixup phase.
220  ///
222 
223  /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT
224  /// entry for the original target.
225  ///
226  /// Indicates that this edge should be transformed into a Delta64 targeting
227  /// the GOT entry for the edge's current target, maintaining the same addend.
228  /// A GOT entry for the target should be created if one does not already
229  /// exist.
230  ///
231  /// Edges of this kind are usually handled by a GOT builder pass inserted by
232  /// default.
233  ///
234  /// Fixup expression:
235  /// NONE
236  ///
237  /// Errors:
238  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
239  /// phase will result in an assert/unreachable during the fixup phase.
240  ///
242 
243  /// A GOT entry offset within GOT getter/constructor, transformed to
244  /// Delta64FromGOT
245  /// pointing at the GOT entry for the original target
246  ///
247  /// Indicates that this edge should be transformed into a Delta64FromGOT
248  /// targeting
249  /// the GOT entry for the edge's current target, maintaining the same addend.
250  /// A GOT entry for the target should be created if one does not already
251  /// exist.
252  ///
253  /// Edges of this kind are usually handled by a GOT builder pass inserted by
254  /// default
255  ///
256  /// Fixup expression:
257  /// NONE
258  ///
259  /// Errors:
260  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
261  /// phase will result in an assert/unreachable during the fixup phase
263 
264  /// A PC-relative load of a GOT entry, relaxable if GOT entry target is
265  /// in-range of the fixup
266  ///
267  /// TODO: Explain the optimization
268  ///
269  /// Fixup expression
270  /// Fixup <- Target - (Fixup + 4) + Addend : int32
271  ///
272  /// Errors:
273  /// - The result of the fixup expression must fit into an int32, otherwise
274  /// an out-of-range error will be returned.
275  //
277 
278  /// A PC-relative REX load of a GOT entry, relaxable if GOT entry target
279  /// is in-range of the fixup.
280  ///
281  /// If the GOT entry target is in-range of the fixup then the load from the
282  /// GOT may be replaced with a direct memory address calculation.
283  ///
284  /// Fixup expression:
285  /// Fixup <- Target - (Fixup + 4) + Addend : int32
286  ///
287  /// Errors:
288  /// - The result of the fixup expression must fit into an int32, otherwise
289  /// an out-of-range error will be returned.
290  ///
292 
293  /// A GOT entry getter/constructor, transformed to
294  /// PCRel32ToGOTLoadREXRelaxable pointing at the GOT entry for the original
295  /// target.
296  ///
297  /// Indicates that this edge should be lowered to a PC32ToGOTLoadREXRelaxable
298  /// targeting the GOT entry for the edge's current target, maintaining the
299  /// same addend. A GOT entry for the target should be created if one does not
300  /// already exist.
301  ///
302  /// Edges of this kind are usually lowered by a GOT builder pass inserted by
303  /// default.
304  ///
305  /// Fixup expression:
306  /// NONE
307  ///
308  /// Errors:
309  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
310  /// phase will result in an assert/unreachable during the fixup phase.
311  ///
313 
314  /// A GOT entry getter/constructor, transformed to
315  /// PCRel32ToGOTLoadRelaxable pointing at the GOT entry for the original
316  /// target.
317  ///
318  /// Indicates that this edge should be lowered to a PC32ToGOTLoadRelaxable
319  /// targeting the GOT entry for the edge's current target, maintaining the
320  /// same addend. A GOT entry for the target should be created if one does not
321  /// already exist.
322  ///
323  /// Edges of this kind are usually lowered by a GOT builder pass inserted by
324  /// default.
325  ///
326  /// Fixup expression:
327  /// NONE
328  ///
329  /// Errors:
330  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
331  /// phase will result in an assert/unreachable during the fixup phase.
332  ///
334 
335  /// A PC-relative REX load of a Thread Local Variable Pointer (TLVP) entry,
336  /// relaxable if the TLVP entry target is in-range of the fixup.
337  ///
338  /// If the TLVP entry target is in-range of the fixup then the load from the
339  /// TLVP may be replaced with a direct memory address calculation.
340  ///
341  /// The target of this edge must be a thread local variable entry of the form
342  /// .quad <tlv getter thunk>
343  /// .quad <tlv key>
344  /// .quad <tlv initializer>
345  ///
346  /// Fixup expression:
347  /// Fixup <- Target - (Fixup + 4) + Addend : int32
348  ///
349  /// Errors:
350  /// - The result of the fixup expression must fit into an int32, otherwise
351  /// an out-of-range error will be returned.
352  /// - The target must be either external, or a TLV entry of the required
353  /// form, otherwise a malformed TLV entry error will be returned.
354  ///
356 
357  /// TODO: Explain the generic edge kind
359 
360  /// A TLVP entry getter/constructor, transformed to
361  /// Delta32ToTLVPLoadREXRelaxable.
362  ///
363  /// Indicates that this edge should be transformed into a
364  /// Delta32ToTLVPLoadREXRelaxable targeting the TLVP entry for the edge's
365  /// current target. A TLVP entry for the target should be created if one does
366  /// not already exist.
367  ///
368  /// Fixup expression:
369  /// NONE
370  ///
371  /// Errors:
372  /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
373  /// phase will result in an assert/unreachable during the fixup phase.
374  ///
376  // First platform specific relocation.
378 };
379 
380 /// Returns a string name for the given x86-64 edge. For debugging purposes
381 /// only.
382 const char *getEdgeKindName(Edge::Kind K);
383 
384 /// Returns true if the given uint64_t value is in range for a uint32_t.
387 }
388 
389 /// Returns true if the given int64_t value is in range for an int32_t.
390 inline bool isInRangeForImmS32(int64_t Value) {
393 }
394 
395 /// Apply fixup expression for edge to block content.
396 inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
397  const Symbol *GOTSymbol) {
398  using namespace support;
399 
400  char *BlockWorkingMem = B.getAlreadyMutableContent().data();
401  char *FixupPtr = BlockWorkingMem + E.getOffset();
402  auto FixupAddress = B.getAddress() + E.getOffset();
403 
404  switch (E.getKind()) {
405 
406  case Pointer64: {
407  uint64_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
408  *(ulittle64_t *)FixupPtr = Value;
409  break;
410  }
411 
412  case Pointer32: {
413  uint64_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
415  *(ulittle32_t *)FixupPtr = Value;
416  else
417  return makeTargetOutOfRangeError(G, B, E);
418  break;
419  }
420  case Pointer32Signed: {
421  int64_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
423  *(little32_t *)FixupPtr = Value;
424  else
425  return makeTargetOutOfRangeError(G, B, E);
426  break;
427  }
428 
429  case Pointer16: {
430  uint64_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
431  if (LLVM_LIKELY(isUInt<16>(Value)))
432  *(ulittle16_t *)FixupPtr = Value;
433  else
434  return makeTargetOutOfRangeError(G, B, E);
435  break;
436  }
437 
438  case PCRel32:
439  case BranchPCRel32:
445  int64_t Value =
446  E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
448  *(little32_t *)FixupPtr = Value;
449  else
450  return makeTargetOutOfRangeError(G, B, E);
451  break;
452  }
453 
454  case Delta64: {
455  int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
456  *(little64_t *)FixupPtr = Value;
457  break;
458  }
459 
460  case Delta32: {
461  int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
463  *(little32_t *)FixupPtr = Value;
464  else
465  return makeTargetOutOfRangeError(G, B, E);
466  break;
467  }
468 
469  case NegDelta64: {
470  int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
471  *(little64_t *)FixupPtr = Value;
472  break;
473  }
474 
475  case NegDelta32: {
476  int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
478  *(little32_t *)FixupPtr = Value;
479  else
480  return makeTargetOutOfRangeError(G, B, E);
481  break;
482  }
483  case Delta64FromGOT: {
484  assert(GOTSymbol && "No GOT section symbol");
485  int64_t Value =
486  E.getTarget().getAddress() - GOTSymbol->getAddress() + E.getAddend();
487  *(little64_t *)FixupPtr = Value;
488  break;
489  }
490 
491  default:
492  return make_error<JITLinkError>(
493  "In graph " + G.getName() + ", section " + B.getSection().getName() +
494  "unsupported edge kind" + getEdgeKindName(E.getKind()));
495  }
496 
497  return Error::success();
498 }
499 
500 /// x86_64 pointer size.
501 constexpr uint64_t PointerSize = 8;
502 
503 /// x86-64 null pointer content.
504 extern const char NullPointerContent[PointerSize];
505 
506 /// x86-64 pointer jump stub content.
507 ///
508 /// Contains the instruction sequence for an indirect jump via an in-memory
509 /// pointer:
510 /// jmpq *ptr(%rip)
511 extern const char PointerJumpStubContent[6];
512 
513 /// Creates a new pointer block in the given section and returns an anonymous
514 /// symbol pointing to it.
515 ///
516 /// If InitialTarget is given then an Pointer64 relocation will be added to the
517 /// block pointing at InitialTarget.
518 ///
519 /// The pointer block will have the following default values:
520 /// alignment: 64-bit
521 /// alignment-offset: 0
522 /// address: highest allowable (~7U)
523 inline Symbol &createAnonymousPointer(LinkGraph &G, Section &PointerSection,
524  Symbol *InitialTarget = nullptr,
525  uint64_t InitialAddend = 0) {
526  auto &B = G.createContentBlock(PointerSection, NullPointerContent,
527  orc::ExecutorAddr(~uint64_t(7)), 8, 0);
528  if (InitialTarget)
529  B.addEdge(Pointer64, 0, *InitialTarget, InitialAddend);
530  return G.addAnonymousSymbol(B, 0, 8, false, false);
531 }
532 
533 /// Create a jump stub block that jumps via the pointer at the given symbol.
534 ///
535 /// The stub block will have the following default values:
536 /// alignment: 8-bit
537 /// alignment-offset: 0
538 /// address: highest allowable: (~5U)
540  Symbol &PointerSymbol) {
541  auto &B = G.createContentBlock(StubSection, PointerJumpStubContent,
542  orc::ExecutorAddr(~uint64_t(5)), 1, 0);
543  B.addEdge(Delta32, 2, PointerSymbol, -4);
544  return B;
545 }
546 
547 /// Create a jump stub that jumps via the pointer at the given symbol and
548 /// an anonymous symbol pointing to it. Return the anonymous symbol.
549 ///
550 /// The stub block will be created by createPointerJumpStubBlock.
552  Section &StubSection,
553  Symbol &PointerSymbol) {
554  return G.addAnonymousSymbol(
555  createPointerJumpStubBlock(G, StubSection, PointerSymbol), 0, 6, true,
556  false);
557 }
558 
559 /// Global Offset Table Builder.
560 class GOTTableManager : public TableManager<GOTTableManager> {
561 public:
562  static StringRef getSectionName() { return "$__GOT"; }
563 
565  Edge::Kind KindToSet = Edge::Invalid;
566  switch (E.getKind()) {
567  case x86_64::Delta64FromGOT: {
568  // we need to make sure that the GOT section exists, but don't otherwise
569  // need to fix up this edge
570  getGOTSection(G);
571  return false;
572  }
575  break;
578  break;
580  KindToSet = x86_64::Delta64;
581  break;
583  KindToSet = x86_64::Delta64FromGOT;
584  break;
586  KindToSet = x86_64::Delta32;
587  break;
588  default:
589  return false;
590  }
591  assert(KindToSet != Edge::Invalid &&
592  "Fell through switch, but no new kind to set");
593  DEBUG_WITH_TYPE("jitlink", {
594  dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
595  << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
596  << formatv("{0:x}", E.getOffset()) << ")\n";
597  });
598  E.setKind(KindToSet);
599  E.setTarget(getEntryForTarget(G, E.getTarget()));
600  return true;
601  }
602 
604  return createAnonymousPointer(G, getGOTSection(G), &Target);
605  }
606 
607 private:
608  Section &getGOTSection(LinkGraph &G) {
609  if (!GOTSection)
610  GOTSection = &G.createSection(getSectionName(), MemProt::Read);
611  return *GOTSection;
612  }
613 
614  Section *GOTSection = nullptr;
615 };
616 
617 /// Procedure Linkage Table Builder.
618 class PLTTableManager : public TableManager<PLTTableManager> {
619 public:
621 
622  static StringRef getSectionName() { return "$__STUBS"; }
623 
625  if (E.getKind() == x86_64::BranchPCRel32 && !E.getTarget().isDefined()) {
626  DEBUG_WITH_TYPE("jitlink", {
627  dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
628  << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
629  << formatv("{0:x}", E.getOffset()) << ")\n";
630  });
631  // Set the edge kind to Branch32ToPtrJumpStubBypassable to enable it to
632  // be optimized when the target is in-range.
634  E.setTarget(getEntryForTarget(G, E.getTarget()));
635  return true;
636  }
637  return false;
638  }
639 
643  }
644 
645 public:
647  if (!PLTSection)
648  PLTSection =
649  &G.createSection(getSectionName(), MemProt::Read | MemProt::Exec);
650  return *PLTSection;
651  }
652 
654  Section *PLTSection = nullptr;
655 };
656 
657 /// Optimize the GOT and Stub relocations if the edge target address is in range
658 /// 1. PCRel32GOTLoadRelaxable. For this edge kind, if the target is in range,
659 /// then replace GOT load with lea
660 /// 2. BranchPCRel32ToPtrJumpStubRelaxable. For this edge kind, if the target is
661 /// in range, replace a indirect jump by plt stub with a direct jump to the
662 /// target
664 
665 } // namespace x86_64
666 } // end namespace jitlink
667 } // end namespace llvm
668 
669 #endif // LLVM_EXECUTIONENGINE_JITLINK_X86_64_H
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:31
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:145
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::max
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:337
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:251
llvm::support::little64_t
detail::packed_endian_specific_integral< int64_t, little, unaligned > little64_t
Definition: Endian.h:281
DEBUG_WITH_TYPE
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition: Debug.h:64
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::support::ulittle32_t
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:272
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::support::ulittle16_t
detail::packed_endian_specific_integral< uint16_t, little, unaligned > ulittle16_t
Definition: Endian.h:270
uint64_t
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::support::little32_t
detail::packed_endian_specific_integral< int32_t, little, unaligned > little32_t
Definition: Endian.h:279
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
TableManager.h
llvm::support::ulittle64_t
detail::packed_endian_specific_integral< uint64_t, little, unaligned > ulittle64_t
Definition: Endian.h:274
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
LLVM_LIKELY
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:209
llvm::Value
LLVM Value Representation.
Definition: Value.h:74