Skip to content

Commit bc2541e

Browse files
author
Jin Huang
committed
[AA] A conservative fix for atomic store instruction. The current atomic store check return all atomic store as a modify instruciton without any memory check. This pr will raise from unordered to Monotonic.
1 parent 17bddd1 commit bc2541e

File tree

2 files changed

+109
-23
lines changed

2 files changed

+109
-23
lines changed

llvm/lib/Analysis/AliasAnalysis.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454

5555
using namespace llvm;
5656

57-
STATISTIC(NumNoAlias, "Number of NoAlias results");
58-
STATISTIC(NumMayAlias, "Number of MayAlias results");
57+
STATISTIC(NumNoAlias, "Number of NoAlias results");
58+
STATISTIC(NumMayAlias, "Number of MayAlias results");
5959
STATISTIC(NumMustAlias, "Number of MustAlias results");
6060

6161
/// Allow disabling BasicAA from the AA results. This is particularly useful
@@ -118,8 +118,8 @@ AliasResult AAResults::alias(const MemoryLocation &LocA,
118118
if (EnableAATrace) {
119119
for (unsigned I = 0; I < AAQI.Depth; ++I)
120120
dbgs() << " ";
121-
dbgs() << "Start " << *LocA.Ptr << " @ " << LocA.Size << ", "
122-
<< *LocB.Ptr << " @ " << LocB.Size << "\n";
121+
dbgs() << "Start " << *LocA.Ptr << " @ " << LocA.Size << ", " << *LocB.Ptr
122+
<< " @ " << LocB.Size << "\n";
123123
}
124124

125125
AAQI.Depth++;
@@ -133,8 +133,8 @@ AliasResult AAResults::alias(const MemoryLocation &LocA,
133133
if (EnableAATrace) {
134134
for (unsigned I = 0; I < AAQI.Depth; ++I)
135135
dbgs() << " ";
136-
dbgs() << "End " << *LocA.Ptr << " @ " << LocA.Size << ", "
137-
<< *LocB.Ptr << " @ " << LocB.Size << " = " << Result << "\n";
136+
dbgs() << "End " << *LocA.Ptr << " @ " << LocA.Size << ", " << *LocB.Ptr
137+
<< " @ " << LocB.Size << " = " << Result << "\n";
138138
}
139139

140140
if (AAQI.Depth == 0) {
@@ -421,9 +421,18 @@ ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
421421
const MemoryLocation &Loc,
422422
AAQueryInfo &AAQI) {
423423
// Be conservative in the face of atomic.
424-
if (isStrongerThan(L->getOrdering(), AtomicOrdering::Unordered))
424+
if (isStrongerThan(L->getOrdering(), AtomicOrdering::Monotonic))
425425
return ModRefInfo::ModRef;
426426

427+
// For Monotonic and unordered loads, we only need to be more conservative
428+
// when the locations are MustAlias to prevent unsafe reordering of accesses
429+
// to the same memory. For MayAlias, we can treat it as a normal read.
430+
if (L->isAtomic()) {
431+
if (Loc.Ptr &&
432+
alias(MemoryLocation::get(L), Loc, AAQI, L) == AliasResult::MustAlias)
433+
return ModRefInfo::ModRef;
434+
}
435+
427436
// If the load address doesn't alias the given address, it doesn't read
428437
// or write the specified memory.
429438
if (Loc.Ptr) {
@@ -439,7 +448,7 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
439448
const MemoryLocation &Loc,
440449
AAQueryInfo &AAQI) {
441450
// Be conservative in the face of atomic.
442-
if (isStrongerThan(S->getOrdering(), AtomicOrdering::Unordered))
451+
if (isStrongerThan(S->getOrdering(), AtomicOrdering::Monotonic))
443452
return ModRefInfo::ModRef;
444453

445454
if (Loc.Ptr) {
@@ -538,7 +547,8 @@ ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
538547
ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
539548
const MemoryLocation &Loc,
540549
AAQueryInfo &AAQI) {
541-
// Acquire/Release atomicrmw has properties that matter for arbitrary addresses.
550+
// Acquire/Release atomicrmw has properties that matter for arbitrary
551+
// addresses.
542552
if (isStrongerThanMonotonic(RMW->getOrdering()))
543553
return ModRefInfo::ModRef;
544554

@@ -600,8 +610,7 @@ ModRefInfo AAResults::getModRefInfo(const Instruction *I,
600610
/// with a smarter AA in place, this test is just wasting compile time.
601611
ModRefInfo AAResults::callCapturesBefore(const Instruction *I,
602612
const MemoryLocation &MemLoc,
603-
DominatorTree *DT,
604-
AAQueryInfo &AAQI) {
613+
DominatorTree *DT, AAQueryInfo &AAQI) {
605614
if (!DT)
606615
return ModRefInfo::ModRef;
607616

@@ -677,7 +686,7 @@ bool AAResults::canInstructionRangeModRef(const Instruction &I1,
677686
"Instructions not in same basic block!");
678687
BasicBlock::const_iterator I = I1.getIterator();
679688
BasicBlock::const_iterator E = I2.getIterator();
680-
++E; // Convert from inclusive to exclusive range.
689+
++E; // Convert from inclusive to exclusive range.
681690

682691
for (; I != E; ++I) // Check every instruction in range
683692
if (isModOrRefSet(getModRefInfo(&*I, Loc) & Mode))

llvm/unittests/Analysis/AliasAnalysisTest.cpp

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ using namespace llvm;
2626

2727
// Set up some test passes.
2828
namespace llvm {
29-
void initializeAATestPassPass(PassRegistry&);
30-
void initializeTestCustomAAWrapperPassPass(PassRegistry&);
31-
}
29+
void initializeAATestPassPass(PassRegistry &);
30+
void initializeTestCustomAAWrapperPassPass(PassRegistry &);
31+
} // namespace llvm
3232

3333
namespace {
3434
struct AATestPass : FunctionPass {
@@ -61,7 +61,7 @@ struct AATestPass : FunctionPass {
6161
return false;
6262
}
6363
};
64-
}
64+
} // namespace
6565

6666
char AATestPass::ID = 0;
6767
INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
@@ -90,7 +90,7 @@ struct TestCustomAAResult : AAResultBase {
9090
return AliasResult::MayAlias;
9191
}
9292
};
93-
}
93+
} // namespace
9494

9595
namespace {
9696
/// A wrapper pass for the legacy pass manager to use with the above custom AA
@@ -126,14 +126,14 @@ class TestCustomAAWrapperPass : public ImmutablePass {
126126
TestCustomAAResult &getResult() { return *Result; }
127127
const TestCustomAAResult &getResult() const { return *Result; }
128128
};
129-
}
129+
} // namespace
130130

131131
char TestCustomAAWrapperPass::ID = 0;
132132
INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
133-
"Test Custom AA Wrapper Pass", false, true)
133+
"Test Custom AA Wrapper Pass", false, true)
134134
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
135135
INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
136-
"Test Custom AA Wrapper Pass", false, true)
136+
"Test Custom AA Wrapper Pass", false, true)
137137

138138
namespace {
139139

@@ -246,7 +246,8 @@ TEST_F(AliasAnalysisTest, BatchAAPhiCycles) {
246246
%s2 = select i1 %c, i8* %a2, i8* %a1
247247
br label %loop
248248
}
249-
)", Err, C);
249+
)",
250+
Err, C);
250251

251252
Function *F = M->getFunction("f");
252253
Instruction *Phi = getInstructionByName(*F, "phi");
@@ -291,7 +292,8 @@ TEST_F(AliasAnalysisTest, BatchAAPhiAssumption) {
291292
%b.next = getelementptr i8, i8* %b, i64 1
292293
br label %loop
293294
}
294-
)", Err, C);
295+
)",
296+
Err, C);
295297

296298
Function *F = M->getFunction("f");
297299
Instruction *A = getInstructionByName(*F, "a");
@@ -425,4 +427,79 @@ TEST_F(AAPassInfraTest, injectExternalAA) {
425427
EXPECT_TRUE(IsCustomAAQueried);
426428
}
427429

428-
} // end anonymous namspace
430+
// Test that a monotonic atomic load is treated as ModRef ONLY against a
431+
// MustAlias locations, and as Ref against a MayAlias location.
432+
TEST_F(AliasAnalysisTest, MonotonicAtomicLoadIsModRefOnlyForMustAlias) {
433+
LLVMContext C;
434+
SMDiagnostic Err;
435+
std::unique_ptr<Module> M = parseAssemblyString(R"(
436+
define void @atomic_load_modref_test(i8* %p1, i8* %p2) {
437+
entry:
438+
%val = load atomic i8, i8* %p1 monotonic, align 1
439+
ret void
440+
}
441+
)",
442+
Err, C);
443+
444+
ASSERT_TRUE(M);
445+
446+
Function *F = M->getFunction("atomic_load_modref_test");
447+
const Instruction *AtomicLoad = &F->getEntryBlock().front();
448+
const Value *Ptr1 = F->getArg(0);
449+
const Value *Ptr2 = F->getArg(1);
450+
451+
MemoryLocation Ptr1Loc = MemoryLocation(Ptr1, LocationSize::precise(1));
452+
MemoryLocation Ptr2Loc = MemoryLocation(Ptr2, LocationSize::precise(1));
453+
454+
auto &AA = getAAResults(*F);
455+
456+
// 1. MustAlias Case: The atomic load on %p1 against a location on %p1.
457+
// This should trigger the new logic and return ModRef.
458+
EXPECT_EQ(ModRefInfo::ModRef, AA.getModRefInfo(AtomicLoad, Ptr1Loc));
459+
460+
// 2. MayAlias Case: The atomic load on %p1 against a location on %p2.
461+
// This should NOT trigger the new logic and should fall back to returning
462+
// Ref.
463+
EXPECT_EQ(ModRefInfo::Ref, AA.getModRefInfo(AtomicLoad, Ptr2Loc));
464+
}
465+
466+
// Test that a monotonic atomic store is no longer considered "strong" and
467+
// falls through to the alias checking logic, while stroner orderings do not.
468+
TEST_F(AliasAnalysisTest, MonotonicAtomicStoreAliasBehavior) {
469+
LLVMContext C;
470+
SMDiagnostic Err;
471+
std::unique_ptr<Module> M = parseAssemblyString(R"(
472+
define void @atomic_store_test(i8* noalias %p1, i8* noalias %p2) {
473+
entry:
474+
store atomic i8 0, i8* %p1 monotonic, align 1
475+
store atomic i8 0, i8* %p1 release, align 1
476+
ret void
477+
}
478+
)",
479+
Err, C);
480+
481+
ASSERT_TRUE(M);
482+
483+
Function *F = M->getFunction("atomic_store_test");
484+
auto It = F->getEntryBlock().begin();
485+
const Instruction *MonotonicStore = &*It++;
486+
const Instruction *ReleaseStore = &*It;
487+
488+
const Value *Ptr2 = F->getArg(1);
489+
MemoryLocation Ptr2Loc = MemoryLocation(Ptr2, LocationSize::precise(1));
490+
491+
auto &AA = getAAResults(*F);
492+
493+
// 1. Test the Monotonic store.
494+
// With the change, the Monotonic store should go through the
495+
// isStrongerThan() check. Since %p1 and %p2 are noalias, the alias check
496+
// should return NoAlias, resulting in NoModRef.
497+
EXPECT_EQ(ModRefInfo::NoModRef, AA.getModRefInfo(MonotonicStore, Ptr2Loc));
498+
499+
// 2. Test the Relase (stronger) store.
500+
// The release atomic store should be caught by the isStrongerThan() check.
501+
// return ModRef without performing an alias check.
502+
EXPECT_EQ(ModRefInfo::ModRef, AA.getModRefInfo(ReleaseStore, Ptr2Loc));
503+
}
504+
505+
} // namespace

0 commit comments

Comments
 (0)