Skip to content

Commit 5bd0474

Browse files
dianqktru
authored andcommitted
[LICM] allow MemoryAccess creation failure (#116813)
Fixes #116809. After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.), MemorySSA might be outdated, and the instruction `I` may have become a non-memory touching instruction. LICM has already handled this, but it does not pass `CreationMustSucceed=false` to `createDefinedAccess`. (cherry picked from commit 18b02bb)
1 parent e80925b commit 5bd0474

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

llvm/include/llvm/Analysis/MemorySSAUpdater.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class MemorySSAUpdater {
192192
const BasicBlock *BB,
193193
MemorySSA::InsertionPlace Point);
194194

195+
MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
196+
const BasicBlock *BB,
197+
MemorySSA::InsertionPlace Point,
198+
bool CreationMustSucceed);
199+
195200
/// Create a MemoryAccess in MemorySSA before an existing MemoryAccess.
196201
///
197202
/// See createMemoryAccessInBB() for usage details.

llvm/lib/Analysis/MemorySSAUpdater.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,8 +1404,17 @@ void MemorySSAUpdater::changeToUnreachable(const Instruction *I) {
14041404
MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
14051405
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
14061406
MemorySSA::InsertionPlace Point) {
1407-
MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(I, Definition);
1408-
MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
1407+
return createMemoryAccessInBB(I, Definition, BB, Point,
1408+
/*CreationMustSucceed=*/true);
1409+
}
1410+
1411+
MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
1412+
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
1413+
MemorySSA::InsertionPlace Point, bool CreationMustSucceed) {
1414+
MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(
1415+
I, Definition, /*Template=*/nullptr, CreationMustSucceed);
1416+
if (NewAccess)
1417+
MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
14091418
return NewAccess;
14101419
}
14111420

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1464,8 +1464,11 @@ static Instruction *cloneInstructionInExitBlock(
14641464

14651465
if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) {
14661466
// Create a new MemoryAccess and let MemorySSA set its defining access.
1467+
// After running some passes, MemorySSA might be outdated, and the
1468+
// instruction `I` may have become a non-memory touching instruction.
14671469
MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB(
1468-
New, nullptr, New->getParent(), MemorySSA::Beginning);
1470+
New, nullptr, New->getParent(), MemorySSA::Beginning,
1471+
/*CreationMustSucceed=*/false);
14691472
if (NewMemAcc) {
14701473
if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
14711474
MSSAU.insertDef(MemDef, /*RenameUses=*/true);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -S < %s | FileCheck %s
3+
4+
; Check that running LICM after SimpleLoopUnswitch does not result in a crash.
5+
6+
define i32 @foo(i1 %arg, ptr %arg1) {
7+
; CHECK-LABEL: define i32 @foo(
8+
; CHECK-SAME: i1 [[ARG:%.*]], ptr [[ARG1:%.*]]) {
9+
; CHECK-NEXT: [[START:.*:]]
10+
; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG]]
11+
; CHECK-NEXT: br i1 [[ARG_FR]], label %[[START_SPLIT_US:.*]], label %[[START_SPLIT:.*]]
12+
; CHECK: [[START_SPLIT_US]]:
13+
; CHECK-NEXT: br label %[[LOOP_US:.*]]
14+
; CHECK: [[LOOP_US]]:
15+
; CHECK-NEXT: br label %[[BB0:.*]]
16+
; CHECK: [[BB0]]:
17+
; CHECK-NEXT: br label %[[BB1:.*]]
18+
; CHECK: [[BB1]]:
19+
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi ptr [ [[ARG1]], %[[BB0]] ]
20+
; CHECK-NEXT: [[I3_US:%.*]] = call i32 [[UNSWITCHED_SELECT_US]]()
21+
; CHECK-NEXT: br i1 true, label %[[LOOP_US]], label %[[RET_SPLIT_US:.*]]
22+
; CHECK: [[RET_SPLIT_US]]:
23+
; CHECK-NEXT: [[I3_LCSSA_US:%.*]] = phi i32 [ [[I3_US]], %[[BB1]] ]
24+
; CHECK-NEXT: br label %[[RET:.*]]
25+
; CHECK: [[START_SPLIT]]:
26+
; CHECK-NEXT: br label %[[LOOP:.*]]
27+
; CHECK: [[LOOP]]:
28+
; CHECK-NEXT: br label %[[BB2:.*]]
29+
; CHECK: [[BB2]]:
30+
; CHECK-NEXT: br i1 false, label %[[LOOP]], label %[[RET_SPLIT:.*]]
31+
; CHECK: [[RET_SPLIT]]:
32+
; CHECK-NEXT: [[I3_LE:%.*]] = call i32 @bar()
33+
; CHECK-NEXT: br label %[[RET]]
34+
; CHECK: [[RET]]:
35+
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[I3_LE]], %[[RET_SPLIT]] ], [ [[I3_LCSSA_US]], %[[RET_SPLIT_US]] ]
36+
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
37+
;
38+
start:
39+
br label %loop
40+
41+
loop: ; preds = %loop, %bb
42+
%i = select i1 %arg, ptr %arg1, ptr @bar
43+
%i3 = call i32 %i()
44+
br i1 %arg, label %loop, label %ret
45+
46+
ret: ; preds = %loop
47+
ret i32 %i3
48+
}
49+
50+
declare i32 @bar() nounwind willreturn memory(none)

0 commit comments

Comments
 (0)