Bug type: crash
Component: DeadStoreElimination
Bug location: llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp: tryFoldIntoCalloc
Issue title: [DSE] crash
Labels: release:backport
crash-on-valid
llvm:transforms
Reported by: JonPsson1

Reduced test case:
[tc_dse.tar.gz](https://github.com/llvm/llvm-project/files/14499403/tc_dse.tar.gz)

opt -mtriple=s390x-unknown-linux -mcpu=z16 -O3 -S ./tc_dse.ll

#6 0x0000000005287456 llvm::BasicAAResult::aliasCheck
#11 0x00000000048f0646 (anonymous namespace)::DSEState::isReadClobber
14 0x00000000049004d8 llvm::DSEPass::run
Segmentation fault (core dumped)

This is reported by user on F37 with clang-15, and is still failing on trunk.

@fhahn @BK1603 @nikic 

Comments: author: nikic
body: llvm-reduce result for `-passes=dse`: https://gist.github.com/nikic/d52c888425c5d4ff3fbd37b4f84778b6

valgrind reports a use-after-free. Probably not invalidating EII correctly somewhere.
author: fhahn
body: Also reproduces with ASAn, looking now

Fix patch:
commit eb8f379567e8d014194faefe02ce92813e237afc
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Mar 6 20:08:00 2024 +0000

    [DSE] Remove malloc from EarliestEscapeInfo before removing. (#84157)
    
    Not removing the malloc from earliest escape info leaves stale entries
    in the cache.
    
    Fixes https://github.com/llvm/llvm-project/issues/84051.
    
    PR: https://github.com/llvm/llvm-project/pull/84157

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 3d1dac5ea17e..392e6ad5a66b 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1908,15 +1908,15 @@ struct DSEState {
                               Malloc->getArgOperand(0), IRB, TLI);
     if (!Calloc)
       return false;
+
     MemorySSAUpdater Updater(&MSSA);
     auto *NewAccess =
       Updater.createMemoryAccessAfter(cast<Instruction>(Calloc), nullptr,
                                       MallocDef);
     auto *NewAccessMD = cast<MemoryDef>(NewAccess);
     Updater.insertDef(NewAccessMD, /*RenameUses=*/true);
-    Updater.removeMemoryAccess(Malloc);
     Malloc->replaceAllUsesWith(Calloc);
-    Malloc->eraseFromParent();
+    deleteDeadInstruction(Malloc);
     return true;
   }
 


Regression tests:
file: llvm/test/Transforms/DeadStoreElimination/malloc-earliest-escape-info-invalidation.ll
commands: opt -p dse -S %s
tests: test_name: widget
test_body: target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"

define void @widget(ptr %a) {
bb:
  %call = tail call ptr @malloc(i64 1)
  tail call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 1, i1 false)
  %call1 = tail call noalias ptr @malloc(i64 0)
  store ptr %call1, ptr %a, align 8
  %load = load ptr, ptr %a, align 8
  %load2 = load i32, ptr %load, align 8
  %getelementptr = getelementptr i8, ptr %call1, i64 0
  %getelementptr3 = getelementptr i8, ptr %getelementptr, i64 1
  store i8 0, ptr %call1, align 1
  %getelementptr4 = getelementptr i8, ptr %getelementptr, i64 8
  store i16 0, ptr %getelementptr4, align 4
  %getelementptr5 = getelementptr i8, ptr %getelementptr, i64 12
  store i32 0, ptr %call1, align 4
  %load6 = load i32, ptr inttoptr (i64 4 to ptr), align 4
  br label %bb48

bb7:                                              ; No predecessors!
  br label %bb9

bb8:                                              ; No predecessors!
  br label %bb53

bb9:                                              ; preds = %bb43, %bb7
  %phi = phi ptr [ %call1, %bb7 ], [ %a, %bb43 ]
  %getelementptr10 = getelementptr i8, ptr %phi, i64 0
  %getelementptr11 = getelementptr i8, ptr %phi, i64 0
  %getelementptr12 = getelementptr i8, ptr %phi, i64 0
  %getelementptr13 = getelementptr i8, ptr %getelementptr12, i64 1
  store i8 0, ptr %call1, align 1
  br label %bb29

bb14:                                             ; No predecessors!
  %getelementptr15 = getelementptr i8, ptr %getelementptr10, i64 8
  %load16 = load i16, ptr %call1, align 4
  br i1 false, label %bb22, label %bb17

bb17:                                             ; preds = %bb14
  %getelementptr18 = getelementptr i8, ptr %getelementptr11, i64 8
  %load19 = load i16, ptr %call1, align 4
  %getelementptr20 = getelementptr i8, ptr %getelementptr12, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr21 = getelementptr i8, ptr %phi, i64 0
  br label %bb25

bb22:                                             ; preds = %bb14
  %getelementptr23 = getelementptr i8, ptr %phi, i64 0
  %getelementptr24 = getelementptr i8, ptr %getelementptr23, i64 12
  br label %bb25

bb25:                                             ; preds = %bb22, %bb17
  %phi26 = phi ptr [ %a, %bb17 ], [ %call1, %bb22 ]
  %phi27 = phi ptr [ %call1, %bb17 ], [ %call1, %bb22 ]
  %phi28 = phi ptr [ %call1, %bb17 ], [ %call1, %bb22 ]
  store i32 0, ptr %call1, align 4
  br label %bb29

bb29:                                             ; preds = %bb25, %bb9
  %phi30 = phi ptr [ %call1, %bb9 ], [ %call1, %bb25 ]
  %phi31 = phi ptr [ %call1, %bb9 ], [ %call1, %bb25 ]
  %load32 = load i8, ptr %call1, align 4
  %load33 = load i8, ptr %call1, align 4
  %getelementptr34 = getelementptr i8, ptr %phi31, i64 12
  %getelementptr35 = getelementptr i8, ptr %getelementptr12, i64 12
  br label %bb86

bb36:                                             ; No predecessors!
  %getelementptr37 = getelementptr i8, ptr %phi30, i64 12
  br label %bb38

bb38:                                             ; preds = %bb38, %bb36
  %getelementptr39 = getelementptr [0 x i32], ptr %getelementptr34, i64 0, i64 0
  %load40 = load i32, ptr %call1, align 4
  %getelementptr41 = getelementptr [0 x i32], ptr %getelementptr37, i64 0, i64 0
  %load42 = load i32, ptr %call1, align 4
  br label %bb38

bb43:                                             ; No predecessors!
  %getelementptr44 = getelementptr i8, ptr %getelementptr12, i64 8
  %load45 = load i16, ptr %call1, align 4
  store i16 0, ptr %call1, align 4
  store i8 0, ptr %call1, align 4
  %getelementptr46 = getelementptr i8, ptr %getelementptr12, i64 12
  store i32 0, ptr %call1, align 4
  %getelementptr47 = getelementptr i8, ptr %getelementptr12, i64 16
  store i32 0, ptr %call1, align 4
  br label %bb9

bb48:                                             ; preds = %bb48, %bb
  %getelementptr49 = getelementptr i8, ptr %call1, i64 0
  %getelementptr50 = getelementptr i8, ptr %getelementptr49, i64 1
  store i8 0, ptr %call1, align 1
  %getelementptr51 = getelementptr i8, ptr %getelementptr49, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr52 = getelementptr i8, ptr %getelementptr49, i64 12
  store i32 0, ptr %call1, align 4
  br label %bb48

bb53:                                             ; preds = %bb71, %bb8
  %phi54 = phi ptr [ %call1, %bb8 ], [ %a, %bb71 ]
  %getelementptr55 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr56 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr57 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr58 = getelementptr i8, ptr %getelementptr57, i64 1
  br label %bb71

bb59:                                             ; No predecessors!
  %getelementptr60 = getelementptr i8, ptr %phi54, i64 0
  %getelementptr61 = getelementptr i8, ptr %getelementptr60, i64 12
  br label %bb67

bb62:                                             ; No predecessors!
  %getelementptr63 = getelementptr i8, ptr %getelementptr56, i64 8
  %load64 = load i16, ptr %call1, align 4
  %getelementptr65 = getelementptr i8, ptr %getelementptr57, i64 8
  store i16 0, ptr %call1, align 4
  %getelementptr66 = getelementptr i8, ptr %phi54, i64 0
  br label %bb67

bb67:                                             ; preds = %bb62, %bb59
  %phi68 = phi ptr [ %a, %bb62 ], [ %call1, %bb59 ]
  %phi69 = phi ptr [ %call1, %bb62 ], [ %call1, %bb59 ]
  %phi70 = phi ptr [ %call1, %bb62 ], [ %call1, %bb59 ]
  store i32 0, ptr %call1, align 4
  br label %bb71

bb71:                                             ; preds = %bb67, %bb53
  %phi72 = phi ptr [ %call1, %bb53 ], [ %call1, %bb67 ]
  %phi73 = phi ptr [ %call1, %bb53 ], [ %call1, %bb67 ]
  %load74 = load i8, ptr %call1, align 4
  %load75 = load i8, ptr %call1, align 4
  %getelementptr76 = getelementptr i8, ptr %phi72, i64 12
  %getelementptr77 = getelementptr i8, ptr %getelementptr57, i64 12
  %getelementptr78 = getelementptr [0 x i32], ptr %getelementptr76, i64 0, i64 0
  %load79 = load i32, ptr %call1, align 4
  %getelementptr80 = getelementptr [0 x i32], ptr %getelementptr77, i64 0, i64 0
  store i32 0, ptr %call1, align 4
  %load81 = load i8, ptr %call1, align 4
  %getelementptr82 = getelementptr i8, ptr %getelementptr57, i64 8
  %load83 = load i16, ptr %call1, align 4
  store i16 0, ptr %call1, align 4
  store i8 0, ptr %call1, align 4
  %getelementptr84 = getelementptr i8, ptr %getelementptr57, i64 12
  store i32 0, ptr %call1, align 4
  %getelementptr85 = getelementptr i8, ptr %getelementptr57, i64 16
  store i32 0, ptr %call1, align 4
  br label %bb53

bb86:                                             ; preds = %bb86, %bb29
  %getelementptr87 = getelementptr [0 x i32], ptr %getelementptr34, i64 0, i64 0
  %load88 = load i32, ptr %call1, align 4
  %getelementptr89 = getelementptr [0 x i32], ptr %getelementptr35, i64 0, i64 0
  store i32 0, ptr %call1, align 4
  br label %bb86
}

declare ptr @malloc(i64)

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0

attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }