From: Andrea Di Biagio Date: Mon, 2 Apr 2018 13:46:49 +0000 (+0000) Subject: [llvm-mca] Do not assume that implicit reads cannot be associated with ReadAdvance... X-Git-Tag: llvmorg-7.0.0-rc1~9218 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6fd62feff8e5f5c24b930f17d902db6526a55b6f;p=platform%2Fupstream%2Fllvm.git [llvm-mca] Do not assume that implicit reads cannot be associated with ReadAdvance entries. 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 --- 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 index 0000000..746333d --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/read-advance-2.s @@ -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) diff --git a/llvm/tools/llvm-mca/InstrBuilder.cpp b/llvm/tools/llvm-mca/InstrBuilder.cpp index 2b0be92..c56a279 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.cpp +++ b/llvm/tools/llvm-mca/InstrBuilder.cpp @@ -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'); diff --git a/llvm/tools/llvm-mca/Instruction.h b/llvm/tools/llvm-mca/Instruction.h index 00ba9b9..d7d2685 100644 --- a/llvm/tools/llvm-mca/Instruction.h +++ b/llvm/tools/llvm-mca/Instruction.h @@ -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