1; REQUIRES: aarch64-registered-target 2 3; RUN: llvm-as %s -o %t0.bc 4; RUN: llvm-as %S/Inputs/ipa.ll -o %t1.bc 5; RUN: llvm-link -disable-lazy-loading %t0.bc %t1.bc -o %t.combined.bc 6 7; RUN: opt -S -analyze -stack-safety-local %t.combined.bc | FileCheck %s --check-prefixes=CHECK,LOCAL 8; RUN: opt -S -passes="print<stack-safety-local>" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL 9 10; RUN: opt -S -analyze -stack-safety %t.combined.bc | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO 11; RUN: opt -S -passes="print-stack-safety" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO 12 13; Do an end-to-test using the new LTO API 14; TODO: Hideous llvm-lto2 invocation, add a --default-symbol-resolution to llvm-lto2? 15; RUN: opt -module-summary %s -o %t.summ0.bc 16; RUN: opt -module-summary %S/Inputs/ipa.ll -o %t.summ1.bc 17 18; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \ 19; RUN: -r %t.summ0.bc,Write1, \ 20; RUN: -r %t.summ0.bc,Write4, \ 21; RUN: -r %t.summ0.bc,Write4_2, \ 22; RUN: -r %t.summ0.bc,Write8, \ 23; RUN: -r %t.summ0.bc,WriteAndReturn8, \ 24; RUN: -r %t.summ0.bc,TestUpdateArg,px \ 25; RUN: -r %t.summ0.bc,ExternalCall, \ 26; RUN: -r %t.summ0.bc,PreemptableWrite1, \ 27; RUN: -r %t.summ0.bc,InterposableWrite1, \ 28; RUN: -r %t.summ0.bc,ReturnDependent, \ 29; RUN: -r %t.summ0.bc,Rec2, \ 30; RUN: -r %t.summ0.bc,RecursiveNoOffset, \ 31; RUN: -r %t.summ0.bc,RecursiveWithOffset, \ 32; RUN: -r %t.summ0.bc,f1,px \ 33; RUN: -r %t.summ0.bc,f2,px \ 34; RUN: -r %t.summ0.bc,f3,px \ 35; RUN: -r %t.summ0.bc,f4,px \ 36; RUN: -r %t.summ0.bc,f5,px \ 37; RUN: -r %t.summ0.bc,f6,px \ 38; RUN: -r %t.summ0.bc,PreemptableCall,px \ 39; RUN: -r %t.summ0.bc,InterposableCall,px \ 40; RUN: -r %t.summ0.bc,PrivateCall,px \ 41; RUN: -r %t.summ0.bc,f7,px \ 42; RUN: -r %t.summ0.bc,f8left,px \ 43; RUN: -r %t.summ0.bc,f8right,px \ 44; RUN: -r %t.summ0.bc,f8oobleft,px \ 45; RUN: -r %t.summ0.bc,f8oobright,px \ 46; RUN: -r %t.summ0.bc,TwoArguments,px \ 47; RUN: -r %t.summ0.bc,TwoArgumentsOOBOne,px \ 48; RUN: -r %t.summ0.bc,TwoArgumentsOOBOther,px \ 49; RUN: -r %t.summ0.bc,TwoArgumentsOOBBoth,px \ 50; RUN: -r %t.summ0.bc,TestRecursiveNoOffset,px \ 51; RUN: -r %t.summ0.bc,TestRecursiveWithOffset,px \ 52; RUN: -r %t.summ1.bc,Write1,px \ 53; RUN: -r %t.summ1.bc,Write4,px \ 54; RUN: -r %t.summ1.bc,Write4_2,px \ 55; RUN: -r %t.summ1.bc,Write8,px \ 56; RUN: -r %t.summ1.bc,WriteAndReturn8,px \ 57; RUN: -r %t.summ1.bc,ExternalCall,px \ 58; RUN: -r %t.summ1.bc,PreemptableWrite1,px \ 59; RUN: -r %t.summ1.bc,InterposableWrite1,px \ 60; RUN: -r %t.summ1.bc,ReturnDependent,px \ 61; RUN: -r %t.summ1.bc,Rec0,px \ 62; RUN: -r %t.summ1.bc,Rec1,px \ 63; RUN: -r %t.summ1.bc,Rec2,px \ 64; RUN: -r %t.summ1.bc,RecursiveNoOffset,px \ 65; RUN: -r %t.summ1.bc,RecursiveWithOffset,px \ 66; RUN: -r %t.summ1.bc,ReturnAlloca,px 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO 67 68; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t-newpm.lto -use-new-pm -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \ 69; RUN: -r %t.summ0.bc,Write1, \ 70; RUN: -r %t.summ0.bc,Write4, \ 71; RUN: -r %t.summ0.bc,Write4_2, \ 72; RUN: -r %t.summ0.bc,Write8, \ 73; RUN: -r %t.summ0.bc,WriteAndReturn8, \ 74; RUN: -r %t.summ0.bc,TestUpdateArg,px \ 75; RUN: -r %t.summ0.bc,ExternalCall, \ 76; RUN: -r %t.summ0.bc,PreemptableWrite1, \ 77; RUN: -r %t.summ0.bc,InterposableWrite1, \ 78; RUN: -r %t.summ0.bc,ReturnDependent, \ 79; RUN: -r %t.summ0.bc,Rec2, \ 80; RUN: -r %t.summ0.bc,RecursiveNoOffset, \ 81; RUN: -r %t.summ0.bc,RecursiveWithOffset, \ 82; RUN: -r %t.summ0.bc,f1,px \ 83; RUN: -r %t.summ0.bc,f2,px \ 84; RUN: -r %t.summ0.bc,f3,px \ 85; RUN: -r %t.summ0.bc,f4,px \ 86; RUN: -r %t.summ0.bc,f5,px \ 87; RUN: -r %t.summ0.bc,f6,px \ 88; RUN: -r %t.summ0.bc,PreemptableCall,px \ 89; RUN: -r %t.summ0.bc,InterposableCall,px \ 90; RUN: -r %t.summ0.bc,PrivateCall,px \ 91; RUN: -r %t.summ0.bc,f7,px \ 92; RUN: -r %t.summ0.bc,f8left,px \ 93; RUN: -r %t.summ0.bc,f8right,px \ 94; RUN: -r %t.summ0.bc,f8oobleft,px \ 95; RUN: -r %t.summ0.bc,f8oobright,px \ 96; RUN: -r %t.summ0.bc,TwoArguments,px \ 97; RUN: -r %t.summ0.bc,TwoArgumentsOOBOne,px \ 98; RUN: -r %t.summ0.bc,TwoArgumentsOOBOther,px \ 99; RUN: -r %t.summ0.bc,TwoArgumentsOOBBoth,px \ 100; RUN: -r %t.summ0.bc,TestRecursiveNoOffset,px \ 101; RUN: -r %t.summ0.bc,TestRecursiveWithOffset,px \ 102; RUN: -r %t.summ1.bc,Write1,px \ 103; RUN: -r %t.summ1.bc,Write4,px \ 104; RUN: -r %t.summ1.bc,Write4_2,px \ 105; RUN: -r %t.summ1.bc,Write8,px \ 106; RUN: -r %t.summ1.bc,WriteAndReturn8,px \ 107; RUN: -r %t.summ1.bc,ExternalCall,px \ 108; RUN: -r %t.summ1.bc,PreemptableWrite1,px \ 109; RUN: -r %t.summ1.bc,InterposableWrite1,px \ 110; RUN: -r %t.summ1.bc,ReturnDependent,px \ 111; RUN: -r %t.summ1.bc,Rec0,px \ 112; RUN: -r %t.summ1.bc,Rec1,px \ 113; RUN: -r %t.summ1.bc,Rec2,px \ 114; RUN: -r %t.summ1.bc,RecursiveNoOffset,px \ 115; RUN: -r %t.summ1.bc,RecursiveWithOffset,px \ 116; RUN: -r %t.summ1.bc,ReturnAlloca,px 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO 117 118target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 119target triple = "aarch64-unknown-linux" 120 121attributes #0 = { noinline sanitize_memtag "target-features"="+mte,+neon" } 122 123declare void @Write1(i8* %p) 124declare void @Write4(i8* %p) 125declare void @Write4_2(i8* %p, i8* %q) 126declare void @Write8(i8* %p) 127declare dso_local i8* @WriteAndReturn8(i8* %p) 128declare dso_local void @ExternalCall(i8* %p) 129declare void @PreemptableWrite1(i8* %p) 130declare void @InterposableWrite1(i8* %p) 131declare i8* @ReturnDependent(i8* %p) 132declare void @Rec2(i8* %p) 133declare void @RecursiveNoOffset(i32* %p, i32 %size, i32* %acc) 134declare void @RecursiveWithOffset(i32 %size, i32* %acc) 135 136; Basic out-of-bounds. 137define void @f1() #0 { 138; CHECK-LABEL: @f1 dso_preemptable{{$}} 139; CHECK-NEXT: args uses: 140; CHECK-NEXT: allocas uses: 141; LOCAL-NEXT: x[4]: empty-set, @Write8(arg0, [0,1)){{$}} 142; GLOBAL-NEXT: x[4]: [0,8), @Write8(arg0, [0,1)){{$}} 143; CHECK-NOT: ]: 144entry: 145 %x = alloca i32, align 4 146 %x1 = bitcast i32* %x to i8* 147 call void @Write8(i8* %x1) 148 ret void 149} 150 151; Basic in-bounds. 152define void @f2() #0 { 153; CHECK-LABEL: @f2 dso_preemptable{{$}} 154; CHECK-NEXT: args uses: 155; CHECK-NEXT: allocas uses: 156; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [0,1)){{$}} 157; GLOBAL-NEXT: x[4]: [0,1), @Write1(arg0, [0,1)){{$}} 158; CHECK-NOT: ]: 159entry: 160 %x = alloca i32, align 4 161 %x1 = bitcast i32* %x to i8* 162 call void @Write1(i8* %x1) 163 ret void 164} 165 166; Another basic in-bounds. 167define void @f3() #0 { 168; CHECK-LABEL: @f3 dso_preemptable{{$}} 169; CHECK-NEXT: args uses: 170; CHECK-NEXT: allocas uses: 171; LOCAL-NEXT: x[4]: empty-set, @Write4(arg0, [0,1)){{$}} 172; GLOBAL-NEXT: x[4]: [0,4), @Write4(arg0, [0,1)){{$}} 173; CHECK-NOT: ]: 174entry: 175 %x = alloca i32, align 4 176 %x1 = bitcast i32* %x to i8* 177 call void @Write4(i8* %x1) 178 ret void 179} 180 181; In-bounds with offset. 182define void @f4() #0 { 183; CHECK-LABEL: @f4 dso_preemptable{{$}} 184; CHECK-NEXT: args uses: 185; CHECK-NEXT: allocas uses: 186; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [1,2)){{$}} 187; GLOBAL-NEXT: x[4]: [1,2), @Write1(arg0, [1,2)){{$}} 188; CHECK-NOT: ]: 189entry: 190 %x = alloca i32, align 4 191 %x1 = bitcast i32* %x to i8* 192 %x2 = getelementptr i8, i8* %x1, i64 1 193 call void @Write1(i8* %x2) 194 ret void 195} 196 197; Out-of-bounds with offset. 198define void @f5() #0 { 199; CHECK-LABEL: @f5 dso_preemptable{{$}} 200; CHECK-NEXT: args uses: 201; CHECK-NEXT: allocas uses: 202; LOCAL-NEXT: empty-set, @Write4(arg0, [1,2)){{$}} 203; GLOBAL-NEXT: [1,5), @Write4(arg0, [1,2)){{$}} 204; CHECK-NOT: ]: 205entry: 206 %x = alloca i32, align 4 207 %x1 = bitcast i32* %x to i8* 208 %x2 = getelementptr i8, i8* %x1, i64 1 209 call void @Write4(i8* %x2) 210 ret void 211} 212 213; External call. 214define void @f6() #0 { 215; CHECK-LABEL: @f6 dso_preemptable{{$}} 216; CHECK-NEXT: args uses: 217; CHECK-NEXT: allocas uses: 218; LOCAL-NEXT: x[4]: empty-set, @ExternalCall(arg0, [0,1)){{$}} 219; GLOBAL-NEXT: x[4]: full-set, @ExternalCall(arg0, [0,1)){{$}} 220; CHECK-NOT: ]: 221entry: 222 %x = alloca i32, align 4 223 %x1 = bitcast i32* %x to i8* 224 call void @ExternalCall(i8* %x1) 225 ret void 226} 227 228; Call to dso_preemptable function 229define void @PreemptableCall() #0 { 230; CHECK-LABEL: @PreemptableCall dso_preemptable{{$}} 231; CHECK-NEXT: args uses: 232; CHECK-NEXT: allocas uses: 233; LOCAL-NEXT: x[4]: empty-set, @PreemptableWrite1(arg0, [0,1)){{$}} 234; GLOBAL-NEXT: x[4]: full-set, @PreemptableWrite1(arg0, [0,1)){{$}} 235; CHECK-NOT: ]: 236entry: 237 %x = alloca i32, align 4 238 %x1 = bitcast i32* %x to i8* 239 call void @PreemptableWrite1(i8* %x1) 240 ret void 241} 242 243; Call to function with interposable linkage 244define void @InterposableCall() #0 { 245; CHECK-LABEL: @InterposableCall dso_preemptable{{$}} 246; CHECK-NEXT: args uses: 247; CHECK-NEXT: allocas uses: 248; LOCAL-NEXT: x[4]: empty-set, @InterposableWrite1(arg0, [0,1)){{$}} 249; NOLTO-NEXT: x[4]: full-set, @InterposableWrite1(arg0, [0,1)){{$}} 250; LTO-NEXT: x[4]: [0,1), @InterposableWrite1(arg0, [0,1)){{$}} 251; CHECK-NOT: ]: 252entry: 253 %x = alloca i32, align 4 254 %x1 = bitcast i32* %x to i8* 255 call void @InterposableWrite1(i8* %x1) 256 ret void 257} 258 259; Call to function with private linkage 260define void @PrivateCall() #0 { 261; CHECK-LABEL: @PrivateCall dso_preemptable{{$}} 262; CHECK-NEXT: args uses: 263; CHECK-NEXT: allocas uses: 264; LOCAL-NEXT: x[4]: empty-set, @PrivateWrite1(arg0, [0,1)){{$}} 265; GLOBAL-NEXT: x[4]: [0,1), @PrivateWrite1(arg0, [0,1)){{$}} 266; CHECK-NOT: ]: 267entry: 268 %x = alloca i32, align 4 269 %x1 = bitcast i32* %x to i8* 270 call void @PrivateWrite1(i8* %x1) 271 ret void 272} 273 274define private void @PrivateWrite1(i8* %p) #0 { 275; CHECK-LABEL: @PrivateWrite1{{$}} 276; CHECK-NEXT: args uses: 277; CHECK-NEXT: p[]: [0,1){{$}} 278; CHECK-NEXT: allocas uses: 279; CHECK-NOT: ]: 280entry: 281 store i8 0, i8* %p, align 1 282 ret void 283} 284 285; Caller returns a dependent value. 286; FIXME: alloca considered unsafe even if the return value is unused. 287define void @f7() #0 { 288; CHECK-LABEL: @f7 dso_preemptable{{$}} 289; CHECK-NEXT: args uses: 290; CHECK-NEXT: allocas uses: 291; LOCAL-NEXT: x[4]: empty-set, @ReturnDependent(arg0, [0,1)){{$}} 292; GLOBAL-NEXT: x[4]: full-set, @ReturnDependent(arg0, [0,1)){{$}} 293; CHECK-NOT: ]: 294entry: 295 %x = alloca i32, align 4 296 %x1 = bitcast i32* %x to i8* 297 %x2 = call i8* @ReturnDependent(i8* %x1) 298 ret void 299} 300 301define void @f8left() #0 { 302; CHECK-LABEL: @f8left dso_preemptable{{$}} 303; CHECK-NEXT: args uses: 304; CHECK-NEXT: allocas uses: 305; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [2,3)){{$}} 306; GLOBAL-NEXT: x[8]: [0,4), @Rec2(arg0, [2,3)){{$}} 307; CHECK-NOT: ]: 308entry: 309 %x = alloca i64, align 4 310 %x1 = bitcast i64* %x to i8* 311 %x2 = getelementptr i8, i8* %x1, i64 2 312; 2 + [-2, 2) = [0, 4) => OK 313 call void @Rec2(i8* %x2) 314 ret void 315} 316 317define void @f8right() #0 { 318; CHECK-LABEL: @f8right dso_preemptable{{$}} 319; CHECK-NEXT: args uses: 320; CHECK-NEXT: allocas uses: 321; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [6,7)){{$}} 322; GLOBAL-NEXT: x[8]: [4,8), @Rec2(arg0, [6,7)){{$}} 323; CHECK-NOT: ]: 324entry: 325 %x = alloca i64, align 4 326 %x1 = bitcast i64* %x to i8* 327 %x2 = getelementptr i8, i8* %x1, i64 6 328; 6 + [-2, 2) = [4, 8) => OK 329 call void @Rec2(i8* %x2) 330 ret void 331} 332 333define void @f8oobleft() #0 { 334; CHECK-LABEL: @f8oobleft dso_preemptable{{$}} 335; CHECK-NEXT: args uses: 336; CHECK-NEXT: allocas uses: 337; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [1,2)){{$}} 338; GLOBAL-NEXT: x[8]: [-1,3), @Rec2(arg0, [1,2)){{$}} 339; CHECK-NOT: ]: 340entry: 341 %x = alloca i64, align 4 342 %x1 = bitcast i64* %x to i8* 343 %x2 = getelementptr i8, i8* %x1, i64 1 344; 1 + [-2, 2) = [-1, 3) => NOT OK 345 call void @Rec2(i8* %x2) 346 ret void 347} 348 349define void @f8oobright() #0 { 350; CHECK-LABEL: @f8oobright dso_preemptable{{$}} 351; CHECK-NEXT: args uses: 352; CHECK-NEXT: allocas uses: 353; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [7,8)){{$}} 354; GLOBAL-NEXT: x[8]: [5,9), @Rec2(arg0, [7,8)){{$}} 355; CHECK-NOT: ]: 356entry: 357 %x = alloca i64, align 4 358 %x1 = bitcast i64* %x to i8* 359 %x2 = getelementptr i8, i8* %x1, i64 7 360; 7 + [-2, 2) = [5, 9) => NOT OK 361 call void @Rec2(i8* %x2) 362 ret void 363} 364 365define void @TwoArguments() #0 { 366; CHECK-LABEL: @TwoArguments dso_preemptable{{$}} 367; CHECK-NEXT: args uses: 368; CHECK-NEXT: allocas uses: 369; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}} 370; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}} 371; CHECK-NOT: ]: 372entry: 373 %x = alloca i64, align 4 374 %x1 = bitcast i64* %x to i8* 375 %x2 = getelementptr i8, i8* %x1, i64 4 376 call void @Write4_2(i8* %x2, i8* %x1) 377 ret void 378} 379 380define void @TwoArgumentsOOBOne() #0 { 381; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}} 382; CHECK-NEXT: args uses: 383; CHECK-NEXT: allocas uses: 384; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}} 385; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}} 386; CHECK-NOT: ]: 387entry: 388 %x = alloca i64, align 4 389 %x1 = bitcast i64* %x to i8* 390 %x2 = getelementptr i8, i8* %x1, i64 5 391 call void @Write4_2(i8* %x2, i8* %x1) 392 ret void 393} 394 395define void @TwoArgumentsOOBOther() #0 { 396; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}} 397; CHECK-NEXT: args uses: 398; CHECK-NEXT: allocas uses: 399; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}} 400; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}} 401; CHECK-NOT: ]: 402entry: 403 %x = alloca i64, align 4 404 %x0 = bitcast i64* %x to i8* 405 %x1 = getelementptr i8, i8* %x0, i64 -1 406 %x2 = getelementptr i8, i8* %x0, i64 4 407 call void @Write4_2(i8* %x2, i8* %x1) 408 ret void 409} 410 411define void @TwoArgumentsOOBBoth() #0 { 412; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}} 413; CHECK-NEXT: args uses: 414; CHECK-NEXT: allocas uses: 415; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}} 416; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}} 417; CHECK-NOT: ]: 418entry: 419 %x = alloca i64, align 4 420 %x0 = bitcast i64* %x to i8* 421 %x1 = getelementptr i8, i8* %x0, i64 -1 422 %x2 = getelementptr i8, i8* %x0, i64 5 423 call void @Write4_2(i8* %x2, i8* %x1) 424 ret void 425} 426 427define i32 @TestRecursiveNoOffset(i32* %p, i32 %size) #0 { 428; CHECK-LABEL: @TestRecursiveNoOffset dso_preemptable{{$}} 429; CHECK-NEXT: args uses: 430; LOCAL-NEXT: p[]: empty-set, @RecursiveNoOffset(arg0, [0,1)){{$}} 431; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [0,1)){{$}} 432; CHECK-NEXT: allocas uses: 433; CHECK-NEXT: sum[4]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}} 434; CHECK-NOT: ]: 435entry: 436 %sum = alloca i32, align 4 437 %0 = bitcast i32* %sum to i8* 438 store i32 0, i32* %sum, align 4 439 call void @RecursiveNoOffset(i32* %p, i32 %size, i32* %sum) 440 %1 = load i32, i32* %sum, align 4 441 ret i32 %1 442} 443 444define void @TestRecursiveWithOffset(i32 %size) #0 { 445; CHECK-LABEL: @TestRecursiveWithOffset dso_preemptable{{$}} 446; CHECK-NEXT: args uses: 447; CHECK-NEXT: allocas uses: 448; LOCAL-NEXT: sum[64]: empty-set, @RecursiveWithOffset(arg1, [0,1)){{$}} 449; GLOBAL-NEXT: sum[64]: full-set, @RecursiveWithOffset(arg1, [0,1)){{$}} 450; CHECK-NOT: ]: 451entry: 452 %sum = alloca i32, i64 16, align 4 453 call void @RecursiveWithOffset(i32 %size, i32* %sum) 454 ret void 455} 456 457; FIXME: IPA should detect that access is safe 458define void @TestUpdateArg() #0 { 459; CHECK-LABEL: @TestUpdateArg dso_preemptable{{$}} 460; CHECK-NEXT: args uses: 461; CHECK-NEXT: allocas uses: 462; LOCAL-NEXT: x[16]: empty-set, @WriteAndReturn8(arg0, [0,1)){{$}} 463; GLOBAL-NEXT: x[16]: full-set, @WriteAndReturn8(arg0, [0,1)){{$}} 464; CHECK-NOT: ]: 465entry: 466 %x = alloca i8, i64 16, align 4 467 %0 = call i8* @WriteAndReturn8(i8* %x) 468 ret void 469} 470 471; The rest is from Inputs/ipa.ll 472 473; CHECK-LABEL: @Write1{{$}} 474; CHECK-NEXT: args uses: 475; CHECK-NEXT: p[]: [0,1){{$}} 476; CHECK-NEXT: allocas uses: 477; CHECK-NOT: ]: 478 479; CHECK-LABEL: @Write4{{$}} 480; CHECK-NEXT: args uses: 481; CHECK-NEXT: p[]: [0,4){{$}} 482; CHECK-NEXT: allocas uses: 483; CHECK-NOT: ]: 484 485; CHECK-LABEL: @Write4_2{{$}} 486; CHECK-NEXT: args uses: 487; CHECK-NEXT: p[]: [0,4){{$}} 488; CHECK-NEXT: q[]: [0,4){{$}} 489; CHECK-NEXT: allocas uses: 490; CHECK-NOT: ]: 491 492; CHECK-LABEL: @Write8{{$}} 493; CHECK-NEXT: args uses: 494; CHECK-NEXT: p[]: [0,8){{$}} 495; CHECK-NEXT: allocas uses: 496; CHECK-NOT: ]: 497 498; CHECK-LABEL: @WriteAndReturn8{{$}} 499; CHECK-NEXT: args uses: 500; CHECK-NEXT: p[]: full-set{{$}} 501; CHECK-NEXT: allocas uses: 502; CHECK-NOT: ]: 503 504; CHECK-LABEL: @PreemptableWrite1 dso_preemptable{{$}} 505; CHECK-NEXT: args uses: 506; CHECK-NEXT: p[]: [0,1){{$}} 507; CHECK-NEXT: allocas uses: 508; CHECK-NOT: ]: 509 510; CHECK-LABEL: @InterposableWrite1 interposable{{$}} 511; CHECK-NEXT: args uses: 512; CHECK-NEXT: p[]: [0,1){{$}} 513; CHECK-NEXT: allocas uses: 514; CHECK-NOT: ]: 515 516; CHECK-LABEL: @ReturnDependent{{$}} 517; CHECK-NEXT: args uses: 518; CHECK-NEXT: p[]: full-set{{$}} 519; CHECK-NEXT: allocas uses: 520; CHECK-NOT: ]: 521 522; CHECK-LABEL: @Rec0{{$}} 523; CHECK-NEXT: args uses: 524; LOCAL-NEXT: p[]: empty-set, @Write4(arg0, [2,3)){{$}} 525; GLOBAL-NEXT: p[]: [2,6) 526; CHECK-NEXT: allocas uses: 527; CHECK-NOT: ]: 528 529; CHECK-LABEL: @Rec1{{$}} 530; CHECK-NEXT: args uses: 531; LOCAL-NEXT: p[]: empty-set, @Rec0(arg0, [1,2)){{$}} 532; GLOBAL-NEXT: p[]: [3,7) 533; CHECK-NEXT: allocas uses: 534; CHECK-NOT: ]: 535 536; CHECK-LABEL: @Rec2{{$}} 537; CHECK-NEXT: args uses: 538; LOCAL-NEXT: p[]: empty-set, @Rec1(arg0, [-5,-4)){{$}} 539; GLOBAL-NEXT: p[]: [-2,2) 540; CHECK-NEXT: allocas uses: 541; CHECK-NOT: ]: 542 543; CHECK-LABEL: @RecursiveNoOffset{{$}} 544; CHECK-NEXT: args uses: 545; LOCAL-NEXT: p[]: [0,4), @RecursiveNoOffset(arg0, [4,5)){{$}} 546; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [4,5)){{$}} 547; CHECK-NEXT: acc[]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}} 548; CHECK-NEXT: allocas uses: 549; CHECK-NOT: ]: 550 551; CHECK-LABEL: @RecursiveWithOffset{{$}} 552; CHECK-NEXT: args uses: 553; LOCAL-NEXT: acc[]: [0,4), @RecursiveWithOffset(arg1, [4,5)){{$}} 554; GLOBAL-NEXT: acc[]: full-set, @RecursiveWithOffset(arg1, [4,5)){{$}} 555; CHECK-NEXT: allocas uses: 556; CHECK-NOT: ]: 557 558; CHECK-LABEL: @ReturnAlloca 559; CHECK-NEXT: args uses: 560; CHECK-NEXT: allocas uses: 561; CHECK-NEXT: x[8]: full-set 562; CHECK-NOT: ]: 563