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));
}
}
// 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);
--- /dev/null
+; 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
+}