Skip to content

Commit

Permalink
[LICM] allow MemoryAccess creation failure (llvm#116813)
Browse files Browse the repository at this point in the history
Fixes llvm#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)
  • Loading branch information
DianQK committed Nov 21, 2024
1 parent 51dee6b commit e3364b6
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 4 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/Analysis/MemorySSAUpdater.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ class MemorySSAUpdater {
const BasicBlock *BB,
MemorySSA::InsertionPlace Point);

MemoryAccess *createMemoryAccessInBB2(Instruction *I,
MemoryAccess *Definition,
const BasicBlock *BB,
MemorySSA::InsertionPlace Point,
bool CreationMustSucceed = true);

/// Create a MemoryAccess in MemorySSA before an existing MemoryAccess.
///
/// See createMemoryAccessInBB() for usage details.
Expand Down
12 changes: 10 additions & 2 deletions llvm/lib/Analysis/MemorySSAUpdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,8 +1404,16 @@ void MemorySSAUpdater::changeToUnreachable(const Instruction *I) {
MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
MemorySSA::InsertionPlace Point) {
MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(I, Definition);
MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
return createMemoryAccessInBB2(I, Definition, BB, Point);
}

MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB2(
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
MemorySSA::InsertionPlace Point, bool CreationMustSucceed) {
MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(
I, Definition, /*Template=*/nullptr, CreationMustSucceed);
if (NewAccess)
MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
return NewAccess;
}

Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1464,8 +1464,11 @@ static Instruction *cloneInstructionInExitBlock(

if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) {
// Create a new MemoryAccess and let MemorySSA set its defining access.
MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB(
New, nullptr, New->getParent(), MemorySSA::Beginning);
// After running some passes, MemorySSA might be outdated, and the
// instruction `I` may have become a non-memory touching instruction.
MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB2(
New, nullptr, New->getParent(), MemorySSA::Beginning,
/*CreationMustSucceed=*/false);
if (NewMemAcc) {
if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
MSSAU.insertDef(MemDef, /*RenameUses=*/true);
Expand Down
50 changes: 50 additions & 0 deletions llvm/test/Transforms/LICM/PR116813-memoryssa-outdated.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -S < %s | FileCheck %s

; Check that running LICM after SimpleLoopUnswitch does not result in a crash.

define i32 @foo(i1 %arg, ptr %arg1) {
; CHECK-LABEL: define i32 @foo(
; CHECK-SAME: i1 [[ARG:%.*]], ptr [[ARG1:%.*]]) {
; CHECK-NEXT: [[START:.*:]]
; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG]]
; CHECK-NEXT: br i1 [[ARG_FR]], label %[[START_SPLIT_US:.*]], label %[[START_SPLIT:.*]]
; CHECK: [[START_SPLIT_US]]:
; CHECK-NEXT: br label %[[LOOP_US:.*]]
; CHECK: [[LOOP_US]]:
; CHECK-NEXT: br label %[[BB0:.*]]
; CHECK: [[BB0]]:
; CHECK-NEXT: br label %[[BB1:.*]]
; CHECK: [[BB1]]:
; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi ptr [ [[ARG1]], %[[BB0]] ]
; CHECK-NEXT: [[I3_US:%.*]] = call i32 [[UNSWITCHED_SELECT_US]]()
; CHECK-NEXT: br i1 true, label %[[LOOP_US]], label %[[RET_SPLIT_US:.*]]
; CHECK: [[RET_SPLIT_US]]:
; CHECK-NEXT: [[I3_LCSSA_US:%.*]] = phi i32 [ [[I3_US]], %[[BB1]] ]
; CHECK-NEXT: br label %[[RET:.*]]
; CHECK: [[START_SPLIT]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: br label %[[BB2:.*]]
; CHECK: [[BB2]]:
; CHECK-NEXT: br i1 false, label %[[LOOP]], label %[[RET_SPLIT:.*]]
; CHECK: [[RET_SPLIT]]:
; CHECK-NEXT: [[I3_LE:%.*]] = call i32 @bar()
; CHECK-NEXT: br label %[[RET]]
; CHECK: [[RET]]:
; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[I3_LE]], %[[RET_SPLIT]] ], [ [[I3_LCSSA_US]], %[[RET_SPLIT_US]] ]
; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
;
start:
br label %loop

loop: ; preds = %loop, %bb
%i = select i1 %arg, ptr %arg1, ptr @bar
%i3 = call i32 %i()
br i1 %arg, label %loop, label %ret

ret: ; preds = %loop
ret i32 %i3
}

declare i32 @bar() nounwind willreturn memory(none)

0 comments on commit e3364b6

Please sign in to comment.