1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt -passes='require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s 3 4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 5 6declare void @may_throw() 7 8declare void @llvm.assume(i1 noundef) #0 9 10define i32 @test1(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) { 11; CHECK-LABEL: define {{[^@]+}}@test1 12; CHECK-SAME: (ptr nonnull dereferenceable(4) [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { 13; CHECK-NEXT: bb: 14; CHECK-NEXT: [[I:%.*]] = icmp ne i32 [[ARG2]], 4 15; CHECK-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[A:%.*]] 16; CHECK: bb4: 17; CHECK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]] 18; CHECK-NEXT: call void @may_throw() 19; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "align"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]) ] 20; CHECK-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4 21; CHECK-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]] 22; CHECK-NEXT: store i32 0, ptr [[ARG]], align 4 23; CHECK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 24; CHECK-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]] 25; CHECK-NEXT: call void @may_throw() 26; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "ignore"(ptr poison) ] 27; CHECK-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4 28; CHECK-NEXT: br label [[B:%.*]] 29; CHECK: A: 30; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "ignore"(ptr poison, i64 4), "ignore"(ptr poison) ] 31; CHECK-NEXT: br label [[B]] 32; CHECK: B: 33; CHECK-NEXT: ret i32 0 34; 35bb: 36 %i = icmp ne i32 %arg2, 4 37 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] 38 br i1 %i, label %bb4, label %A 39 40bb4: ; preds = %bb 41 %i5 = add nsw i32 %arg3, %arg2 42 call void @may_throw() 43 %i6 = load i32, ptr %arg, align 4 44 %i7 = add nsw i32 %i5, %i6 45 store i32 0, ptr %arg, align 4 46 call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4) ] 47 %i8 = load i32, ptr %arg1, align 4 48 %i9 = add nsw i32 %i7, %i8 49 call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] 50 call void @may_throw() 51 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] 52 store i32 %i9, ptr %arg1, align 4 53 br label %B 54 55A: ; preds = %bb 56 call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] 57 br label %B 58 59B: ; preds = %A, %bb4 60 ret i32 0 61} 62 63define i32 @test2(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) { 64; CHECK-LABEL: define {{[^@]+}}@test2 65; CHECK-SAME: (ptr [[ARG:%.*]], ptr nonnull align 4 dereferenceable(4) [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) { 66; CHECK-NEXT: bb: 67; CHECK-NEXT: [[I4:%.*]] = load i32, ptr [[ARG1]], align 4 68; CHECK-NEXT: [[I5:%.*]] = icmp ne i32 [[I4]], 0 69; CHECK-NEXT: br i1 [[I5]], label [[BB7:%.*]], label [[BB17:%.*]] 70; CHECK: bb7: 71; CHECK-NEXT: call void @may_throw() 72; CHECK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4 73; CHECK-NEXT: [[I9:%.*]] = getelementptr inbounds i32, ptr [[ARG1]], i64 2 74; CHECK-NEXT: store i32 [[I8]], ptr [[I9]], align 4 75; CHECK-NEXT: call void @may_throw() 76; CHECK-NEXT: call void @may_throw() 77; CHECK-NEXT: [[I10:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1 78; CHECK-NEXT: [[I11:%.*]] = load ptr, ptr [[I10]], align 8 79; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 12), "align"(ptr [[I11]], i64 4), "dereferenceable"(ptr [[I11]], i64 4), "nonnull"(ptr [[I11]]) ] 80; CHECK-NEXT: [[I13:%.*]] = load i32, ptr [[I11]], align 4 81; CHECK-NEXT: [[I14:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1 82; CHECK-NEXT: [[I15:%.*]] = load ptr, ptr [[I14]], align 8 83; CHECK-NEXT: [[I16:%.*]] = getelementptr inbounds i32, ptr [[I15]], i64 2 84; CHECK-NEXT: store i32 [[I13]], ptr [[I16]], align 4 85; CHECK-NEXT: call void @may_throw() 86; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] 87; CHECK-NEXT: br label [[BB33:%.*]] 88; CHECK: bb17: 89; CHECK-NEXT: [[I18:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 7 90; CHECK-NEXT: [[I19:%.*]] = load ptr, ptr [[I18]], align 8 91; CHECK-NEXT: [[I21:%.*]] = load i32, ptr [[I19]], align 4 92; CHECK-NEXT: [[I22:%.*]] = icmp ne i32 [[I21]], 0 93; CHECK-NEXT: br i1 [[I22]], label [[BB23:%.*]], label [[BB31:%.*]] 94; CHECK: bb23: 95; CHECK-NEXT: call void @may_throw() 96; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] 97; CHECK-NEXT: [[I24:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2 98; CHECK-NEXT: [[I25:%.*]] = load ptr, ptr [[I24]], align 8 99; CHECK-NEXT: [[I27:%.*]] = load i32, ptr [[I25]], align 4 100; CHECK-NEXT: [[I28:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2 101; CHECK-NEXT: [[I29:%.*]] = load ptr, ptr [[I28]], align 8 102; CHECK-NEXT: [[I30:%.*]] = getelementptr inbounds i32, ptr [[I29]], i64 2 103; CHECK-NEXT: store i32 [[I27]], ptr [[I30]], align 4 104; CHECK-NEXT: call void @may_throw() 105; CHECK-NEXT: br label [[BB31]] 106; CHECK: bb31: 107; CHECK-NEXT: br label [[BB32:%.*]] 108; CHECK: bb32: 109; CHECK-NEXT: br label [[BB33]] 110; CHECK: bb33: 111; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ] 112; CHECK-NEXT: ret i32 0 113; 114bb: 115 %i4 = load i32, ptr %arg1, align 4 116 %i5 = icmp ne i32 %i4, 0 117 call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4) ] 118 call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] 119 br i1 %i5, label %bb7, label %bb17 120 121bb7: ; preds = %bb 122 call void @may_throw() 123 call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ] 124 %i8 = load i32, ptr %arg1, align 4 125 %i9 = getelementptr inbounds i32, ptr %arg1, i64 2 126 store i32 %i8, ptr %i9, align 4 127 call void @may_throw() 128 call void @may_throw() 129 call void @llvm.assume(i1 true) [ "align"(ptr %i9, i64 4), "dereferenceable"(ptr %i9, i64 4), "nonnull"(ptr %i9) ] 130 %i10 = getelementptr inbounds ptr, ptr %arg, i64 1 131 %i11 = load ptr, ptr %i10, align 8 132 %i13 = load i32, ptr %i11, align 4 133 call void @llvm.assume(i1 true) [ "align"(ptr %i11, i64 4), "dereferenceable"(ptr %i11, i64 4), "nonnull"(ptr %i11) ] 134 %i14 = getelementptr inbounds ptr, ptr %arg, i64 1 135 %i15 = load ptr, ptr %i14, align 8 136 %i16 = getelementptr inbounds i32, ptr %i15, i64 2 137 store i32 %i13, ptr %i16, align 4 138 call void @may_throw() 139 call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] 140 br label %bb33 141 142bb17: ; preds = %bb 143 %i18 = getelementptr inbounds ptr, ptr %arg, i64 7 144 %i19 = load ptr, ptr %i18, align 8 145 %i21 = load i32, ptr %i19, align 4 146 %i22 = icmp ne i32 %i21, 0 147 br i1 %i22, label %bb23, label %bb31 148 149bb23: ; preds = %bb17 150 call void @may_throw() 151 call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] 152 %i24 = getelementptr inbounds ptr, ptr %arg, i64 2 153 %i25 = load ptr, ptr %i24, align 8 154 %i27 = load i32, ptr %i25, align 4 155 %i28 = getelementptr inbounds ptr, ptr %arg, i64 2 156 %i29 = load ptr, ptr %i28, align 8 157 %i30 = getelementptr inbounds i32, ptr %i29, i64 2 158 store i32 %i27, ptr %i30, align 4 159 call void @may_throw() 160 br label %bb31 161 162bb31: ; preds = %bb23, %bb17 163 br label %bb32 164 165bb32: ; preds = %bb31 166 br label %bb33 167 168bb33: ; preds = %bb32, %bb7 169 call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ] 170 ret i32 0 171} 172 173define i32 @test3(ptr nonnull %p, i32 %i) { 174; CHECK-LABEL: define {{[^@]+}}@test3 175; CHECK-SAME: (ptr nonnull [[P:%.*]], i32 [[I:%.*]]) { 176; CHECK-NEXT: bb: 177; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 178; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 179; CHECK: A: 180; CHECK-NEXT: ret i32 0 181; CHECK: B: 182; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 183; CHECK-NEXT: ret i32 [[RET]] 184; 185bb: 186 %cond = icmp ne i32 %i, 0 187 call void @llvm.assume(i1 true) [ "nonnull"(ptr %p) ] 188 br i1 %cond, label %A, label %B 189 190A: ; preds = %bb 191 ret i32 0 192 193B: ; preds = %bb 194 %ret = load i32, ptr %p, align 4 195 ret i32 %ret 196} 197 198define i32 @test4(ptr %p, i32 %i) { 199; CHECK-LABEL: define {{[^@]+}}@test4 200; CHECK-SAME: (ptr nonnull dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) { 201; CHECK-NEXT: bb: 202; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 203; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 204; CHECK: A: 205; CHECK-NEXT: ret i32 0 206; CHECK: B: 207; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 208; CHECK-NEXT: ret i32 [[RET]] 209; 210bb: 211 %cond = icmp ne i32 %i, 0 212 call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] 213 br i1 %cond, label %A, label %B 214 215A: ; preds = %bb 216 ret i32 0 217 218B: ; preds = %bb 219 %ret = load i32, ptr %p, align 4 220 ret i32 %ret 221} 222 223define i32 @test4A(ptr %p, i32 %i) { 224; CHECK-LABEL: define {{[^@]+}}@test4A 225; CHECK-SAME: (ptr [[P:%.*]], i32 [[I:%.*]]) { 226; CHECK-NEXT: bb: 227; CHECK-NEXT: call void @may_throw() 228; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 229; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i32 32) ] 230; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 231; CHECK: A: 232; CHECK-NEXT: ret i32 0 233; CHECK: B: 234; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 235; CHECK-NEXT: ret i32 [[RET]] 236; 237bb: 238 call void @may_throw() 239 %cond = icmp ne i32 %i, 0 240 call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] 241 br i1 %cond, label %A, label %B 242 243A: ; preds = %bb 244 ret i32 0 245 246B: ; preds = %bb 247 %ret = load i32, ptr %p, align 4 248 ret i32 %ret 249} 250 251define i32 @test5(ptr dereferenceable(64) %p, i32 %i) { 252; CHECK-LABEL: define {{[^@]+}}@test5 253; CHECK-SAME: (ptr nonnull dereferenceable(64) [[P:%.*]], i32 [[I:%.*]]) { 254; CHECK-NEXT: bb: 255; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 256; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 257; CHECK: A: 258; CHECK-NEXT: ret i32 0 259; CHECK: B: 260; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 261; CHECK-NEXT: ret i32 [[RET]] 262; 263bb: 264 %cond = icmp ne i32 %i, 0 265 call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ] 266 br i1 %cond, label %A, label %B 267 268A: ; preds = %bb 269 ret i32 0 270 271B: ; preds = %bb 272 %ret = load i32, ptr %p, align 4 273 ret i32 %ret 274} 275 276define i32 @test5A(ptr dereferenceable(8) %p, i32 %i) { 277; CHECK-LABEL: define {{[^@]+}}@test5A 278; CHECK-SAME: (ptr dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) { 279; CHECK-NEXT: bb: 280; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[I]], 0 281; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "ignore"(ptr poison, i32 32) ] 282; CHECK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]] 283; CHECK: A: 284; CHECK-NEXT: ret i32 0 285; CHECK: B: 286; CHECK-NEXT: [[RET:%.*]] = load i32, ptr [[P]], align 4 287; CHECK-NEXT: ret i32 [[RET]] 288; 289bb: 290 %cond = icmp ne i32 %i, 0 291 call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(ptr %p, i32 32) ] 292 br i1 %cond, label %A, label %B 293 294A: ; preds = %bb 295 ret i32 0 296 297B: ; preds = %bb 298 %ret = load i32, ptr %p, align 4 299 ret i32 %ret 300} 301 302define i32 @test6() { 303; CHECK-LABEL: define {{[^@]+}}@test6() { 304; CHECK-NEXT: bb: 305; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] 306; CHECK-NEXT: call void @may_throw() 307; CHECK-NEXT: ret i32 0 308; 309bb: 310 call void @llvm.assume(i1 true) [ "cold"() ] 311 call void @llvm.assume(i1 true) [ "cold"() ] 312 call void @may_throw() 313 call void @llvm.assume(i1 true) [ "cold"() ] 314 ret i32 0 315} 316 317define i32 @test7(ptr %p) { 318; CHECK-LABEL: define {{[^@]+}}@test7 319; CHECK-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]]) { 320; CHECK-NEXT: bb: 321; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ] 322; CHECK-NEXT: ret i32 0 323; 324bb: 325 call void @llvm.assume(i1 true) [ "cold"() ] 326 call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4) ] 327 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i32 4) ] 328 call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4), "nonnull"(ptr %p) ] 329 ret i32 0 330} 331 332attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } 333