Skip to content

Commit 5753ee2

Browse files
committed
[LICM] Avoid assertion failure on stale MemoryDef
It can happen that the call is originally created as a MemoryDef, and then later transforms show it is actually read-only and could be a MemoryUse -- however, this is not guaranteed to be reflected in MSSA.
1 parent cabf643 commit 5753ee2

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,11 +1241,16 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
12411241
if (Behavior.doesNotAccessMemory())
12421242
return true;
12431243
if (Behavior.onlyReadsMemory()) {
1244+
// Might have stale MemoryDef for call that was later inferred to be
1245+
// read-only.
1246+
auto *MU = dyn_cast<MemoryUse>(MSSA->getMemoryAccess(CI));
1247+
if (!MU)
1248+
return false;
1249+
12441250
// If we can prove there are no writes to the memory read by the call, we
12451251
// can hoist or sink.
12461252
return !pointerInvalidatedByLoop(
1247-
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop, I, Flags,
1248-
/*InvariantGroup=*/false);
1253+
MSSA, MU, CurLoop, I, Flags, /*InvariantGroup=*/false);
12491254
}
12501255

12511256
if (Behavior.onlyWritesMemory()) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes="function(print<memoryssa>),cgscc(function-attrs),function(loop-mssa(licm))" < %s 2>/dev/null | FileCheck %s
3+
4+
@g = external global i16
5+
6+
define i16 @fn() {
7+
; CHECK-LABEL: define i16 @fn(
8+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
9+
; CHECK-NEXT: [[V:%.*]] = load i16, ptr @g, align 2
10+
; CHECK-NEXT: ret i16 [[V]]
11+
;
12+
%v = load i16, ptr @g
13+
ret i16 %v
14+
}
15+
16+
declare void @fn2(i16)
17+
18+
define void @test() {
19+
; CHECK-LABEL: define void @test() {
20+
; CHECK-NEXT: [[ENTRY:.*:]]
21+
; CHECK-NEXT: br label %[[LOOP:.*]]
22+
; CHECK: [[LOOP]]:
23+
; CHECK-NEXT: [[CALL:%.*]] = call i16 @fn(i32 0)
24+
; CHECK-NEXT: call void @fn2(i16 [[CALL]])
25+
; CHECK-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
26+
; CHECK: [[EXIT]]:
27+
; CHECK-NEXT: ret void
28+
;
29+
entry:
30+
br label %loop
31+
32+
loop:
33+
%call = call i16 @fn(i32 0) ; intentional signature mismatch
34+
call void @fn2(i16 %call)
35+
br i1 false, label %loop, label %exit
36+
37+
exit:
38+
ret void
39+
}

0 commit comments

Comments
 (0)