226 lines · plain
1; RUN: opt %s -mtriple amdgcn-- -passes='print<uniformity>' -disable-output 2>&1 | FileCheck %s2 3;4; Entry5; |6; v7; -------->H---------8; | | |9; | v |10; | --->T---- |11; | | | |12; | | V |13; S<---R P <---14; ^ ^ |15; | | Div |16; | --- Q <--17; | |18; | v19; -------- U20; |21; v22; Exit23;24; The divergent branch is at Q that exits an irreducible cycle with25; entries T and P nested inside a reducible cycle with header H. R is26; assigned label R, which reaches P. S is a join node with label S. If27; this is propagated to P via H, then P is incorrectly recognized as a28; join, making the inner cycle divergent. P is always executed29; convergently -- either by threads that reconverged at header H, or30; by threads that are still executing the inner cycle. Thus, any PHI31; at P should not be marked divergent.32 33define amdgpu_kernel void @nested_irreducible(i32 %a, i32 %b, i32 %c) {34; CHECK=LABEL: UniformityInfo for function 'nested_irreducible':35; CHECK-NOT: CYCLES ASSUMED DIVERGENT:36; CHECK: CYCLES WITH DIVERGENT EXIT:37; CHECK-DAG: depth=2: entries(P T) R Q38; CHECK-DAG: depth=1: entries(H) S P T R Q U39entry:40 %cond.uni = icmp slt i32 %a, 041 %tid = call i32 @llvm.amdgcn.workitem.id.x()42 %cond.div = icmp slt i32 %tid, 043 br label %H44 45H:46 br i1 %cond.uni, label %T, label %P47 48P:49; CHECK-LABEL: BLOCK P50; CHECK-NOT: DIVERGENT: %pp.phi =51; CHECK-NOT: DIVERGENT: %pp =52 %pp.phi = phi i32 [ %a, %H], [ %b, %T ]53 %pp = add i32 %b, 154 br label %Q55 56Q:57; CHECK-LABEL: BLOCK Q58; CHECK-NOT: DIVERGENT: %qq =59; CHECK-NOT: DIVERGENT: %qq.uni =60 %qq = add i32 %b, 161 %qq.uni = add i32 %pp.phi, 162 br i1 %cond.div, label %R, label %U63 64R:65 br i1 %cond.uni, label %S, label %T66 67T:68; CHECK-LABEL: BLOCK T69; CHECK-NOT: DIVERGENT: %tt.phi =70; CHECK-NOT: DIVERGENT: %tt =71 %tt.phi = phi i32 [ %qq, %R ], [ %a, %H ]72 %tt = add i32 %b, 173 br label %P74 75S:76; CHECK-LABEL: BLOCK S77; CHECK: DIVERGENT: %ss.phi =78; CHECK-NOT: DIVERGENT: %ss =79 %ss.phi = phi i32 [ %qq.uni, %U ], [ %a, %R ]80 %ss = add i32 %b, 181 br label %H82 83U:84 br i1 %cond.uni, label %S, label %exit85 86exit:87; CHECK: DIVERGENT: %ee.div =88; CHECK-NOT: DIVERGENT: %ee =89 %ee.div = add i32 %qq.uni, 190 %ee = add i32 %b, 191 ret void92}93 94;95; Entry96; |97; v98; -->-------->H---------99; | ^ | |100; | | | |101; | | | |102; | | | |103; | | v V104; | R<-------T-->U--->P105; | Div |106; | |107; ----------- Q <-------108; |109; v110; Exit111;112; This is a reducible cycle with a divergent branch at T. Disjoint113; paths eventually join at the header H, which is assigned label H.114; Node P is assigned label U. If the header label were propagated to115; P, it will be incorrectly recgonized as a join. P is always executed116; convergently -- either by threads that reconverged at header H, or117; by threads that diverged at T (and eventually reconverged at H).118; Thus, any PHI at P should not be marked divergent.119 120define amdgpu_kernel void @header_label_1(i32 %a, i32 %b, i32 %c) {121; CHECK=LABEL: UniformityInfo for function 'header_label_1':122; CHECK-NOT: CYCLES ASSUMED DIVERGENT:123; CHECK: CYCLES WITH DIVERGENT EXIT:124; CHECK: depth=1: entries(H) Q P U T R125entry:126 %cond.uni = icmp slt i32 %a, 0127 %tid = call i32 @llvm.amdgcn.workitem.id.x()128 %cond.div = icmp slt i32 %tid, 0129 br label %H130 131H:132 br i1 %cond.uni, label %T, label %P133 134P:135; CHECK-LABEL: BLOCK P136; CHECK-NOT: DIVERGENT: %pp.phi =137; CHECK-NOT: DIVERGENT: %pp =138 %pp.phi = phi i32 [ %a, %H], [ %b, %U ]139 %pp = add i32 %b, 1140 br label %Q141 142Q:143; CHECK-LABEL: BLOCK Q144; CHECK-NOT: DIVERGENT: %qq =145; CHECK-NOT: DIVERGENT: %qq.uni =146 %qq = add i32 %b, 1147 %qq.uni = add i32 %pp.phi, 1148 br i1 %cond.uni, label %exit, label %H149 150R:151 br label %H152 153T:154 br i1 %cond.div, label %R, label %U155 156U:157 br label %P158 159exit:160; CHECK-LABEL: BLOCK exit161; CHECK: DIVERGENT: %ee.div =162; CHECK-NOT: DIVERGENT: %ee =163 %ee.div = add i32 %qq.uni, 1164 %ee = add i32 %b, 1165 ret void166}167 168; entry169; |170; --> H1171; | | \172; | | H2(div)173; | \ / \174; | B C175; ^ \ /176; \------D177; |178; X179;180; This is a reducible cycle with a divergent branch at H2. Disjoint181; paths eventually join at the header D, which is assigned label D.182; Node B is assigned label B. If the header label D were propagated to183; B, it will be incorrectly recgonized as a join. B is always executed184; convergently -- either by threads that reconverged at header H1, or185; by threads that diverge at H2 (and eventually reconverged at H1).186; Thus, any PHI at B should not be marked divergent.187 188define amdgpu_kernel void @header_label_2(i32 %a, i32 %b, i32 %c) {189; CHECK-LABEL: UniformityInfo for function 'header_label_2':190; CHECK-NOT: CYCLES ASSUMED DIVERGENT:191; CHECK-NOT: CYCLES WITH DIVERGENT EXIT:192entry:193 %cond.uni = icmp slt i32 %a, 0194 %tid = call i32 @llvm.amdgcn.workitem.id.x()195 %cond.div = icmp slt i32 %tid, 0196 br label %H1197 198H1:199 br i1 %cond.uni, label %B, label %H2200 201H2:202 br i1 %cond.div, label %B, label %C203 204B:205; CHECK-LABEL: BLOCK B206; CHECK-NOT: DIVERGENT: %bb.phi =207 %bb.phi = phi i32 [%a, %H1], [%b, %H2]208 br label %D209 210C:211 br label %D212 213D:214; CHECK-LABEL: BLOCK D215; CHECK: DIVERGENT: %dd.phi =216 %dd.phi = phi i32 [%a, %B], [%b, %C]217 br i1 %cond.uni, label %exit, label %H1218 219exit:220 %ee.1 = add i32 %dd.phi, 1221 %ee.2 = add i32 %b, 1222 ret void223}224 225declare i32 @llvm.amdgcn.workitem.id.x() #0226