]> granicus.if.org Git - llvm/commitdiff
[MC][X86] Correctly model additional operand latency caused by transfer delays from...
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Wed, 23 Jan 2019 16:35:07 +0000 (16:35 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Wed, 23 Jan 2019 16:35:07 +0000 (16:35 +0000)
This patch adds a new ReadAdvance definition named ReadInt2Fpu.
ReadInt2Fpu allows x86 scheduling models to accurately describe delays caused by
data transfers from the integer unit to the floating point unit.
ReadInt2Fpu currently defaults to a delay of zero cycles (i.e. no delay) for all
x86 models excluding BtVer2. That means, this patch is only a functional change
for the Jaguar cpu model only.

Tablegen definitions for instructions (V)PINSR* have been updated to account for
the new ReadInt2Fpu. That read is mapped to the the GPR input operand.
On Jaguar, int-to-fpu transfers are modeled as a +6cy delay. Before this patch,
that extra delay was added to the opcode latency. In practice, the insert opcode
only executes for 1cy. Most of the actual latency is actually contributed by the
so-called operand-latency. According to the AMD SOG for family 16h, (V)PINSR*
latency is defined by expression f+1, where f is defined as a forwarding delay
from the integer unit to the fpu.

When printing instruction latency from MCA (see InstructionInfoView.cpp) and LLC
(only when flag -print-schedule is speified), we now need to account for any
extra forwarding delays. We do this by checking if scheduling classes declare
any negative ReadAdvance entries. Quoting a code comment in TargetSchedule.td:
"A negative advance effectively increases latency, which may be used for
cross-domain stalls". When computing the instruction latency for the purpose of
our scheduling tests, we now add any extra delay to the formula. This avoids
regressing existing codegen and mca schedule tests. It comes with the cost of an
extra (but very simple) hook in MCSchedModel.

Differential Revision: https://reviews.llvm.org/D57056

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351965 91177308-0d34-0410-b5e6-96231b3b80d8

24 files changed:
include/llvm/MC/MCSchedule.h
include/llvm/MC/MCSubtargetInfo.h
include/llvm/MCA/Instruction.h
lib/CodeGen/TargetSubtargetInfo.cpp
lib/MC/MCSchedule.cpp
lib/MCA/InstrBuilder.cpp
lib/Target/X86/X86InstrMMX.td
lib/Target/X86/X86InstrSSE.td
lib/Target/X86/X86SchedBroadwell.td
lib/Target/X86/X86SchedHaswell.td
lib/Target/X86/X86SchedSandyBridge.td
lib/Target/X86/X86SchedSkylakeClient.td
lib/Target/X86/X86SchedSkylakeServer.td
lib/Target/X86/X86Schedule.td
lib/Target/X86/X86ScheduleAtom.td
lib/Target/X86/X86ScheduleBdVer2.td
lib/Target/X86/X86ScheduleBtVer2.td
lib/Target/X86/X86ScheduleSLM.td
lib/Target/X86/X86ScheduleZnver1.td
test/CodeGen/X86/mmx-schedule.ll
test/CodeGen/X86/sse41-schedule.ll
test/tools/llvm-mca/X86/BtVer2/int-to-fpu-forwarding-1.s
test/tools/llvm-mca/X86/BtVer2/int-to-fpu-forwarding-3.s
tools/llvm-mca/Views/InstructionInfoView.cpp

index 25a3a9cdb8f0a03884d235cf3faab2765d781aa7..df3248ee6e863f1528c2efaac9e57d4ee32cea06 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_MC_MCSCHEDULE_H
 #define LLVM_MC_MCSCHEDULE_H
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/DataTypes.h"
@@ -369,6 +370,11 @@ struct MCSchedModel {
   getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
                           const MCInst &Inst) const;
 
+  /// Returns the maximum forwarding delay for register reads dependent on
+  /// writes of scheduling class WriteResourceIdx.
+  static unsigned getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries,
+                                           unsigned WriteResourceIdx = 0);
+
   /// Returns the default initialized model.
   static const MCSchedModel &GetDefaultSchedModel() { return Default; }
   static const MCSchedModel Default;
index 03eea1e8dce33eb7cbdd68fcfe09fecac54fce43..2ad72c3c325f4e9d1f7decd2ceda5696aa9ca614 100644 (file)
@@ -152,6 +152,16 @@ public:
     return 0;
   }
 
+  /// Return the set of ReadAdvance entries declared by the scheduling class
+  /// descriptor in input.
+  ArrayRef<MCReadAdvanceEntry>
+  getReadAdvanceEntries(const MCSchedClassDesc &SC) const {
+    if (!SC.NumReadAdvanceEntries)
+      return ArrayRef<MCReadAdvanceEntry>();
+    return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx],
+                                        SC.NumReadAdvanceEntries);
+  }
+
   /// Get scheduling itinerary of a CPU.
   InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
 
index 27d135e35106de65ae4bddce26e406da0158054a..3effa2b7654415c4234832a2124fa85a7256c6e6 100644 (file)
@@ -332,6 +332,10 @@ struct InstrDesc {
   unsigned MaxLatency;
   // Number of MicroOps for this instruction.
   unsigned NumMicroOps;
+  // SchedClassID used to construct this InstrDesc.
+  // This information is currently used by views to do fast queries on the
+  // subtarget when computing the reciprocal throughput.
+  unsigned SchedClassID;
 
   bool MayLoad;
   bool MayStore;
index c9f90b88cac37c437635827d7a7754bb27e7e887..e34f9a1579dad1ef181c70939a558692169bcc08 100644 (file)
@@ -88,6 +88,12 @@ std::string TargetSubtargetInfo::getSchedInfoStr(const MachineInstr &MI) const {
   TargetSchedModel TSchedModel;
   TSchedModel.init(this);
   unsigned Latency = TSchedModel.computeInstrLatency(&MI);
+
+  // Add extra latency due to forwarding delays.
+  const MCSchedClassDesc &SCDesc = *TSchedModel.resolveSchedClass(&MI);
+  Latency +=
+      MCSchedModel::getForwardingDelayCycles(getReadAdvanceEntries(SCDesc));
+
   double RThroughput = TSchedModel.computeReciprocalThroughput(&MI);
   return createSchedInfoStr(Latency, RThroughput);
 }
@@ -99,9 +105,17 @@ std::string TargetSubtargetInfo::getSchedInfoStr(MCInst const &MCI) const {
   TargetSchedModel TSchedModel;
   TSchedModel.init(this);
   unsigned Latency;
-  if (TSchedModel.hasInstrSchedModel())
+  if (TSchedModel.hasInstrSchedModel()) {
     Latency = TSchedModel.computeInstrLatency(MCI);
-  else if (TSchedModel.hasInstrItineraries()) {
+    // Add extra latency due to forwarding delays.
+    const MCSchedModel &SM = *TSchedModel.getMCSchedModel();
+    unsigned SClassID = getInstrInfo()->get(MCI.getOpcode()).getSchedClass();
+    while (SM.getSchedClassDesc(SClassID)->isVariant())
+      SClassID = resolveVariantSchedClass(SClassID, &MCI, SM.ProcID);
+    const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SClassID);  
+    Latency +=
+        MCSchedModel::getForwardingDelayCycles(getReadAdvanceEntries(SCDesc));
+  } else if (TSchedModel.hasInstrItineraries()) {
     auto *ItinData = TSchedModel.getInstrItineraries();
     Latency = ItinData->getStageLatency(
         getInstrInfo()->get(MCI.getOpcode()).getSchedClass());
index 6797a47c75aca88016d7c30ae3567035cf6dbbe7..1fc5ec5e975f8424f384deb9dc8658230ab2ea85 100644 (file)
@@ -149,3 +149,19 @@ MCSchedModel::getReciprocalThroughput(unsigned SchedClass,
   // that it can execute at the maximum default issue width.
   return 1.0 / DefaultIssueWidth;
 }
+
+unsigned
+MCSchedModel::getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries,
+                                       unsigned WriteResourceID) {
+  if (Entries.empty())
+    return 0;
+
+  int DelayCycles = 0;
+  for (const MCReadAdvanceEntry &E : Entries) {
+    if (E.WriteResourceID != WriteResourceID)
+      continue;
+    DelayCycles = std::min(DelayCycles, E.Cycles);
+  }
+
+  return std::abs(DelayCycles);
+}
index 4b0ec329f9ea223ab9c42178849bd29e7b402474..1e08f898523679849974fe63729f8725a93e62ca 100644 (file)
@@ -532,6 +532,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
   // Create a new empty descriptor.
   std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>();
   ID->NumMicroOps = SCDesc.NumMicroOps;
+  ID->SchedClassID = SchedClassID;
 
   if (MCDesc.isCall() && FirstCallInst) {
     // We don't correctly model calls.
index c00c4f4ca091c1c19b4ccb16dc93f4f399990478..8e2a45b1bedeabd81484fa5e314c6ec07a9fb0ea 100644 (file)
@@ -543,7 +543,7 @@ let Predicates = [HasMMX, HasSSE1] in {
                     "pinsrw\t{$src3, $src2, $dst|$dst, $src2, $src3}",
                     [(set VR64:$dst, (int_x86_mmx_pinsr_w VR64:$src1,
                                       GR32orGR64:$src2, imm:$src3))]>,
-                    Sched<[WriteVecInsert]>;
+                    Sched<[WriteVecInsert, ReadDefault, ReadInt2Fpu]>;
 
   def MMX_PINSRWrm : MMXIi8<0xC4, MRMSrcMem,
                    (outs VR64:$dst),
index 807af7f4808c91a0372a0bf28231af791467e4fa..e6427b1764a8be1210442ec15967e1f96aa2f49e 100644 (file)
@@ -4122,7 +4122,7 @@ multiclass sse2_pinsrw<bit Is2Addr = 1> {
            "vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
        [(set VR128:$dst,
          (X86pinsrw VR128:$src1, GR32orGR64:$src2, imm:$src3))]>,
-       Sched<[WriteVecInsert]>;
+       Sched<[WriteVecInsert, ReadDefault, ReadInt2Fpu]>;
   def rm : Ii8<0xC4, MRMSrcMem,
                       (outs VR128:$dst), (ins VR128:$src1,
                        i16mem:$src2, u8imm:$src3),
@@ -5577,7 +5577,7 @@ multiclass SS41I_insert8<bits<8> opc, string asm, bit Is2Addr = 1> {
                    "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")),
       [(set VR128:$dst,
         (X86pinsrb VR128:$src1, GR32orGR64:$src2, imm:$src3))]>,
-      Sched<[WriteVecInsert]>;
+      Sched<[WriteVecInsert, ReadDefault, ReadInt2Fpu]>;
   def rm : SS4AIi8<opc, MRMSrcMem, (outs VR128:$dst),
       (ins VR128:$src1, i8mem:$src2, u8imm:$src3),
       !if(Is2Addr,
@@ -5603,7 +5603,7 @@ multiclass SS41I_insert32<bits<8> opc, string asm, bit Is2Addr = 1> {
                    "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")),
       [(set VR128:$dst,
         (v4i32 (insertelt VR128:$src1, GR32:$src2, imm:$src3)))]>,
-      Sched<[WriteVecInsert]>;
+      Sched<[WriteVecInsert, ReadDefault, ReadInt2Fpu]>;
   def rm : SS4AIi8<opc, MRMSrcMem, (outs VR128:$dst),
       (ins VR128:$src1, i32mem:$src2, u8imm:$src3),
       !if(Is2Addr,
@@ -5629,7 +5629,7 @@ multiclass SS41I_insert64<bits<8> opc, string asm, bit Is2Addr = 1> {
                    "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}")),
       [(set VR128:$dst,
         (v2i64 (insertelt VR128:$src1, GR64:$src2, imm:$src3)))]>,
-      Sched<[WriteVecInsert]>;
+      Sched<[WriteVecInsert, ReadDefault, ReadInt2Fpu]>;
   def rm : SS4AIi8<opc, MRMSrcMem, (outs VR128:$dst),
       (ins VR128:$src1, i64mem:$src2, u8imm:$src3),
       !if(Is2Addr,
index 03feff138e6f6d0caedcf1005caf0ddf44f278d9..821948d2d85937b9b48c24d7d9cc8aa4332b11ae 100644 (file)
@@ -81,6 +81,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 5>;
 def : ReadAdvance<ReadAfterVecYLd, 6>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 155d77224a6746b7121bdef0fd94b55536a78f37..dc040e0e7d321e9f6ad2e1b4baa37a58c7904fdf 100644 (file)
@@ -86,6 +86,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 6>;
 def : ReadAdvance<ReadAfterVecYLd, 7>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 4f47acde7cfaa4a50986ed558411378e8d42dbc9..503b905842b3646505e718e9b1aa67447f40f170 100644 (file)
@@ -76,6 +76,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 6>;
 def : ReadAdvance<ReadAfterVecYLd, 7>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 7d84d814d94bc8e153bcd07e3e501bc902640a98..71045897376fab24da094baac62f041742b62cbc 100644 (file)
@@ -80,6 +80,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 6>;
 def : ReadAdvance<ReadAfterVecYLd, 7>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 0d452f9beb396b9a2bb3526810e8a5521715d98a..8bd80078891dd4dad582cefc06144086908e37ae 100644 (file)
@@ -80,6 +80,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 6>;
 def : ReadAdvance<ReadAfterVecYLd, 7>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 886c3aef3f5f266fd9ee66438d28ae643888021e..f50cb6210466aab06a80fb23560962cc9a4c5872 100644 (file)
@@ -17,6 +17,12 @@ def ReadAfterVecLd : SchedRead;
 def ReadAfterVecXLd : SchedRead;
 def ReadAfterVecYLd : SchedRead;
 
+// Instructions that move data between general purpose registers and vector
+// registers may be subject to extra latency due to data bypass delays.
+// This SchedRead describes a bypass delay caused by data being moved from the
+// integer unit to the floating point unit.
+def ReadInt2Fpu : SchedRead;
+
 // Instructions with both a load and a store folded are modeled as a folded
 // load + WriteRMW.
 def WriteRMW : SchedWrite;
index 779692b7da62cc232897bbce791a69e65b0ff41b..bf50aeee1dffb29876d33ad5bf9df73112ad20b0 100644 (file)
@@ -46,6 +46,8 @@ def : ReadAdvance<ReadAfterVecLd, 3>;
 def : ReadAdvance<ReadAfterVecXLd, 3>;
 def : ReadAdvance<ReadAfterVecYLd, 3>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when dispatched by the schedulers.
index ca14ed478f077a21c968986a8bdcbb6da490a0c1..90ca79915fa74e012981908ece055a67348e36d1 100644 (file)
@@ -250,6 +250,8 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 5>;
 def : ReadAdvance<ReadAfterVecYLd, 5>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // A folded store needs a cycle on the PdStore for the store data.
 def : WriteRes<WriteRMW, [PdStore]>;
 
index 8d8de3e8e157a8304096fed198ca2fc5b1abcae2..3a2ed733f56fff8af69d51255078db6c03464867 100644 (file)
@@ -108,6 +108,11 @@ def : ReadAdvance<ReadAfterVecLd, 5>;
 def : ReadAdvance<ReadAfterVecXLd, 5>;
 def : ReadAdvance<ReadAfterVecYLd, 5>;
 
+/// "Additional 6 cycle transfer operation which moves a floating point
+/// operation input value from the integer unit to the floating point unit.
+/// Reference: AMDfam16h SOG (Appendix A "Instruction Latencies", Section A.2).
+def : ReadAdvance<ReadInt2Fpu, -6>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when dispatched by the schedulers.
@@ -540,7 +545,7 @@ defm : X86WriteResPairUnsupported<WriteVarShuffle256>;
 // Vector insert/extract operations.
 ////////////////////////////////////////////////////////////////////////////////
 
-defm : X86WriteRes<WriteVecInsert,      [JFPU01, JVALU], 7, [1,1], 2>;
+defm : X86WriteRes<WriteVecInsert,      [JFPU01, JVALU], 1, [1,1], 2>;
 defm : X86WriteRes<WriteVecInsertLd,    [JFPU01, JVALU, JLAGU], 4, [1,1,1], 1>;
 defm : X86WriteRes<WriteVecExtract,     [JFPU0, JFPA, JALU0], 3, [1,1,1], 1>;
 defm : X86WriteRes<WriteVecExtractSt,   [JFPU1, JSTC, JSAGU], 3, [1,1,1], 1>;
index 5dca0ff7019950641d12832733f4c0e3279542d9..fc150fca5458ac8c2bc3d572da0eefb14d7fa0dc 100644 (file)
@@ -52,6 +52,8 @@ def : ReadAdvance<ReadAfterVecLd, 3>;
 def : ReadAdvance<ReadAfterVecXLd, 3>;
 def : ReadAdvance<ReadAfterVecYLd, 3>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // Many SchedWrites are defined in pairs with and without a folded load.
 // Instructions with folded loads are usually micro-fused, so they only appear
 // as two micro-ops when queued in the reservation station.
index 0407afc420307cca2ce994c0143c898739db5c3d..1a75281cf0cd0c2d0943555509167c3f4dff789c 100644 (file)
@@ -94,6 +94,8 @@ def : ReadAdvance<ReadAfterVecLd, 8>;
 def : ReadAdvance<ReadAfterVecXLd, 8>;
 def : ReadAdvance<ReadAfterVecYLd, 8>;
 
+def : ReadAdvance<ReadInt2Fpu, 0>;
+
 // The Integer PRF for Zen is 168 entries, and it holds the architectural and
 // speculative version of the 64-bit integer registers.
 // Reference: "Software Optimization Guide for AMD Family 17h Processors"
index 51dc5e102ff1578aa59144b24d37e4623ba23cf3..d423b9a2a90ab3d9736c924354e4d197c100e70f 100644 (file)
@@ -3887,8 +3887,8 @@ define i64 @test_pinsrw(x86_mmx %a0, i32 %a1, i16* %a2) optsize {
 ;
 ; BTVER2-LABEL: test_pinsrw:
 ; BTVER2:       # %bb.0:
-; BTVER2-NEXT:    pinsrw $0, %edi, %mm0 # sched: [7:0.50]
 ; BTVER2-NEXT:    movswl (%rsi), %eax # sched: [4:1.00]
+; BTVER2-NEXT:    pinsrw $0, %edi, %mm0 # sched: [7:0.50]
 ; BTVER2-NEXT:    pinsrw $1, %eax, %mm0 # sched: [7:0.50]
 ; BTVER2-NEXT:    movq %mm0, %rax # sched: [4:1.00]
 ; BTVER2-NEXT:    retq # sched: [4:1.00]
index ea606463fc17b09d26a912d2e3b76c57bec09cfe..4870434a8aefe187c786ab924ff77daf034e82f7 100644 (file)
@@ -2679,15 +2679,15 @@ define <2 x i64> @test_pinsrq(<2 x i64> %a0, <2 x i64> %a1, i64 %a2, i64 *%a3) {
 ;
 ; BTVER2-SSE-LABEL: test_pinsrq:
 ; BTVER2-SSE:       # %bb.0:
-; BTVER2-SSE-NEXT:    pinsrq $1, %rdi, %xmm0 # sched: [7:0.50]
 ; BTVER2-SSE-NEXT:    pinsrq $1, (%rsi), %xmm1 # sched: [4:1.00]
+; BTVER2-SSE-NEXT:    pinsrq $1, %rdi, %xmm0 # sched: [7:0.50]
 ; BTVER2-SSE-NEXT:    paddq %xmm1, %xmm0 # sched: [1:0.50]
 ; BTVER2-SSE-NEXT:    retq # sched: [4:1.00]
 ;
 ; BTVER2-LABEL: test_pinsrq:
 ; BTVER2:       # %bb.0:
-; BTVER2-NEXT:    vpinsrq $1, %rdi, %xmm0, %xmm0 # sched: [7:0.50]
 ; BTVER2-NEXT:    vpinsrq $1, (%rsi), %xmm1, %xmm1 # sched: [4:1.00]
+; BTVER2-NEXT:    vpinsrq $1, %rdi, %xmm0, %xmm0 # sched: [7:0.50]
 ; BTVER2-NEXT:    vpaddq %xmm1, %xmm0, %xmm0 # sched: [1:0.50]
 ; BTVER2-NEXT:    retq # sched: [4:1.00]
 ;
index 9e44702ae79a2d2ba835d837b4d8ee08f03d1a43..398a52a84791317573ce0a7821a2ab3bc03fa35b 100644 (file)
@@ -27,12 +27,12 @@ vpinsrq $1, %rax, %xmm0, %xmm0
 
 # CHECK:      Iterations:        500
 # CHECK-NEXT: Instructions:      1000
-# CHECK-NEXT: Total Cycles:      7003
+# CHECK-NEXT: Total Cycles:      1003
 # CHECK-NEXT: Total uOps:        2000
 
 # CHECK:      Dispatch Width:    2
-# CHECK-NEXT: uOps Per Cycle:    0.29
-# CHECK-NEXT: IPC:               0.14
+# CHECK-NEXT: uOps Per Cycle:    1.99
+# CHECK-NEXT: IPC:               1.00
 # CHECK-NEXT: Block RThroughput: 2.0
 
 # CHECK:      Instruction Info:
@@ -76,12 +76,12 @@ vpinsrq $1, %rax, %xmm0, %xmm0
 
 # CHECK:      Iterations:        500
 # CHECK-NEXT: Instructions:      1000
-# CHECK-NEXT: Total Cycles:      7003
+# CHECK-NEXT: Total Cycles:      1003
 # CHECK-NEXT: Total uOps:        2000
 
 # CHECK:      Dispatch Width:    2
-# CHECK-NEXT: uOps Per Cycle:    0.29
-# CHECK-NEXT: IPC:               0.14
+# CHECK-NEXT: uOps Per Cycle:    1.99
+# CHECK-NEXT: IPC:               1.00
 # CHECK-NEXT: Block RThroughput: 2.0
 
 # CHECK:      Instruction Info:
@@ -125,12 +125,12 @@ vpinsrq $1, %rax, %xmm0, %xmm0
 
 # CHECK:      Iterations:        500
 # CHECK-NEXT: Instructions:      1000
-# CHECK-NEXT: Total Cycles:      7003
+# CHECK-NEXT: Total Cycles:      1003
 # CHECK-NEXT: Total uOps:        2000
 
 # CHECK:      Dispatch Width:    2
-# CHECK-NEXT: uOps Per Cycle:    0.29
-# CHECK-NEXT: IPC:               0.14
+# CHECK-NEXT: uOps Per Cycle:    1.99
+# CHECK-NEXT: IPC:               1.00
 # CHECK-NEXT: Block RThroughput: 2.0
 
 # CHECK:      Instruction Info:
@@ -174,12 +174,12 @@ vpinsrq $1, %rax, %xmm0, %xmm0
 
 # CHECK:      Iterations:        500
 # CHECK-NEXT: Instructions:      1000
-# CHECK-NEXT: Total Cycles:      7003
+# CHECK-NEXT: Total Cycles:      1003
 # CHECK-NEXT: Total uOps:        2000
 
 # CHECK:      Dispatch Width:    2
-# CHECK-NEXT: uOps Per Cycle:    0.29
-# CHECK-NEXT: IPC:               0.14
+# CHECK-NEXT: uOps Per Cycle:    1.99
+# CHECK-NEXT: IPC:               1.00
 # CHECK-NEXT: Block RThroughput: 2.0
 
 # CHECK:      Instruction Info:
index 4e130be859764c60e94ac21e9eaac7c50ce34986..00c13f9ef59a9039d04361c3d829c927be5400d2 100644 (file)
@@ -9,12 +9,12 @@ vpinsrb $1, %eax, %xmm0, %xmm0
 
 # CHECK:      Iterations:        500
 # CHECK-NEXT: Instructions:      1500
-# CHECK-NEXT: Total Cycles:      7004
+# CHECK-NEXT: Total Cycles:      1509
 # CHECK-NEXT: Total uOps:        2500
 
 # CHECK:      Dispatch Width:    2
-# CHECK-NEXT: uOps Per Cycle:    0.36
-# CHECK-NEXT: IPC:               0.21
+# CHECK-NEXT: uOps Per Cycle:    1.66
+# CHECK-NEXT: IPC:               0.99
 # CHECK-NEXT: Block RThroughput: 2.5
 
 # CHECK:      Instruction Info:
@@ -57,18 +57,18 @@ vpinsrb $1, %eax, %xmm0, %xmm0
 # CHECK-NEXT:  -      -      -      -      -     1.00    -      -      -      -      -     1.00    -      -     vpinsrb        $1, %eax, %xmm0, %xmm0
 
 # CHECK:      Timeline view:
-# CHECK-NEXT:                     0123456789          0123456789
-# CHECK-NEXT: Index     0123456789          0123456789          012345
+# CHECK-NEXT:                     01234567
+# CHECK-NEXT: Index     0123456789
 
-# CHECK:      [0,0]     DeER .    .    .    .    .    .    .    .    .   addl  %eax, %eax
-# CHECK-NEXT: [0,1]     .DeeeeeeeER    .    .    .    .    .    .    .   vpinsrb       $0, %eax, %xmm0, %xmm0
-# CHECK-NEXT: [0,2]     . D======eeeeeeeER  .    .    .    .    .    .   vpinsrb       $1, %eax, %xmm0, %xmm0
-# CHECK-NEXT: [1,0]     .  DeE-----------R  .    .    .    .    .    .   addl  %eax, %eax
-# CHECK-NEXT: [1,1]     .   D===========eeeeeeeER.    .    .    .    .   vpinsrb       $0, %eax, %xmm0, %xmm0
-# CHECK-NEXT: [1,2]     .    D=================eeeeeeeER   .    .    .   vpinsrb       $1, %eax, %xmm0, %xmm0
-# CHECK-NEXT: [2,0]     .    .DeE----------------------R   .    .    .   addl  %eax, %eax
-# CHECK-NEXT: [2,1]     .    . D======================eeeeeeeER .    .   vpinsrb       $0, %eax, %xmm0, %xmm0
-# CHECK-NEXT: [2,2]     .    .  D============================eeeeeeeER   vpinsrb       $1, %eax, %xmm0, %xmm0
+# CHECK:      [0,0]     DeER .    .    . .   addl      %eax, %eax
+# CHECK-NEXT: [0,1]     .D======eER    . .   vpinsrb   $0, %eax, %xmm0, %xmm0
+# CHECK-NEXT: [0,2]     . D======eER   . .   vpinsrb   $1, %eax, %xmm0, %xmm0
+# CHECK-NEXT: [1,0]     .  DeE-----R   . .   addl      %eax, %eax
+# CHECK-NEXT: [1,1]     .   D======eER . .   vpinsrb   $0, %eax, %xmm0, %xmm0
+# CHECK-NEXT: [1,2]     .    D======eER. .   vpinsrb   $1, %eax, %xmm0, %xmm0
+# CHECK-NEXT: [2,0]     .    .DeE-----R. .   addl      %eax, %eax
+# CHECK-NEXT: [2,1]     .    . D======eER.   vpinsrb   $0, %eax, %xmm0, %xmm0
+# CHECK-NEXT: [2,2]     .    .  D======eER   vpinsrb   $1, %eax, %xmm0, %xmm0
 
 # CHECK:      Average Wait times (based on the timeline view):
 # CHECK-NEXT: [0]: Executions
@@ -77,6 +77,6 @@ vpinsrb $1, %eax, %xmm0, %xmm0
 # CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
 
 # CHECK:            [0]    [1]    [2]    [3]
-# CHECK-NEXT: 0.     3     1.0    1.0    11.0      addl        %eax, %eax
-# CHECK-NEXT: 1.     3     12.0   0.0    0.0       vpinsrb     $0, %eax, %xmm0, %xmm0
-# CHECK-NEXT: 2.     3     18.0   0.0    0.0       vpinsrb     $1, %eax, %xmm0, %xmm0
+# CHECK-NEXT: 0.     3     1.0    1.0    3.3       addl        %eax, %eax
+# CHECK-NEXT: 1.     3     7.0    0.0    0.0       vpinsrb     $0, %eax, %xmm0, %xmm0
+# CHECK-NEXT: 2.     3     7.0    0.0    0.0       vpinsrb     $1, %eax, %xmm0, %xmm0
index 60b8b1f51413f0de3b0b2257d3deb25aad91825f..1fbffa3e5b69798f0bc694de641e015a1abb1788 100644 (file)
@@ -43,6 +43,9 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
     const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
     unsigned NumMicroOpcodes = SCDesc.NumMicroOps;
     unsigned Latency = MCSchedModel::computeInstrLatency(STI, SCDesc);
+    // Add extra latency due to delays in the forwarding data paths.
+    Latency += MCSchedModel::getForwardingDelayCycles(
+        STI.getReadAdvanceEntries(SCDesc));
     Optional<double> RThroughput =
         MCSchedModel::getReciprocalThroughput(STI, SCDesc);