LLVM  14.0.0git
Trace.cpp
Go to the documentation of this file.
1 //===- Trace.cpp - XRay Trace Loading implementation. ---------------------===//
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 // XRay log reader implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 #include "llvm/XRay/Trace.h"
13 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/Support/Error.h"
17 #include "llvm/XRay/BlockIndexer.h"
21 #include "llvm/XRay/FDRRecords.h"
25 #include <memory>
26 #include <vector>
27 
28 using namespace llvm;
29 using namespace llvm::xray;
30 using llvm::yaml::Input;
31 
32 namespace {
33 using XRayRecordStorage =
34  std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
35 
36 Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian,
37  XRayFileHeader &FileHeader,
38  std::vector<XRayRecord> &Records) {
39  if (Data.size() < 32)
40  return make_error<StringError>(
41  "Not enough bytes for an XRay log.",
42  std::make_error_code(std::errc::invalid_argument));
43 
44  if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
45  return make_error<StringError>(
46  "Invalid-sized XRay data.",
47  std::make_error_code(std::errc::invalid_argument));
48 
49  DataExtractor Reader(Data, IsLittleEndian, 8);
50  uint64_t OffsetPtr = 0;
51  auto FileHeaderOrError = readBinaryFormatHeader(Reader, OffsetPtr);
52  if (!FileHeaderOrError)
53  return FileHeaderOrError.takeError();
54  FileHeader = std::move(FileHeaderOrError.get());
55 
56  // Each record after the header will be 32 bytes, in the following format:
57  //
58  // (2) uint16 : record type
59  // (1) uint8 : cpu id
60  // (1) uint8 : type
61  // (4) sint32 : function id
62  // (8) uint64 : tsc
63  // (4) uint32 : thread id
64  // (4) uint32 : process id
65  // (8) - : padding
66  while (Reader.isValidOffset(OffsetPtr)) {
67  if (!Reader.isValidOffsetForDataOfSize(OffsetPtr, 32))
68  return createStringError(
69  std::make_error_code(std::errc::executable_format_error),
70  "Not enough bytes to read a full record at offset %" PRId64 ".",
71  OffsetPtr);
72  auto PreReadOffset = OffsetPtr;
73  auto RecordType = Reader.getU16(&OffsetPtr);
74  if (OffsetPtr == PreReadOffset)
75  return createStringError(
76  std::make_error_code(std::errc::executable_format_error),
77  "Failed reading record type at offset %" PRId64 ".", OffsetPtr);
78 
79  switch (RecordType) {
80  case 0: { // Normal records.
81  Records.emplace_back();
82  auto &Record = Records.back();
83  Record.RecordType = RecordType;
84 
85  PreReadOffset = OffsetPtr;
86  Record.CPU = Reader.getU8(&OffsetPtr);
87  if (OffsetPtr == PreReadOffset)
88  return createStringError(
89  std::make_error_code(std::errc::executable_format_error),
90  "Failed reading CPU field at offset %" PRId64 ".", OffsetPtr);
91 
92  PreReadOffset = OffsetPtr;
93  auto Type = Reader.getU8(&OffsetPtr);
94  if (OffsetPtr == PreReadOffset)
95  return createStringError(
96  std::make_error_code(std::errc::executable_format_error),
97  "Failed reading record type field at offset %" PRId64 ".",
98  OffsetPtr);
99 
100  switch (Type) {
101  case 0:
102  Record.Type = RecordTypes::ENTER;
103  break;
104  case 1:
105  Record.Type = RecordTypes::EXIT;
106  break;
107  case 2:
109  break;
110  case 3:
112  break;
113  default:
114  return createStringError(
115  std::make_error_code(std::errc::executable_format_error),
116  "Unknown record type '%d' at offset %" PRId64 ".", Type, OffsetPtr);
117  }
118 
119  PreReadOffset = OffsetPtr;
120  Record.FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));
121  if (OffsetPtr == PreReadOffset)
122  return createStringError(
123  std::make_error_code(std::errc::executable_format_error),
124  "Failed reading function id field at offset %" PRId64 ".",
125  OffsetPtr);
126 
127  PreReadOffset = OffsetPtr;
128  Record.TSC = Reader.getU64(&OffsetPtr);
129  if (OffsetPtr == PreReadOffset)
130  return createStringError(
131  std::make_error_code(std::errc::executable_format_error),
132  "Failed reading TSC field at offset %" PRId64 ".", OffsetPtr);
133 
134  PreReadOffset = OffsetPtr;
135  Record.TId = Reader.getU32(&OffsetPtr);
136  if (OffsetPtr == PreReadOffset)
137  return createStringError(
138  std::make_error_code(std::errc::executable_format_error),
139  "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);
140 
141  PreReadOffset = OffsetPtr;
142  Record.PId = Reader.getU32(&OffsetPtr);
143  if (OffsetPtr == PreReadOffset)
144  return createStringError(
145  std::make_error_code(std::errc::executable_format_error),
146  "Failed reading process id at offset %" PRId64 ".", OffsetPtr);
147 
148  break;
149  }
150  case 1: { // Arg payload record.
151  auto &Record = Records.back();
152 
153  // We skip the next two bytes of the record, because we don't need the
154  // type and the CPU record for arg payloads.
155  OffsetPtr += 2;
156  PreReadOffset = OffsetPtr;
157  int32_t FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));
158  if (OffsetPtr == PreReadOffset)
159  return createStringError(
160  std::make_error_code(std::errc::executable_format_error),
161  "Failed reading function id field at offset %" PRId64 ".",
162  OffsetPtr);
163 
164  PreReadOffset = OffsetPtr;
165  auto TId = Reader.getU32(&OffsetPtr);
166  if (OffsetPtr == PreReadOffset)
167  return createStringError(
168  std::make_error_code(std::errc::executable_format_error),
169  "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);
170 
171  PreReadOffset = OffsetPtr;
172  auto PId = Reader.getU32(&OffsetPtr);
173  if (OffsetPtr == PreReadOffset)
174  return createStringError(
175  std::make_error_code(std::errc::executable_format_error),
176  "Failed reading process id field at offset %" PRId64 ".",
177  OffsetPtr);
178 
179  // Make a check for versions above 3 for the Pid field
180  if (Record.FuncId != FuncId || Record.TId != TId ||
181  (FileHeader.Version >= 3 ? Record.PId != PId : false))
182  return createStringError(
183  std::make_error_code(std::errc::executable_format_error),
184  "Corrupted log, found arg payload following non-matching "
185  "function+thread record. Record for function %d != %d at offset "
186  "%" PRId64 ".",
187  Record.FuncId, FuncId, OffsetPtr);
188 
189  PreReadOffset = OffsetPtr;
190  auto Arg = Reader.getU64(&OffsetPtr);
191  if (OffsetPtr == PreReadOffset)
192  return createStringError(
193  std::make_error_code(std::errc::executable_format_error),
194  "Failed reading argument payload at offset %" PRId64 ".",
195  OffsetPtr);
196 
197  Record.CallArgs.push_back(Arg);
198  break;
199  }
200  default:
201  return createStringError(
202  std::make_error_code(std::errc::executable_format_error),
203  "Unknown record type '%d' at offset %" PRId64 ".", RecordType,
204  OffsetPtr);
205  }
206  // Advance the offset pointer enough bytes to align to 32-byte records for
207  // basic mode logs.
208  OffsetPtr += 8;
209  }
210  return Error::success();
211 }
212 
213 /// Reads a log in FDR mode for version 1 of this binary format. FDR mode is
214 /// defined as part of the compiler-rt project in xray_fdr_logging.h, and such
215 /// a log consists of the familiar 32 bit XRayHeader, followed by sequences of
216 /// of interspersed 16 byte Metadata Records and 8 byte Function Records.
217 ///
218 /// The following is an attempt to document the grammar of the format, which is
219 /// parsed by this function for little-endian machines. Since the format makes
220 /// use of BitFields, when we support big-endian architectures, we will need to
221 /// adjust not only the endianness parameter to llvm's RecordExtractor, but also
222 /// the bit twiddling logic, which is consistent with the little-endian
223 /// convention that BitFields within a struct will first be packed into the
224 /// least significant bits the address they belong to.
225 ///
226 /// We expect a format complying with the grammar in the following pseudo-EBNF
227 /// in Version 1 of the FDR log.
228 ///
229 /// FDRLog: XRayFileHeader ThreadBuffer*
230 /// XRayFileHeader: 32 bytes to identify the log as FDR with machine metadata.
231 /// Includes BufferSize
232 /// ThreadBuffer: NewBuffer WallClockTime NewCPUId FunctionSequence EOB
233 /// BufSize: 8 byte unsigned integer indicating how large the buffer is.
234 /// NewBuffer: 16 byte metadata record with Thread Id.
235 /// WallClockTime: 16 byte metadata record with human readable time.
236 /// Pid: 16 byte metadata record with Pid
237 /// NewCPUId: 16 byte metadata record with CPUId and a 64 bit TSC reading.
238 /// EOB: 16 byte record in a thread buffer plus mem garbage to fill BufSize.
239 /// FunctionSequence: NewCPUId | TSCWrap | FunctionRecord
240 /// TSCWrap: 16 byte metadata record with a full 64 bit TSC reading.
241 /// FunctionRecord: 8 byte record with FunctionId, entry/exit, and TSC delta.
242 ///
243 /// In Version 2, we make the following changes:
244 ///
245 /// ThreadBuffer: BufferExtents NewBuffer WallClockTime NewCPUId
246 /// FunctionSequence
247 /// BufferExtents: 16 byte metdata record describing how many usable bytes are
248 /// in the buffer. This is measured from the start of the buffer
249 /// and must always be at least 48 (bytes).
250 ///
251 /// In Version 3, we make the following changes:
252 ///
253 /// ThreadBuffer: BufferExtents NewBuffer WallClockTime Pid NewCPUId
254 /// FunctionSequence
255 /// EOB: *deprecated*
256 ///
257 /// In Version 4, we make the following changes:
258 ///
259 /// CustomEventRecord now includes the CPU data.
260 ///
261 /// In Version 5, we make the following changes:
262 ///
263 /// CustomEventRecord and TypedEventRecord now use TSC delta encoding similar to
264 /// what FunctionRecord instances use, and we no longer need to include the CPU
265 /// id in the CustomEventRecord.
266 ///
267 Error loadFDRLog(StringRef Data, bool IsLittleEndian,
268  XRayFileHeader &FileHeader, std::vector<XRayRecord> &Records) {
269 
270  if (Data.size() < 32)
271  return createStringError(std::make_error_code(std::errc::invalid_argument),
272  "Not enough bytes for an XRay FDR log.");
273  DataExtractor DE(Data, IsLittleEndian, 8);
274 
275  uint64_t OffsetPtr = 0;
276  auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr);
277  if (!FileHeaderOrError)
278  return FileHeaderOrError.takeError();
279  FileHeader = std::move(FileHeaderOrError.get());
280 
281  // First we load the records into memory.
282  std::vector<std::unique_ptr<Record>> FDRRecords;
283 
284  {
285  FileBasedRecordProducer P(FileHeader, DE, OffsetPtr);
286  LogBuilderConsumer C(FDRRecords);
287  while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
288  auto R = P.produce();
289  if (!R)
290  return R.takeError();
291  if (auto E = C.consume(std::move(R.get())))
292  return E;
293  }
294  }
295 
296  // Next we index the records into blocks.
298  {
299  BlockIndexer Indexer(Index);
300  for (auto &R : FDRRecords)
301  if (auto E = R->apply(Indexer))
302  return E;
303  if (auto E = Indexer.flush())
304  return E;
305  }
306 
307  // Then we verify the consistency of the blocks.
308  {
309  for (auto &PTB : Index) {
310  auto &Blocks = PTB.second;
311  for (auto &B : Blocks) {
313  for (auto *R : B.Records)
314  if (auto E = R->apply(Verifier))
315  return E;
316  if (auto E = Verifier.verify())
317  return E;
318  }
319  }
320  }
321 
322  // This is now the meat of the algorithm. Here we sort the blocks according to
323  // the Walltime record in each of the blocks for the same thread. This allows
324  // us to more consistently recreate the execution trace in temporal order.
325  // After the sort, we then reconstitute `Trace` records using a stateful
326  // visitor associated with a single process+thread pair.
327  {
328  for (auto &PTB : Index) {
329  auto &Blocks = PTB.second;
330  llvm::sort(Blocks, [](const BlockIndexer::Block &L,
331  const BlockIndexer::Block &R) {
332  return (L.WallclockTime->seconds() < R.WallclockTime->seconds() &&
333  L.WallclockTime->nanos() < R.WallclockTime->nanos());
334  });
335  auto Adder = [&](const XRayRecord &R) { Records.push_back(R); };
336  TraceExpander Expander(Adder, FileHeader.Version);
337  for (auto &B : Blocks) {
338  for (auto *R : B.Records)
339  if (auto E = R->apply(Expander))
340  return E;
341  }
342  if (auto E = Expander.flush())
343  return E;
344  }
345  }
346 
347  return Error::success();
348 }
349 
350 Error loadYAMLLog(StringRef Data, XRayFileHeader &FileHeader,
351  std::vector<XRayRecord> &Records) {
353  Input In(Data);
354  In >> Trace;
355  if (In.error())
356  return make_error<StringError>("Failed loading YAML Data.", In.error());
357 
358  FileHeader.Version = Trace.Header.Version;
359  FileHeader.Type = Trace.Header.Type;
360  FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
361  FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
362  FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
363 
364  if (FileHeader.Version != 1)
365  return make_error<StringError>(
366  Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
367  std::make_error_code(std::errc::invalid_argument));
368 
369  Records.clear();
370  std::transform(Trace.Records.begin(), Trace.Records.end(),
371  std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
372  return XRayRecord{R.RecordType, R.CPU, R.Type,
373  R.FuncId, R.TSC, R.TId,
374  R.PId, R.CallArgs, R.Data};
375  });
376  return Error::success();
377 }
378 } // namespace
379 
382  if (!FdOrErr)
383  return FdOrErr.takeError();
384 
385  uint64_t FileSize;
386  if (auto EC = sys::fs::file_size(Filename, FileSize)) {
387  return make_error<StringError>(
388  Twine("Cannot read log from '") + Filename + "'", EC);
389  }
390  if (FileSize < 4) {
391  return make_error<StringError>(
392  Twine("File '") + Filename + "' too small for XRay.",
393  std::make_error_code(std::errc::executable_format_error));
394  }
395 
396  // Map the opened file into memory and use a StringRef to access it later.
397  std::error_code EC;
398  sys::fs::mapped_file_region MappedFile(
399  *FdOrErr, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0,
400  EC);
401  sys::fs::closeFile(*FdOrErr);
402  if (EC) {
403  return make_error<StringError>(
404  Twine("Cannot read log from '") + Filename + "'", EC);
405  }
406  auto Data = StringRef(MappedFile.data(), MappedFile.size());
407 
408  // TODO: Lift the endianness and implementation selection here.
409  DataExtractor LittleEndianDE(Data, true, 8);
410  auto TraceOrError = loadTrace(LittleEndianDE, Sort);
411  if (!TraceOrError) {
412  DataExtractor BigEndianDE(Data, false, 8);
413  consumeError(TraceOrError.takeError());
414  TraceOrError = loadTrace(BigEndianDE, Sort);
415  }
416  return TraceOrError;
417 }
418 
420  // Attempt to detect the file type using file magic. We have a slight bias
421  // towards the binary format, and we do this by making sure that the first 4
422  // bytes of the binary file is some combination of the following byte
423  // patterns: (observe the code loading them assumes they're little endian)
424  //
425  // 0x01 0x00 0x00 0x00 - version 1, "naive" format
426  // 0x01 0x00 0x01 0x00 - version 1, "flight data recorder" format
427  // 0x02 0x00 0x01 0x00 - version 2, "flight data recorder" format
428  //
429  // YAML files don't typically have those first four bytes as valid text so we
430  // try loading assuming YAML if we don't find these bytes.
431  //
432  // Only if we can't load either the binary or the YAML format will we yield an
433  // error.
434  DataExtractor HeaderExtractor(DE.getData(), DE.isLittleEndian(), 8);
435  uint64_t OffsetPtr = 0;
436  uint16_t Version = HeaderExtractor.getU16(&OffsetPtr);
437  uint16_t Type = HeaderExtractor.getU16(&OffsetPtr);
438 
439  enum BinaryFormatType { NAIVE_FORMAT = 0, FLIGHT_DATA_RECORDER_FORMAT = 1 };
440 
441  Trace T;
442  switch (Type) {
443  case NAIVE_FORMAT:
444  if (Version == 1 || Version == 2 || Version == 3) {
445  if (auto E = loadNaiveFormatLog(DE.getData(), DE.isLittleEndian(),
446  T.FileHeader, T.Records))
447  return std::move(E);
448  } else {
449  return make_error<StringError>(
450  Twine("Unsupported version for Basic/Naive Mode logging: ") +
451  Twine(Version),
452  std::make_error_code(std::errc::executable_format_error));
453  }
454  break;
455  case FLIGHT_DATA_RECORDER_FORMAT:
456  if (Version >= 1 && Version <= 5) {
457  if (auto E = loadFDRLog(DE.getData(), DE.isLittleEndian(), T.FileHeader,
458  T.Records))
459  return std::move(E);
460  } else {
461  return make_error<StringError>(
462  Twine("Unsupported version for FDR Mode logging: ") + Twine(Version),
463  std::make_error_code(std::errc::executable_format_error));
464  }
465  break;
466  default:
467  if (auto E = loadYAMLLog(DE.getData(), T.FileHeader, T.Records))
468  return std::move(E);
469  }
470 
471  if (Sort)
472  llvm::stable_sort(T.Records, [&](const XRayRecord &L, const XRayRecord &R) {
473  return L.TSC < R.TSC;
474  });
475 
476  return std::move(T);
477 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::xray::XRayFileHeader::ConstantTSC
bool ConstantTSC
Whether the CPU that produced the timestamp counters (TSC) move at a constant rate.
Definition: XRayRecord.h:37
FileSystem.h
llvm::xray::FileBasedRecordProducer
Definition: FDRRecordProducer.h:27
T
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
llvm::xray::LogBuilderConsumer
Definition: FDRRecordConsumer.h:28
llvm::FunctionLoweringInfo::StatepointRelocationRecord
Helper object to track which of three possible relocation mechanisms are used for a particular value ...
Definition: FunctionLoweringInfo.h:95
llvm::xray::RecordTypes::EXIT
@ EXIT
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
Error.h
llvm::xray::XRayFileHeader::Version
uint16_t Version
Version of the XRay implementation that produced this file.
Definition: XRayRecord.h:29
YAMLXRayRecord.h
llvm::xray::BlockIndexer::Block
Definition: BlockIndexer.h:28
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::xray::loadTraceFile
Expected< Trace > loadTraceFile(StringRef Filename, bool Sort=false)
This function will attempt to load XRay trace records from the provided |Filename|.
Definition: Trace.cpp:380
BlockIndexer.h
llvm::xray
Definition: BlockIndexer.h:22
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
STLExtras.h
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1045
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::xray::XRayFileHeader::Type
uint16_t Type
A numeric identifier for the type of file this is.
Definition: XRayRecord.h:33
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:207
llvm::xray::XRayRecord
An XRayRecord is the denormalized view of data associated in a trace.
Definition: XRayRecord.h:69
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:206
llvm::xray::RecordTypes::TAIL_EXIT
@ TAIL_EXIT
llvm::xray::XRayFileHeader::NonstopTSC
bool NonstopTSC
Whether the CPU that produced the timestamp counters (TSC) do not stop.
Definition: XRayRecord.h:40
llvm::DataExtractor::isLittleEndian
bool isLittleEndian() const
Get the endianness for this extractor.
Definition: DataExtractor.h:97
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::xray::YAMLXRayTrace
Definition: YAMLXRayRecord.h:44
llvm::xray::TraceExpander
Definition: FDRTraceExpander.h:23
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::Trace::end
iterator end()
Definition: Trace.h:87
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
FDRRecordConsumer.h
llvm::sys::fs::openNativeFileForRead
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
llvm::xray::BlockVerifier
Definition: BlockVerifier.h:23
llvm::xray::readBinaryFormatHeader
Expected< XRayFileHeader > readBinaryFormatHeader(DataExtractor &HeaderExtractor, uint64_t &OffsetPtr)
Convenience function for loading the file header given a data extractor at a specified offset.
Definition: FileHeaderReader.cpp:14
FDRRecordProducer.h
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
Verifier
verify safepoint Safepoint IR Verifier
Definition: SafepointIRVerifier.cpp:253
readonly
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 where P can be anything The alignment inference code cannot handle loads from globals in static non mode because it doesn t look through the extra dyld stub load If you try vec_align ll without relocation you ll see what I mean We should lower which eliminates a constant pool load For float z nounwind readonly
Definition: README-SSE.txt:421
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
uint64_t
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
llvm::xray::YAMLXRayRecord
Definition: YAMLXRayRecord.h:31
BlockVerifier.h
FuncId
Profile::FuncID FuncId
Definition: Profile.cpp:321
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::xray::RecordTypes::ENTER
@ ENTER
llvm::Record
Definition: Record.h:1486
llvm::xray::loadTrace
Expected< Trace > loadTrace(const DataExtractor &Extractor, bool Sort=false)
This function will attempt to load XRay trace records from the provided DataExtractor.
Definition: Trace.cpp:419
llvm::sys::fs::mapped_file_region::data
char * data() const
Definition: Path.cpp:1160
llvm::xray::BlockIndexer
Definition: BlockIndexer.h:26
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::xray::BlockIndexer::Block::WallclockTime
WallclockRecord * WallclockTime
Definition: BlockIndexer.h:31
Trace.h
llvm::Trace
Definition: Trace.h:30
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition: BitcodeReader.h:270
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1735
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1241
llvm::Trace::begin
iterator begin()
Definition: Trace.h:85
uint16_t
llvm::xray::WallclockRecord::seconds
uint64_t seconds() const
Definition: FDRRecords.h:148
llvm::xray::XRayFileHeader::CycleFrequency
uint64_t CycleFrequency
The number of cycles per second for the CPU that produced the timestamp counter (TSC) values.
Definition: XRayRecord.h:45
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
DataExtractor.h
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1541
llvm::sys::fs::mapped_file_region::size
size_t size() const
Definition: Path.cpp:1155
llvm::xray::XRayFileHeader
XRay traces all have a header providing some top-matter information useful to help tools determine ho...
Definition: XRayRecord.h:27
transform
instcombine should handle this transform
Definition: README.txt:262
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:599
llvm::sys::fs::mapped_file_region
This class represents a memory mapped file.
Definition: FileSystem.h:1250
llvm::sys::fs::file_size
std::error_code file_size(const Twine &Path, uint64_t &Result)
Get file size.
Definition: FileSystem.h:691
llvm::DataExtractor
Definition: DataExtractor.h:41
Version
uint64_t Version
Definition: RawMemProfReader.cpp:25
llvm::xray::Trace
A Trace object represents the records that have been loaded from XRay log files generated by instrume...
Definition: Trace.h:46
llvm::DataExtractor::getData
StringRef getData() const
Get the data pointed to by this extractor.
Definition: DataExtractor.h:95
FileHeaderReader.h
FDRTraceExpander.h
llvm::xray::WallclockRecord::nanos
uint32_t nanos() const
Definition: FDRRecords.h:149
llvm::xray::RecordTypes::ENTER_ARG
@ ENTER_ARG
FDRRecords.h
llvm::DataExtractor::getU16
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
Definition: DataExtractor.cpp:93
RecordType
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Definition: StatepointLowering.cpp:75