; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -S -passes=newgvn < %s | FileCheck %s ; MemorySSA says that load1 depends on the lifetime start. ; That's OK since MemorySSA is may-alias; however, NewGVN should ; check whether the lifetime start *actually* defines the loaded pointer ; before simplifying to uninitialized memory. define void @foo(ptr %arg) { ; CHECK-LABEL: define void @foo( ; CHECK-SAME: ptr [[ARG:%.*]]) { ; CHECK-NEXT: [[BB:.*:]] ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i8, align 16 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ALLOCA]]) ; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[ARG]], align 8 ; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[LOAD]], align 8 ; CHECK-NEXT: [[CALL:%.*]] = call ptr [[LOAD1]](ptr [[ALLOCA]]) ; CHECK-NEXT: ret void ; bb: %alloca = alloca i8, align 16 call void @llvm.lifetime.start.p0(ptr %alloca) %load = load ptr, ptr %arg, align 8 %load1 = load ptr, ptr %load, align 8 %call = call ptr %load1(ptr %alloca) ret void } declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 declare ptr @malloc(i64) ; This case is handled correctly. ; Since malloc returns a pointer, NewGVN checks whether ; it is the same pointer, an equivalent one, or a must-alias. define void @wombat(ptr %arg) { ; CHECK-LABEL: define void @wombat( ; CHECK-SAME: ptr [[ARG:%.*]]) { ; CHECK-NEXT: [[BB:.*:]] ; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 1) ; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[ARG]], align 8 ; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[LOAD]], align 8 ; CHECK-NEXT: [[CALL2:%.*]] = call ptr [[LOAD1]](ptr [[CALL]]) ; CHECK-NEXT: ret void ; bb: %call = call ptr @malloc(i64 1) %load = load ptr, ptr %arg, align 8 %load1 = load ptr, ptr %load, align 8 %call2 = call ptr %load1(ptr %call) ret void } attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }