[llvm-mca] Do not assume that implicit reads cannot be associated with ReadAdvance...
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 2 Apr 2018 13:46:49 +0000 (13:46 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 2 Apr 2018 13:46:49 +0000 (13:46 +0000)
Before, the instruction builder incorrectly assumed that only explicit reads
could have been associated with ReadAdvance entries.
This patch fixes the issue and adds a test to verify it.

llvm-svn: 328972

llvm/test/tools/llvm-mca/X86/BtVer2/read-advance-2.s [new file with mode: 0644]
llvm/tools/llvm-mca/InstrBuilder.cpp
llvm/tools/llvm-mca/Instruction.h

diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/read-advance-2.s b/llvm/test/tools/llvm-mca/X86/BtVer2/read-advance-2.s
new file mode 100644 (file)
index 0000000..746333d
--- /dev/null
@@ -0,0 +1,26 @@
+# 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)
index 2b0be92..c56a279 100644 (file)
@@ -277,8 +277,18 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
     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="
@@ -349,9 +359,9 @@ static void populateReads(InstrDesc &ID, const MCInst &MCI,
   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');
index 00ba9b9..d7d2685 100644 (file)
@@ -32,7 +32,8 @@ constexpr int UNKNOWN_CYCLES = -512;
 
 /// \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
@@ -44,7 +45,7 @@ struct WriteDescriptor {
   // 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
@@ -63,9 +64,9 @@ struct ReadDescriptor {
   // 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