1; REQUIRES: aarch64-registered-target 2; REQUIRES: shell 3 4; RUN: llvm-as %s -o %t0.bc 5; RUN: llvm-as %S/Inputs/ipa.ll -o %t1.bc 6; RUN: llvm-link -disable-lazy-loading %t0.bc %t1.bc -o %t.combined.bc 7 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 -passes="print-stack-safety" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO 11 12; Do an end-to-test using the new LTO API 13; TODO: Hideous llvm-lto2 invocation, add a --default-symbol-resolution to llvm-lto2? 14; RUN: opt -module-summary %s -o %t.summ0.bc 15; RUN: opt -module-summary %S/Inputs/ipa.ll -o %t.summ1.bc 16 17; RUN: llvm-dis %t.summ0.bc -o - > %t.ids.txt 18; RUN: llvm-dis %t.summ1.bc -o - >> %t.ids.txt 19 20; RUN: echo > %t.res.txt \ 21; RUN: -r %t.summ0.bc,ExternalCall, \ 22; RUN: -r %t.summ0.bc,f1,px \ 23; RUN: -r %t.summ0.bc,f2,px \ 24; RUN: -r %t.summ0.bc,f3,px \ 25; RUN: -r %t.summ0.bc,f4,px \ 26; RUN: -r %t.summ0.bc,f5,px \ 27; RUN: -r %t.summ0.bc,f6,px \ 28; RUN: -r %t.summ0.bc,f7,px \ 29; RUN: -r %t.summ0.bc,f8left,px \ 30; RUN: -r %t.summ0.bc,f8oobleft,px \ 31; RUN: -r %t.summ0.bc,f8oobright,px \ 32; RUN: -r %t.summ0.bc,f8right,px \ 33; RUN: -r %t.summ0.bc,InterposableCall,px \ 34; RUN: -r %t.summ0.bc,InterposableWrite1, \ 35; RUN: -r %t.summ0.bc,PreemptableCall,px \ 36; RUN: -r %t.summ0.bc,PreemptableWrite1, \ 37; RUN: -r %t.summ0.bc,PrivateCall,px \ 38; RUN: -r %t.summ0.bc,Rec2, \ 39; RUN: -r %t.summ0.bc,RecursiveNoOffset, \ 40; RUN: -r %t.summ0.bc,RecursiveWithOffset, \ 41; RUN: -r %t.summ0.bc,ReturnDependent, \ 42; RUN: -r %t.summ0.bc,TestCrossModuleConflict,px \ 43; RUN: -r %t.summ0.bc,TestCrossModuleOnce,px \ 44; RUN: -r %t.summ0.bc,TestCrossModuleTwice,px \ 45; RUN: -r %t.summ0.bc,TestCrossModuleWeak,px \ 46; RUN: -r %t.summ0.bc,TestRecursiveNoOffset,px \ 47; RUN: -r %t.summ0.bc,TestRecursiveWithOffset,px \ 48; RUN: -r %t.summ0.bc,TestUpdateArg,px \ 49; RUN: -r %t.summ0.bc,TwoArguments,px \ 50; RUN: -r %t.summ0.bc,TwoArgumentsOOBBoth,px \ 51; RUN: -r %t.summ0.bc,TwoArgumentsOOBOne,px \ 52; RUN: -r %t.summ0.bc,TwoArgumentsOOBOther,px \ 53; RUN: -r %t.summ0.bc,Weak,x \ 54; RUN: -r %t.summ0.bc,Write1, \ 55; RUN: -r %t.summ0.bc,Write1DiffModule,x \ 56; RUN: -r %t.summ0.bc,Write1Module0,px \ 57; RUN: -r %t.summ0.bc,Write1Private,x \ 58; RUN: -r %t.summ0.bc,Write1SameModule,x \ 59; RUN: -r %t.summ0.bc,Write1Weak,x \ 60; RUN: -r %t.summ0.bc,Write4_2, \ 61; RUN: -r %t.summ0.bc,Write4, \ 62; RUN: -r %t.summ0.bc,Write8, \ 63; RUN: -r %t.summ0.bc,WriteAndReturn8, \ 64; RUN: -r %t.summ1.bc,ExternalCall,px \ 65; RUN: -r %t.summ1.bc,InterposableWrite1,px \ 66; RUN: -r %t.summ1.bc,PreemptableWrite1,px \ 67; RUN: -r %t.summ1.bc,Rec0,px \ 68; RUN: -r %t.summ1.bc,Rec1,px \ 69; RUN: -r %t.summ1.bc,Rec2,px \ 70; RUN: -r %t.summ1.bc,RecursiveNoOffset,px \ 71; RUN: -r %t.summ1.bc,RecursiveWithOffset,px \ 72; RUN: -r %t.summ1.bc,ReturnAlloca,px \ 73; RUN: -r %t.summ1.bc,ReturnDependent,px \ 74; RUN: -r %t.summ1.bc,Weak,x \ 75; RUN: -r %t.summ1.bc,Write1,px \ 76; RUN: -r %t.summ1.bc,Write1DiffModule,px \ 77; RUN: -r %t.summ1.bc,Write1Module0,x \ 78; RUN: -r %t.summ1.bc,Write1Private,px \ 79; RUN: -r %t.summ1.bc,Write1SameModule,px \ 80; RUN: -r %t.summ1.bc,Write1Weak,px \ 81; RUN: -r %t.summ1.bc,Write4_2,px \ 82; RUN: -r %t.summ1.bc,Write4,px \ 83; RUN: -r %t.summ1.bc,Write8,px \ 84; RUN: -r %t.summ1.bc,WriteAndReturn8,px 85 86; RUN: llvm-lto2 run -opaque-pointers=0 %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \ 87; RUN: $(cat %t.res.txt) \ 88; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO 89 90; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-run -thinlto-distributed-indexes -thinlto-threads 1 -O0 $(cat %t.res.txt) 91; RUN: (cat %t.ids.txt ; llvm-dis %t.summ1.bc.thinlto.bc -o -) | FileCheck --check-prefixes=INDEX %s 92 93target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 94target triple = "aarch64-unknown-linux" 95 96attributes #0 = { noinline sanitize_memtag "target-features"="+mte,+neon" } 97 98declare void @Write1(i8* %p) 99declare void @Write4(i8* %p) 100declare void @Write4_2(i8* %p, i8* %q) 101declare void @Write8(i8* %p) 102declare dso_local i8* @WriteAndReturn8(i8* %p) 103declare dso_local void @ExternalCall(i8* %p) 104declare void @PreemptableWrite1(i8* %p) 105declare void @InterposableWrite1(i8* %p) 106declare i8* @ReturnDependent(i8* %p) 107declare void @Rec2(i8* %p) 108declare void @RecursiveNoOffset(i32* %p, i32 %size, i32* %acc) 109declare void @RecursiveWithOffset(i32 %size, i32* %acc) 110declare void @Write1SameModule(i8* %p) 111declare void @Write1DiffModule(i8* %p) 112declare void @Write1Private(i8* %p) 113declare void @Write1Weak(i8* %p) 114 115; Basic out-of-bounds. 116define void @f1() #0 { 117; CHECK-LABEL: @f1 dso_preemptable{{$}} 118; CHECK-NEXT: args uses: 119; CHECK-NEXT: allocas uses: 120; LOCAL-NEXT: x[4]: empty-set, @Write8(arg0, [0,1)){{$}} 121; GLOBAL-NEXT: x[4]: [0,8), @Write8(arg0, [0,1)){{$}} 122; GLOBAL-NEXT: safe accesses: 123; CHECK-EMPTY: 124entry: 125 %x = alloca i32, align 4 126 %x1 = bitcast i32* %x to i8* 127 call void @Write8(i8* %x1) 128 ret void 129} 130 131; Basic in-bounds. 132define void @f2() #0 { 133; CHECK-LABEL: @f2 dso_preemptable{{$}} 134; CHECK-NEXT: args uses: 135; CHECK-NEXT: allocas uses: 136; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [0,1)){{$}} 137; GLOBAL-NEXT: x[4]: [0,1), @Write1(arg0, [0,1)){{$}} 138; GLOBAL-NEXT: safe accesses: 139; CHECK-EMPTY: 140entry: 141 %x = alloca i32, align 4 142 %x1 = bitcast i32* %x to i8* 143 call void @Write1(i8* %x1) 144 ret void 145} 146 147; Another basic in-bounds. 148define void @f3() #0 { 149; CHECK-LABEL: @f3 dso_preemptable{{$}} 150; CHECK-NEXT: args uses: 151; CHECK-NEXT: allocas uses: 152; LOCAL-NEXT: x[4]: empty-set, @Write4(arg0, [0,1)){{$}} 153; GLOBAL-NEXT: x[4]: [0,4), @Write4(arg0, [0,1)){{$}} 154; GLOBAL-NEXT: safe accesses: 155; CHECK-EMPTY: 156entry: 157 %x = alloca i32, align 4 158 %x1 = bitcast i32* %x to i8* 159 call void @Write4(i8* %x1) 160 ret void 161} 162 163; In-bounds with offset. 164define void @f4() #0 { 165; CHECK-LABEL: @f4 dso_preemptable{{$}} 166; CHECK-NEXT: args uses: 167; CHECK-NEXT: allocas uses: 168; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [1,2)){{$}} 169; GLOBAL-NEXT: x[4]: [1,2), @Write1(arg0, [1,2)){{$}} 170; GLOBAL-NEXT: safe accesses: 171; CHECK-EMPTY: 172entry: 173 %x = alloca i32, align 4 174 %x1 = bitcast i32* %x to i8* 175 %x2 = getelementptr i8, i8* %x1, i64 1 176 call void @Write1(i8* %x2) 177 ret void 178} 179 180; Out-of-bounds with offset. 181define void @f5() #0 { 182; CHECK-LABEL: @f5 dso_preemptable{{$}} 183; CHECK-NEXT: args uses: 184; CHECK-NEXT: allocas uses: 185; LOCAL-NEXT: empty-set, @Write4(arg0, [1,2)){{$}} 186; GLOBAL-NEXT: [1,5), @Write4(arg0, [1,2)){{$}} 187; GLOBAL-NEXT: safe accesses: 188; CHECK-EMPTY: 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 @Write4(i8* %x2) 194 ret void 195} 196 197; External call. 198define void @f6() #0 { 199; CHECK-LABEL: @f6 dso_preemptable{{$}} 200; CHECK-NEXT: args uses: 201; CHECK-NEXT: allocas uses: 202; LOCAL-NEXT: x[4]: empty-set, @ExternalCall(arg0, [0,1)){{$}} 203; GLOBAL-NEXT: x[4]: full-set, @ExternalCall(arg0, [0,1)){{$}} 204; GLOBAL-NEXT: safe accesses: 205; CHECK-EMPTY: 206entry: 207 %x = alloca i32, align 4 208 %x1 = bitcast i32* %x to i8* 209 call void @ExternalCall(i8* %x1) 210 ret void 211} 212 213; Call to dso_preemptable function 214define void @PreemptableCall() #0 { 215; CHECK-LABEL: @PreemptableCall dso_preemptable{{$}} 216; CHECK-NEXT: args uses: 217; CHECK-NEXT: allocas uses: 218; LOCAL-NEXT: x[4]: empty-set, @PreemptableWrite1(arg0, [0,1)){{$}} 219; GLOBAL-NEXT: x[4]: full-set, @PreemptableWrite1(arg0, [0,1)){{$}} 220; GLOBAL-NEXT: safe accesses: 221; CHECK-EMPTY: 222entry: 223 %x = alloca i32, align 4 224 %x1 = bitcast i32* %x to i8* 225 call void @PreemptableWrite1(i8* %x1) 226 ret void 227} 228 229; Call to function with interposable linkage 230define void @InterposableCall() #0 { 231; CHECK-LABEL: @InterposableCall dso_preemptable{{$}} 232; CHECK-NEXT: args uses: 233; CHECK-NEXT: allocas uses: 234; LOCAL-NEXT: x[4]: empty-set, @InterposableWrite1(arg0, [0,1)){{$}} 235; NOLTO-NEXT: x[4]: full-set, @InterposableWrite1(arg0, [0,1)){{$}} 236; LTO-NEXT: x[4]: [0,1), @InterposableWrite1(arg0, [0,1)){{$}} 237; GLOBAL-NEXT: safe accesses: 238; CHECK-EMPTY: 239entry: 240 %x = alloca i32, align 4 241 %x1 = bitcast i32* %x to i8* 242 call void @InterposableWrite1(i8* %x1) 243 ret void 244} 245 246; Call to function with private linkage 247define void @PrivateCall() #0 { 248; CHECK-LABEL: @PrivateCall dso_preemptable{{$}} 249; CHECK-NEXT: args uses: 250; CHECK-NEXT: allocas uses: 251; LOCAL-NEXT: x[4]: empty-set, @PrivateWrite1(arg0, [0,1)){{$}} 252; GLOBAL-NEXT: x[4]: [0,1), @PrivateWrite1(arg0, [0,1)){{$}} 253; GLOBAL-NEXT: safe accesses: 254; CHECK-EMPTY: 255entry: 256 %x = alloca i32, align 4 257 %x1 = bitcast i32* %x to i8* 258 call void @PrivateWrite1(i8* %x1) 259 ret void 260} 261 262define private void @PrivateWrite1(i8* %p) #0 { 263; CHECK-LABEL: @PrivateWrite1{{$}} 264; CHECK-NEXT: args uses: 265; CHECK-NEXT: p[]: [0,1){{$}} 266; CHECK-NEXT: allocas uses: 267; GLOBAL-NEXT: safe accesses: 268; GLOBAL-NEXT: store i8 0, i8* %p, align 1 269; CHECK-EMPTY: 270entry: 271 store i8 0, i8* %p, align 1 272 ret void 273} 274 275; Caller returns a dependent value. 276; FIXME: alloca considered unsafe even if the return value is unused. 277define void @f7() #0 { 278; CHECK-LABEL: @f7 dso_preemptable{{$}} 279; CHECK-NEXT: args uses: 280; CHECK-NEXT: allocas uses: 281; LOCAL-NEXT: x[4]: empty-set, @ReturnDependent(arg0, [0,1)){{$}} 282; GLOBAL-NEXT: x[4]: full-set, @ReturnDependent(arg0, [0,1)){{$}} 283; GLOBAL-NEXT: safe accesses: 284; CHECK-EMPTY: 285entry: 286 %x = alloca i32, align 4 287 %x1 = bitcast i32* %x to i8* 288 %x2 = call i8* @ReturnDependent(i8* %x1) 289 ret void 290} 291 292define void @f8left() #0 { 293; CHECK-LABEL: @f8left dso_preemptable{{$}} 294; CHECK-NEXT: args uses: 295; CHECK-NEXT: allocas uses: 296; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [2,3)){{$}} 297; GLOBAL-NEXT: x[8]: [0,4), @Rec2(arg0, [2,3)){{$}} 298; GLOBAL-NEXT: safe accesses: 299; CHECK-EMPTY: 300entry: 301 %x = alloca i64, align 4 302 %x1 = bitcast i64* %x to i8* 303 %x2 = getelementptr i8, i8* %x1, i64 2 304; 2 + [-2, 2) = [0, 4) => OK 305 call void @Rec2(i8* %x2) 306 ret void 307} 308 309define void @f8right() #0 { 310; CHECK-LABEL: @f8right dso_preemptable{{$}} 311; CHECK-NEXT: args uses: 312; CHECK-NEXT: allocas uses: 313; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [6,7)){{$}} 314; GLOBAL-NEXT: x[8]: [4,8), @Rec2(arg0, [6,7)){{$}} 315; GLOBAL-NEXT: safe accesses: 316; CHECK-EMPTY: 317entry: 318 %x = alloca i64, align 4 319 %x1 = bitcast i64* %x to i8* 320 %x2 = getelementptr i8, i8* %x1, i64 6 321; 6 + [-2, 2) = [4, 8) => OK 322 call void @Rec2(i8* %x2) 323 ret void 324} 325 326define void @f8oobleft() #0 { 327; CHECK-LABEL: @f8oobleft dso_preemptable{{$}} 328; CHECK-NEXT: args uses: 329; CHECK-NEXT: allocas uses: 330; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [1,2)){{$}} 331; GLOBAL-NEXT: x[8]: [-1,3), @Rec2(arg0, [1,2)){{$}} 332; GLOBAL-NEXT: safe accesses: 333; CHECK-EMPTY: 334entry: 335 %x = alloca i64, align 4 336 %x1 = bitcast i64* %x to i8* 337 %x2 = getelementptr i8, i8* %x1, i64 1 338; 1 + [-2, 2) = [-1, 3) => NOT OK 339 call void @Rec2(i8* %x2) 340 ret void 341} 342 343define void @f8oobright() #0 { 344; CHECK-LABEL: @f8oobright dso_preemptable{{$}} 345; CHECK-NEXT: args uses: 346; CHECK-NEXT: allocas uses: 347; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [7,8)){{$}} 348; GLOBAL-NEXT: x[8]: [5,9), @Rec2(arg0, [7,8)){{$}} 349; GLOBAL-NEXT: safe accesses: 350; CHECK-EMPTY: 351entry: 352 %x = alloca i64, align 4 353 %x1 = bitcast i64* %x to i8* 354 %x2 = getelementptr i8, i8* %x1, i64 7 355; 7 + [-2, 2) = [5, 9) => NOT OK 356 call void @Rec2(i8* %x2) 357 ret void 358} 359 360define void @TwoArguments() #0 { 361; CHECK-LABEL: @TwoArguments dso_preemptable{{$}} 362; CHECK-NEXT: args uses: 363; CHECK-NEXT: allocas uses: 364; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}} 365; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}} 366; GLOBAL-NEXT: safe accesses: 367; CHECK-EMPTY: 368entry: 369 %x = alloca i64, align 4 370 %x1 = bitcast i64* %x to i8* 371 %x2 = getelementptr i8, i8* %x1, i64 4 372 call void @Write4_2(i8* %x2, i8* %x1) 373 ret void 374} 375 376define void @TwoArgumentsOOBOne() #0 { 377; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}} 378; CHECK-NEXT: args uses: 379; CHECK-NEXT: allocas uses: 380; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}} 381; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}} 382; GLOBAL-NEXT: safe accesses: 383; CHECK-EMPTY: 384entry: 385 %x = alloca i64, align 4 386 %x1 = bitcast i64* %x to i8* 387 %x2 = getelementptr i8, i8* %x1, i64 5 388 call void @Write4_2(i8* %x2, i8* %x1) 389 ret void 390} 391 392define void @TwoArgumentsOOBOther() #0 { 393; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}} 394; CHECK-NEXT: args uses: 395; CHECK-NEXT: allocas uses: 396; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}} 397; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}} 398; GLOBAL-NEXT: safe accesses: 399; CHECK-EMPTY: 400entry: 401 %x = alloca i64, align 4 402 %x0 = bitcast i64* %x to i8* 403 %x1 = getelementptr i8, i8* %x0, i64 -1 404 %x2 = getelementptr i8, i8* %x0, i64 4 405 call void @Write4_2(i8* %x2, i8* %x1) 406 ret void 407} 408 409define void @TwoArgumentsOOBBoth() #0 { 410; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}} 411; CHECK-NEXT: args uses: 412; CHECK-NEXT: allocas uses: 413; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}} 414; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}} 415; GLOBAL-NEXT: safe accesses: 416; CHECK-EMPTY: 417entry: 418 %x = alloca i64, align 4 419 %x0 = bitcast i64* %x to i8* 420 %x1 = getelementptr i8, i8* %x0, i64 -1 421 %x2 = getelementptr i8, i8* %x0, i64 5 422 call void @Write4_2(i8* %x2, i8* %x1) 423 ret void 424} 425 426define i32 @TestRecursiveNoOffset(i32* %p, i32 %size) #0 { 427; CHECK-LABEL: @TestRecursiveNoOffset dso_preemptable{{$}} 428; CHECK-NEXT: args uses: 429; LOCAL-NEXT: p[]: empty-set, @RecursiveNoOffset(arg0, [0,1)){{$}} 430; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [0,1)){{$}} 431; CHECK-NEXT: allocas uses: 432; CHECK-NEXT: sum[4]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}} 433; GLOBAL-NEXT: safe accesses: 434; GLOBAL-NEXT: store i32 0, i32* %sum, align 4 435; GLOBAL-NEXT: %1 = load i32, i32* %sum, align 4 436; CHECK-EMPTY: 437entry: 438 %sum = alloca i32, align 4 439 %0 = bitcast i32* %sum to i8* 440 store i32 0, i32* %sum, align 4 441 call void @RecursiveNoOffset(i32* %p, i32 %size, i32* %sum) 442 %1 = load i32, i32* %sum, align 4 443 ret i32 %1 444} 445 446define void @TestRecursiveWithOffset(i32 %size) #0 { 447; CHECK-LABEL: @TestRecursiveWithOffset dso_preemptable{{$}} 448; CHECK-NEXT: args uses: 449; CHECK-NEXT: allocas uses: 450; LOCAL-NEXT: sum[64]: empty-set, @RecursiveWithOffset(arg1, [0,1)){{$}} 451; GLOBAL-NEXT: sum[64]: full-set, @RecursiveWithOffset(arg1, [0,1)){{$}} 452; GLOBAL-NEXT: safe accesses: 453; CHECK-EMPTY: 454entry: 455 %sum = alloca i32, i64 16, align 4 456 call void @RecursiveWithOffset(i32 %size, i32* %sum) 457 ret void 458} 459 460; FIXME: IPA should detect that access is safe 461define void @TestUpdateArg() #0 { 462; CHECK-LABEL: @TestUpdateArg dso_preemptable{{$}} 463; CHECK-NEXT: args uses: 464; CHECK-NEXT: allocas uses: 465; LOCAL-NEXT: x[16]: empty-set, @WriteAndReturn8(arg0, [0,1)){{$}} 466; GLOBAL-NEXT: x[16]: full-set, @WriteAndReturn8(arg0, [0,1)){{$}} 467; GLOBAL-NEXT: safe accesses: 468; CHECK-EMPTY: 469entry: 470 %x = alloca i8, i64 16, align 4 471 %0 = call i8* @WriteAndReturn8(i8* %x) 472 ret void 473} 474 475define void @TestCrossModuleOnce() #0 { 476; CHECK-DAG: @TestCrossModuleOnce dso_preemptable{{$}} 477; CHECK-NEXT: args uses: 478; CHECK-NEXT: allocas uses: 479; LOCAL-NEXT: y[1]: empty-set, @Write1SameModule(arg0, [0,1)){{$}} 480; GLOBAL-NEXT: y[1]: [0,1), @Write1SameModule(arg0, [0,1)){{$}} 481; GLOBAL-NEXT: safe accesses: 482; CHECK-EMPTY: 483entry: 484 %y = alloca i8, align 4 485 call void @Write1SameModule(i8* %y) 486 ret void 487} 488 489define void @TestCrossModuleTwice() #0 { 490; CHECK-DAG: @TestCrossModuleTwice dso_preemptable{{$}} 491; CHECK-NEXT: args uses: 492; CHECK-NEXT: allocas uses: 493; LOCAL-NEXT: z[1]: empty-set, @Write1DiffModule(arg0, [0,1)){{$}} 494; GLOBAL-NEXT: z[1]: [0,1), @Write1DiffModule(arg0, [0,1)){{$}} 495; GLOBAL-NEXT: safe accesses: 496; CHECK-EMPTY: 497entry: 498 %z = alloca i8, align 4 499 call void @Write1DiffModule(i8* %z) 500 ret void 501} 502 503define void @TestCrossModuleConflict() #0 { 504; CHECK-DAG: @TestCrossModuleConflict dso_preemptable{{$}} 505; CHECK-NEXT: args uses: 506; CHECK-NEXT: allocas uses: 507; LOCAL-NEXT: x[1]: empty-set, @Write1Private(arg0, [0,1)){{$}} 508; GLOBAL-NEXT: x[1]: [-1,0), @Write1Private(arg0, [0,1)){{$}} 509; GLOBAL-NEXT: safe accesses: 510; CHECK-EMPTY: 511entry: 512 %x = alloca i8, align 4 513 call void @Write1Private(i8* %x) 514 ret void 515} 516 517; FIXME: LTO should match NOLTO 518define void @TestCrossModuleWeak() #0 { 519; CHECK-DAG: @TestCrossModuleWeak dso_preemptable{{$}} 520; CHECK-NEXT: args uses: 521; CHECK-NEXT: allocas uses: 522; LOCAL-NEXT: x[1]: empty-set, @Write1Weak(arg0, [0,1)){{$}} 523; NOLTO-NEXT: x[1]: [1,2), @Write1Weak(arg0, [0,1)){{$}} 524; LTO-NEXT: x[1]: full-set, @Write1Weak(arg0, [0,1)){{$}} 525; GLOBAL-NEXT: safe accesses: 526; CHECK-EMPTY: 527entry: 528 %x = alloca i8, align 4 529 call void @Write1Weak(i8* %x) 530 ret void 531} 532 533define private dso_local void @Private(i8* %p) #0 { 534entry: 535 %p1 = getelementptr i8, i8* %p, i64 1 536 store i8 0, i8* %p1, align 1 537 ret void 538} 539 540define dso_local void @Write1Module0(i8* %p) #0 { 541entry: 542 store i8 0, i8* %p, align 1 543 ret void 544} 545 546define dso_local void @Weak(i8* %p) #0 { 547entry: 548 %p1 = getelementptr i8, i8* %p, i64 1 549 store i8 0, i8* %p1, align 1 550 ret void 551} 552 553; The rest is from Inputs/ipa.ll 554 555; CHECK-LABEL: @Write1{{$}} 556; CHECK-NEXT: args uses: 557; CHECK-NEXT: p[]: [0,1){{$}} 558; CHECK-NEXT: allocas uses: 559; GLOBAL-NEXT: safe accesses: 560; GLOBAL-NEXT: store i8 0, i8* %p, align 1 561; CHECK-EMPTY: 562 563; CHECK-LABEL: @Write4{{$}} 564; CHECK-NEXT: args uses: 565; CHECK-NEXT: p[]: [0,4){{$}} 566; CHECK-NEXT: allocas uses: 567; GLOBAL-NEXT: safe accesses: 568; GLOBAL-NEXT: store i32 0, i32* %0, align 1 569; CHECK-EMPTY: 570 571; CHECK-LABEL: @Write4_2{{$}} 572; CHECK-NEXT: args uses: 573; CHECK-NEXT: p[]: [0,4){{$}} 574; CHECK-NEXT: q[]: [0,4){{$}} 575; CHECK-NEXT: allocas uses: 576; GLOBAL-NEXT: safe accesses: 577; GLOBAL-NEXT: store i32 0, i32* %0, align 1 578; GLOBAL-NEXT: store i32 0, i32* %1, align 1 579; CHECK-EMPTY: 580 581; CHECK-LABEL: @Write8{{$}} 582; CHECK-NEXT: args uses: 583; CHECK-NEXT: p[]: [0,8){{$}} 584; CHECK-NEXT: allocas uses: 585; GLOBAL-NEXT: safe accesses: 586; GLOBAL-NEXT: store i64 0, i64* %0, align 1 587; CHECK-EMPTY: 588 589; CHECK-LABEL: @WriteAndReturn8{{$}} 590; CHECK-NEXT: args uses: 591; CHECK-NEXT: p[]: full-set{{$}} 592; CHECK-NEXT: allocas uses: 593; GLOBAL-NEXT: safe accesses: 594; GLOBAL-NEXT: store i8 0, i8* %p, align 1 595; CHECK-EMPTY: 596 597; CHECK-LABEL: @PreemptableWrite1 dso_preemptable{{$}} 598; CHECK-NEXT: args uses: 599; CHECK-NEXT: p[]: [0,1){{$}} 600; CHECK-NEXT: allocas uses: 601; GLOBAL-NEXT: safe accesses: 602; GLOBAL-NEXT: store i8 0, i8* %p, align 1 603; CHECK-EMPTY: 604 605; CHECK-LABEL: @InterposableWrite1 interposable{{$}} 606; CHECK-NEXT: args uses: 607; CHECK-NEXT: p[]: [0,1){{$}} 608; CHECK-NEXT: allocas uses: 609; GLOBAL-NEXT: safe accesses: 610; GLOBAL-NEXT: store i8 0, i8* %p, align 1 611; CHECK-EMPTY: 612 613; CHECK-LABEL: @ReturnDependent{{$}} 614; CHECK-NEXT: args uses: 615; CHECK-NEXT: p[]: full-set{{$}} 616; CHECK-NEXT: allocas uses: 617; GLOBAL-NEXT: safe accesses: 618; CHECK-EMPTY: 619 620; CHECK-LABEL: @Rec0{{$}} 621; CHECK-NEXT: args uses: 622; LOCAL-NEXT: p[]: empty-set, @Write4(arg0, [2,3)){{$}} 623; GLOBAL-NEXT: p[]: [2,6) 624; CHECK-NEXT: allocas uses: 625; GLOBAL-NEXT: safe accesses: 626; CHECK-EMPTY: 627 628; CHECK-LABEL: @Rec1{{$}} 629; CHECK-NEXT: args uses: 630; LOCAL-NEXT: p[]: empty-set, @Rec0(arg0, [1,2)){{$}} 631; GLOBAL-NEXT: p[]: [3,7) 632; CHECK-NEXT: allocas uses: 633; GLOBAL-NEXT: safe accesses: 634; CHECK-EMPTY: 635 636; CHECK-LABEL: @Rec2{{$}} 637; CHECK-NEXT: args uses: 638; LOCAL-NEXT: p[]: empty-set, @Rec1(arg0, [-5,-4)){{$}} 639; GLOBAL-NEXT: p[]: [-2,2) 640; CHECK-NEXT: allocas uses: 641; GLOBAL-NEXT: safe accesses: 642; CHECK-EMPTY: 643 644; CHECK-LABEL: @RecursiveNoOffset{{$}} 645; CHECK-NEXT: args uses: 646; LOCAL-NEXT: p[]: [0,4), @RecursiveNoOffset(arg0, [4,5)){{$}} 647; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [4,5)){{$}} 648; CHECK-NEXT: acc[]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}} 649; CHECK-NEXT: allocas uses: 650; GLOBAL-NEXT: safe accesses: 651; GLOBAL-NEXT: %0 = load i32, i32* %p, align 4 652; GLOBAL-NEXT: %1 = load i32, i32* %acc, align 4 653; GLOBAL-NEXT: store i32 %add, i32* %acc, align 4 654; CHECK-EMPTY: 655 656; CHECK-LABEL: @RecursiveWithOffset{{$}} 657; CHECK-NEXT: args uses: 658; LOCAL-NEXT: acc[]: [0,4), @RecursiveWithOffset(arg1, [4,5)){{$}} 659; GLOBAL-NEXT: acc[]: full-set, @RecursiveWithOffset(arg1, [4,5)){{$}} 660; CHECK-NEXT: allocas uses: 661; GLOBAL-NEXT: safe accesses: 662; GLOBAL-NEXT: store i32 0, i32* %acc, align 4 663; CHECK-EMPTY: 664 665; CHECK-LABEL: @ReturnAlloca 666; CHECK-NEXT: args uses: 667; CHECK-NEXT: allocas uses: 668; CHECK-NEXT: x[8]: full-set 669; GLOBAL-NEXT: safe accesses: 670; CHECK-EMPTY: 671 672; INDEX-LABEL: ^0 = module: 673; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]] 674; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]] 675; INDEX-DAG: name: "TwoArgumentsOOBOther"{{.*}} guid = [[TwoArgumentsOOBOther:[-0-9]+]] 676; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]] 677; INDEX-DAG: name: "f1"{{.*}} guid = [[f1:[-0-9]+]] 678; INDEX-DAG: name: "PrivateWrite1"{{.*}} guid = [[PrivateWrite1:[-0-9]+]] 679; INDEX-DAG: name: "TestRecursiveNoOffset"{{.*}} guid = [[TestRecursiveNoOffset:[-0-9]+]] 680; INDEX-DAG: name: "f8left"{{.*}} guid = [[f8left:[-0-9]+]] 681; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]] 682; INDEX-DAG: name: "f7"{{.*}} guid = [[f7:[-0-9]+]] 683; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]] 684; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]] 685; INDEX-DAG: name: "TwoArgumentsOOBOne"{{.*}} guid = [[TwoArgumentsOOBOne:[-0-9]+]] 686; INDEX-DAG: name: "f3"{{.*}} guid = [[f3:[-0-9]+]] 687; INDEX-DAG: name: "f8right"{{.*}} guid = [[f8right:[-0-9]+]] 688; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]] 689; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]] 690; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]] 691; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]] 692; INDEX-DAG: name: "TestUpdateArg"{{.*}} guid = [[TestUpdateArg:[-0-9]+]] 693; INDEX-DAG: name: "TestCrossModuleTwice"{{.*}} guid = [[TestCrossModuleTwice:[-0-9]+]] 694; INDEX-DAG: name: "TestCrossModuleWeak"{{.*}} guid = [[TestCrossModuleWeak:[-0-9]+]] 695; INDEX-DAG: name: "f2"{{.*}} guid = [[f2:[-0-9]+]] 696; INDEX-DAG: name: "PrivateCall"{{.*}} guid = [[PrivateCall:[-0-9]+]] 697; INDEX-DAG: name: "TestRecursiveWithOffset"{{.*}} guid = [[TestRecursiveWithOffset:[-0-9]+]] 698; INDEX-DAG: name: "f8oobleft"{{.*}} guid = [[f8oobleft:[-0-9]+]] 699; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]] 700; INDEX-DAG: name: "f4"{{.*}} guid = [[f4:[-0-9]+]] 701; INDEX-DAG: name: "TestCrossModuleConflict"{{.*}} guid = [[TestCrossModuleConflict:[-0-9]+]] 702; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]] 703; INDEX-DAG: name: "TwoArgumentsOOBBoth"{{.*}} guid = [[TwoArgumentsOOBBoth:[-0-9]+]] 704; INDEX-DAG: name: "f5"{{.*}} guid = [[f5:[-0-9]+]] 705; INDEX-DAG: name: "f6"{{.*}} guid = [[f6:[-0-9]+]] 706; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]] 707; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]] 708; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]] 709; INDEX-DAG: name: "f8oobright"{{.*}} guid = [[f8oobright:[-0-9]+]] 710; INDEX-DAG: name: "InterposableCall"{{.*}} guid = [[InterposableCall:[-0-9]+]] 711; INDEX-DAG: name: "TestCrossModuleOnce"{{.*}} guid = [[TestCrossModuleOnce:[-0-9]+]] 712; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]] 713; INDEX-DAG: name: "TwoArguments"{{.*}} guid = [[TwoArguments:[-0-9]+]] 714; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]] 715; INDEX-DAG: name: "PreemptableCall"{{.*}} guid = [[PreemptableCall:[-0-9]+]] 716; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]] 717; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]] 718; INDEX-LABEL: = blockcount: 719 720; INDEX-LABEL: ^0 = module: 721; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]] 722; INDEX-DAG: name: "Rec0"{{.*}} guid = [[Rec0:[-0-9]+]] 723; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]] 724; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]] 725; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]] 726; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]] 727; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]] 728; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]] 729; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]] 730; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]] 731; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]] 732; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]] 733; INDEX-DAG: name: "Rec1"{{.*}} guid = [[Rec1:[-0-9]+]] 734; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]] 735; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]] 736; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]] 737; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]] 738; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]] 739; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]] 740; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]] 741; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]] 742; INDEX-DAG: name: "ReturnAlloca"{{.*}} guid = [[ReturnAlloca:[-0-9]+]] 743; INDEX-LABEL: = blockcount: 744 745; INDEX-LABEL: ^0 = module: 746; INDEX-DAG: guid: [[ReturnDependent]], {{.*}}, funcFlags: ({{.*}})))) 747; INDEX-DAG: guid: [[Rec0]], {{.*}}, params: ((param: 0, offset: [2, 5]))))) 748; INDEX-DAG: guid: [[Rec2]], {{.*}}, params: ((param: 0, offset: [-2, 1]))))) 749; INDEX-DAG: guid: [[Write4]], {{.*}}, params: ((param: 0, offset: [0, 3]))))) 750; INDEX-DAG: guid: [[Write1SameModule]], {{.*}}, params: ((param: 0, offset: [0, 0]))))) 751; INDEX-DAG: guid: [[Write8]], {{.*}}, params: ((param: 0, offset: [0, 7]))))) 752; INDEX-DAG: guid: [[Write4_2]], {{.*}}, params: ((param: 0, offset: [0, 3]), (param: 1, offset: [0, 3]))))) 753; INDEX-DAG: guid: [[RecursiveWithOffset]], {{.*}}, calls: ((callee: ^{{[0-9]+}}))))) 754; INDEX-DAG: guid: [[Weak]], {{.*}}, funcFlags: ({{.*}})))) 755; INDEX-DAG: guid: [[Write1Private]], {{.*}}, params: ((param: 0, offset: [-1, -1]))))) 756; INDEX-DAG: guid: [[InterposableWrite1]], {{.*}}, params: ((param: 0, offset: [0, 0]))))) 757; INDEX-DAG: guid: [[Private]], {{.*}}, params: ((param: 0, offset: [-1, -1]))))) 758; INDEX-DAG: guid: [[Rec1]], {{.*}}, params: ((param: 0, offset: [3, 6]))))) 759; INDEX-DAG: guid: [[RecursiveNoOffset]], {{.*}}, params: ((param: 2, offset: [0, 3]))))) 760; INDEX-DAG: guid: [[Write1Weak]], {{.*}}, calls: ((callee: ^{{[0-9]+}}))))) 761; INDEX-DAG: guid: [[Write1]], {{.*}}, params: ((param: 0, offset: [0, 0]))))) 762; INDEX-DAG: guid: [[PreemptableWrite1]], {{.*}}, funcFlags: ({{.*}})))) 763; INDEX-DAG: guid: [[WriteAndReturn8]], {{.*}}, funcFlags: ({{.*}})))) 764; INDEX-DAG: guid: [[Write1DiffModule]], {{.*}}, funcFlags: ({{.*}})))) 765; INDEX-DAG: guid: [[ReturnAlloca]], {{.*}}, insts: 2))) 766; INDEX-LABEL: blockcount: 767