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