
isValidAssumeForContext() handles a couple of trivial cases even if no dominator tree is available. This adds one more for the case where there is an assume in the entry block, and a use in some other block. The entry block always dominates all blocks. As having context instruction but not having DT is fairly rare, there is not much impact. Only test change is in assume-builder.ll, where less redundant assumes are generated. I've found having this special case is useful for an upcoming change though.
1293 lines
72 KiB
LLVM
1293 lines
72 KiB
LLVM
; 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<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
|
|
; 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"
|
|
|
|
%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) [ "align"(ptr [[P]], i64 8) ]
|
|
; BASIC-NEXT: store i32 0, ptr [[P]], align 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) [ "align"(ptr [[P]], i64 32) ]
|
|
; BASIC-NEXT: store i32 0, ptr [[P]], align 32
|
|
; 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) [ "align"(ptr [[P]], i64 8) ]
|
|
; ALL-NEXT: store i32 0, ptr [[P]], align 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) [ "align"(ptr [[P]], i64 32) ]
|
|
; ALL-NEXT: store i32 0, ptr [[P]], align 32
|
|
; 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) [ "align"(ptr [[P]], i64 8) ]
|
|
; WITH-AC-NEXT: store i32 0, ptr [[P]], align 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) [ "align"(ptr [[P]], i64 32) ]
|
|
; WITH-AC-NEXT: store i32 0, ptr [[P]], align 32
|
|
; 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) [ "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) [ "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 }
|