Bug type: crash
Component: LICM
MemorySSAUpdater
Bug location: llvm/lib/Analysis/MemorySSAUpdater.cpp: MemorySSAUpdater::createMemoryAccessBefore
MemorySSAUpdater::createMemoryAccessInBB
llvm/lib/Transforms/Scalar/LICM.cpp: cloneInstructionInExitBlock
Issue title: [SimpleLoopUnswitch][LICM] Assertion `NewAccess != nullptr && "Tried to create a memory access for a " "non-memory touching instruction"'
Labels: crash
llvm:analysis
llvm:transforms
Reported by: DianQK

The following IR triggers the assertion mentioned in the title:

```llvm
; opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)'
define i32 @foo(i1 %arg, ptr %arg1) {
bb:
  br label %bb2

bb2:                                              ; preds = %bb2, %bb
  %i = select i1 %arg, ptr %arg1, ptr @bar
  %i3 = call i32 %i()
  br i1 %arg, label %bb2, label %bb4

bb4:                                              ; preds = %bb2
  ret i32 %i3
}

declare i32 @bar() nounwind willreturn memory(none)
```

https://llvm.godbolt.org/z/bj79jxo8x


Fix patch:
commit 18b02bbf441660683df7f3925946984203d49bab
Author: DianQK <dianqk@dianqk.net>
Date:   Wed Nov 20 19:52:51 2024 +0800

    [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`.

diff --git a/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
index d4da3ef1146d..055feceefb05 100644
--- a/llvm/include/llvm/Analysis/MemorySSAUpdater.h
+++ b/llvm/include/llvm/Analysis/MemorySSAUpdater.h
@@ -190,7 +190,8 @@ public:
   /// inaccessible and it *must* have removeMemoryAccess called on it.
   MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
                                        const BasicBlock *BB,
-                                       MemorySSA::InsertionPlace Point);
+                                       MemorySSA::InsertionPlace Point,
+                                       bool CreationMustSucceed = true);
 
   /// Create a MemoryAccess in MemorySSA before an existing MemoryAccess.
   ///
diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp
index aa550f0b6a7b..f672bd0e1e13 100644
--- a/llvm/lib/Analysis/MemorySSAUpdater.cpp
+++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp
@@ -1403,9 +1403,11 @@ 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);
+    MemorySSA::InsertionPlace Point, bool CreationMustSucceed) {
+  MemoryUseOrDef *NewAccess = MSSA->createDefinedAccess(
+      I, Definition, /*Template=*/nullptr, CreationMustSucceed);
+  if (NewAccess)
+    MSSA->insertIntoListsForBlock(NewAccess, BB, Point);
   return NewAccess;
 }
 
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index fa04ced7182d..94bfe44a847a 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1465,8 +1465,11 @@ static Instruction *cloneInstructionInExitBlock(
 
   if (MSSAU.getMemorySSA()->getMemoryAccess(&I)) {
     // Create a new MemoryAccess and let MemorySSA set its defining access.
+    // After running some passes, MemorySSA might be outdated, and the
+    // instruction `I` may have become a non-memory touching instruction.
     MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB(
-        New, nullptr, New->getParent(), MemorySSA::Beginning);
+        New, nullptr, New->getParent(), MemorySSA::Beginning,
+        /*CreationMustSucceed=*/false);
     if (NewMemAcc) {
       if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
         MSSAU.insertDef(MemDef, /*RenameUses=*/true);


Regression tests:
file: llvm/test/Transforms/LICM/PR116813-memoryssa-outdated.ll
commands: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -S < %s
tests: test_name: <module>
test_body: 
; Check that running LICM after SimpleLoopUnswitch does not result in a crash.

define i32 @foo(i1 %arg, ptr %arg1) {
;
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)