[ScheduleDAGInstrs] Handle instructions with multiple MMOs
authorGeoff Berry <gberry@codeaurora.org>
Tue, 12 Apr 2016 15:50:19 +0000 (15:50 +0000)
committerGeoff Berry <gberry@codeaurora.org>
Tue, 12 Apr 2016 15:50:19 +0000 (15:50 +0000)
Summary:
In getUnderlyingObjectsForInstr(): Don't give up on instructions with
multiple MMOs, instead look through all the MMOs and if they all meet
the conservative criteria previously used for single MMO instructions,
then return all of the underlying objects derived from the MMOs.

The change to ScheduleDAGInstrs::buildSchedGraph() is needed to avoid
the case where multiple underlying objects are present and are related
in such a way that successive iterations of the loop end up adding a
dependency from an instruction to itself.

Reviewers: atrick, hfinkel

Subscribers: MatzeB, mcrosier, llvm-commits

Differential Revision: http://reviews.llvm.org/D18093

llvm-svn: 266084

llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
llvm/test/CodeGen/AArch64/arm64-misched-multimmo.ll [new file with mode: 0644]

index 61b636d..c9c9a47 100644 (file)
@@ -159,45 +159,48 @@ static void getUnderlyingObjectsForInstr(const MachineInstr *MI,
                                          const MachineFrameInfo *MFI,
                                          UnderlyingObjectsVector &Objects,
                                          const DataLayout &DL) {
-  if (!MI->hasOneMemOperand() ||
-      (!(*MI->memoperands_begin())->getValue() &&
-       !(*MI->memoperands_begin())->getPseudoValue()) ||
-      (*MI->memoperands_begin())->isVolatile())
-    return;
-
-  if (const PseudoSourceValue *PSV =
-      (*MI->memoperands_begin())->getPseudoValue()) {
-    // Function that contain tail calls don't have unique PseudoSourceValue
-    // objects. Two PseudoSourceValues might refer to the same or overlapping
-    // locations. The client code calling this function assumes this is not the
-    // case. So return a conservative answer of no known object.
-    if (MFI->hasTailCall())
+  for (auto *MMO : MI->memoperands()) {
+    if (MMO->isVolatile()) {
+      Objects.clear();
       return;
+    }
+
+    if (const PseudoSourceValue *PSV = MMO->getPseudoValue()) {
+      // Function that contain tail calls don't have unique PseudoSourceValue
+      // objects. Two PseudoSourceValues might refer to the same or overlapping
+      // locations. The client code calling this function assumes this is not the
+      // case. So return a conservative answer of no known object.
+      if (MFI->hasTailCall()) {
+        Objects.clear();
+        return;
+      }
+
+      // For now, ignore PseudoSourceValues which may alias LLVM IR values
+      // because the code that uses this function has no way to cope with
+      // such aliases.
+      if (PSV->isAliased(MFI)) {
+        Objects.clear();
+        return;
+      }
 
-    // For now, ignore PseudoSourceValues which may alias LLVM IR values
-    // because the code that uses this function has no way to cope with
-    // such aliases.
-    if (!PSV->isAliased(MFI)) {
       bool MayAlias = PSV->mayAlias(MFI);
       Objects.push_back(UnderlyingObjectsVector::value_type(PSV, MayAlias));
-    }
-    return;
-  }
+    } else if (const Value *V = MMO->getValue()) {
+      SmallVector<Value *, 4> Objs;
+      getUnderlyingObjects(V, Objs, DL);
 
-  const Value *V = (*MI->memoperands_begin())->getValue();
-  if (!V)
-    return;
-
-  SmallVector<Value *, 4> Objs;
-  getUnderlyingObjects(V, Objs, DL);
+      for (Value *V : Objs) {
+        if (!isIdentifiedObject(V)) {
+          Objects.clear();
+          return;
+        }
 
-  for (Value *V : Objs) {
-    if (!isIdentifiedObject(V)) {
+        Objects.push_back(UnderlyingObjectsVector::value_type(V, true));
+      }
+    } else {
       Objects.clear();
       return;
     }
-
-    Objects.push_back(UnderlyingObjectsVector::value_type(V, true));
   }
 }
 
@@ -1037,6 +1040,14 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
           // Add dependencies to previous stores and loads mapped to V.
           addChainDependencies(SU, stores_, V);
           addChainDependencies(SU, (ThisMayAlias ? Loads : NonAliasLoads), V);
+        }
+        // Update the store map after all chains have been added to avoid adding
+        // self-loop edge if multiple underlying objects are present.
+        for (auto &underlObj : Objs) {
+          ValueType V = underlObj.getPointer();
+          bool ThisMayAlias = underlObj.getInt();
+
+          Value2SUsMap &stores_ = (ThisMayAlias ? Stores : NonAliasStores);
 
           // Map this store to V.
           stores_.insert(SU, V);
diff --git a/llvm/test/CodeGen/AArch64/arm64-misched-multimmo.ll b/llvm/test/CodeGen/AArch64/arm64-misched-multimmo.ll
new file mode 100644 (file)
index 0000000..d4e8aa1
--- /dev/null
@@ -0,0 +1,23 @@
+; REQUIRES: asserts
+; RUN: llc < %s -mtriple=arm64-linux-gnu -mcpu=cortex-a57 -enable-misched=0 -debug-only=misched -o - 2>&1 > /dev/null | FileCheck %s
+
+
+@G1 = common global [100 x i32] zeroinitializer, align 4
+@G2 = common global [100 x i32] zeroinitializer, align 4
+
+; Check that no scheduling dependencies are created between the paired loads and the store during post-RA MI scheduling.
+;
+; CHECK-LABEL: # Machine code for function foo: Properties: <Post SSA
+; CHECK: SU(2):   %W{{[0-9]+}}<def>, %W{{[0-9]+}}<def> = LDPWi
+; CHECK: Successors:
+; CHECK-NOT: ch SU(4)
+; CHECK: SU(3)
+; CHECK: SU(4):   STRWui %WZR, %X{{[0-9]+}}
+define i32 @foo() {
+entry:
+  %0 = load i32, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @G2, i64 0, i64 0), align 4
+  %1 = load i32, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @G2, i64 0, i64 1), align 4
+  store i32 0, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @G1, i64 0, i64 0), align 4
+  %add = add nsw i32 %1, %0
+  ret i32 %add
+}