Skip to content

[FlattenCFG] Fix an Imprecise Usage of AA #128117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 18, 2025

Conversation

Chengjunp
Copy link
Contributor

@Chengjunp Chengjunp commented Feb 21, 2025

In current FlattenCFG, using isNoAlias for two instructions is imprecise. For example, when passing a store instruction and a load instruction directly into AA->isNoAlias, it will always return NoAlias. This happens because when checking the types of the two Values, the store instruction (which has a void type) causes the analysis to return NoAlias.

For instructions, we should use getModRefInfo instead of isNoAlias, as aliasing is a concept of memory locations.

In this patch, AAResults::getModRefInfo is supported to take in two instructions. It will check whether two instructions may access the same memory location or not. And in FlattenCFG, we use this new helper function to do the check instead of isNoAlias.

Unit tests and lit tests are also included to this patch.

@llvmbot
Copy link
Member

llvmbot commented Feb 21, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Chengjun (Chengjunp)

Changes

In current FlattenCFG, the alias check between two instructions is imprecise. Specifically, AA->isNoAlias should not be called with two instructions directly. When passing a store instruction and a load instruction directly into AA->isNoAlias always returns NoAlias. This happens because when checking the types of the two Values, the store instruction (which has a void type) causes the analysis to return NoAlias.

In this patch, we take the MemoryLocations from the instructions and then do the alias check on these two MemoryLocations. Related tests are also added.


Full diff: https://github.com/llvm/llvm-project/pull/128117.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/FlattenCFG.cpp (+6-2)
  • (modified) llvm/test/Transforms/Util/flatten-cfg.ll (+87-1)
diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 16b4bb1981d8b..151ca06f3498a 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -357,8 +357,12 @@ bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
       for (BasicBlock::iterator BI(PBI2), BE(PTI2); BI != BE; ++BI) {
         if (BI->mayReadFromMemory() || BI->mayWriteToMemory()) {
           // Check alias with Head2.
-          if (!AA || !AA->isNoAlias(&*iter1, &*BI))
-            return false;
+          if (AA) {
+            MemoryLocation Loc1 = MemoryLocation::get(&*iter1);
+            MemoryLocation Loc2 = MemoryLocation::get(&*BI);
+            if (!AA->isNoAlias(Loc1, Loc2))
+              return false;
+          }
         }
       }
     }
diff --git a/llvm/test/Transforms/Util/flatten-cfg.ll b/llvm/test/Transforms/Util/flatten-cfg.ll
index 038dcaa47419a..bb592a7031031 100644
--- a/llvm/test/Transforms/Util/flatten-cfg.ll
+++ b/llvm/test/Transforms/Util/flatten-cfg.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -passes=flatten-cfg -S < %s | FileCheck %s
+; RUN: opt -passes='require<aa>,flatten-cfg' -S < %s | FileCheck %s
 
 
 ; This test checks whether the pass completes without a crash.
@@ -309,3 +309,89 @@ if.then.y:
 exit:
   ret i1 %cmp.y
 }
+
+; Test that two if-regions are not merged when there's potential aliasing
+; between a store in the first if-region and a load in the second if-region's header
+define i32 @test_alias(i32 %a, i32 %b, ptr %p1, ptr %p2) {
+; CHECK-LABEL: define i32 @test_alias
+; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    store i32 42, ptr [[P1]], align 4
+; CHECK-NEXT:    [[COND1:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    br i1 [[COND1]], label [[IF_THEN1:%.*]], label [[IF_END1:%.*]]
+; CHECK:       if.then1:
+; CHECK-NEXT:    store i32 100, ptr [[P2]], align 4
+; CHECK-NEXT:    br label [[IF_END1]]
+; CHECK:       if.end1:
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[P1]], align 4
+; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT:    br i1 [[COND2]], label [[IF_THEN2:%.*]], label [[IF_END2:%.*]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    store i32 100, ptr [[P2]], align 4
+; CHECK-NEXT:    br label [[IF_END2]]
+; CHECK:       if.end2:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  store i32 42, ptr %p1
+  %cond1 = icmp eq i32 %a, 0
+  br i1 %cond1, label %if.then1, label %if.end1
+
+if.then1:
+  store i32 100, ptr %p2  ; May alias with the load below
+  br label %if.end1
+
+if.end1:
+  %val = load i32, ptr %p1  ; This load prevents merging due to potential alias
+  %cond2 = icmp eq i32 %b, 0
+  br i1 %cond2, label %if.then2, label %if.end2
+
+if.then2:
+  store i32 100, ptr %p2
+  br label %if.end2
+
+if.end2:
+  ret i32 0
+}
+
+; Test that two if-regions are merged when there's no potential aliasing
+; between a store in the first if-region and a load in the second if-region's header
+define i32 @test_no_alias(i32 %a, i32 %b) {
+; CHECK-LABEL: define i32 @test_no_alias
+; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    store i32 42, ptr [[P]], align 4
+; CHECK-NEXT:    [[COND1:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr @g, align 4
+; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[COND1]], [[COND2]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN2:%.*]], label [[IF_END2:%.*]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    store i32 100, ptr [[P]], align 4
+; CHECK-NEXT:    br label [[IF_END2]]
+; CHECK:       if.end2:
+; CHECK-NEXT:    ret i32 0
+;
+  entry:
+  %p = alloca i32
+  store i32 42, ptr %p
+  %cond1 = icmp eq i32 %a, 0
+  br i1 %cond1, label %if.then1, label %if.end1
+
+if.then1:
+  store i32 100, ptr %p  ; No alias with the load below
+  br label %if.end1
+
+if.end1:
+  %val = load i32, ptr @g
+  %cond2 = icmp eq i32 %b, 0
+  br i1 %cond2, label %if.then2, label %if.end2
+
+if.then2:
+  store i32 100, ptr %p
+  br label %if.end2
+
+if.end2:
+  ret i32 0
+}
\ No newline at end of file

@@ -357,8 +357,12 @@ bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
for (BasicBlock::iterator BI(PBI2), BE(PTI2); BI != BE; ++BI) {
if (BI->mayReadFromMemory() || BI->mayWriteToMemory()) {
// Check alias with Head2.
if (!AA || !AA->isNoAlias(&*iter1, &*BI))
return false;
if (AA) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to return false if (!AA).

return false;
if (AA) {
MemoryLocation Loc1 = MemoryLocation::get(&*iter1);
MemoryLocation Loc2 = MemoryLocation::get(&*BI);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test where BI is a call? I expect that to crash.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just added a case including this. Yeah, it will crash with my previous implementation. It should work now with my new implementation.

if (AA) {
MemoryLocation Loc1 = MemoryLocation::get(&*iter1);
MemoryLocation Loc2 = MemoryLocation::get(&*BI);
if (!AA->isNoAlias(Loc1, Loc2))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't wrong (for non-calls), but getModRefInfo would be more appropriate here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing this out. Instead of making modifications here, I choose to implement a new alias helper function that takes in two instructions. Could you please help me check whether that is the right way to use getModRefInfo check the alias between two instructions? Thanks!

@Chengjunp Chengjunp requested a review from nikic February 22, 2025 03:11
Copy link

github-actions bot commented Feb 25, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@@ -381,6 +381,14 @@ class AAResults {
MemoryLocation::getBeforeOrAfter(V2));
}

/// A convenience wrapper around the \c isNoAlias for two instructions.
bool isNoAlias(const Instruction *I1, const Instruction *I2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using NoAlias terminology isn't right. Aliasing is a concept of memory locations. For instructions, you are interested in memory effects, as provided by getModRefInfo(). Adding a getModRefInfo() overload that accepts two instructions would be fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect the implementation to look somewhat similar to getModRefInfo() for an instruction and call:

ModRefInfo AAResults::getModRefInfo(const Instruction *I, const CallBase *Call2,
AAQueryInfo &AAQI) {
// We may have two calls.
if (const auto *Call1 = dyn_cast<CallBase>(I)) {
// Check if the two calls modify the same memory.
return getModRefInfo(Call1, Call2, AAQI);
}
// If this is a fence, just return ModRef.
if (I->isFenceLike())
return ModRefInfo::ModRef;
// Otherwise, check if the call modifies or references the
// location this memory access defines. The best we can say
// is that if the call references what this instruction
// defines, it must be clobbered by this location.
const MemoryLocation DefLoc = MemoryLocation::get(I);
ModRefInfo MR = getModRefInfo(Call2, DefLoc, AAQI);
if (isModOrRefSet(MR))
return ModRefInfo::ModRef;
return ModRefInfo::NoModRef;
}

@Chengjunp Chengjunp requested a review from nikic February 26, 2025 01:19
@Chengjunp
Copy link
Contributor Author

Hi @nikic , could you help to review the change please? Thanks!

@Chengjunp
Copy link
Contributor Author

Ping @nikic

@Chengjunp
Copy link
Contributor Author

Ping @nikic.

// Check whether two instructions may read or write the same memory location.
ModRefInfo AAResults::getModRefInfo(const Instruction *I1,
const Instruction *I2) {
SimpleAAQueryInfo AAQIP(*this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should accept AAQueryInfo as parameter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify this bit: We should have a method taking AAQI, and another helper that uses SimplieAAQueryInfo and call the main method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the methods. Let me know whether it is you expected.

return getModRefInfo(I1, Call2, AAQIP);

ModRefInfo MR = getModRefInfo(I1, MemoryLocation::getOrNone(I2), AAQIP);
return isModOrRefSet(MR) ? ModRefInfo::ModRef : ModRefInfo::NoModRef;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be more precise, but it's okay to start with.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be a better / more precise way to check the ModRefInfo? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, what you are currently doing is a very crude check that the two instructions somehow access the same memory. It can be made more precise by checking the kind of access. For example, if both instructions only read memory, we can actually return NoModRef, because read-read dependences can be ignored. I guess you could easily handle that part by updating your mayReadOrWriteMemory checks to check that at least one is a write instead.

Then if I1 is a read (and I2 a write) we can return Ref instead. If I1 is write (and I1 a read) we can return Mod. (This is why the order of the argument matters.)

Basically, what the Call-Call handling does starting from:

// If they both only read from memory, there is no dependence.

I think it's ok if you add a FIXME.

@Chengjunp Chengjunp requested a review from nikic April 15, 2025 19:34
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

return getModRefInfo(I1, Call2, AAQIP);

ModRefInfo MR = getModRefInfo(I1, MemoryLocation::getOrNone(I2), AAQIP);
return isModOrRefSet(MR) ? ModRefInfo::ModRef : ModRefInfo::NoModRef;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, what you are currently doing is a very crude check that the two instructions somehow access the same memory. It can be made more precise by checking the kind of access. For example, if both instructions only read memory, we can actually return NoModRef, because read-read dependences can be ignored. I guess you could easily handle that part by updating your mayReadOrWriteMemory checks to check that at least one is a write instead.

Then if I1 is a read (and I2 a write) we can return Ref instead. If I1 is write (and I1 a read) we can return Mod. (This is why the order of the argument matters.)

Basically, what the Call-Call handling does starting from:

// If they both only read from memory, there is no dependence.

I think it's ok if you add a FIXME.

@Chengjunp
Copy link
Contributor Author

Hi @nikic, thank you so much for your review. Could you help to merge the change?

I'm also working on #125965. It would be great if you can also help to review that PR.

@nikic nikic merged commit 9b8bc53 into llvm:main Apr 18, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 18, 2025

LLVM Buildbot has detected a new failure on builder sanitizer-aarch64-linux-bootstrap-msan running on sanitizer-buildbot10 while building llvm at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/94/builds/6329

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 84839 tests, 72 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70
FAIL: LLVM :: Other/spirv-sim/constant.spv (62889 of 84839)
******************** TEST 'LLVM :: Other/spirv-sim/constant.spv' FAILED ********************
Exit Code: 139

Command Output (stderr):
--
RUN: at line 1 has no command after substitutions
'/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=a --wave=1 --expects=2 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv # RUN: at line 2
+ /usr/bin/python3 /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=a --wave=1 --expects=2 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv
'/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv # RUN: at line 3
+ /usr/bin/python3 /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv
/home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/test/Other/spirv-sim/Output/constant.spv.script: line 3: 1722737 Segmentation fault      (core dumped) '/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
Slowest Tests:
--------------------------------------------------------------------------
27.03s: Clang :: Driver/fsanitize.c
23.88s: LLVM :: tools/llvm-reduce/parallel-workitem-kill.ll
19.96s: Clang :: Preprocessor/riscv-target-features.c
18.10s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
17.73s: Clang :: OpenMP/target_update_codegen.cpp
17.25s: Clang :: Driver/arm-cortex-cpus-2.c
16.83s: Clang :: Driver/arm-cortex-cpus-1.c
14.89s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c
14.70s: Clang :: Preprocessor/aarch64-target-features.c
14.35s: Clang :: Preprocessor/arm-target-features.c
12.63s: Clang :: Analysis/a_flaky_crash.cpp
11.88s: Clang :: Preprocessor/predefined-arch-macros.c
11.71s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c
11.37s: Clang :: Driver/clang_f_opts.c
11.32s: Clang :: Driver/linux-ld.c
10.10s: lit :: shtest-define.py
10.07s: Clang :: Driver/cl-options.c
10.02s: Clang :: Driver/x86-target-features.c
10.02s: LLVM-Unit :: Support/./SupportTests/ProgramEnvTest/TestExecuteNoWaitDetached
9.31s: Clang :: Analysis/runtime-regression.c
Step 13 (stage3/msan check) failure: stage3/msan check (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 84839 tests, 72 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70
FAIL: LLVM :: Other/spirv-sim/constant.spv (62889 of 84839)
******************** TEST 'LLVM :: Other/spirv-sim/constant.spv' FAILED ********************
Exit Code: 139

Command Output (stderr):
--
RUN: at line 1 has no command after substitutions
'/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=a --wave=1 --expects=2 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv # RUN: at line 2
+ /usr/bin/python3 /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=a --wave=1 --expects=2 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv
'/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv # RUN: at line 3
+ /usr/bin/python3 /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv
/home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm_build2_msan/test/Other/spirv-sim/Output/constant.spv.script: line 3: 1722737 Segmentation fault      (core dumped) '/usr/bin/python3' /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/utils/spirv-sim/spirv-sim.py --function=b --wave=1 --expects=1 -i /home/b/sanitizer-aarch64-linux-bootstrap-msan/build/llvm-project/llvm/test/Other/spirv-sim/constant.spv

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
Slowest Tests:
--------------------------------------------------------------------------
27.03s: Clang :: Driver/fsanitize.c
23.88s: LLVM :: tools/llvm-reduce/parallel-workitem-kill.ll
19.96s: Clang :: Preprocessor/riscv-target-features.c
18.10s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
17.73s: Clang :: OpenMP/target_update_codegen.cpp
17.25s: Clang :: Driver/arm-cortex-cpus-2.c
16.83s: Clang :: Driver/arm-cortex-cpus-1.c
14.89s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c
14.70s: Clang :: Preprocessor/aarch64-target-features.c
14.35s: Clang :: Preprocessor/arm-target-features.c
12.63s: Clang :: Analysis/a_flaky_crash.cpp
11.88s: Clang :: Preprocessor/predefined-arch-macros.c
11.71s: Clang :: CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c
11.37s: Clang :: Driver/clang_f_opts.c
11.32s: Clang :: Driver/linux-ld.c
10.10s: lit :: shtest-define.py
10.07s: Clang :: Driver/cl-options.c
10.02s: Clang :: Driver/x86-target-features.c
10.02s: LLVM-Unit :: Support/./SupportTests/ProgramEnvTest/TestExecuteNoWaitDetached
9.31s: Clang :: Analysis/runtime-regression.c

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
In current `FlattenCFG`, using `isNoAlias` for two instructions is
imprecise. For example, when passing a store instruction and a load
instruction directly into `AA->isNoAlias`, it will always return
`NoAlias`. This happens because when checking the types of the two
Values, the store instruction (which has a `void` type) causes the
analysis to return `NoAlias`.

For instructions, we should use `getModRefInfo` instead of `isNoAlias`,
as aliasing is a concept of memory locations.

In this patch, `AAResults::getModRefInfo` is supported to take in two
instructions. It will check whether two instructions may access the same
memory location or not. And in `FlattenCFG`, we use this new helper
function to do the check instead of `isNoAlias`.

Unit tests and lit tests are also included to this patch.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
In current `FlattenCFG`, using `isNoAlias` for two instructions is
imprecise. For example, when passing a store instruction and a load
instruction directly into `AA->isNoAlias`, it will always return
`NoAlias`. This happens because when checking the types of the two
Values, the store instruction (which has a `void` type) causes the
analysis to return `NoAlias`.

For instructions, we should use `getModRefInfo` instead of `isNoAlias`,
as aliasing is a concept of memory locations.

In this patch, `AAResults::getModRefInfo` is supported to take in two
instructions. It will check whether two instructions may access the same
memory location or not. And in `FlattenCFG`, we use this new helper
function to do the check instead of `isNoAlias`.

Unit tests and lit tests are also included to this patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants