--- /dev/null
+# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -resource-pressure=0 -timeline < %s | FileCheck %s
+
+ imull %esi
+ imull (%rdi)
+
+
+# The second integer multiply can start at cycle 2 because the implicit reads
+# can start after the load operand is evaluated.
+
+# CHECK: Instruction Info:
+# CHECK-NEXT: [1]: #uOps
+# CHECK-NEXT: [2]: Latency
+# CHECK-NEXT: [3]: RThroughput
+# CHECK-NEXT: [4]: MayLoad
+# CHECK-NEXT: [5]: MayStore
+# CHECK-NEXT: [6]: HasSideEffects
+
+# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
+# CHECK-NEXT: 2 3 1.00 imull %esi
+# CHECK-NEXT: 2 6 1.00 * imull (%rdi)
+
+
+# CHECK: Timeline view:
+# CHECK: Index 0123456789
+# CHECK: [0,0] DeeeER . imull %esi
+# CHECK-NEXT: [0,1] .DeeeeeeER imull (%rdi)
WriteDescriptor &Write = ID.Writes[Index];
Write.OpIndex = -1;
Write.RegisterID = MCDesc.getImplicitDefs()[CurrentDef];
- Write.Latency = ID.MaxLatency;
- Write.SClassOrWriteResourceID = 0;
+ if (Index < NumWriteLatencyEntries) {
+ const MCWriteLatencyEntry &WLE =
+ *STI.getWriteLatencyEntry(&SCDesc, Index);
+ // Conservatively default to MaxLatency.
+ Write.Latency = WLE.Cycles == -1 ? ID.MaxLatency : WLE.Cycles;
+ Write.SClassOrWriteResourceID = WLE.WriteResourceID;
+ } else {
+ // Assign a default latency for this write.
+ Write.Latency = ID.MaxLatency;
+ Write.SClassOrWriteResourceID = 0;
+ }
+
Write.IsOptionalDef = false;
assert(Write.RegisterID != 0 && "Expected a valid phys register!");
DEBUG(dbgs() << "\t\tOpIdx=" << Write.OpIndex << ", PhysReg="
for (unsigned CurrentUse = 0; CurrentUse < NumImplicitUses; ++CurrentUse) {
ReadDescriptor &Read = ID.Reads[NumExplicitUses + CurrentUse];
Read.OpIndex = -1;
- Read.UseIndex = -1;
+ Read.UseIndex = NumExplicitUses + CurrentUse;
Read.RegisterID = MCDesc.getImplicitUses()[CurrentUse];
- Read.HasReadAdvanceEntries = false;
+ Read.HasReadAdvanceEntries = HasReadAdvanceEntries;
Read.SchedClassID = SchedClassID;
DEBUG(dbgs() << "\t\tOpIdx=" << Read.OpIndex
<< ", RegisterID=" << Read.RegisterID << '\n');
/// \brief A register write descriptor.
struct WriteDescriptor {
- int OpIndex; // Operand index. -1 if this is an implicit write.
+ // Operand index. -1 if this is an implicit write.
+ int OpIndex;
// Write latency. Number of cycles before write-back stage.
int Latency;
// This field is set to a value different than zero only if this
// YMM super-register if the write is associated to a legacy SSE instruction.
bool FullyUpdatesSuperRegs;
// Instruction itineraries would set this field to the SchedClass ID.
- // Otherwise, it defaults to the WriteResourceID from teh MCWriteLatencyEntry
+ // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
// element associated to this write.
// When computing read latencies, this value is matched against the
// "ReadAdvance" information. The hardware backend may implement
// A MCOperand index. This is used by the Dispatch logic to identify register
// reads. This field defaults to -1 if this is an implicit read.
int OpIndex;
- // The actual "UseIdx". This field defaults to -1 if this is an implicit read.
- // This is used by the scheduler to solve ReadAdvance queries.
- int UseIndex;
+ // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
+ // uses always come first in the sequence of uses.
+ unsigned UseIndex;
// This field is only set if this is an implicit read.
unsigned RegisterID;
// Scheduling Class Index. It is used to query the scheduling model for the