; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature ; RUN: opt -assume-builder -verify --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=BASIC ; RUN: opt -assume-builder -verify --enable-knowledge-retention --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL ; RUN: opt -enable-new-pm=0 -assumption-cache-tracker -assume-builder -verify --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=WITH-AC ; RUN: opt -enable-new-pm=0 -domtree -assumption-cache-tracker -assume-builder -verify --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=CROSS-BLOCK,CROSS-BLOCK-OLDPM ; RUN: opt -enable-new-pm=0 -assume-builder -domtree -assumption-cache-tracker -assume-simplify -verify --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=FULL-SIMPLIFY ; 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<assumptions>,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=WITH-AC ; RUN: opt -passes='require<domtree>,require<assumptions>,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=CROSS-BLOCK,CROSS-BLOCK-NEWMP ; RUN: opt -passes='assume-builder,require<domtree>,require<assumptions>,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" declare void @func(i32*, i32*) declare void @func_cold(i32*) cold willreturn nounwind declare void @func_strbool(i32*) "no-jump-tables" declare void @func_many(i32*) "no-jump-tables" nounwind "less-precise-fpmad" willreturn norecurse declare void @func_argattr(i32* align 8, i32* nonnull) nounwind declare void @func_argattr2(i32* noundef align 8, i32* noundef nonnull) nounwind declare void @may_throw() define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) { ; BASIC-LABEL: define {{[^@]+}}@test ; BASIC-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) { ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i64 16) ] ; BASIC-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ] ; BASIC-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; BASIC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR6:#.*]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; BASIC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) ; BASIC-NEXT: call void @func(i32* [[P1]], i32* [[P]]) ; BASIC-NEXT: call void @func_strbool(i32* [[P1]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ] ; BASIC-NEXT: call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]]) ; BASIC-NEXT: call void @func_many(i32* align 8 [[P1]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; BASIC-NEXT: call void @func_many(i32* noundef align 8 [[P1]]) ; BASIC-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ] ; BASIC-NEXT: call void @func_argattr2(i32* [[P2]], i32* [[P3]]) ; BASIC-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]]) ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ] ; BASIC-NEXT: call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]]) ; BASIC-NEXT: ret void ; ; ALL-LABEL: define {{[^@]+}}@test ; ALL-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) { ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i64 16) ] ; ALL-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ] ; ALL-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR6:#.*]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) ; ALL-NEXT: call void @func(i32* [[P1]], i32* [[P]]) ; ALL-NEXT: call void @func_strbool(i32* [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ] ; ALL-NEXT: call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "norecurse"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_many(i32* align 8 [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8), "norecurse"(), "nounwind"(), "willreturn"() ] ; ALL-NEXT: call void @func_many(i32* noundef align 8 [[P1]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nounwind"() ] ; ALL-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]), "nounwind"() ] ; ALL-NEXT: call void @func_argattr2(i32* [[P2]], i32* [[P3]]) ; ALL-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]]) ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ] ; ALL-NEXT: call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]]) ; ALL-NEXT: ret void ; ; WITH-AC-LABEL: define {{[^@]+}}@test ; WITH-AC-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) { ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i64 16) ] ; WITH-AC-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ] ; WITH-AC-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; WITH-AC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR6:#.*]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; WITH-AC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) ; WITH-AC-NEXT: call void @func(i32* [[P1]], i32* [[P]]) ; WITH-AC-NEXT: call void @func_strbool(i32* [[P1]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ] ; WITH-AC-NEXT: call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]]) ; WITH-AC-NEXT: call void @func_many(i32* align 8 [[P1]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; WITH-AC-NEXT: call void @func_many(i32* noundef align 8 [[P1]]) ; WITH-AC-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ] ; WITH-AC-NEXT: call void @func_argattr2(i32* [[P2]], i32* [[P3]]) ; WITH-AC-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]]) ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ] ; WITH-AC-NEXT: call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]]) ; WITH-AC-NEXT: ret void ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test ; CROSS-BLOCK-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) { ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i64 16) ] ; CROSS-BLOCK-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ] ; CROSS-BLOCK-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; CROSS-BLOCK-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR6:#.*]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; CROSS-BLOCK-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) ; CROSS-BLOCK-NEXT: call void @func(i32* [[P1]], i32* [[P]]) ; CROSS-BLOCK-NEXT: call void @func_strbool(i32* [[P1]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ] ; CROSS-BLOCK-NEXT: call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]]) ; CROSS-BLOCK-NEXT: call void @func_many(i32* align 8 [[P1]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; CROSS-BLOCK-NEXT: call void @func_many(i32* noundef align 8 [[P1]]) ; CROSS-BLOCK-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ] ; CROSS-BLOCK-NEXT: call void @func_argattr2(i32* [[P2]], i32* [[P3]]) ; CROSS-BLOCK-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]]) ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ] ; CROSS-BLOCK-NEXT: call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]]) ; CROSS-BLOCK-NEXT: ret void ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test ; FULL-SIMPLIFY-SAME: (i32* nonnull dereferenceable(16) [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]]) { ; FULL-SIMPLIFY-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ] ; FULL-SIMPLIFY-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] ; FULL-SIMPLIFY-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) [[ATTR6:#.*]] ; FULL-SIMPLIFY-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @func(i32* [[P1]], i32* [[P]]) ; FULL-SIMPLIFY-NEXT: call void @func_strbool(i32* [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ] ; FULL-SIMPLIFY-NEXT: call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]]) ; FULL-SIMPLIFY-NEXT: call void @func_many(i32* align 8 [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; FULL-SIMPLIFY-NEXT: call void @func_many(i32* noundef align 8 [[P1]]) ; FULL-SIMPLIFY-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "noundef"(i32* [[P2]]), "align"(i32* [[P2]], i64 8), "noundef"(i32* [[P3]]), "nonnull"(i32* [[P3]]) ] ; FULL-SIMPLIFY-NEXT: call void @func_argattr2(i32* [[P2]], i32* [[P3]]) ; FULL-SIMPLIFY-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "noundef"(i32* [[P]]) ] ; FULL-SIMPLIFY-NEXT: call void @func(i32* noundef nonnull [[P1]], i32* noundef nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: ret void ; call void @func(i32* nonnull dereferenceable(16) %P, i32* null) call void @func(i32* dereferenceable(12) %P1, i32* nonnull %P) call void @func_cold(i32* dereferenceable(12) %P1) cold call void @func_cold(i32* dereferenceable(12) %P1) call void @func(i32* %P1, i32* %P) call void @func_strbool(i32* %P1) call void @func(i32* dereferenceable(32) %P, i32* dereferenceable(8) %P) call void @func_many(i32* align 8 %P1) call void @func_many(i32* align 8 noundef %P1) call void @func_argattr(i32* %P2, i32* %P3) call void @func_argattr2(i32* %P2, i32* %P3) call void @func(i32* nonnull %P1, i32* nonnull %P) call void @func(i32* nonnull noundef %P1, i32* nonnull noundef %P) ret void } %struct.S = type { i32, i8, i32* } define i32 @test2(%struct.S* %0, i32* %1, i8* %2) { ; BASIC-LABEL: define {{[^@]+}}@test2 ; BASIC-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) { ; BASIC-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; BASIC-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; BASIC-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; BASIC-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; BASIC-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; BASIC-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; BASIC-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; BASIC-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; BASIC-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; BASIC-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; BASIC-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; BASIC-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; BASIC-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; BASIC-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; BASIC-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; BASIC-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; BASIC-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; BASIC-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 4 ; BASIC-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; BASIC-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; BASIC-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; BASIC-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; BASIC-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; BASIC-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; BASIC-NEXT: ret i32 [[TMP28]] ; ; ALL-LABEL: define {{[^@]+}}@test2 ; ALL-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) { ; ALL-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; ALL-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; ALL-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; ALL-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; ALL-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; ALL-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; ALL-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; ALL-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; ALL-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; ALL-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; ALL-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; ALL-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; ALL-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; ALL-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; ALL-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; ALL-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; ALL-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; ALL-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; ALL-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 4 ; ALL-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; ALL-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; ALL-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; ALL-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; ALL-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; ALL-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; ALL-NEXT: ret i32 [[TMP28]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test2 ; WITH-AC-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) { ; WITH-AC-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; WITH-AC-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; WITH-AC-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; WITH-AC-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; WITH-AC-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; WITH-AC-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; WITH-AC-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; WITH-AC-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; WITH-AC-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; WITH-AC-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; WITH-AC-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; WITH-AC-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; WITH-AC-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; WITH-AC-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; WITH-AC-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; WITH-AC-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; WITH-AC-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; WITH-AC-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 4 ; WITH-AC-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; WITH-AC-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; WITH-AC-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; WITH-AC-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; WITH-AC-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; WITH-AC-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; WITH-AC-NEXT: ret i32 [[TMP28]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test2 ; CROSS-BLOCK-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) { ; CROSS-BLOCK-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; CROSS-BLOCK-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; CROSS-BLOCK-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; CROSS-BLOCK-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; CROSS-BLOCK-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; CROSS-BLOCK-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; CROSS-BLOCK-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; CROSS-BLOCK-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; CROSS-BLOCK-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; CROSS-BLOCK-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 4 ; CROSS-BLOCK-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; CROSS-BLOCK-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; CROSS-BLOCK-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; CROSS-BLOCK-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; CROSS-BLOCK-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; CROSS-BLOCK-NEXT: ret i32 [[TMP28]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test2 ; FULL-SIMPLIFY-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) { ; FULL-SIMPLIFY-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; FULL-SIMPLIFY-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; FULL-SIMPLIFY-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; FULL-SIMPLIFY-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; FULL-SIMPLIFY-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; FULL-SIMPLIFY-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; FULL-SIMPLIFY-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; FULL-SIMPLIFY-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; FULL-SIMPLIFY-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; FULL-SIMPLIFY-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; FULL-SIMPLIFY-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8), "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4), "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; FULL-SIMPLIFY-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; FULL-SIMPLIFY-NEXT: ret i32 [[TMP28]] ; %4 = alloca %struct.S*, align 8 %5 = alloca i32*, align 8 %6 = alloca i8*, align 8 %7 = alloca %struct.S, align 8 store %struct.S* %0, %struct.S** %4, align 8 store i32* %1, i32** %5, align 8 store i8* %2, i8** %6 %8 = load i32*, i32** %5, align 8 %9 = load i32, i32* %8, align 4 %10 = trunc i32 %9 to i8 %11 = load i8*, i8** %6, align 8 store i8 %10, i8* %11, align 1 %12 = bitcast %struct.S* %7 to i8* %13 = load %struct.S*, %struct.S** %4 %14 = bitcast %struct.S* %13 to i8* %15 = bitcast %struct.S* %7 to i8* %16 = load %struct.S*, %struct.S** %4, align 8 %17 = getelementptr inbounds %struct.S, %struct.S* %16, i32 0, i32 0 %18 = load i32, i32* %17, align 8 %19 = load %struct.S*, %struct.S** %4, align 8 %20 = getelementptr inbounds %struct.S, %struct.S* %19, i32 0, i32 1 %21 = load i8, i8* %20, align 4 %22 = sext i8 %21 to i32 %23 = add nsw i32 %18, %22 %24 = load %struct.S*, %struct.S** %4, align 8 %25 = getelementptr inbounds %struct.S, %struct.S* %24, i32 0, i32 2 %26 = load i32*, i32** %25, align 8 %27 = load i32, i32* %26, align 4 %28 = add nsw i32 %23, %27 ret i32 %28 } define i32 @test3(%struct.S* %0, i32* %1, i8* %2) "null-pointer-is-valid"="true" { ; BASIC-LABEL: define {{[^@]+}}@test3 ; BASIC-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) [[ATTR4:#.*]] { ; BASIC-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; BASIC-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; BASIC-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; BASIC-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; BASIC-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; BASIC-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; BASIC-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; BASIC-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; BASIC-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; BASIC-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; BASIC-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; BASIC-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; BASIC-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 32 ; BASIC-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; BASIC-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; BASIC-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; BASIC-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; BASIC-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 8 ; BASIC-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; BASIC-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; BASIC-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; BASIC-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; BASIC-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; BASIC-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; BASIC-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; BASIC-NEXT: ret i32 [[TMP28]] ; ; ALL-LABEL: define {{[^@]+}}@test3 ; ALL-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) [[ATTR4:#.*]] { ; ALL-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; ALL-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; ALL-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; ALL-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; ALL-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; ALL-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; ALL-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; ALL-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; ALL-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; ALL-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; ALL-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; ALL-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; ALL-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; ALL-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 32 ; ALL-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; ALL-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; ALL-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; ALL-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; ALL-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 8 ; ALL-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; ALL-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; ALL-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; ALL-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; ALL-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; ALL-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; ALL-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; ALL-NEXT: ret i32 [[TMP28]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test3 ; WITH-AC-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) [[ATTR4:#.*]] { ; WITH-AC-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; WITH-AC-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; WITH-AC-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; WITH-AC-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; WITH-AC-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; WITH-AC-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; WITH-AC-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; WITH-AC-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; WITH-AC-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; WITH-AC-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; WITH-AC-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; WITH-AC-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; WITH-AC-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 32 ; WITH-AC-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; WITH-AC-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; WITH-AC-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; WITH-AC-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; WITH-AC-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 8 ; WITH-AC-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; WITH-AC-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; WITH-AC-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; WITH-AC-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; WITH-AC-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; WITH-AC-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; WITH-AC-NEXT: ret i32 [[TMP28]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test3 ; CROSS-BLOCK-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) [[ATTR4:#.*]] { ; CROSS-BLOCK-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; CROSS-BLOCK-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; CROSS-BLOCK-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; CROSS-BLOCK-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; CROSS-BLOCK-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; CROSS-BLOCK-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; CROSS-BLOCK-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 32 ; CROSS-BLOCK-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; CROSS-BLOCK-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; CROSS-BLOCK-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 8 ; CROSS-BLOCK-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; CROSS-BLOCK-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; CROSS-BLOCK-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; CROSS-BLOCK-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; CROSS-BLOCK-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; CROSS-BLOCK-NEXT: ret i32 [[TMP28]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test3 ; FULL-SIMPLIFY-SAME: (%struct.S* [[TMP0:%.*]], i32* [[TMP1:%.*]], i8* [[TMP2:%.*]]) [[ATTR4:#.*]] { ; FULL-SIMPLIFY-NEXT: [[TMP4:%.*]] = alloca %struct.S*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = alloca i32*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP6:%.*]] = alloca i8*, align 8 ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = alloca [[STRUCT_S:%.*]], align 8 ; FULL-SIMPLIFY-NEXT: store %struct.S* [[TMP0]], %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: store i32* [[TMP1]], i32** [[TMP5]], align 8 ; FULL-SIMPLIFY-NEXT: store i8* [[TMP2]], i8** [[TMP6]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = load i32*, i32** [[TMP5]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = trunc i32 [[TMP9]] to i8 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = load i8*, i8** [[TMP6]], align 8 ; FULL-SIMPLIFY-NEXT: store i8 [[TMP10]], i8* [[TMP11]], align 1 ; FULL-SIMPLIFY-NEXT: [[TMP12:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; FULL-SIMPLIFY-NEXT: [[TMP13:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 32 ; FULL-SIMPLIFY-NEXT: [[TMP14:%.*]] = bitcast %struct.S* [[TMP13]] to i8* ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: [[TMP15:%.*]] = bitcast %struct.S* [[TMP7]] to i8* ; FULL-SIMPLIFY-NEXT: [[TMP16:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP16]], i32 0, i32 0 ; FULL-SIMPLIFY-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP19:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP19]], i32 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[TMP21:%.*]] = load i8, i8* [[TMP20]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP22:%.*]] = sext i8 [[TMP21]] to i32 ; FULL-SIMPLIFY-NEXT: [[TMP23:%.*]] = add nsw i32 [[TMP18]], [[TMP22]] ; FULL-SIMPLIFY-NEXT: [[TMP24:%.*]] = load %struct.S*, %struct.S** [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.S* [[TMP16]], i64 4), "nonnull"(%struct.S* [[TMP16]]), "align"(%struct.S* [[TMP16]], i64 8), "dereferenceable"(%struct.S* [[TMP19]], i64 5), "nonnull"(%struct.S* [[TMP19]]), "align"(%struct.S* [[TMP19]], i64 4), "dereferenceable"(%struct.S* [[TMP24]], i64 16), "nonnull"(%struct.S* [[TMP24]]), "align"(%struct.S* [[TMP24]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[TMP24]], i32 0, i32 2 ; FULL-SIMPLIFY-NEXT: [[TMP26:%.*]] = load i32*, i32** [[TMP25]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP27:%.*]] = load i32, i32* [[TMP26]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP28:%.*]] = add nsw i32 [[TMP23]], [[TMP27]] ; FULL-SIMPLIFY-NEXT: ret i32 [[TMP28]] ; %4 = alloca %struct.S*, align 8 %5 = alloca i32*, align 8 %6 = alloca i8*, align 8 %7 = alloca %struct.S, align 8 store %struct.S* %0, %struct.S** %4, align 8 store i32* %1, i32** %5, align 8 store i8* %2, i8** %6, align 8 %8 = load i32*, i32** %5, align 8 %9 = load i32, i32* %8, align 4 %10 = trunc i32 %9 to i8 %11 = load i8*, i8** %6 store i8 %10, i8* %11, align 1 %12 = bitcast %struct.S* %7 to i8* %13 = load %struct.S*, %struct.S** %4, align 32 %14 = bitcast %struct.S* %13 to i8* call void @may_throw() %15 = bitcast %struct.S* %7 to i8* %16 = load %struct.S*, %struct.S** %4, align 8 %17 = getelementptr inbounds %struct.S, %struct.S* %16, i32 0, i32 0 %18 = load i32, i32* %17, align 8 %19 = load %struct.S*, %struct.S** %4, align 8 %20 = getelementptr inbounds %struct.S, %struct.S* %19, i32 0, i32 1 %21 = load i8, i8* %20, align 8 %22 = sext i8 %21 to i32 %23 = add nsw i32 %18, %22 %24 = load %struct.S*, %struct.S** %4, align 8 %25 = getelementptr inbounds %struct.S, %struct.S* %24, i32 0, i32 2 %26 = load i32*, i32** %25 %27 = load i32, i32* %26, align 4 %28 = add nsw i32 %23, %27 ret i32 %28 } define dso_local i32 @_Z6squarePi(i32* %P, i32* %P1, i1 %cond) { ; BASIC-LABEL: define {{[^@]+}}@_Z6squarePi ; BASIC-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i1 [[COND:%.*]]) { ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ] ; BASIC-NEXT: store i32 0, i32* [[P]], align 4 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; BASIC-NEXT: store i32 0, i32* [[P1]], align 8 ; BASIC-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; BASIC: A: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 8) ] ; BASIC-NEXT: store i32 0, i32* [[P]], align 8 ; BASIC-NEXT: store i32 0, i32* [[P1]], align 4 ; BASIC-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; BASIC: B: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 8) ] ; BASIC-NEXT: store i32 0, i32* [[P]], align 8 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; BASIC-NEXT: store i32 0, i32* [[P1]], align 8 ; BASIC-NEXT: br label [[C]] ; BASIC: C: ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 32) ] ; BASIC-NEXT: store i32 0, i32* [[P]], align 32 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 4) ] ; BASIC-NEXT: store i32 0, i32* [[P1]], align 4 ; BASIC-NEXT: ret i32 0 ; ; ALL-LABEL: define {{[^@]+}}@_Z6squarePi ; ALL-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i1 [[COND:%.*]]) { ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ] ; ALL-NEXT: store i32 0, i32* [[P]], align 4 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; ALL-NEXT: store i32 0, i32* [[P1]], align 8 ; ALL-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; ALL: A: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 8) ] ; ALL-NEXT: store i32 0, i32* [[P]], align 8 ; ALL-NEXT: store i32 0, i32* [[P1]], align 4 ; ALL-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; ALL: B: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 8) ] ; ALL-NEXT: store i32 0, i32* [[P]], align 8 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; ALL-NEXT: store i32 0, i32* [[P1]], align 8 ; ALL-NEXT: br label [[C]] ; ALL: C: ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 32) ] ; ALL-NEXT: store i32 0, i32* [[P]], align 32 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 4) ] ; ALL-NEXT: store i32 0, i32* [[P1]], align 4 ; ALL-NEXT: ret i32 0 ; ; WITH-AC-LABEL: define {{[^@]+}}@_Z6squarePi ; WITH-AC-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i1 [[COND:%.*]]) { ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ] ; WITH-AC-NEXT: store i32 0, i32* [[P]], align 4 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; WITH-AC-NEXT: store i32 0, i32* [[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"(i32* [[P]], i64 8) ] ; WITH-AC-NEXT: store i32 0, i32* [[P]], align 8 ; WITH-AC-NEXT: store i32 0, i32* [[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"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 8) ] ; WITH-AC-NEXT: store i32 0, i32* [[P]], align 8 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; WITH-AC-NEXT: store i32 0, i32* [[P1]], align 8 ; WITH-AC-NEXT: br label [[C]] ; WITH-AC: C: ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 32) ] ; WITH-AC-NEXT: store i32 0, i32* [[P]], align 32 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 4) ] ; WITH-AC-NEXT: store i32 0, i32* [[P1]], align 4 ; WITH-AC-NEXT: ret i32 0 ; ; CROSS-BLOCK-OLDPM-LABEL: define {{[^@]+}}@_Z6squarePi ; CROSS-BLOCK-OLDPM-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i1 [[COND:%.*]]) { ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P]], align 4 ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P1]], align 8 ; CROSS-BLOCK-OLDPM-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; CROSS-BLOCK-OLDPM: A: ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 8) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P]], align 8 ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P1]], align 4 ; CROSS-BLOCK-OLDPM-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; CROSS-BLOCK-OLDPM: B: ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 8) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P]], align 8 ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P1]], align 8 ; CROSS-BLOCK-OLDPM-NEXT: br label [[C]] ; CROSS-BLOCK-OLDPM: C: ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 32) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P]], align 32 ; CROSS-BLOCK-OLDPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 4) ] ; CROSS-BLOCK-OLDPM-NEXT: store i32 0, i32* [[P1]], align 4 ; CROSS-BLOCK-OLDPM-NEXT: ret i32 0 ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@_Z6squarePi ; FULL-SIMPLIFY-SAME: (i32* nonnull align 4 dereferenceable(4) [[P:%.*]], i32* nonnull align 8 dereferenceable(4) [[P1:%.*]], i1 [[COND:%.*]]) { ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P]], align 4 ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[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"(i32* [[P]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P]], align 8 ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[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"(i32* undef, i64 4), "ignore"(i32* undef), "align"(i32* [[P]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P]], align 8 ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P1]], align 8 ; FULL-SIMPLIFY-NEXT: br label [[C]] ; FULL-SIMPLIFY: C: ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i32* undef, i64 4), "ignore"(i32* undef), "align"(i32* [[P]], i64 32) ] ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P]], align 32 ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[P1]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 0 ; ; CROSS-BLOCK-NEWMP-LABEL: define {{[^@]+}}@_Z6squarePi ; CROSS-BLOCK-NEWMP-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i1 [[COND:%.*]]) { ; CROSS-BLOCK-NEWMP-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 4), "nonnull"(i32* [[P]]), "align"(i32* [[P]], i64 4) ] ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P]], align 4 ; CROSS-BLOCK-NEWMP-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]), "align"(i32* [[P1]], i64 8) ] ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P1]], align 8 ; CROSS-BLOCK-NEWMP-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] ; CROSS-BLOCK-NEWMP: A: ; CROSS-BLOCK-NEWMP-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 8) ] ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P]], align 8 ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P1]], align 4 ; CROSS-BLOCK-NEWMP-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]] ; CROSS-BLOCK-NEWMP: B: ; CROSS-BLOCK-NEWMP-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 8) ] ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P]], align 8 ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P1]], align 8 ; CROSS-BLOCK-NEWMP-NEXT: br label [[C]] ; CROSS-BLOCK-NEWMP: C: ; CROSS-BLOCK-NEWMP-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P]], i64 32) ] ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P]], align 32 ; CROSS-BLOCK-NEWMP-NEXT: store i32 0, i32* [[P1]], align 4 ; CROSS-BLOCK-NEWMP-NEXT: ret i32 0 ; store i32 0, i32* %P, align 4 store i32 0, i32* %P1, align 8 br i1 %cond, label %A, label %B A: store i32 0, i32* %P, align 8 store i32 0, i32* %P1, align 4 br i1 %cond, label %C, label %B B: store i32 0, i32* %P, align 8 store i32 0, i32* %P1, align 8 br label %C C: store i32 0, i32* %P, align 32 store i32 0, i32* %P1, align 4 ret i32 0 } define dso_local i32 @test4A(i32* %0, i32* %1, i32 %2, i32 %3) { ; BASIC-LABEL: define {{[^@]+}}@test4A ; BASIC-SAME: (i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) { ; BASIC-NEXT: [[TMP5:%.*]] = icmp ne i32* [[TMP1]], null ; BASIC-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP12:%.*]] ; BASIC: 6: ; BASIC-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0]], i64 4), "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; BASIC-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 ; BASIC-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] ; BASIC-NEXT: store i32 0, i32* [[TMP0]], align 4 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]), "align"(i32* [[TMP1]], i64 4) ] ; BASIC-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 ; BASIC-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] ; BASIC-NEXT: call void @may_throw() ; BASIC-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 ; BASIC-NEXT: br label [[TMP12]] ; BASIC: 12: ; BASIC-NEXT: ret i32 0 ; ; ALL-LABEL: define {{[^@]+}}@test4A ; ALL-SAME: (i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) { ; ALL-NEXT: [[TMP5:%.*]] = icmp ne i32* [[TMP1]], null ; ALL-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP12:%.*]] ; ALL: 6: ; ALL-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0]], i64 4), "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; ALL-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 ; ALL-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] ; ALL-NEXT: store i32 0, i32* [[TMP0]], align 4 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]), "align"(i32* [[TMP1]], i64 4) ] ; ALL-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 ; ALL-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] ; ALL-NEXT: call void @may_throw() ; ALL-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 ; ALL-NEXT: br label [[TMP12]] ; ALL: 12: ; ALL-NEXT: ret i32 0 ; ; WITH-AC-LABEL: define {{[^@]+}}@test4A ; WITH-AC-SAME: (i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) { ; WITH-AC-NEXT: [[TMP5:%.*]] = icmp ne i32* [[TMP1]], null ; WITH-AC-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP12:%.*]] ; WITH-AC: 6: ; WITH-AC-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0]], i64 4), "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; WITH-AC-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 ; WITH-AC-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] ; WITH-AC-NEXT: store i32 0, i32* [[TMP0]], align 4 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]), "align"(i32* [[TMP1]], i64 4) ] ; WITH-AC-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 ; WITH-AC-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] ; WITH-AC-NEXT: call void @may_throw() ; WITH-AC-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 ; WITH-AC-NEXT: br label [[TMP12]] ; WITH-AC: 12: ; WITH-AC-NEXT: ret i32 0 ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test4A ; CROSS-BLOCK-SAME: (i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) { ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = icmp ne i32* [[TMP1]], null ; CROSS-BLOCK-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP12:%.*]] ; CROSS-BLOCK: 6: ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0]], i64 4), "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] ; CROSS-BLOCK-NEXT: store i32 0, i32* [[TMP0]], align 4 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]), "align"(i32* [[TMP1]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] ; CROSS-BLOCK-NEXT: call void @may_throw() ; CROSS-BLOCK-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 ; CROSS-BLOCK-NEXT: br label [[TMP12]] ; CROSS-BLOCK: 12: ; CROSS-BLOCK-NEXT: ret i32 0 ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test4A ; FULL-SIMPLIFY-SAME: (i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) { ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = icmp ne i32* [[TMP1]], null ; FULL-SIMPLIFY-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP12:%.*]] ; FULL-SIMPLIFY: 6: ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0]], i64 4), "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4), "dereferenceable"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]), "align"(i32* [[TMP1]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] ; FULL-SIMPLIFY-NEXT: store i32 0, i32* [[TMP0]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] ; FULL-SIMPLIFY-NEXT: call void @may_throw() ; FULL-SIMPLIFY-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 ; FULL-SIMPLIFY-NEXT: br label [[TMP12]] ; FULL-SIMPLIFY: 12: ; FULL-SIMPLIFY-NEXT: ret i32 0 ; %5 = icmp ne i32* %1, null br i1 %5, label %6, label %12 6: ; preds = %4 %7 = add nsw i32 %3, %2 call void @may_throw() %8 = load i32, i32* %0, align 4 %9 = add nsw i32 %7, %8 store i32 0, i32* %0, align 4 %10 = load i32, i32* %1, align 4 %11 = add nsw i32 %9, %10 call void @may_throw() store i32 %11, i32* %1, align 4 br label %12 12: ; preds = %6, %4 ret i32 0 } declare void @may_throwv2(i32* %P) define dso_local i32 @terminator(i32* %P) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; BASIC-LABEL: define {{[^@]+}}@terminator ; BASIC-SAME: (i32* [[P:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; BASIC-NEXT: invoke void @may_throwv2(i32* nonnull [[P]]) ; BASIC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; BASIC: Catch: ; BASIC-NEXT: [[V:%.*]] = landingpad { i8*, i32 } ; BASIC-NEXT: catch i8* null ; BASIC-NEXT: br label [[EXIT]] ; BASIC: Exit: ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 0, [[CATCH]] ] ; BASIC-NEXT: ret i32 [[DOT0]] ; ; ALL-LABEL: define {{[^@]+}}@terminator ; ALL-SAME: (i32* [[P:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; ALL-NEXT: invoke void @may_throwv2(i32* nonnull [[P]]) ; ALL-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; ALL: Catch: ; ALL-NEXT: [[V:%.*]] = landingpad { i8*, i32 } ; ALL-NEXT: catch i8* null ; ALL-NEXT: br label [[EXIT]] ; ALL: Exit: ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 0, [[CATCH]] ] ; ALL-NEXT: ret i32 [[DOT0]] ; ; WITH-AC-LABEL: define {{[^@]+}}@terminator ; WITH-AC-SAME: (i32* [[P:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; WITH-AC-NEXT: invoke void @may_throwv2(i32* nonnull [[P]]) ; WITH-AC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; WITH-AC: Catch: ; WITH-AC-NEXT: [[V:%.*]] = landingpad { i8*, i32 } ; WITH-AC-NEXT: catch i8* null ; WITH-AC-NEXT: br label [[EXIT]] ; WITH-AC: Exit: ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 0, [[CATCH]] ] ; WITH-AC-NEXT: ret i32 [[DOT0]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@terminator ; CROSS-BLOCK-SAME: (i32* [[P:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; CROSS-BLOCK-NEXT: invoke void @may_throwv2(i32* nonnull [[P]]) ; CROSS-BLOCK-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; CROSS-BLOCK: Catch: ; CROSS-BLOCK-NEXT: [[V:%.*]] = landingpad { i8*, i32 } ; CROSS-BLOCK-NEXT: catch i8* null ; CROSS-BLOCK-NEXT: br label [[EXIT]] ; CROSS-BLOCK: Exit: ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 0, [[CATCH]] ] ; CROSS-BLOCK-NEXT: ret i32 [[DOT0]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@terminator ; FULL-SIMPLIFY-SAME: (i32* [[P:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; FULL-SIMPLIFY-NEXT: invoke void @may_throwv2(i32* nonnull [[P]]) ; FULL-SIMPLIFY-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]] ; FULL-SIMPLIFY: Catch: ; FULL-SIMPLIFY-NEXT: [[V:%.*]] = landingpad { i8*, i32 } ; FULL-SIMPLIFY-NEXT: catch i8* null ; FULL-SIMPLIFY-NEXT: br label [[EXIT]] ; FULL-SIMPLIFY: Exit: ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 0, [[CATCH]] ] ; FULL-SIMPLIFY-NEXT: ret i32 [[DOT0]] ; invoke void @may_throwv2(i32* nonnull %P) to label %Exit unwind label %Catch Catch: ; preds = %0 %v = landingpad { i8*, i32 } catch i8* null br label %Exit Exit: ; preds = %7, %5 %.0 = phi i32 [ 1, %0 ], [ 0, %Catch ] ret i32 %.0 } declare dso_local i32 @__gxx_personality_v0(...) define dso_local i32 @test5(i8* %0, i32 %1) { ; BASIC-LABEL: define {{[^@]+}}@test5 ; BASIC-SAME: (i8* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; BASIC-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i64* ; BASIC-NEXT: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16* ; BASIC-NEXT: [[TMP5:%.*]] = sext i32 [[TMP1]] to i64 ; BASIC-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i64 [[TMP5]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i16* [[TMP6]], i64 2), "nonnull"(i8* [[TMP0]]), "align"(i8* [[TMP0]], i64 8) ] ; BASIC-NEXT: [[TMP7:%.*]] = load i16, i16* [[TMP6]], align 2 ; BASIC-NEXT: [[A:%.*]] = load i16, i16* [[TMP6]], align 4 ; BASIC-NEXT: [[TMP8:%.*]] = sext i16 [[TMP7]] to i64 ; BASIC-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, i64* [[TMP3]], i64 [[TMP8]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP9]], i64 8) ] ; BASIC-NEXT: [[TMP10:%.*]] = load i64, i64* [[TMP9]], align 16 ; BASIC-NEXT: [[B:%.*]] = load i64, i64* [[TMP9]], align 32 ; BASIC-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP10]] to i32 ; BASIC-NEXT: ret i32 [[TMP11]] ; ; ALL-LABEL: define {{[^@]+}}@test5 ; ALL-SAME: (i8* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; ALL-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i64* ; ALL-NEXT: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16* ; ALL-NEXT: [[TMP5:%.*]] = sext i32 [[TMP1]] to i64 ; ALL-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i64 [[TMP5]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i16* [[TMP6]], i64 2), "nonnull"(i8* [[TMP0]]), "align"(i8* [[TMP0]], i64 8) ] ; ALL-NEXT: [[TMP7:%.*]] = load i16, i16* [[TMP6]], align 2 ; ALL-NEXT: [[A:%.*]] = load i16, i16* [[TMP6]], align 4 ; ALL-NEXT: [[TMP8:%.*]] = sext i16 [[TMP7]] to i64 ; ALL-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, i64* [[TMP3]], i64 [[TMP8]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP9]], i64 8) ] ; ALL-NEXT: [[TMP10:%.*]] = load i64, i64* [[TMP9]], align 16 ; ALL-NEXT: [[B:%.*]] = load i64, i64* [[TMP9]], align 32 ; ALL-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP10]] to i32 ; ALL-NEXT: ret i32 [[TMP11]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test5 ; WITH-AC-SAME: (i8* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; WITH-AC-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i64* ; WITH-AC-NEXT: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16* ; WITH-AC-NEXT: [[TMP5:%.*]] = sext i32 [[TMP1]] to i64 ; WITH-AC-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i64 [[TMP5]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i16* [[TMP6]], i64 2), "nonnull"(i8* [[TMP0]]), "align"(i8* [[TMP0]], i64 8) ] ; WITH-AC-NEXT: [[TMP7:%.*]] = load i16, i16* [[TMP6]], align 2 ; WITH-AC-NEXT: [[A:%.*]] = load i16, i16* [[TMP6]], align 4 ; WITH-AC-NEXT: [[TMP8:%.*]] = sext i16 [[TMP7]] to i64 ; WITH-AC-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, i64* [[TMP3]], i64 [[TMP8]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP9]], i64 8) ] ; WITH-AC-NEXT: [[TMP10:%.*]] = load i64, i64* [[TMP9]], align 16 ; WITH-AC-NEXT: [[B:%.*]] = load i64, i64* [[TMP9]], align 32 ; WITH-AC-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP10]] to i32 ; WITH-AC-NEXT: ret i32 [[TMP11]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test5 ; CROSS-BLOCK-SAME: (i8* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; CROSS-BLOCK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i64* ; CROSS-BLOCK-NEXT: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16* ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = sext i32 [[TMP1]] to i64 ; CROSS-BLOCK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i64 [[TMP5]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i16* [[TMP6]], i64 2), "nonnull"(i8* [[TMP0]]), "align"(i8* [[TMP0]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = load i16, i16* [[TMP6]], align 2 ; CROSS-BLOCK-NEXT: [[A:%.*]] = load i16, i16* [[TMP6]], align 4 ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = sext i16 [[TMP7]] to i64 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, i64* [[TMP3]], i64 [[TMP8]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP9]], i64 8) ] ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = load i64, i64* [[TMP9]], align 16 ; CROSS-BLOCK-NEXT: [[B:%.*]] = load i64, i64* [[TMP9]], align 32 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP10]] to i32 ; CROSS-BLOCK-NEXT: ret i32 [[TMP11]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test5 ; FULL-SIMPLIFY-SAME: (i8* nonnull align 8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; FULL-SIMPLIFY-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to i64* ; FULL-SIMPLIFY-NEXT: [[TMP4:%.*]] = bitcast i8* [[TMP0]] to i16* ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = sext i32 [[TMP1]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i64 [[TMP5]] ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = load i16, i16* [[TMP6]], align 2 ; FULL-SIMPLIFY-NEXT: [[A:%.*]] = load i16, i16* [[TMP6]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = sext i16 [[TMP7]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, i64* [[TMP3]], i64 [[TMP8]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i16* [[TMP6]], i64 2), "dereferenceable"(i64* [[TMP9]], i64 8) ] ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = load i64, i64* [[TMP9]], align 16 ; FULL-SIMPLIFY-NEXT: [[B:%.*]] = load i64, i64* [[TMP9]], align 32 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP10]] to i32 ; FULL-SIMPLIFY-NEXT: ret i32 [[TMP11]] ; %3 = bitcast i8* %0 to i64* %4 = bitcast i8* %0 to i16* %5 = sext i32 %1 to i64 %6 = getelementptr inbounds i16, i16* %4, i64 %5 %7 = load i16, i16* %6, align 2 %A = load i16, i16* %6, align 4 %8 = sext i16 %7 to i64 %9 = getelementptr inbounds i64, i64* %3, i64 %8 %10 = load i64, i64* %9, align 16 %B = load i64, i64* %9, align 32 %11 = trunc i64 %10 to i32 ret i32 %11 } define i32 @test6(i32* %0, i32 %1, i32* %2) { ; BASIC-LABEL: define {{[^@]+}}@test6 ; BASIC-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* [[TMP2:%.*]]) { ; BASIC-NEXT: br label [[TMP4:%.*]] ; BASIC: 4: ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP16:%.*]], [[TMP6:%.*]] ] ; BASIC-NEXT: [[TMP5:%.*]] = icmp slt i32 [[DOT0]], [[TMP1]] ; BASIC-NEXT: br i1 [[TMP5]], label [[TMP6]], label [[TMP17:%.*]] ; BASIC: 6: ; BASIC-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP1]], [[DOT0]] ; BASIC-NEXT: [[TMP8:%.*]] = sext i32 [[TMP7]] to i64 ; BASIC-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP8]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; BASIC-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 ; BASIC-NEXT: [[TMP11:%.*]] = mul nsw i32 [[DOT0]], [[TMP10]] ; BASIC-NEXT: [[TMP12:%.*]] = sext i32 [[DOT0]] to i64 ; BASIC-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP12]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP13]], i64 4) ] ; BASIC-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 ; BASIC-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP14]], [[TMP11]] ; BASIC-NEXT: store i32 [[TMP15]], i32* [[TMP13]], align 4 ; BASIC-NEXT: [[TMP16]] = add nsw i32 [[DOT0]], 1 ; BASIC-NEXT: br label [[TMP4]] ; BASIC: 17: ; BASIC-NEXT: [[TMP18:%.*]] = sext i32 [[TMP1]] to i64 ; BASIC-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP18]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP2]]), "align"(i32* [[TMP2]], i64 4) ] ; BASIC-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 ; BASIC-NEXT: ret i32 [[TMP20]] ; ; ALL-LABEL: define {{[^@]+}}@test6 ; ALL-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* [[TMP2:%.*]]) { ; ALL-NEXT: br label [[TMP4:%.*]] ; ALL: 4: ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP16:%.*]], [[TMP6:%.*]] ] ; ALL-NEXT: [[TMP5:%.*]] = icmp slt i32 [[DOT0]], [[TMP1]] ; ALL-NEXT: br i1 [[TMP5]], label [[TMP6]], label [[TMP17:%.*]] ; ALL: 6: ; ALL-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP1]], [[DOT0]] ; ALL-NEXT: [[TMP8:%.*]] = sext i32 [[TMP7]] to i64 ; ALL-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP8]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; ALL-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 ; ALL-NEXT: [[TMP11:%.*]] = mul nsw i32 [[DOT0]], [[TMP10]] ; ALL-NEXT: [[TMP12:%.*]] = sext i32 [[DOT0]] to i64 ; ALL-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP12]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP13]], i64 4) ] ; ALL-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 ; ALL-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP14]], [[TMP11]] ; ALL-NEXT: store i32 [[TMP15]], i32* [[TMP13]], align 4 ; ALL-NEXT: [[TMP16]] = add nsw i32 [[DOT0]], 1 ; ALL-NEXT: br label [[TMP4]] ; ALL: 17: ; ALL-NEXT: [[TMP18:%.*]] = sext i32 [[TMP1]] to i64 ; ALL-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP18]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP2]]), "align"(i32* [[TMP2]], i64 4) ] ; ALL-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 ; ALL-NEXT: ret i32 [[TMP20]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test6 ; WITH-AC-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* [[TMP2:%.*]]) { ; WITH-AC-NEXT: br label [[TMP4:%.*]] ; WITH-AC: 4: ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP16:%.*]], [[TMP6:%.*]] ] ; WITH-AC-NEXT: [[TMP5:%.*]] = icmp slt i32 [[DOT0]], [[TMP1]] ; WITH-AC-NEXT: br i1 [[TMP5]], label [[TMP6]], label [[TMP17:%.*]] ; WITH-AC: 6: ; WITH-AC-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP1]], [[DOT0]] ; WITH-AC-NEXT: [[TMP8:%.*]] = sext i32 [[TMP7]] to i64 ; WITH-AC-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP8]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; WITH-AC-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 ; WITH-AC-NEXT: [[TMP11:%.*]] = mul nsw i32 [[DOT0]], [[TMP10]] ; WITH-AC-NEXT: [[TMP12:%.*]] = sext i32 [[DOT0]] to i64 ; WITH-AC-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP12]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP13]], i64 4) ] ; WITH-AC-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 ; WITH-AC-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP14]], [[TMP11]] ; WITH-AC-NEXT: store i32 [[TMP15]], i32* [[TMP13]], align 4 ; WITH-AC-NEXT: [[TMP16]] = add nsw i32 [[DOT0]], 1 ; WITH-AC-NEXT: br label [[TMP4]] ; WITH-AC: 17: ; WITH-AC-NEXT: [[TMP18:%.*]] = sext i32 [[TMP1]] to i64 ; WITH-AC-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP18]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP2]]), "align"(i32* [[TMP2]], i64 4) ] ; WITH-AC-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 ; WITH-AC-NEXT: ret i32 [[TMP20]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test6 ; CROSS-BLOCK-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* [[TMP2:%.*]]) { ; CROSS-BLOCK-NEXT: br label [[TMP4:%.*]] ; CROSS-BLOCK: 4: ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP16:%.*]], [[TMP6:%.*]] ] ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[DOT0]], [[TMP1]] ; CROSS-BLOCK-NEXT: br i1 [[TMP5]], label [[TMP6]], label [[TMP17:%.*]] ; CROSS-BLOCK: 6: ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP1]], [[DOT0]] ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = sext i32 [[TMP7]] to i64 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP8]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = mul nsw i32 [[DOT0]], [[TMP10]] ; CROSS-BLOCK-NEXT: [[TMP12:%.*]] = sext i32 [[DOT0]] to i64 ; CROSS-BLOCK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP12]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP13]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 ; CROSS-BLOCK-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP14]], [[TMP11]] ; CROSS-BLOCK-NEXT: store i32 [[TMP15]], i32* [[TMP13]], align 4 ; CROSS-BLOCK-NEXT: [[TMP16]] = add nsw i32 [[DOT0]], 1 ; CROSS-BLOCK-NEXT: br label [[TMP4]] ; CROSS-BLOCK: 17: ; CROSS-BLOCK-NEXT: [[TMP18:%.*]] = sext i32 [[TMP1]] to i64 ; CROSS-BLOCK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP18]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP2]]), "align"(i32* [[TMP2]], i64 4) ] ; CROSS-BLOCK-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 ; CROSS-BLOCK-NEXT: ret i32 [[TMP20]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test6 ; FULL-SIMPLIFY-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* [[TMP2:%.*]]) { ; FULL-SIMPLIFY-NEXT: br label [[TMP4:%.*]] ; FULL-SIMPLIFY: 4: ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP16:%.*]], [[TMP6:%.*]] ] ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = icmp slt i32 [[DOT0]], [[TMP1]] ; FULL-SIMPLIFY-NEXT: br i1 [[TMP5]], label [[TMP6]], label [[TMP17:%.*]] ; FULL-SIMPLIFY: 6: ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP1]], [[DOT0]] ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = sext i32 [[TMP7]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP8]] ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = mul nsw i32 [[DOT0]], [[TMP10]] ; FULL-SIMPLIFY-NEXT: [[TMP12:%.*]] = sext i32 [[DOT0]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP12]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]), "align"(i32* [[TMP0]], i64 4), "dereferenceable"(i32* [[TMP13]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP14]], [[TMP11]] ; FULL-SIMPLIFY-NEXT: store i32 [[TMP15]], i32* [[TMP13]], align 4 ; FULL-SIMPLIFY-NEXT: [[TMP16]] = add nsw i32 [[DOT0]], 1 ; FULL-SIMPLIFY-NEXT: br label [[TMP4]] ; FULL-SIMPLIFY: 17: ; FULL-SIMPLIFY-NEXT: [[TMP18:%.*]] = sext i32 [[TMP1]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP18]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP2]]), "align"(i32* [[TMP2]], i64 4) ] ; FULL-SIMPLIFY-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 [[TMP20]] ; br label %4 4: ; preds = %6, %3 %.0 = phi i32 [ 0, %3 ], [ %16, %6 ] %5 = icmp slt i32 %.0, %1 br i1 %5, label %6, label %17 6: ; preds = %4 %7 = add nsw i32 %1, %.0 %8 = sext i32 %7 to i64 %9 = getelementptr inbounds i32, i32* %0, i64 %8 %10 = load i32, i32* %9, align 4 %11 = mul nsw i32 %.0, %10 %12 = sext i32 %.0 to i64 %13 = getelementptr inbounds i32, i32* %0, i64 %12 %14 = load i32, i32* %13, align 4 %15 = add nsw i32 %14, %11 store i32 %15, i32* %13, align 4 %16 = add nsw i32 %.0, 1 br label %4 17: ; preds = %4 %18 = sext i32 %1 to i64 %19 = getelementptr inbounds i32, i32* %2, i64 %18 %20 = load i32, i32* %19, align 4 ret i32 %20 } %struct.A = type { i8*, i64*, [4 x [4 x %struct.D]], i64 } %struct.D = type { i64, i64 } define i32 @test7(%struct.A* nonnull %0, i32 %1) { ; BASIC-LABEL: define {{[^@]+}}@test7 ; BASIC-SAME: (%struct.A* nonnull [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; BASIC-NEXT: [[TMP3:%.*]] = sext i32 [[TMP1]] to i64 ; BASIC-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP0]], i64 0, i32 3 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.A* [[TMP0]], i64 280), "align"(%struct.A* [[TMP0]], i64 16) ] ; BASIC-NEXT: [[TMP5:%.*]] = load i64, i64* [[TMP4]], align 8 ; BASIC-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 2, i64 [[TMP3]], i64 [[TMP5]], i32 0 ; BASIC-NEXT: [[TMP7:%.*]] = load i64, i64* [[TMP6]], align 32 ; BASIC-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 1 ; BASIC-NEXT: [[TMP9:%.*]] = load i64*, i64** [[TMP8]], align 8 ; BASIC-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, i64* [[TMP9]], i64 [[TMP5]] ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP10]], i64 8), "nonnull"(i64* [[TMP9]]), "align"(i64* [[TMP9]], i64 8) ] ; BASIC-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; BASIC-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; BASIC-NEXT: [[TMP11:%.*]] = bitcast %struct.A* [[TMP0]] to i32** ; BASIC-NEXT: [[TMP12:%.*]] = load i32*, i32** [[TMP11]], align 8 ; BASIC-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 ; BASIC-NEXT: ret i32 [[TMP13]] ; ; ALL-LABEL: define {{[^@]+}}@test7 ; ALL-SAME: (%struct.A* nonnull [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; ALL-NEXT: [[TMP3:%.*]] = sext i32 [[TMP1]] to i64 ; ALL-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP0]], i64 0, i32 3 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.A* [[TMP0]], i64 280), "align"(%struct.A* [[TMP0]], i64 16) ] ; ALL-NEXT: [[TMP5:%.*]] = load i64, i64* [[TMP4]], align 8 ; ALL-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 2, i64 [[TMP3]], i64 [[TMP5]], i32 0 ; ALL-NEXT: [[TMP7:%.*]] = load i64, i64* [[TMP6]], align 32 ; ALL-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 1 ; ALL-NEXT: [[TMP9:%.*]] = load i64*, i64** [[TMP8]], align 8 ; ALL-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, i64* [[TMP9]], i64 [[TMP5]] ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP10]], i64 8), "nonnull"(i64* [[TMP9]]), "align"(i64* [[TMP9]], i64 8) ] ; ALL-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; ALL-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; ALL-NEXT: [[TMP11:%.*]] = bitcast %struct.A* [[TMP0]] to i32** ; ALL-NEXT: [[TMP12:%.*]] = load i32*, i32** [[TMP11]], align 8 ; ALL-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 ; ALL-NEXT: ret i32 [[TMP13]] ; ; WITH-AC-LABEL: define {{[^@]+}}@test7 ; WITH-AC-SAME: (%struct.A* nonnull [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; WITH-AC-NEXT: [[TMP3:%.*]] = sext i32 [[TMP1]] to i64 ; WITH-AC-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP0]], i64 0, i32 3 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.A* [[TMP0]], i64 280), "align"(%struct.A* [[TMP0]], i64 16) ] ; WITH-AC-NEXT: [[TMP5:%.*]] = load i64, i64* [[TMP4]], align 8 ; WITH-AC-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 2, i64 [[TMP3]], i64 [[TMP5]], i32 0 ; WITH-AC-NEXT: [[TMP7:%.*]] = load i64, i64* [[TMP6]], align 32 ; WITH-AC-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 1 ; WITH-AC-NEXT: [[TMP9:%.*]] = load i64*, i64** [[TMP8]], align 8 ; WITH-AC-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, i64* [[TMP9]], i64 [[TMP5]] ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP10]], i64 8), "nonnull"(i64* [[TMP9]]), "align"(i64* [[TMP9]], i64 8) ] ; WITH-AC-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; WITH-AC-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; WITH-AC-NEXT: [[TMP11:%.*]] = bitcast %struct.A* [[TMP0]] to i32** ; WITH-AC-NEXT: [[TMP12:%.*]] = load i32*, i32** [[TMP11]], align 8 ; WITH-AC-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 ; WITH-AC-NEXT: ret i32 [[TMP13]] ; ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test7 ; CROSS-BLOCK-SAME: (%struct.A* nonnull [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; CROSS-BLOCK-NEXT: [[TMP3:%.*]] = sext i32 [[TMP1]] to i64 ; CROSS-BLOCK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP0]], i64 0, i32 3 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(%struct.A* [[TMP0]], i64 280), "align"(%struct.A* [[TMP0]], i64 16) ] ; CROSS-BLOCK-NEXT: [[TMP5:%.*]] = load i64, i64* [[TMP4]], align 8 ; CROSS-BLOCK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 2, i64 [[TMP3]], i64 [[TMP5]], i32 0 ; CROSS-BLOCK-NEXT: [[TMP7:%.*]] = load i64, i64* [[TMP6]], align 32 ; CROSS-BLOCK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 1 ; CROSS-BLOCK-NEXT: [[TMP9:%.*]] = load i64*, i64** [[TMP8]], align 8 ; CROSS-BLOCK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, i64* [[TMP9]], i64 [[TMP5]] ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP10]], i64 8), "nonnull"(i64* [[TMP9]]), "align"(i64* [[TMP9]], i64 8) ] ; CROSS-BLOCK-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; CROSS-BLOCK-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; CROSS-BLOCK-NEXT: [[TMP11:%.*]] = bitcast %struct.A* [[TMP0]] to i32** ; CROSS-BLOCK-NEXT: [[TMP12:%.*]] = load i32*, i32** [[TMP11]], align 8 ; CROSS-BLOCK-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 ; CROSS-BLOCK-NEXT: ret i32 [[TMP13]] ; ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test7 ; FULL-SIMPLIFY-SAME: (%struct.A* nonnull align 16 dereferenceable(280) [[TMP0:%.*]], i32 [[TMP1:%.*]]) { ; FULL-SIMPLIFY-NEXT: [[TMP3:%.*]] = sext i32 [[TMP1]] to i64 ; FULL-SIMPLIFY-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP0]], i64 0, i32 3 ; FULL-SIMPLIFY-NEXT: [[TMP5:%.*]] = load i64, i64* [[TMP4]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 2, i64 [[TMP3]], i64 [[TMP5]], i32 0 ; FULL-SIMPLIFY-NEXT: [[TMP7:%.*]] = load i64, i64* [[TMP6]], align 32 ; FULL-SIMPLIFY-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP0]], i64 0, i32 1 ; FULL-SIMPLIFY-NEXT: [[TMP9:%.*]] = load i64*, i64** [[TMP8]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP10:%.*]] = getelementptr inbounds i64, i64* [[TMP9]], i64 [[TMP5]] ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i64* [[TMP10]], i64 8), "nonnull"(i64* [[TMP9]]), "align"(i64* [[TMP9]], i64 8) ] ; FULL-SIMPLIFY-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; FULL-SIMPLIFY-NEXT: store i64 [[TMP7]], i64* [[TMP10]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP11:%.*]] = bitcast %struct.A* [[TMP0]] to i32** ; FULL-SIMPLIFY-NEXT: [[TMP12:%.*]] = load i32*, i32** [[TMP11]], align 8 ; FULL-SIMPLIFY-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 ; FULL-SIMPLIFY-NEXT: ret i32 [[TMP13]] ; %3 = sext i32 %1 to i64 %4 = getelementptr inbounds %struct.A, %struct.A* %0, i64 0, i32 3 %5 = load i64, i64* %4, align 8 %6 = getelementptr inbounds %struct.A, %struct.A* %0, i64 0, i32 2, i64 %3, i64 %5, i32 0 %7 = load i64, i64* %6, align 32 %8 = getelementptr inbounds %struct.A, %struct.A* %0, i64 0, i32 1 %9 = load i64*, i64** %8, align 8 %10 = getelementptr inbounds i64, i64* %9, i64 %5 store i64 %7, i64* %10, align 8 store i64 %7, i64* %10, align 8 %11 = bitcast %struct.A* %0 to i32** %12 = load i32*, i32** %11, align 8 %13 = load i32, i32* %12, align 4 ret i32 %13 }