606 lines · plain
1; RUN: opt %s -mtriple amdgcn-- -passes='print<uniformity>' -disable-output 2>&1 | FileCheck %s2 3define amdgpu_kernel void @cycle_diverge_enter(i32 %n, i32 %a, i32 %b) #0 {4; entry(div)5; / \6; H <-> B7; |8; X9; CHECK-LABEL: for function 'cycle_diverge_enter':10; CHECK-NOT: DIVERGENT: %uni.11; CHECK-NOT: DIVERGENT: br i1 %uni.12 13entry:14 %tid = call i32 @llvm.amdgcn.workitem.id.x()15 %div.cond = icmp slt i32 %tid, 016 %uni.cond = icmp slt i32 %a, 017 br i1 %div.cond, label %B, label %H ; divergent branch18 19H:20 %div.merge.h = phi i32 [ 0, %entry ], [ %b, %B ]21 br label %B22; CHECK: DIVERGENT: %div.merge.h23 24B:25 %div.merge.b = phi i32 [ %a, %H ], [1, %entry ]26 %div.cond.b = icmp sgt i32 %div.merge.b, 027 %div.b.inc = add i32 %b, 128 br i1 %div.cond, label %X, label %H ; divergent branch29; CHECK: DIVERGENT: %div.merge.b30 31X:32 %div.use = add i32 %div.merge.b, 133 ret void34; CHECK: DIVERGENT: %div.use =35 36}37 38define amdgpu_kernel void @cycle_diverge_exit(i32 %n, i32 %a, i32 %b) #0 {39; entry40; / \41; H <-> B(div)42; |43; X44;45; CHECK-LABEL: for function 'cycle_diverge_exit':46; CHECK-NOT: DIVERGENT: %uni.47; CHECK-NOT: DIVERGENT: br i1 %uni.48 49entry:50 %tid = call i32 @llvm.amdgcn.workitem.id.x()51 %div.cond = icmp slt i32 %tid, 052 %uni.cond = icmp slt i32 %a, 053 br i1 %uni.cond, label %B, label %H54 55H:56 %uni.merge.h = phi i32 [ 0, %entry ], [ %b, %B ]57 br label %B58 59B:60 %uni.merge.b = phi i32 [ %a, %H ], [1, %entry ]61 %uni.cond.b = icmp sgt i32 %uni.merge.b, 062 %uni.b.inc = add i32 %b, 163 br i1 %div.cond, label %X, label %H ; divergent branch64 65X:66 %div.use = add i32 %uni.merge.b, 167 ret void68; CHECK: DIVERGENT: %div.use =69}70 71define amdgpu_kernel void @cycle_reentrance(i32 %n, i32 %a, i32 %b) #0 {72; For this case, threads enter the cycle from C would take C->D->H,73; at the point of H, diverged threads may continue looping in cycle(H-B-D)74; until all threads exit the cycle(H-B-D) and cause temporal divergence75; exiting at edge H->C. We currently do not analyze such kind of inner76; cycle temporal divergence. Instead, we mark all values in the cycle77; being divergent conservatively.78; entry--\79; | |80; ---> H(div)|81; | / \ /82; | B C<--83; ^ \ /84; \----D85; |86; X87; CHECK-LABEL: for function 'cycle_reentrance':88; CHECK-NOT: DIVERGENT: %uni.89; CHECK-NOT: DIVERGENT: br i1 %uni.90 91entry:92 %tid = call i32 @llvm.amdgcn.workitem.id.x()93 %div.cond = icmp slt i32 %tid, 094 %uni.cond = icmp slt i32 %a, 095 br i1 %uni.cond, label %H, label %C96 97H:98 %div.merge.h = phi i32 [ 0, %entry ], [ %b, %D ]99 br i1 %div.cond, label %B, label %C ; divergent branch100 101B:102 %div.inc.b = add i32 %div.merge.h, 1103; CHECK: DIVERGENT: %div.inc.b104 br label %D105 106C:107 %div.merge.c = phi i32 [0, %entry], [%div.merge.h, %H]108 %div.inc.c = add i32 %div.merge.c, 2109; CHECK: DIVERGENT: %div.inc.c110 br label %D111 112D:113 %div.merge.d = phi i32 [ %div.inc.b, %B ], [ %div.inc.c, %C ]114; CHECK: DIVERGENT: %div.merge.d115 br i1 %uni.cond, label %X, label %H116 117X:118 ret void119}120 121define amdgpu_kernel void @cycle_reentrance2(i32 %n, i32 %a, i32 %b) #0 {122; This is mostly the same as cycle_reentrance, the only difference is123; the successor order, thus different dfs visiting order. This is just124; make sure we are doing uniform analysis correctly under different dfs125; order.126; entry--\127; | |128; ---> H(div)|129; | / \ /130; | B C<--131; ^ \ /132; \----D133; |134; X135; CHECK-LABEL: for function 'cycle_reentrance2':136; CHECK-NOT: DIVERGENT: %uni.137; CHECK-NOT: DIVERGENT: br i1 %uni.138 139entry:140 %tid = call i32 @llvm.amdgcn.workitem.id.x()141 %div.cond = icmp slt i32 %tid, 0142 %uni.cond = icmp slt i32 %a, 0143 br i1 %uni.cond, label %C, label %H144 145H:146 %div.merge.h = phi i32 [ 0, %entry ], [ %b, %D ]147 br i1 %div.cond, label %B, label %C ; divergent branch148 149B:150 %div.inc.b = add i32 %div.merge.h, 1151; CHECK: DIVERGENT: %div.inc.b152 br label %D153 154C:155 %div.merge.c = phi i32 [0, %entry], [%div.merge.h, %H]156 %div.inc.c = add i32 %div.merge.c, 2157; CHECK: DIVERGENT: %div.inc.c158 br label %D159 160D:161 %div.merge.d = phi i32 [ %div.inc.b, %B ], [ %div.inc.c, %C ]162; CHECK: DIVERGENT: %div.merge.d163 br i1 %uni.cond, label %X, label %H164 165X:166 ret void167}168 169define amdgpu_kernel void @cycle_join_dominated_by_diverge(i32 %n, i32 %a, i32 %b) #0 {170; the join-node D is dominated by diverge point H2171; entry172; | |173; --> H1 |174; | \|175; | H2(div)176; | / \177; | B C178; ^ \ /179; \------D180; |181; X182; CHECK-LABEL: for function 'cycle_join_dominated_by_diverge':183; CHECK-NOT: DIVERGENT: %uni.184; CHECK-NOT: DIVERGENT: br i1 %uni.185 186entry:187 %tid = call i32 @llvm.amdgcn.workitem.id.x()188 %div.cond = icmp slt i32 %tid, 0189 %uni.cond = icmp slt i32 %a, 0190 br i1 %uni.cond, label %H1, label %H2191 192H1:193 %uni.merge.h1 = phi i32 [ 0, %entry ], [ %b, %D ]194 br label %H2195 196H2:197 %uni.merge.h2 = phi i32 [ 0, %entry ], [ %b, %H1 ]198 br i1 %div.cond, label %B, label %C ; divergent branch199 200B:201 %uni.inc.b = add i32 %uni.merge.h2, 1202 br label %D203 204C:205 %uni.inc.c = add i32 %uni.merge.h2, 2206 br label %D207 208D:209 %div.merge.d = phi i32 [ %uni.inc.b, %B ], [ %uni.inc.c, %C ]210; CHECK: DIVERGENT: %div.merge.d211 br i1 %uni.cond, label %X, label %H1212 213X:214 ret void215}216 217define amdgpu_kernel void @cycle_join_dominated_by_entry(i32 %n, i32 %a, i32 %b) #0 {218; the join-node D is dominated by cycle entry H2219; entry220; | |221; --> H1 |222; | \|223; | H2 -----224; | | |225; | A(div) |226; | / \ v227; | B C /228; ^ \ / /229; \------D <-/230; |231; X232; CHECK-LABEL: for function 'cycle_join_dominated_by_entry':233; CHECK-NOT: DIVERGENT: %uni.234; CHECK-NOT: DIVERGENT: br i1 %uni.235 236entry:237 %tid = call i32 @llvm.amdgcn.workitem.id.x()238 %div.cond = icmp slt i32 %tid, 0239 %uni.cond = icmp slt i32 %a, 0240 br i1 %uni.cond, label %H1, label %H2241 242H1:243 %uni.merge.h1 = phi i32 [ 0, %entry ], [ %b, %D ]244 br label %H2245 246H2:247 %uni.merge.h2 = phi i32 [ 0, %entry ], [ %b, %H1 ]248 br i1 %uni.cond, label %A, label %D249 250A:251 br i1 %div.cond, label %B, label %C ; divergent branch252 253B:254 %uni.inc.b = add i32 %uni.merge.h2, 1255 br label %D256 257C:258 %uni.inc.c = add i32 %uni.merge.h2, 2259 br label %D260 261D:262 %div.merge.d = phi i32 [ %uni.inc.b, %B ], [ %uni.inc.c, %C ], [%uni.merge.h2, %H2]263; CHECK: DIVERGENT: %div.merge.d264 br i1 %uni.cond, label %X, label %H1265 266X:267 ret void268}269 270define amdgpu_kernel void @cycle_join_not_dominated(i32 %n, i32 %a, i32 %b) #0 {271; if H is the header, the sync label propagation may stop at join node D.272; But join node D is not dominated by divergence starting block C, and also273; not dominated by any entries(H/C). So we conservatively mark all the values274; in the cycle divergent for now.275; entry276; | |277; ---> H |278; | / \ v279; | B<--C(div)280; ^ \ /281; \----D282; |283; X284; CHECK-LABEL: for function 'cycle_join_not_dominated':285; CHECK-NOT: DIVERGENT: %uni.286 287entry:288 %tid = call i32 @llvm.amdgcn.workitem.id.x()289 %div.cond = icmp slt i32 %tid, 0290 %uni.cond = icmp slt i32 %a, 0291 br i1 %uni.cond, label %C, label %H292 293H:294 %div.merge.h = phi i32 [ 0, %entry ], [ %b, %D ]295 br i1 %uni.cond, label %B, label %C296 297B:298 %div.merge.b = phi i32 [ 0, %H ], [ %b, %C ]299 %div.inc.b = add i32 %div.merge.b, 1300; CHECK: DIVERGENT: %div.inc.b301 br label %D302 303C:304 %div.merge.c = phi i32 [0, %entry], [%div.merge.h, %H]305 %div.inc.c = add i32 %div.merge.c, 2306; CHECK: DIVERGENT: %div.inc.c307 br i1 %div.cond, label %D, label %B ; divergent branch308 309D:310 %div.merge.d = phi i32 [ %div.inc.b, %B ], [ %div.inc.c, %C ]311; CHECK: DIVERGENT: %div.merge.d312 br i1 %uni.cond, label %X, label %H313 314X:315 ret void316}317 318define amdgpu_kernel void @cycle_join_not_dominated2(i32 %n, i32 %a, i32 %b) #0 {319; This is mostly the same as cycle_join_not_dominated, the only difference is320; the dfs visiting order, so the cycle analysis result is different.321; entry322; | |323; ---> H |324; | / \ v325; | B<--C(div)326; ^ \ /327; \----D328; |329; X330; CHECK-LABEL: for function 'cycle_join_not_dominated2':331; CHECK-NOT: DIVERGENT: %uni.332 333entry:334 %tid = call i32 @llvm.amdgcn.workitem.id.x()335 %div.cond = icmp slt i32 %tid, 0336 %uni.cond = icmp slt i32 %a, 0337 br i1 %uni.cond, label %H, label %C338 339H:340 %div.merge.h = phi i32 [ 0, %entry ], [ %b, %D ]341 br i1 %uni.cond, label %B, label %C342 343B:344 %div.merge.b = phi i32 [ 0, %H ], [ %b, %C ]345 %div.inc.b = add i32 %div.merge.b, 1346; CHECK: DIVERGENT: %div.inc.b347 br label %D348 349C:350 %div.merge.c = phi i32 [0, %entry], [%div.merge.h, %H]351 %div.inc.c = add i32 %div.merge.c, 2352; CHECK: DIVERGENT: %div.inc.c353 br i1 %div.cond, label %D, label %B ; divergent branch354 355D:356 %div.merge.d = phi i32 [ %div.inc.b, %B ], [ %div.inc.c, %C ]357; CHECK: DIVERGENT: %div.merge.d358 br i1 %uni.cond, label %X, label %H359 360X:361 ret void362}363 364define amdgpu_kernel void @natural_loop_two_backedges(i32 %n, i32 %a, i32 %b) #0 {365; FIXME: the uni.merge.h can be viewed as uniform.366; CHECK-LABEL: for function 'natural_loop_two_backedges':367 368entry:369 %tid = call i32 @llvm.amdgcn.workitem.id.x()370 %div.cond = icmp slt i32 %tid, 0371 %uni.cond = icmp slt i32 %a, 0372 br label %H373 374H:375 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %B ], [ %uni.inc, %C]376 %uni.inc = add i32 %uni.merge.h, 1377 br label %B378 379B:380 br i1 %div.cond, label %C, label %H381 382C:383 br i1 %uni.cond, label %X, label %H384 385X:386 ret void387}388 389define amdgpu_kernel void @natural_loop_two_backedges2(i32 %n, i32 %a, i32 %b) #0 {390; FIXME: the uni.merge.h can be viewed as uniform.391; CHECK-LABEL: for function 'natural_loop_two_backedges2':392 393entry:394 %tid = call i32 @llvm.amdgcn.workitem.id.x()395 %div.cond = icmp slt i32 %tid, 0396 %uni.cond = icmp slt i32 %a, 0397 br label %H398 399H:400 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %B ], [ %uni.inc, %C]401 %uni.inc = add i32 %uni.merge.h, 1402 br i1 %uni.cond, label %B, label %D403 404B:405 br i1 %div.cond, label %C, label %H406 407C:408 br label %H409 410D:411 br i1 %uni.cond, label %B, label %X412 413X:414 ret void415}416 417define amdgpu_kernel void @cycle_enter_nested(i32 %n, i32 %a, i32 %b) #0 {418;419; entry(div)420; | \421; --> H1 |422; / | |423; | -> H2 |424; | | | /425; | \--B <--426; ^ |427; \----C428; |429; X430; CHECK-LABEL: for function 'cycle_enter_nested':431; CHECK-NOT: DIVERGENT: %uni.432; CHECK-NOT: DIVERGENT: br i1 %uni.433 434entry:435 %tid = call i32 @llvm.amdgcn.workitem.id.x()436 %div.cond = icmp slt i32 %tid, 0437 %uni.cond = icmp slt i32 %a, 0438 br i1 %div.cond, label %B, label %H1439 440H1:441 %div.merge.h1 = phi i32 [ 1, %entry ], [ %b, %C ]442 br label %H2443; CHECK: DIVERGENT: %div.merge.h1444 445H2:446 %div.merge.h2 = phi i32 [ 2, %B ], [ %a, %H1 ]447; CHECK: DIVERGENT: %div.merge.h2448 br label %B449 450B:451 %div.merge.b = phi i32 [0, %entry], [%a, %H2]452; CHECK: DIVERGENT: %div.merge.b453 br i1 %uni.cond, label %C, label %H2454 455C:456 br i1 %uni.cond, label %X, label %H1457 458X:459 ret void460}461 462define amdgpu_kernel void @cycle_inner_exit_enter(i32 %n, i32 %a, i32 %b) #0 {463; entry464; / \465; E1-> A-> E2466; ^ | \467; | E3-> E4468; | ^ /469; | \ /470; C <----B471; |472; X473; CHECK-LABEL: for function 'cycle_inner_exit_enter':474; CHECK-NOT: DIVERGENT: %uni.475; CHECK-NOT: DIVERGENT: br i1 %uni.476 477entry:478 %tid = call i32 @llvm.amdgcn.workitem.id.x()479 %div.cond = icmp slt i32 %tid, 0480 %uni.cond = icmp slt i32 %a, 0481 br i1 %uni.cond, label %E2, label %E1482 483E1:484 %div.merge.e1 = phi i32 [ 1, %entry ], [ %b, %C ]485 br label %A486; CHECK: DIVERGENT: %div.merge.e1487 488A:489 br i1 %uni.cond, label %E2, label %E3490 491E2:492 %div.merge.e2 = phi i32 [ 2, %entry ], [ %a, %A ]493; CHECK: DIVERGENT: %div.merge.e2494 br label %E4495 496E3:497 %div.merge.e3 = phi i32 [ 0, %A ], [ %b, %B ]498; CHECK: DIVERGENT: %div.merge.e3499 br label %E4500 501E4:502 %div.merge.e4 = phi i32 [ 0, %E2 ], [ %a, %E3 ]503; CHECK: DIVERGENT: %div.merge.e4504 br label %B505 506B:507 br i1 %div.cond, label %C, label %E3508 509C:510 br i1 %uni.cond, label %X, label %E1511 512X:513 ret void514}515 516define amdgpu_kernel void @cycle_inner_exit_enter2(i32 %n, i32 %a, i32 %b) #0 {517; This case is almost the same as cycle_inner_exit_enter, with only different518; dfs visiting order, thus different cycle hierarchy.519; entry520; / \521; E1-> A-> E2522; ^ | \523; | E3-> E4524; | ^ /525; | \ /526; C <----B527; |528; X529; CHECK-LABEL: for function 'cycle_inner_exit_enter2':530; CHECK-NOT: DIVERGENT: %uni.531; CHECK-NOT: DIVERGENT: br i1 %uni.532 533entry:534 %tid = call i32 @llvm.amdgcn.workitem.id.x()535 %div.cond = icmp slt i32 %tid, 0536 %uni.cond = icmp slt i32 %a, 0537 br i1 %uni.cond, label %E1, label %E2538 539E1:540 %div.merge.e1 = phi i32 [ 1, %entry ], [ %b, %C ]541 br label %A542; CHECK: DIVERGENT: %div.merge.e1543 544A:545 br i1 %uni.cond, label %E2, label %E3546 547E2:548 %div.merge.e2 = phi i32 [ 2, %entry ], [ %a, %A ]549; CHECK: DIVERGENT: %div.merge.e2550 br label %E4551 552E3:553 %div.merge.e3 = phi i32 [ 0, %A ], [ %b, %B ]554; CHECK: DIVERGENT: %div.merge.e3555 br label %E4556 557E4:558 %div.merge.e4 = phi i32 [ 0, %E2 ], [ %a, %E3 ]559; CHECK: DIVERGENT: %div.merge.e4560 br label %B561 562B:563 br i1 %div.cond, label %C, label %E3564 565C:566 br i1 %uni.cond, label %X, label %E1567 568X:569 ret void570}571 572define amdgpu_kernel void @always_uniform() {573; CHECK-LABEL: UniformityInfo for function 'always_uniform':574; CHECK: CYCLES ASSUMED DIVERGENT:575; CHECK: depth=1: entries(bb2 bb3)576 577bb:578 %inst = tail call i32 @llvm.amdgcn.mbcnt.hi(i32 0, i32 0)579 %inst1 = icmp ugt i32 %inst, 0580 br i1 %inst1, label %bb3, label %bb2581; CHECK: DIVERGENT: %inst = tail call i32 @llvm.amdgcn.mbcnt.hi(i32 0, i32 0)582; CHECK: DIVERGENT: %inst1 = icmp ugt i32 %inst, 0583; CHECK: DIVERGENT: br i1 %inst1, label %bb3, label %bb2584 585bb2: ; preds = %bb3, %bb586 br label %bb3587 588bb3: ; preds = %bb2, %bb589 %inst4 = tail call i64 @llvm.amdgcn.icmp.i64.i16(i16 0, i16 0, i32 0)590 %inst5 = trunc i64 %inst4 to i32591 %inst6 = and i32 0, %inst5592 br label %bb2593; CHECK-LABEL: BLOCK bb3594; CHECK-NOT: DIVERGENT: {{.*}} call i64 @llvm.amdgcn.icmp.i64.i16595; CHECK: DIVERGENT: %inst5 = trunc i64 %inst4 to i32596; CHECK: DIVERGENT: %inst6 = and i32 0, %inst5597}598 599declare i32 @llvm.amdgcn.mbcnt.hi(i32, i32)600 601declare i64 @llvm.amdgcn.icmp.i64.i16(i16, i16, i32 immarg)602 603declare i32 @llvm.amdgcn.workitem.id.x() #0604 605attributes #0 = { nounwind readnone }606