; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature ; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=BASIC ; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL ; RUN: opt -passes='require,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=WITH-AC ; RUN: opt -passes='require,require,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=CROSS-BLOCK ; RUN: opt -passes='assume-builder,require,require,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=FULL-SIMPLIFY target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" %struct.S = type { i32, i8, ptr } %struct.A = type { ptr, ptr, [4 x [4 x %struct.D]], i64 } %struct.D = type { i64, i64 } declare void @func(ptr, ptr) declare void @func_cold(ptr) #0 declare void @func_strbool(ptr) #1 declare void @func_many(ptr) #2 declare void @func_argattr(ptr align 8, ptr nonnull) #3 declare void @func_argattr2(ptr noundef align 8, ptr noundef nonnull) #3 declare void @may_throw() define void @test(ptr %P, ptr %P1, ptr %P2, ptr %P3) { ; BASIC-LABEL: define {{[^@]+}}@test ; BASIC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ] ; BASIC-NEXT: call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ] ; BASIC-NEXT: call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; BASIC-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; BASIC-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) ; BASIC-NEXT: call void @func(ptr [[P1]], ptr [[P]]) ; BASIC-NEXT: call void @func_strbool(ptr [[P1]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ] ; BASIC-NEXT: call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]]) ; BASIC-NEXT: call void @func_many(ptr align 8 [[P1]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; BASIC-NEXT: call void @func_many(ptr noundef align 8 [[P1]]) ; BASIC-NEXT: call void @func_argattr(ptr [[P2]], ptr [[P3]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ] ; BASIC-NEXT: call void @func_argattr2(ptr [[P2]], ptr [[P3]]) ; BASIC-NEXT: call void @func(ptr nonnull [[P1]], ptr nonnull [[P]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ] ; BASIC-NEXT: call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]]) ; BASIC-NEXT: ret void ; ; ALL-LABEL: define {{[^@]+}}@test ; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ] ; ALL-NEXT: call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ] ; ALL-NEXT: call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) ; ALL-NEXT: call void @func(ptr [[P1]], ptr [[P]]) ; ALL-NEXT: call void @func_strbool(ptr [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ] ; ALL-NEXT: call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "norecurse"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_many(ptr align 8 [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8), "norecurse"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_many(ptr noundef align 8 [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nounwind"() ] ; ALL-NEXT: call void @func_argattr(ptr [[P2]], ptr [[P3]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]), "nounwind"() ] ; ALL-NEXT: call void @func_argattr2(ptr [[P2]], ptr [[P3]]) ; ALL-NEXT: call void @func(ptr nonnull [[P1]], ptr nonnull [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ] ; ALL-NEXT: call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]]) ; ALL-NEXT: ret void ; ; WITH-AC-LABEL: define {{[^@]+}}@test ; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ] ; WITH-AC-NEXT: call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ] ; WITH-AC-NEXT: call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; WITH-AC-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; WITH-AC-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) ; WITH-AC-NEXT: call void @func(ptr [[P1]], ptr [[P]]) ; WITH-AC-NEXT: call void @func_strbool(ptr [[P1]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ] ; WITH-AC-NEXT: call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]]) ; WITH-AC-NEXT: call void @func_many(ptr align 8 [[P1]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; WITH-AC-NEXT: call void @func_many(ptr noundef align 8 [[P1]]) ; WITH-AC-NEXT: call void @func_argattr(ptr [[P2]], ptr [[P3]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ] ; WITH-AC-NEXT: call void @func_argattr2(ptr [[P2]], ptr [[P3]]) ; WITH-AC-NEXT: call void @func(ptr nonnull [[P1]], ptr nonnull [[P]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ] ; WITH-AC-NEXT: call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]]) ; WITH-AC-NEXT: ret void ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test ; CROSS-BLOCK-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ] ; CROSS-BLOCK-NEXT: call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ] ; CROSS-BLOCK-NEXT: call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; CROSS-BLOCK-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; CROSS-BLOCK-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) ; CROSS-BLOCK-NEXT: call void @func(ptr [[P1]], ptr [[P]]) ; CROSS-BLOCK-NEXT: call void @func_strbool(ptr [[P1]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ] ; CROSS-BLOCK-NEXT: call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]]) ; CROSS-BLOCK-NEXT: call void @func_many(ptr align 8 [[P1]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; CROSS-BLOCK-NEXT: call void @func_many(ptr noundef align 8 [[P1]]) ; CROSS-BLOCK-NEXT: call void @func_argattr(ptr [[P2]], ptr [[P3]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ] ; CROSS-BLOCK-NEXT: call void @func_argattr2(ptr [[P2]], ptr [[P3]]) ; CROSS-BLOCK-NEXT: call void @func(ptr nonnull [[P1]], ptr nonnull [[P]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ] ; CROSS-BLOCK-NEXT: call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]]) ; CROSS-BLOCK-NEXT: ret void ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test ; FULL-SIMPLIFY-SAME: (ptr nonnull dereferenceable(16) [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ] ; FULL-SIMPLIFY-NEXT: call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; FULL-SIMPLIFY-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]] ; FULL-SIMPLIFY-NEXT: call void @func_cold(ptr dereferenceable(12) [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @func(ptr [[P1]], ptr [[P]]) ; FULL-SIMPLIFY-NEXT: call void @func_strbool(ptr [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ] ; FULL-SIMPLIFY-NEXT: call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]]) ; FULL-SIMPLIFY-NEXT: call void @func_many(ptr align 8 [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; FULL-SIMPLIFY-NEXT: call void @func_many(ptr noundef align 8 [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @func_argattr(ptr [[P2]], ptr [[P3]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ] ; FULL-SIMPLIFY-NEXT: call void @func_argattr2(ptr [[P2]], ptr [[P3]]) ; FULL-SIMPLIFY-NEXT: call void @func(ptr nonnull [[P1]], ptr nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ] ; FULL-SIMPLIFY-NEXT: call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: ret void ; bb: call void @func(ptr nonnull dereferenceable(16) %P, ptr null) call void @func(ptr dereferenceable(12) %P1, ptr nonnull %P) call void @func_cold(ptr dereferenceable(12) %P1) #5 call void @func_cold(ptr dereferenceable(12) %P1) call void @func(ptr %P1, ptr %P) call void @func_strbool(ptr %P1) call void @func(ptr dereferenceable(32) %P, ptr dereferenceable(8) %P) call void @func_many(ptr align 8 %P1) call void @func_many(ptr noundef align 8 %P1) call void @func_argattr(ptr %P2, ptr %P3) call void @func_argattr2(ptr %P2, ptr %P3) call void @func(ptr nonnull %P1, ptr nonnull %P) call void @func(ptr noundef nonnull %P1, ptr noundef nonnull %P) ret void } define i32 @test2(ptr %arg, ptr %arg1, ptr %arg2) { ; BASIC-LABEL: define {{[^@]+}}@test2 ; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: [[I:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; BASIC-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; BASIC-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; BASIC-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; BASIC-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; BASIC-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; BASIC-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; BASIC-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; BASIC-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; BASIC-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; BASIC-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ] ; BASIC-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 4 ; BASIC-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; BASIC-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; BASIC-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ] ; BASIC-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; BASIC-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; BASIC-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; BASIC-NEXT: ret i32 [[I26]] ; ; ALL-LABEL: define {{[^@]+}}@test2 ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: [[I:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; ALL-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; ALL-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; ALL-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; ALL-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; ALL-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; ALL-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; ALL-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; ALL-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; ALL-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; ALL-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ] ; ALL-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 4 ; ALL-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; ALL-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; ALL-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ] ; ALL-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; ALL-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; ALL-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; ALL-NEXT: ret i32 [[I26]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test2 ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: [[I:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; WITH-AC-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; WITH-AC-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; WITH-AC-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; WITH-AC-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; WITH-AC-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; WITH-AC-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; WITH-AC-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; WITH-AC-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; WITH-AC-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; WITH-AC-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ] ; WITH-AC-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 4 ; WITH-AC-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; WITH-AC-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; WITH-AC-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ] ; WITH-AC-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; WITH-AC-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; WITH-AC-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; WITH-AC-NEXT: ret i32 [[I26]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test2 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: [[I:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; CROSS-BLOCK-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; CROSS-BLOCK-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 4 ; CROSS-BLOCK-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; CROSS-BLOCK-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; CROSS-BLOCK-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ] ; CROSS-BLOCK-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; CROSS-BLOCK-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; CROSS-BLOCK-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; CROSS-BLOCK-NEXT: ret i32 [[I26]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test2 ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; FULL-SIMPLIFY-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; FULL-SIMPLIFY-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 4 ; FULL-SIMPLIFY-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; FULL-SIMPLIFY-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; FULL-SIMPLIFY-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4), "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; FULL-SIMPLIFY-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; FULL-SIMPLIFY-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; FULL-SIMPLIFY-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; FULL-SIMPLIFY-NEXT: ret i32 [[I26]] ; bb: %i = alloca ptr, align 8 %i3 = alloca ptr, align 8 %i4 = alloca ptr, align 8 %i5 = alloca %struct.S, align 8 store ptr %arg, ptr %i, align 8 store ptr %arg1, ptr %i3, align 8 store ptr %arg2, ptr %i4, align 8 %i6 = load ptr, ptr %i3, align 8 %i7 = load i32, ptr %i6, align 4 %i8 = trunc i32 %i7 to i8 %i9 = load ptr, ptr %i4, align 8 store i8 %i8, ptr %i9, align 1 %i11 = load ptr, ptr %i, align 8 %i14 = load ptr, ptr %i, align 8 %i16 = load i32, ptr %i14, align 8 %i17 = load ptr, ptr %i, align 8 %i18 = getelementptr inbounds %struct.S, ptr %i17, i32 0, i32 1 %i19 = load i8, ptr %i18, align 4 %i20 = sext i8 %i19 to i32 %i21 = add nsw i32 %i16, %i20 %i22 = load ptr, ptr %i, align 8 %i23 = getelementptr inbounds %struct.S, ptr %i22, i32 0, i32 2 %i24 = load ptr, ptr %i23, align 8 %i25 = load i32, ptr %i24, align 4 %i26 = add nsw i32 %i21, %i25 ret i32 %i26 } define i32 @test3(ptr %arg, ptr %arg1, ptr %arg2) #4 { ; BASIC-LABEL: define {{[^@]+}}@test3 ; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] { ; BASIC-NEXT: bb: ; BASIC-NEXT: [[I:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; BASIC-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; BASIC-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; BASIC-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; BASIC-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; BASIC-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; BASIC-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; BASIC-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; BASIC-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; BASIC-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; BASIC-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 32 ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; BASIC-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ] ; BASIC-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 8 ; BASIC-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; BASIC-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; BASIC-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; BASIC-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ] ; BASIC-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; BASIC-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; BASIC-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; BASIC-NEXT: ret i32 [[I26]] ; ; ALL-LABEL: define {{[^@]+}}@test3 ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] { ; ALL-NEXT: bb: ; ALL-NEXT: [[I:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; ALL-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; ALL-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; ALL-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; ALL-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; ALL-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; ALL-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; ALL-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; ALL-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; ALL-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; ALL-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 32 ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; ALL-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ] ; ALL-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 8 ; ALL-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; ALL-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; ALL-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; ALL-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ] ; ALL-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; ALL-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; ALL-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; ALL-NEXT: ret i32 [[I26]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test3 ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: [[I:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; WITH-AC-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; WITH-AC-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; WITH-AC-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; WITH-AC-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; WITH-AC-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; WITH-AC-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; WITH-AC-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; WITH-AC-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; WITH-AC-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; WITH-AC-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 32 ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; WITH-AC-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ] ; WITH-AC-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 8 ; WITH-AC-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; WITH-AC-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; WITH-AC-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; WITH-AC-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ] ; WITH-AC-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; WITH-AC-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; WITH-AC-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; WITH-AC-NEXT: ret i32 [[I26]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test3 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: [[I:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; CROSS-BLOCK-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; CROSS-BLOCK-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 32 ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; CROSS-BLOCK-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 8 ; CROSS-BLOCK-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; CROSS-BLOCK-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; CROSS-BLOCK-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; CROSS-BLOCK-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ] ; CROSS-BLOCK-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; CROSS-BLOCK-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; CROSS-BLOCK-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; CROSS-BLOCK-NEXT: ret i32 [[I26]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test3 ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = alloca ptr, align 8 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG]], ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG1]], ptr [[I3]], align 8 ; FULL-SIMPLIFY-NEXT: store ptr [[ARG2]], ptr [[I4]], align 8 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = load ptr, ptr [[I3]], align 8 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = load i32, ptr [[I6]], align 4 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = load ptr, ptr [[I4]], align 8 ; FULL-SIMPLIFY-NEXT: store i8 [[I8]], ptr [[I9]], align 1 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = load ptr, ptr [[I]], align 32 ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: [[I14:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: [[I16:%.*]] = load i32, ptr [[I14]], align 8 ; FULL-SIMPLIFY-NEXT: [[I17:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[I19:%.*]] = load i8, ptr [[I18]], align 8 ; FULL-SIMPLIFY-NEXT: [[I20:%.*]] = sext i8 [[I19]] to i32 ; FULL-SIMPLIFY-NEXT: [[I21:%.*]] = add nsw i32 [[I16]], [[I20]] ; FULL-SIMPLIFY-NEXT: [[I22:%.*]] = load ptr, ptr [[I]], align 8 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4), "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2 ; FULL-SIMPLIFY-NEXT: [[I24:%.*]] = load ptr, ptr [[I23]], align 8 ; FULL-SIMPLIFY-NEXT: [[I25:%.*]] = load i32, ptr [[I24]], align 4 ; FULL-SIMPLIFY-NEXT: [[I26:%.*]] = add nsw i32 [[I21]], [[I25]] ; FULL-SIMPLIFY-NEXT: ret i32 [[I26]] ; bb: %i = alloca ptr, align 8 %i3 = alloca ptr, align 8 %i4 = alloca ptr, align 8 %i5 = alloca %struct.S, align 8 store ptr %arg, ptr %i, align 8 store ptr %arg1, ptr %i3, align 8 store ptr %arg2, ptr %i4, align 8 %i6 = load ptr, ptr %i3, align 8 %i7 = load i32, ptr %i6, align 4 %i8 = trunc i32 %i7 to i8 %i9 = load ptr, ptr %i4, align 8 store i8 %i8, ptr %i9, align 1 %i11 = load ptr, ptr %i, align 32 call void @may_throw() %i14 = load ptr, ptr %i, align 8 %i16 = load i32, ptr %i14, align 8 %i17 = load ptr, ptr %i, align 8 %i18 = getelementptr inbounds %struct.S, ptr %i17, i32 0, i32 1 %i19 = load i8, ptr %i18, align 8 %i20 = sext i8 %i19 to i32 %i21 = add nsw i32 %i16, %i20 %i22 = load ptr, ptr %i, align 8 %i23 = getelementptr inbounds %struct.S, ptr %i22, i32 0, i32 2 %i24 = load ptr, ptr %i23, align 8 %i25 = load i32, ptr %i24, align 4 %i26 = add nsw i32 %i21, %i25 ret i32 %i26 } define dso_local i32 @_Z6squarePi(ptr %P, ptr %P1, i1 %cond) { ; BASIC-LABEL: define {{[^@]+}}@_Z6squarePi ; BASIC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ] ; BASIC-NEXT: store i32 0, ptr [[P]], align 4 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; BASIC-NEXT: store i32 0, ptr [[P1]], align 8 ; BASIC-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; BASIC: A: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; BASIC-NEXT: store i32 0, ptr [[P]], align 8 ; BASIC-NEXT: store i32 0, ptr [[P1]], align 4 ; BASIC-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; BASIC: B: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ] ; BASIC-NEXT: store i32 0, ptr [[P]], align 8 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; BASIC-NEXT: store i32 0, ptr [[P1]], align 8 ; BASIC-NEXT: br label [[C]] ; BASIC: C: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ] ; BASIC-NEXT: store i32 0, ptr [[P]], align 32 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ] ; BASIC-NEXT: store i32 0, ptr [[P1]], align 4 ; BASIC-NEXT: ret i32 0 ; ; ALL-LABEL: define {{[^@]+}}@_Z6squarePi ; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ] ; ALL-NEXT: store i32 0, ptr [[P]], align 4 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; ALL-NEXT: store i32 0, ptr [[P1]], align 8 ; ALL-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; ALL: A: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; ALL-NEXT: store i32 0, ptr [[P]], align 8 ; ALL-NEXT: store i32 0, ptr [[P1]], align 4 ; ALL-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; ALL: B: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ] ; ALL-NEXT: store i32 0, ptr [[P]], align 8 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; ALL-NEXT: store i32 0, ptr [[P1]], align 8 ; ALL-NEXT: br label [[C]] ; ALL: C: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ] ; ALL-NEXT: store i32 0, ptr [[P]], align 32 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ] ; ALL-NEXT: store i32 0, ptr [[P1]], align 4 ; ALL-NEXT: ret i32 0 ; ; WITH-AC-LABEL: define {{[^@]+}}@_Z6squarePi ; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ] ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 4 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 8 ; WITH-AC-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; WITH-AC: A: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 8 ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 4 ; WITH-AC-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; WITH-AC: B: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ] ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 8 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 8 ; WITH-AC-NEXT: br label [[C]] ; WITH-AC: C: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ] ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 32 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ] ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 4 ; WITH-AC-NEXT: ret i32 0 ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@_Z6squarePi ; CROSS-BLOCK-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 4 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 8 ; CROSS-BLOCK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; CROSS-BLOCK: A: ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 8 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 4 ; CROSS-BLOCK-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; CROSS-BLOCK: B: ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 8 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 8 ; CROSS-BLOCK-NEXT: br label [[C]] ; CROSS-BLOCK: C: ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 32 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 4 ; CROSS-BLOCK-NEXT: ret i32 0 ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@_Z6squarePi ; FULL-SIMPLIFY-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]], ptr nonnull align 8 dereferenceable(4) [[P1:%.*]], i1 [[COND:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 4 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 8 ; FULL-SIMPLIFY-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; FULL-SIMPLIFY: A: ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 8 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 4 ; FULL-SIMPLIFY-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; FULL-SIMPLIFY: B: ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "ignore"(ptr undef, i64 4), "ignore"(ptr undef), "align"(ptr [[P]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 8 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 8 ; FULL-SIMPLIFY-NEXT: br label [[C]] ; FULL-SIMPLIFY: C: ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "ignore"(ptr undef, i64 4), "ignore"(ptr undef), "align"(ptr [[P]], i64 32) ] ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 32 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 0 ; bb: store i32 0, ptr %P, align 4 store i32 0, ptr %P1, align 8 br i1 %cond, label %A, label %B A: ; preds = %bb store i32 0, ptr %P, align 8 store i32 0, ptr %P1, align 4 br i1 %cond, label %C, label %B B: ; preds = %A, %bb store i32 0, ptr %P, align 8 store i32 0, ptr %P1, align 8 br label %C C: ; preds = %B, %A store i32 0, ptr %P, align 32 store i32 0, ptr %P1, align 4 ret i32 0 } define dso_local i32 @test4A(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) { ; BASIC-LABEL: define {{[^@]+}}@test4A ; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null ; BASIC-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]] ; BASIC: bb4: ; BASIC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; BASIC-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 ; BASIC-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] ; BASIC-NEXT: store i32 0, ptr [[ARG]], align 4 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ] ; BASIC-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 ; BASIC-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 ; BASIC-NEXT: br label [[BB10]] ; BASIC: bb10: ; BASIC-NEXT: ret i32 0 ; ; ALL-LABEL: define {{[^@]+}}@test4A ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null ; ALL-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]] ; ALL: bb4: ; ALL-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; ALL-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 ; ALL-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] ; ALL-NEXT: store i32 0, ptr [[ARG]], align 4 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ] ; ALL-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 ; ALL-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 ; ALL-NEXT: br label [[BB10]] ; ALL: bb10: ; ALL-NEXT: ret i32 0 ; ; WITH-AC-LABEL: define {{[^@]+}}@test4A ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null ; WITH-AC-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]] ; WITH-AC: bb4: ; WITH-AC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; WITH-AC-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 ; WITH-AC-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] ; WITH-AC-NEXT: store i32 0, ptr [[ARG]], align 4 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ] ; WITH-AC-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 ; WITH-AC-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 ; WITH-AC-NEXT: br label [[BB10]] ; WITH-AC: bb10: ; WITH-AC-NEXT: ret i32 0 ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test4A ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null ; CROSS-BLOCK-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]] ; CROSS-BLOCK: bb4: ; CROSS-BLOCK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] ; CROSS-BLOCK-NEXT: store i32 0, ptr [[ARG]], align 4 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 ; CROSS-BLOCK-NEXT: br label [[BB10]] ; CROSS-BLOCK: bb10: ; CROSS-BLOCK-NEXT: ret i32 0 ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test4A ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null ; FULL-SIMPLIFY-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]] ; FULL-SIMPLIFY: bb4: ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[ARG]], align 4 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 ; FULL-SIMPLIFY-NEXT: br label [[BB10]] ; FULL-SIMPLIFY: bb10: ; FULL-SIMPLIFY-NEXT: ret i32 0 ; bb: %i = icmp ne ptr %arg1, null br i1 %i, label %bb4, label %bb10 bb4: ; preds = %bb %i5 = add nsw i32 %arg3, %arg2 call void @may_throw() %i6 = load i32, ptr %arg, align 4 %i7 = add nsw i32 %i5, %i6 store i32 0, ptr %arg, align 4 %i8 = load i32, ptr %arg1, align 4 %i9 = add nsw i32 %i7, %i8 call void @may_throw() store i32 %i9, ptr %arg1, align 4 br label %bb10 bb10: ; preds = %bb4, %bb ret i32 0 } declare void @may_throwv2(ptr) define dso_local i32 @terminator(ptr %P) personality ptr @__gxx_personality_v0 { ; BASIC-LABEL: define {{[^@]+}}@terminator ; BASIC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 { ; BASIC-NEXT: bb: ; BASIC-NEXT: invoke void @may_throwv2(ptr nonnull [[P]]) ; BASIC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; BASIC: Catch: ; BASIC-NEXT: [[V:%.*]] = landingpad { ptr, i32 } ; BASIC-NEXT: catch ptr null ; BASIC-NEXT: br label [[EXIT]] ; BASIC: Exit: ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ] ; BASIC-NEXT: ret i32 [[DOT0]] ; ; ALL-LABEL: define {{[^@]+}}@terminator ; ALL-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 { ; ALL-NEXT: bb: ; ALL-NEXT: invoke void @may_throwv2(ptr nonnull [[P]]) ; ALL-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; ALL: Catch: ; ALL-NEXT: [[V:%.*]] = landingpad { ptr, i32 } ; ALL-NEXT: catch ptr null ; ALL-NEXT: br label [[EXIT]] ; ALL: Exit: ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ] ; ALL-NEXT: ret i32 [[DOT0]] ; ; WITH-AC-LABEL: define {{[^@]+}}@terminator ; WITH-AC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: invoke void @may_throwv2(ptr nonnull [[P]]) ; WITH-AC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; WITH-AC: Catch: ; WITH-AC-NEXT: [[V:%.*]] = landingpad { ptr, i32 } ; WITH-AC-NEXT: catch ptr null ; WITH-AC-NEXT: br label [[EXIT]] ; WITH-AC: Exit: ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ] ; WITH-AC-NEXT: ret i32 [[DOT0]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@terminator ; CROSS-BLOCK-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: invoke void @may_throwv2(ptr nonnull [[P]]) ; CROSS-BLOCK-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; CROSS-BLOCK: Catch: ; CROSS-BLOCK-NEXT: [[V:%.*]] = landingpad { ptr, i32 } ; CROSS-BLOCK-NEXT: catch ptr null ; CROSS-BLOCK-NEXT: br label [[EXIT]] ; CROSS-BLOCK: Exit: ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ] ; CROSS-BLOCK-NEXT: ret i32 [[DOT0]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@terminator ; FULL-SIMPLIFY-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: invoke void @may_throwv2(ptr nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; FULL-SIMPLIFY: Catch: ; FULL-SIMPLIFY-NEXT: [[V:%.*]] = landingpad { ptr, i32 } ; FULL-SIMPLIFY-NEXT: catch ptr null ; FULL-SIMPLIFY-NEXT: br label [[EXIT]] ; FULL-SIMPLIFY: Exit: ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ] ; FULL-SIMPLIFY-NEXT: ret i32 [[DOT0]] ; bb: invoke void @may_throwv2(ptr nonnull %P) to label %Exit unwind label %Catch Catch: ; preds = %bb %v = landingpad { ptr, i32 } catch ptr null br label %Exit Exit: ; preds = %Catch, %bb %.0 = phi i32 [ 1, %bb ], [ 0, %Catch ] ret i32 %.0 } declare dso_local i32 @__gxx_personality_v0(...) define dso_local i32 @test5(ptr %arg, i32 %arg1) { ; BASIC-LABEL: define {{[^@]+}}@test5 ; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64 ; BASIC-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ] ; BASIC-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2 ; BASIC-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4 ; BASIC-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64 ; BASIC-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ] ; BASIC-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16 ; BASIC-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32 ; BASIC-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32 ; BASIC-NEXT: ret i32 [[I9]] ; ; ALL-LABEL: define {{[^@]+}}@test5 ; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64 ; ALL-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ] ; ALL-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2 ; ALL-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4 ; ALL-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64 ; ALL-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ] ; ALL-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16 ; ALL-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32 ; ALL-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32 ; ALL-NEXT: ret i32 [[I9]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test5 ; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64 ; WITH-AC-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ] ; WITH-AC-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2 ; WITH-AC-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4 ; WITH-AC-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64 ; WITH-AC-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ] ; WITH-AC-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16 ; WITH-AC-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32 ; WITH-AC-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32 ; WITH-AC-NEXT: ret i32 [[I9]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test5 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ] ; CROSS-BLOCK-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2 ; CROSS-BLOCK-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ] ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16 ; CROSS-BLOCK-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32 ; CROSS-BLOCK-NEXT: ret i32 [[I9]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test5 ; FULL-SIMPLIFY-SAME: (ptr nonnull align 8 [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]] ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2 ; FULL-SIMPLIFY-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "dereferenceable"(ptr [[I7]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16 ; FULL-SIMPLIFY-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32 ; FULL-SIMPLIFY-NEXT: ret i32 [[I9]] ; bb: %i3 = sext i32 %arg1 to i64 %i4 = getelementptr inbounds i16, ptr %arg, i64 %i3 %i5 = load i16, ptr %i4, align 2 %A = load i16, ptr %i4, align 4 %i6 = sext i16 %i5 to i64 %i7 = getelementptr inbounds i64, ptr %arg, i64 %i6 %i8 = load i64, ptr %i7, align 16 %B = load i64, ptr %i7, align 32 %i9 = trunc i64 %i8 to i32 ret i32 %i9 } define i32 @test6(ptr %arg, i32 %arg1, ptr %arg2) { ; BASIC-LABEL: define {{[^@]+}}@test6 ; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: br label [[BB3:%.*]] ; BASIC: bb3: ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ] ; BASIC-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]] ; BASIC-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]] ; BASIC: bb4: ; BASIC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]] ; BASIC-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64 ; BASIC-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; BASIC-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4 ; BASIC-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]] ; BASIC-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64 ; BASIC-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ] ; BASIC-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 ; BASIC-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]] ; BASIC-NEXT: store i32 [[I13]], ptr [[I11]], align 4 ; BASIC-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1 ; BASIC-NEXT: br label [[BB3]] ; BASIC: bb15: ; BASIC-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64 ; BASIC-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ] ; BASIC-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4 ; BASIC-NEXT: ret i32 [[I18]] ; ; ALL-LABEL: define {{[^@]+}}@test6 ; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: br label [[BB3:%.*]] ; ALL: bb3: ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ] ; ALL-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]] ; ALL-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]] ; ALL: bb4: ; ALL-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]] ; ALL-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64 ; ALL-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; ALL-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4 ; ALL-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]] ; ALL-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64 ; ALL-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ] ; ALL-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 ; ALL-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]] ; ALL-NEXT: store i32 [[I13]], ptr [[I11]], align 4 ; ALL-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1 ; ALL-NEXT: br label [[BB3]] ; ALL: bb15: ; ALL-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64 ; ALL-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ] ; ALL-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4 ; ALL-NEXT: ret i32 [[I18]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test6 ; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: br label [[BB3:%.*]] ; WITH-AC: bb3: ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ] ; WITH-AC-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]] ; WITH-AC-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]] ; WITH-AC: bb4: ; WITH-AC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]] ; WITH-AC-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64 ; WITH-AC-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; WITH-AC-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4 ; WITH-AC-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]] ; WITH-AC-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64 ; WITH-AC-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ] ; WITH-AC-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 ; WITH-AC-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]] ; WITH-AC-NEXT: store i32 [[I13]], ptr [[I11]], align 4 ; WITH-AC-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1 ; WITH-AC-NEXT: br label [[BB3]] ; WITH-AC: bb15: ; WITH-AC-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64 ; WITH-AC-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ] ; WITH-AC-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4 ; WITH-AC-NEXT: ret i32 [[I18]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test6 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: br label [[BB3:%.*]] ; CROSS-BLOCK: bb3: ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ] ; CROSS-BLOCK-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]] ; CROSS-BLOCK-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]] ; CROSS-BLOCK: bb4: ; CROSS-BLOCK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]] ; CROSS-BLOCK-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]] ; CROSS-BLOCK-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 ; CROSS-BLOCK-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]] ; CROSS-BLOCK-NEXT: store i32 [[I13]], ptr [[I11]], align 4 ; CROSS-BLOCK-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1 ; CROSS-BLOCK-NEXT: br label [[BB3]] ; CROSS-BLOCK: bb15: ; CROSS-BLOCK-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64 ; CROSS-BLOCK-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ] ; CROSS-BLOCK-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4 ; CROSS-BLOCK-NEXT: ret i32 [[I18]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test6 ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: br label [[BB3:%.*]] ; FULL-SIMPLIFY: bb3: ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ] ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]] ; FULL-SIMPLIFY-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]] ; FULL-SIMPLIFY: bb4: ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]] ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]] ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]] ; FULL-SIMPLIFY-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[I11]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 ; FULL-SIMPLIFY-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]] ; FULL-SIMPLIFY-NEXT: store i32 [[I13]], ptr [[I11]], align 4 ; FULL-SIMPLIFY-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1 ; FULL-SIMPLIFY-NEXT: br label [[BB3]] ; FULL-SIMPLIFY: bb15: ; FULL-SIMPLIFY-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64 ; FULL-SIMPLIFY-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 [[I18]] ; bb: br label %bb3 bb3: ; preds = %bb4, %bb %.0 = phi i32 [ 0, %bb ], [ %i14, %bb4 ] %i = icmp slt i32 %.0, %arg1 br i1 %i, label %bb4, label %bb15 bb4: ; preds = %bb3 %i5 = add nsw i32 %arg1, %.0 %i6 = sext i32 %i5 to i64 %i7 = getelementptr inbounds i32, ptr %arg, i64 %i6 %i8 = load i32, ptr %i7, align 4 %i9 = mul nsw i32 %.0, %i8 %i10 = sext i32 %.0 to i64 %i11 = getelementptr inbounds i32, ptr %arg, i64 %i10 %i12 = load i32, ptr %i11, align 4 %i13 = add nsw i32 %i12, %i9 store i32 %i13, ptr %i11, align 4 %i14 = add nsw i32 %.0, 1 br label %bb3 bb15: ; preds = %bb3 %i16 = sext i32 %arg1 to i64 %i17 = getelementptr inbounds i32, ptr %arg2, i64 %i16 %i18 = load i32, ptr %i17, align 4 ret i32 %i18 } define i32 @test7(ptr nonnull %arg, i32 %arg1) { ; BASIC-LABEL: define {{[^@]+}}@test7 ; BASIC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; BASIC-NEXT: bb: ; BASIC-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64 ; BASIC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ] ; BASIC-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8 ; BASIC-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0 ; BASIC-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32 ; BASIC-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1 ; BASIC-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8 ; BASIC-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ] ; BASIC-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; BASIC-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; BASIC-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8 ; BASIC-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4 ; BASIC-NEXT: ret i32 [[I11]] ; ; ALL-LABEL: define {{[^@]+}}@test7 ; ALL-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; ALL-NEXT: bb: ; ALL-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64 ; ALL-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ] ; ALL-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8 ; ALL-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0 ; ALL-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32 ; ALL-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1 ; ALL-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8 ; ALL-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ] ; ALL-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; ALL-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; ALL-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8 ; ALL-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4 ; ALL-NEXT: ret i32 [[I11]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test7 ; WITH-AC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; WITH-AC-NEXT: bb: ; WITH-AC-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64 ; WITH-AC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ] ; WITH-AC-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8 ; WITH-AC-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0 ; WITH-AC-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32 ; WITH-AC-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1 ; WITH-AC-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8 ; WITH-AC-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ] ; WITH-AC-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; WITH-AC-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; WITH-AC-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8 ; WITH-AC-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4 ; WITH-AC-NEXT: ret i32 [[I11]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test7 ; CROSS-BLOCK-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; CROSS-BLOCK-NEXT: bb: ; CROSS-BLOCK-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64 ; CROSS-BLOCK-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ] ; CROSS-BLOCK-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ] ; CROSS-BLOCK-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; CROSS-BLOCK-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; CROSS-BLOCK-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4 ; CROSS-BLOCK-NEXT: ret i32 [[I11]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test7 ; FULL-SIMPLIFY-SAME: (ptr nonnull align 16 dereferenceable(280) [[ARG:%.*]], i32 [[ARG1:%.*]]) { ; FULL-SIMPLIFY-NEXT: bb: ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64 ; FULL-SIMPLIFY-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3 ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; FULL-SIMPLIFY-NEXT: store i64 [[I5]], ptr [[I8]], align 8 ; FULL-SIMPLIFY-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 [[I11]] ; bb: %i = sext i32 %arg1 to i64 %i2 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 3 %i3 = load i64, ptr %i2, align 8 %i4 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 2, i64 %i, i64 %i3, i32 0 %i5 = load i64, ptr %i4, align 32 %i6 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 1 %i7 = load ptr, ptr %i6, align 8 %i8 = getelementptr inbounds i64, ptr %i7, i64 %i3 store i64 %i5, ptr %i8, align 8 store i64 %i5, ptr %i8, align 8 %i10 = load ptr, ptr %arg, align 8 %i11 = load i32, ptr %i10, align 4 ret i32 %i11 } attributes #0 = { cold nounwind willreturn } attributes #1 = { "no-jump-tables" } attributes #2 = { norecurse nounwind willreturn "less-precise-fpmad" "no-jump-tables" } attributes #3 = { nounwind } attributes #4 = { null_pointer_is_valid } attributes #5 = { cold }