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