]> granicus.if.org Git - llvm/commitdiff
[Hexagon] Check for potential bank conflicts in post-RA scheduling
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Mon, 28 Aug 2017 18:36:21 +0000 (18:36 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Mon, 28 Aug 2017 18:36:21 +0000 (18:36 +0000)
Insert artificial edges between loads that could cause a cache bank
conflict.

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

lib/Target/Hexagon/HexagonSubtarget.cpp
lib/Target/Hexagon/HexagonSubtarget.h
lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
test/CodeGen/Hexagon/bank-conflict-load.mir [new file with mode: 0644]

index d9fa3b2548e3db4df5f41ea4537dcad1d6e8435e..5803886f8b0a04c82cc49725de97acf299672372 100644 (file)
@@ -93,6 +93,10 @@ static cl::opt<bool> SchedPredsCloser("sched-preds-closer",
 static cl::opt<bool> SchedRetvalOptimization("sched-retval-optimization",
   cl::Hidden, cl::ZeroOrMore, cl::init(true));
 
+static cl::opt<bool> EnableCheckBankConflict("hexagon-check-bank-conflict",
+  cl::Hidden, cl::ZeroOrMore, cl::init(true),
+  cl::desc("Enable checking for cache bank conflicts"));
+
 
 void HexagonSubtarget::initializeEnvironment() {
   UseMemOps = false;
@@ -247,6 +251,52 @@ void HexagonSubtarget::CallMutation::apply(ScheduleDAGInstrs *DAG) {
   }
 }
 
+void HexagonSubtarget::BankConflictMutation::apply(ScheduleDAGInstrs *DAG) {
+  if (!EnableCheckBankConflict)
+    return;
+
+  const auto &HII = static_cast<const HexagonInstrInfo&>(*DAG->TII);
+
+  // Create artificial edges between loads that could likely cause a bank
+  // conflict. Since such loads would normally not have any dependency
+  // between them, we cannot rely on existing edges.
+  for (unsigned i = 0, e = DAG->SUnits.size(); i != e; ++i) {
+    SUnit &S0 = DAG->SUnits[i];
+    MachineInstr &L0 = *S0.getInstr();
+    if (!L0.mayLoad() || L0.mayStore() ||
+        HII.getAddrMode(L0) != HexagonII::BaseImmOffset)
+      continue;
+    int Offset0;
+    unsigned Size0;
+    unsigned Base0 = HII.getBaseAndOffset(L0, Offset0, Size0);
+    // Is the access size is longer than the L1 cache line, skip the check.
+    if (Base0 == 0 || Size0 >= 32)
+      continue;
+    // Scan only up to 32 instructions ahead (to avoid n^2 complexity).
+    for (unsigned j = i+1, m = std::min(i+32, e); j != m; ++j) {
+      SUnit &S1 = DAG->SUnits[j];
+      MachineInstr &L1 = *S1.getInstr();
+      if (!L1.mayLoad() || L1.mayStore() ||
+          HII.getAddrMode(L1) != HexagonII::BaseImmOffset)
+        continue;
+      int Offset1;
+      unsigned Size1;
+      unsigned Base1 = HII.getBaseAndOffset(L1, Offset1, Size1);
+      if (Base1 == 0 || Size1 >= 32 || Base0 != Base1)
+        continue;
+      // Check bits 3 and 4 of the offset: if they differ, a bank conflict
+      // is unlikely.
+      if (((Offset0 ^ Offset1) & 0x18) != 0)
+        continue;
+      // Bits 3 and 4 are the same, add an artificial edge and set extra
+      // latency.
+      SDep A(&S0, SDep::Artificial);
+      A.setLatency(1);
+      S1.addPred(A, true);
+    }
+  }
+}
+
 
 HexagonSubtarget::HexagonSubtarget(const Triple &TT, StringRef CPU,
                                    StringRef FS, const TargetMachine &TM)
@@ -330,6 +380,7 @@ void HexagonSubtarget::getPostRAMutations(
     std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
   Mutations.push_back(llvm::make_unique<UsrOverflowMutation>());
   Mutations.push_back(llvm::make_unique<HVXMemLatencyMutation>());
+  Mutations.push_back(llvm::make_unique<BankConflictMutation>());
 }
 
 void HexagonSubtarget::getSMSMutations(
index 542929d94a706d7b570228b14bfd83e9a22808a0..bdaf12e17d979fceb59ed64af9255a3d97e8a93d 100644 (file)
@@ -68,6 +68,9 @@ public:
     bool shouldTFRICallBind(const HexagonInstrInfo &HII,
           const SUnit &Inst1, const SUnit &Inst2) const;
   };
+  struct BankConflictMutation : public ScheduleDAGMutation {
+    void apply(ScheduleDAGInstrs *DAG) override;
+  };
 
 private:
   std::string CPUString;
index a6d134365a62b8b1a5a74a2ed2ae3e5c713cb040..9b4530f22973b4373d2ec7efffbd16d4dc23b5de 100644 (file)
@@ -105,6 +105,7 @@ HexagonPacketizerList::HexagonPacketizerList(MachineFunction &MF,
 
   addMutation(make_unique<HexagonSubtarget::UsrOverflowMutation>());
   addMutation(make_unique<HexagonSubtarget::HVXMemLatencyMutation>());
+  addMutation(make_unique<HexagonSubtarget::BankConflictMutation>());
 }
 
 // Check if FirstI modifies a register that SecondI reads.
diff --git a/test/CodeGen/Hexagon/bank-conflict-load.mir b/test/CodeGen/Hexagon/bank-conflict-load.mir
new file mode 100644 (file)
index 0000000..fe7aac1
--- /dev/null
@@ -0,0 +1,28 @@
+# RUN: llc -march=hexagon -run-pass post-RA-sched %s -o - | FileCheck %s
+
+# The two loads from %a (%r0) can cause a bank conflict. Check that they
+# are not scheduled next to each other.
+
+# CHECK: L2_loadri_io %r0, 8
+# CHECK: L2_loadri_io killed %r1, 0
+# CHECK: L2_loadri_io killed %r0, 12
+
+--- |
+  define void @foo(i32* %a, i32* %b) {
+    ret void
+  }
+...
+
+---
+name: foo
+tracksRegLiveness: true
+
+body: |
+  bb.0:
+    liveins: %r0, %r1
+
+    %r2 = L2_loadri_io %r0, 8 :: (load 4 from %ir.a)
+    %r3 = L2_loadri_io killed %r0, 12 :: (load 4 from %ir.a)
+    %r4 = L2_loadri_io killed %r1, 0 :: (load 4 from %ir.b)
+...
+