llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Ryotaro Kasuga (kasuga-fj)
<details>
<summary>Changes</summary>
Previously loop-interchange can be applied even though the loop has call
instructions which may access the memory. The root cause of this problem is
that the implementation didn't match the comment, like below:
```cpp
// readnone functions do not prevent interchanging.
if (CI->onlyWritesMemory() || isa<PseudoProbeInst>(CI))
continue;
```
However, I think ensuring `readnone` is insufficient in the first place,
because the LLVM Language Reference states about `readnone` as follows:
```
This attribute indicates that the function does not dereference that pointer
argument, even though it may read or write the memory that the pointer points
to if accessed through other pointers.
```
So, this patch fixes the issue by verifying that all the calls in the loop have
the `memory(none)` attribute. We could probably check that all the arguments of
the calls have `readnone`, but I believe just calling `doesNotAccessMemory` is
simpler and sufficient in practical cases (though I haven't actually checked).
Fixes #<!-- -->200796.
---
Full diff: https://github.com/llvm/llvm-project/pull/200828.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/LoopInterchange.cpp (+4-2)
- (modified) llvm/test/Transforms/LoopInterchange/memory-attr.ll (+7-19)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 9d424ae13e28a..1af873cb6ecfe 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -1474,8 +1474,10 @@ bool
LoopInterchangeLegality::canInterchangeLoops(unsigned InnerLoopId,
for (auto *BB : OuterLoop->blocks())
for (Instruction &I : *BB)
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
- // readnone functions do not prevent interchanging.
- if (CI->onlyWritesMemory() || isa<PseudoProbeInst>(CI))
+ if (isa<PseudoProbeInst>(CI))
+ continue;
+ // Functions which don't access memories do not prevent interchanging.
+ if (CI->doesNotAccessMemory())
continue;
LLVM_DEBUG(
dbgs() << "Loops with call instructions cannot be interchanged "
diff --git a/llvm/test/Transforms/LoopInterchange/memory-attr.ll
b/llvm/test/Transforms/LoopInterchange/memory-attr.ll
index c32f48ef63694..c2f0c74167b5e 100644
--- a/llvm/test/Transforms/LoopInterchange/memory-attr.ll
+++ b/llvm/test/Transforms/LoopInterchange/memory-attr.ll
@@ -8,36 +8,24 @@
; The writeonly call may write to `%A` at some unknown index, so we cannot
; interchange the loops.
;
-; FIXME: These loops are now interchanged.
-;
define void @call_writeonly(ptr %A) {
; CHECK-LABEL: define void @call_writeonly(
; CHECK-SAME: ptr [[A:%.*]]) {
-; CHECK-NEXT: [[INNER_PREHEADER:.*:]]
-; CHECK-NEXT: br label %[[INNER:.*]]
-; CHECK: [[OUTER_HEADER_PREHEADER1:.*]]:
-; CHECK-NEXT: br label %[[OUTER_HEADER_PREHEADER:.*]]
-; CHECK: [[OUTER_HEADER_PREHEADER]]:
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], %[[OUTER_LATCH:.*]] ],
[ 0, %[[OUTER_HEADER_PREHEADER1]] ]
-; CHECK-NEXT: br label %[[INNER_SPLIT1:.*]]
-; CHECK: [[INNER]]:
+; CHECK-NEXT: [[INNER:.*]]:
; CHECK-NEXT: br label %[[INNER1:.*]]
; CHECK: [[INNER1]]:
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[TMP2:%.*]], %[[INNER_SPLIT:.*]] ], [
0, %[[INNER]] ]
-; CHECK-NEXT: br label %[[OUTER_HEADER_PREHEADER1]]
-; CHECK: [[INNER_SPLIT1]]:
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[INNER]] ], [ [[I_NEXT:%.*]],
%[[OUTER_LATCH:.*]] ]
+; CHECK-NEXT: br label %[[OUTER_HEADER_PREHEADER1:.*]]
+; CHECK: [[OUTER_HEADER_PREHEADER1]]:
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ 0, %[[INNER1]] ], [ [[TMP2:%.*]],
%[[OUTER_HEADER_PREHEADER1]] ]
; CHECK-NEXT: call void @writeonly(ptr [[A]])
-; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[J]], 1
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 100
-; CHECK-NEXT: br label %[[OUTER_LATCH]]
-; CHECK: [[INNER_SPLIT]]:
; CHECK-NEXT: [[TMP2]] = add i64 [[J]], 1
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], 100
-; CHECK-NEXT: br i1 [[TMP3]], label %[[EXIT:.*]], label %[[INNER1]]
+; CHECK-NEXT: br i1 [[TMP3]], label %[[OUTER_LATCH]], label
%[[OUTER_HEADER_PREHEADER1]]
; CHECK: [[OUTER_LATCH]]:
; CHECK-NEXT: [[I_NEXT]] = add i64 [[I]], 1
; CHECK-NEXT: [[EC_OUTER:%.*]] = icmp eq i64 [[I_NEXT]], 100
-; CHECK-NEXT: br i1 [[EC_OUTER]], label %[[INNER_SPLIT]], label
%[[OUTER_HEADER_PREHEADER]]
+; CHECK-NEXT: br i1 [[EC_OUTER]], label %[[EXIT:.*]], label %[[INNER1]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
``````````
</details>
https://github.com/llvm/llvm-project/pull/200828
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits