[llvm-tblgen] CodeGenSchedModels::hasReadOfWrite gets wrong predication result
authorZi Xuan Wu (Zeson) <zixuan.wu@linux.alibaba.com>
Wed, 14 Sep 2022 07:52:27 +0000 (15:52 +0800)
committerZi Xuan Wu <zixuan.wu@linux.alibaba.com>
Mon, 19 Sep 2022 06:22:43 +0000 (14:22 +0800)
CodeGenSchedModels::hasReadOfWrite tries to predicate whether the WriteDef is contained in the list of ValidWrites of someone ProcReadAdvance,
so that WriteID of WriteDef can be compressed and reusable.

It tries to iterate all ProcReadAdvance entry, but not all ProcReadAdvance defs also inherit from SchedRead.
Some ProcReadAdvances are defined by ReadAdvance.So it's not complete to enumerate all ProcReadAdvances if just iterate all SchedReads.

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

llvm/test/TableGen/CompressWriteLatencyEntry.td [new file with mode: 0644]
llvm/utils/TableGen/CodeGenSchedule.cpp

diff --git a/llvm/test/TableGen/CompressWriteLatencyEntry.td b/llvm/test/TableGen/CompressWriteLatencyEntry.td
new file mode 100644 (file)
index 0000000..88273e8
--- /dev/null
@@ -0,0 +1,54 @@
+// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s 2>&1 | FileCheck %s
+
+// Make sure that ReadAdvance entries are correctly processed.
+// Not all ProcReadAdvance definitions implicitly inherit from SchedRead.
+// Some ProcReadAdvances are subclasses of ReadAdvance.
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+let OutOperandList = (outs), InOperandList = (ins) in {
+  def Inst_A : Instruction;
+  def Inst_B : Instruction;
+  def Inst_C : Instruction;
+
+}
+
+let CompleteModel = 0 in {
+  def SchedModel_A: SchedMachineModel;
+}
+
+def Read_D : SchedRead;
+
+// CHECK: extern const llvm::MCWriteLatencyEntry MyTargetWriteLatencyTable[] = {
+// CHECK-NEXT:  { 0,  0}, // Invalid
+// CHECK-NEXT:  { 1,  0}, // #1 Write_A_Write_C
+// CHECK-NEXT:  { 1,  2} // #2 Write_B
+// CHECK-NEXT: }; // MyTargetWriteLatencyTable
+
+// CHECK: extern const llvm::MCReadAdvanceEntry MyTargetReadAdvanceTable[] = {
+// CHECK-NEXT:  {0,  0,  0}, // Invalid
+// CHECK-NEXT:  {0,  2,  1} // #1
+// CHECK-NEXT: }; // MyTargetReadAdvanceTable
+
+// CHECK:  static const llvm::MCSchedClassDesc SchedModel_ASchedClasses[] = {
+// CHECK-NEXT:  {DBGFIELD("InvalidSchedClass")  8191, false, false, false, 0, 0,  0, 0,  0, 0},
+// CHECK-NEXT:  {DBGFIELD("Inst_A")             1, false, false, false,  0, 0,  1, 1,  0, 0}, // #1
+// CHECK-NEXT:  {DBGFIELD("Inst_B")             1, false, false, false,  0, 0,  2, 1,  0, 0}, // #2
+// CHECK-NEXT:  {DBGFIELD("Inst_C")             1, false, false, false,  0, 0,  1, 1,  1, 1}, // #3
+// CHECK-NEXT: }; // SchedModel_ASchedClasses
+
+let SchedModel = SchedModel_A in {
+  def Write_A : SchedWriteRes<[]>;
+  def Write_B : SchedWriteRes<[]>;
+  def Write_C : SchedWriteRes<[]>;
+
+  def : InstRW<[Write_A], (instrs Inst_A)>;
+  def : InstRW<[Write_B], (instrs Inst_B)>;
+  def : InstRW<[Write_C, Read_D], (instrs Inst_C)>;
+
+  def : ReadAdvance<Read_D, 1, [Write_B]>;
+}
+
+def ProcessorA: ProcessorModel<"ProcessorA", SchedModel_A, []>;
index c9e6eea..7146a80 100644 (file)
@@ -734,14 +734,12 @@ unsigned CodeGenSchedModels::getSchedRWIdx(const Record *Def,
 }
 
 bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
-  for (const CodeGenSchedRW &Read : SchedReads) {
-    Record *ReadDef = Read.TheDef;
-    if (!ReadDef || !ReadDef->isSubClassOf("ProcReadAdvance"))
-      continue;
-
-    RecVec ValidWrites = ReadDef->getValueAsListOfDefs("ValidWrites");
-    if (is_contained(ValidWrites, WriteDef)) {
-      return true;
+  for (auto& ProcModel : ProcModels) {
+    const RecVec &RADefs = ProcModel.ReadAdvanceDefs;
+    for (auto& RADef : RADefs) {
+      RecVec ValidWrites = RADef->getValueAsListOfDefs("ValidWrites");
+      if (is_contained(ValidWrites, WriteDef))
+        return true;
     }
   }
   return false;