; ModuleID = '/tmp/test.c' source_filename = "/tmp/test.c" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" %struct.Arg = type { i8, i64 } define noundef i64 @evalexpr_broken(ptr %0) { entry: %isnullp = getelementptr %struct.Arg, ptr %0, i32 0 %arg0p = getelementptr %struct.Arg, ptr %0, i32 1 ; value that's needed just temporarily, during "operation" below store i8 38, ptr %isnullp %arg0 = load i64, ptr %arg0p ; operation that has been optimized out would be here, elided for brevity %isnull = load i8, ptr %isnullp ; signal that memory at %isnullp isn't needed anymore store i8 poison, ptr %isnullp ret i64 %arg0 } define noundef i64 @evalexpr_works(ptr %0) { entry: %isnullp = getelementptr %struct.Arg, ptr %0, i32 0 %arg0p = getelementptr %struct.Arg, ptr %0, i32 1 store i8 38, ptr %isnullp %arg0 = load i64, ptr %arg0p %isnull = load i8, ptr %isnullp store i8 poison, ptr %isnullp ; now that the return value isn't needed anymore, optimizer can optimize away ; the store to %isnullp ret i64 0 }