1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt -enable-new-pm=0 -domtree -assumption-cache-tracker -assume-simplify -verify --enable-knowledge-retention -S %s | FileCheck %s 3; RUN: opt -passes='require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s 4 5target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 6 7declare void @may_throw() 8declare void @llvm.assume(i1) 9 10define i32 @test1(i32* %0, i32* %1, i32 %2, i32 %3) { 11; CHECK-LABEL: define {{[^@]+}}@test1 12; CHECK-SAME: (i32* nonnull dereferenceable(4) [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) 13; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP2]], 4 14; CHECK-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[A:%.*]] 15; CHECK: 6: 16; CHECK-NEXT: [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] 17; CHECK-NEXT: call void @may_throw() 18; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[TMP0]], i64 4), "align"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]) ] 19; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4 20; CHECK-NEXT: [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] 21; CHECK-NEXT: store i32 0, i32* [[TMP0]], align 4 22; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4 23; CHECK-NEXT: [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] 24; CHECK-NEXT: call void @may_throw() 25; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "ignore"(i32* undef) ] 26; CHECK-NEXT: store i32 [[TMP11]], i32* [[TMP1]], align 4 27; CHECK-NEXT: br label [[B:%.*]] 28; CHECK: A: 29; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[TMP0]], i64 4), "ignore"(i32* undef, i64 4), "ignore"(i32* undef) ] 30; CHECK-NEXT: br label [[B]] 31; CHECK: B: 32; CHECK-NEXT: ret i32 0 33; 34 %5 = icmp ne i32 %2, 4 35 call void @llvm.assume(i1 true) ["dereferenceable"(i32* %0, i64 4), "nonnull"(i32* %0) ] 36 br i1 %5, label %6, label %A 37 386: ; preds = %4 39 %7 = add nsw i32 %3, %2 40 call void @may_throw() 41 %8 = load i32, i32* %0, align 4 42 %9 = add nsw i32 %7, %8 43 store i32 0, i32* %0, align 4 44 call void @llvm.assume(i1 true) [ "align"(i32* %0, i64 4), "dereferenceable"(i32* %0, i64 4) ] 45 %10 = load i32, i32* %1, align 4 46 %11 = add nsw i32 %9, %10 47 call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "nonnull"(i32* %1) ] 48 call void @may_throw() 49 call void @llvm.assume(i1 true) [ "dereferenceable"(i32* %1, i64 4), "nonnull"(i32* %1) ] 50 store i32 %11, i32* %1, align 4 51 br label %B 52 53A: 54 call void @llvm.assume(i1 true) [ "align"(i32* %0, i64 4), "dereferenceable"(i32* %0, i64 4), "nonnull"(i32* %0) ] 55 br label %B 56 57B: ; preds = %6, %4 58 ret i32 0 59} 60 61define i32 @test2(i32** %0, i32* %1, i32 %2, i32 %3) { 62; CHECK-LABEL: define {{[^@]+}}@test2 63; CHECK-SAME: (i32** [[TMP0:%.*]], i32* nonnull align 4 dereferenceable(4) [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) 64; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 0 65; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 4 66; CHECK-NEXT: [[TMP7:%.*]] = icmp ne i32 [[TMP6]], 0 67; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 0 68; CHECK-NEXT: br i1 [[TMP7]], label [[TMP9:%.*]], label [[TMP19:%.*]] 69; CHECK: 9: 70; CHECK-NEXT: call void @may_throw() 71; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[TMP8]], i64 4), "dereferenceable"(i32* [[TMP8]], i64 4), "nonnull"(i32* [[TMP8]]) ] 72; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP8]], align 4 73; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 2 74; CHECK-NEXT: store i32 [[TMP10]], i32* [[TMP11]], align 4 75; CHECK-NEXT: call void @may_throw() 76; CHECK-NEXT: call void @may_throw() 77; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 1 78; CHECK-NEXT: [[TMP13:%.*]] = load i32*, i32** [[TMP12]], align 8 79; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[TMP13]], i64 0 80; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 12), "align"(i32* [[TMP13]], i64 4), "dereferenceable"(i32* [[TMP13]], i64 4), "nonnull"(i32* [[TMP13]]) ] 81; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 82; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 1 83; CHECK-NEXT: [[TMP17:%.*]] = load i32*, i32** [[TMP16]], align 8 84; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i32, i32* [[TMP17]], i64 2 85; CHECK-NEXT: store i32 [[TMP15]], i32* [[TMP18]], align 4 86; CHECK-NEXT: call void @may_throw() 87; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ] 88; CHECK-NEXT: br label [[TMP35:%.*]] 89; CHECK: 19: 90; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 7 91; CHECK-NEXT: [[TMP21:%.*]] = load i32*, i32** [[TMP20]], align 8 92; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i32, i32* [[TMP21]], i64 0 93; CHECK-NEXT: [[TMP23:%.*]] = load i32, i32* [[TMP22]], align 4 94; CHECK-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 95; CHECK-NEXT: br i1 [[TMP24]], label [[TMP25:%.*]], label [[TMP33:%.*]] 96; CHECK: 25: 97; CHECK-NEXT: call void @may_throw() 98; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ] 99; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 2 100; CHECK-NEXT: [[TMP27:%.*]] = load i32*, i32** [[TMP26]], align 8 101; CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds i32, i32* [[TMP27]], i64 0 102; CHECK-NEXT: [[TMP29:%.*]] = load i32, i32* [[TMP28]], align 4 103; CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 2 104; CHECK-NEXT: [[TMP31:%.*]] = load i32*, i32** [[TMP30]], align 8 105; CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds i32, i32* [[TMP31]], i64 2 106; CHECK-NEXT: store i32 [[TMP29]], i32* [[TMP32]], align 4 107; CHECK-NEXT: call void @may_throw() 108; CHECK-NEXT: br label [[TMP33]] 109; CHECK: 33: 110; CHECK-NEXT: br label [[TMP34:%.*]] 111; CHECK: 34: 112; CHECK-NEXT: br label [[TMP35]] 113; CHECK: 35: 114; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ] 115; CHECK-NEXT: ret i32 0 116; 117 %5 = getelementptr inbounds i32, i32* %1, i64 0 118 %6 = load i32, i32* %5, align 4 119 %7 = icmp ne i32 %6, 0 120 call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "dereferenceable"(i32* %1, i64 4) ] 121 call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "nonnull"(i32* %1) ] 122 %8 = getelementptr inbounds i32, i32* %1, i64 0 123 br i1 %7, label %9, label %19 124 1259: ; preds = %4 126 call void @may_throw() 127 call void @llvm.assume(i1 true) [ "align"(i32* %8, i64 4), "dereferenceable"(i32* %8, i64 4), "nonnull"(i32* %8) ] 128 %10 = load i32, i32* %8, align 4 129 %11 = getelementptr inbounds i32, i32* %1, i64 2 130 store i32 %10, i32* %11, align 4 131 call void @may_throw() 132 call void @may_throw() 133 call void @llvm.assume(i1 true) [ "align"(i32* %11, i64 4), "dereferenceable"(i32* %11, i64 4), "nonnull"(i32* %11) ] 134 %12 = getelementptr inbounds i32*, i32** %0, i64 1 135 %13 = load i32*, i32** %12, align 8 136 %14 = getelementptr inbounds i32, i32* %13, i64 0 137 %15 = load i32, i32* %14, align 4 138 call void @llvm.assume(i1 true) [ "align"(i32* %14, i64 4), "dereferenceable"(i32* %14, i64 4), "nonnull"(i32* %14) ] 139 %16 = getelementptr inbounds i32*, i32** %0, i64 1 140 %17 = load i32*, i32** %16, align 8 141 %18 = getelementptr inbounds i32, i32* %17, i64 2 142 store i32 %15, i32* %18, align 4 143 call void @may_throw() 144 call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ] 145 br label %35 146 14719: ; preds = %4 148 %20 = getelementptr inbounds i32*, i32** %0, i64 7 149 %21 = load i32*, i32** %20, align 8 150 %22 = getelementptr inbounds i32, i32* %21, i64 0 151 %23 = load i32, i32* %22, align 4 152 %24 = icmp ne i32 %23, 0 153 br i1 %24, label %25, label %33 154 15525: ; preds = %19 156 call void @may_throw() 157 call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ] 158 %26 = getelementptr inbounds i32*, i32** %0, i64 2 159 %27 = load i32*, i32** %26, align 8 160 %28 = getelementptr inbounds i32, i32* %27, i64 0 161 %29 = load i32, i32* %28, align 4 162 %30 = getelementptr inbounds i32*, i32** %0, i64 2 163 %31 = load i32*, i32** %30, align 8 164 %32 = getelementptr inbounds i32, i32* %31, i64 2 165 store i32 %29, i32* %32, align 4 166 call void @may_throw() 167 br label %33 168 16933: ; preds = %25, %19 170 br label %34 171 17234: ; preds = %33 173 br label %35 174 17535: ; preds = %34, %8 176 call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ] 177 ret i32 0 178} 179 180define i32 @test3(i32* nonnull %p, i32 %i) { 181; CHECK-LABEL: define {{[^@]+}}@test3 182; CHECK-SAME: (i32* nonnull [[P:%.*]], i32 [[I:%.*]]) 183; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 184; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 185; CHECK: A: 186; CHECK-NEXT: ret i32 0 187; CHECK: B: 188; CHECK-NEXT: [[RET:%.*]] = load i32, i32* [[P]] 189; CHECK-NEXT: ret i32 [[RET]] 190; 191 %cond = icmp ne i32 %i, 0 192 call void @llvm.assume(i1 true) [ "nonnull"(i32* %p) ] 193 br i1 %cond, label %A, label %B 194A: 195 ret i32 0 196B: 197 %ret = load i32, i32* %p 198 ret i32 %ret 199} 200 201define i32 @test4(i32* %p, i32 %i) { 202; CHECK-LABEL: define {{[^@]+}}@test4 203; CHECK-SAME: (i32* nonnull dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) 204; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 205; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 206; CHECK: A: 207; CHECK-NEXT: ret i32 0 208; CHECK: B: 209; CHECK-NEXT: [[RET:%.*]] = load i32, i32* [[P]] 210; CHECK-NEXT: ret i32 [[RET]] 211; 212 %cond = icmp ne i32 %i, 0 213 call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ] 214 br i1 %cond, label %A, label %B 215A: 216 ret i32 0 217B: 218 %ret = load i32, i32* %p 219 ret i32 %ret 220} 221 222define i32 @test4A(i32* %p, i32 %i) { 223; CHECK-LABEL: define {{[^@]+}}@test4A 224; CHECK-SAME: (i32* [[P:%.*]], i32 [[I:%.*]]) 225; CHECK-NEXT: call void @may_throw() 226; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 227; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i32 32) ] 228; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 229; CHECK: A: 230; CHECK-NEXT: ret i32 0 231; CHECK: B: 232; CHECK-NEXT: [[RET:%.*]] = load i32, i32* [[P]] 233; CHECK-NEXT: ret i32 [[RET]] 234; 235 call void @may_throw() 236 %cond = icmp ne i32 %i, 0 237 call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ] 238 br i1 %cond, label %A, label %B 239A: 240 ret i32 0 241B: 242 %ret = load i32, i32* %p 243 ret i32 %ret 244} 245 246define i32 @test5(i32* dereferenceable(64) %p, i32 %i) { 247; CHECK-LABEL: define {{[^@]+}}@test5 248; CHECK-SAME: (i32* nonnull dereferenceable(64) [[P:%.*]], i32 [[I:%.*]]) 249; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 250; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 251; CHECK: A: 252; CHECK-NEXT: ret i32 0 253; CHECK: B: 254; CHECK-NEXT: [[RET:%.*]] = load i32, i32* [[P]] 255; CHECK-NEXT: ret i32 [[RET]] 256; 257 %cond = icmp ne i32 %i, 0 258 call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ] 259 br i1 %cond, label %A, label %B 260A: 261 ret i32 0 262B: 263 %ret = load i32, i32* %p 264 ret i32 %ret 265} 266 267 268define i32 @test5A(i32* dereferenceable(8) %p, i32 %i) { 269; CHECK-LABEL: define {{[^@]+}}@test5A 270; CHECK-SAME: (i32* dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) 271; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 272; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "ignore"(i32* undef, i32 32) ] 273; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 274; CHECK: A: 275; CHECK-NEXT: ret i32 0 276; CHECK: B: 277; CHECK-NEXT: [[RET:%.*]] = load i32, i32* [[P]] 278; CHECK-NEXT: ret i32 [[RET]] 279; 280 %cond = icmp ne i32 %i, 0 281 call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(i32* %p, i32 32) ] 282 br i1 %cond, label %A, label %B 283A: 284 ret i32 0 285B: 286 %ret = load i32, i32* %p 287 ret i32 %ret 288} 289 290define i32 @test6() { 291; CHECK-LABEL: define {{[^@]+}}@test6() 292; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] 293; CHECK-NEXT: call void @may_throw() 294; CHECK-NEXT: ret i32 0 295; 296 call void @llvm.assume(i1 true) [ "cold"() ] 297 call void @llvm.assume(i1 true) [ "cold"() ] 298 call void @may_throw() 299 call void @llvm.assume(i1 true) [ "cold"() ] 300 ret i32 0 301} 302 303define i32 @test7(i32* %p) { 304; CHECK-LABEL: define {{[^@]+}}@test7 305; CHECK-SAME: (i32* align 4 dereferenceable(4) [[P:%.*]]) 306; CHECK-NEXT: [[P1:%.*]] = bitcast i32* [[P]] to i8* 307; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "nonnull"(i32* [[P]]) ] 308; CHECK-NEXT: ret i32 0 309; 310 %p1 = bitcast i32* %p to i8* 311 call void @llvm.assume(i1 true) [ "cold"() ] 312 call void @llvm.assume(i1 true) [ "align"(i32* %p, i32 4) ] 313 call void @llvm.assume(i1 true) [ "dereferenceable"(i32* %p, i32 4) ] 314 call void @llvm.assume(i1 true) [ "align"(i8* %p1, i32 4), "nonnull"(i8* %p1) ] 315 ret i32 0 316} 317