223 lines · plain
1; RUN: opt -mtriple amdgcn-unknown-amdhsa -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s2 3; divergent loop (H<header><exiting to X>, B<exiting to Y>)4; the divergent join point in %exit is obscured by uniform control joining in %X5define amdgpu_kernel void @hidden_loop_diverge(i32 %n, i32 %a, i32 %b) #0 {6; CHECK-LABEL: for function 'hidden_loop_diverge':7; CHECK-NOT: DIVERGENT: %uni.8; CHECK-NOT: DIVERGENT: br i1 %uni.9 10entry:11 %tid = call i32 @llvm.amdgcn.workitem.id.x()12 %uni.cond = icmp slt i32 %a, 013 br i1 %uni.cond, label %X, label %H ; uniform14 15H:16 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %B ]17 %div.exitx = icmp slt i32 %tid, 018 br i1 %div.exitx, label %X, label %B ; divergent branch19; CHECK: DIVERGENT: %div.exitx =20; CHECK: DIVERGENT: br i1 %div.exitx,21 22B:23 %uni.inc = add i32 %uni.merge.h, 124 %div.exity = icmp sgt i32 %tid, 025 br i1 %div.exity, label %Y, label %H ; divergent branch26; CHECK: DIVERGENT: %div.exity =27; CHECK: DIVERGENT: br i1 %div.exity,28 29X:30 %div.merge.x = phi i32 [ %a, %entry ], [ %uni.merge.h, %H ] ; temporal divergent phi31 br i1 %uni.cond, label %Y, label %exit32; CHECK: DIVERGENT: %div.merge.x =33 34Y:35 %div.merge.y = phi i32 [ 42, %X ], [ %b, %B ]36 br label %exit37; CHECK: DIVERGENT: %div.merge.y =38 39exit:40 %div.merge.exit = phi i32 [ %a, %X ], [ %b, %Y ]41 ret void42; CHECK: DIVERGENT: %div.merge.exit =43}44 45; divergent loop (H<header><exiting to X>, B<exiting to Y>)46; the phi nodes in X and Y don't actually receive divergent values47define amdgpu_kernel void @unobserved_loop_diverge(i32 %n, i32 %a, i32 %b) #0 {48; CHECK-LABEL: for function 'unobserved_loop_diverge':49; CHECK-NOT: DIVERGENT: %uni.50; CHECK-NOT: DIVERGENT: br i1 %uni.51 52entry:53 %tid = call i32 @llvm.amdgcn.workitem.id.x()54 %uni.cond = icmp slt i32 %a, 055 br i1 %uni.cond, label %X, label %H ; uniform56 57H:58 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %B ]59 %div.exitx = icmp slt i32 %tid, 060 br i1 %div.exitx, label %X, label %B ; divergent branch61; CHECK: DIVERGENT: %div.exitx =62; CHECK: DIVERGENT: br i1 %div.exitx,63 64B:65 %uni.inc = add i32 %uni.merge.h, 166 %div.exity = icmp sgt i32 %tid, 067 br i1 %div.exity, label %Y, label %H ; divergent branch68; CHECK: DIVERGENT: %div.exity =69; CHECK: DIVERGENT: br i1 %div.exity,70 71X:72 %uni.merge.x = phi i32 [ %a, %entry ], [ %b, %H ]73 br label %exit74 75Y:76 %uni.merge.y = phi i32 [ %b, %B ]77 br label %exit78 79exit:80 %div.merge.exit = phi i32 [ %a, %X ], [ %b, %Y ]81 ret void82; CHECK: DIVERGENT: %div.merge.exit =83}84 85; divergent loop (G<header>, L<exiting to D>) inside divergent loop (H<header>, B<exiting to X>, C<exiting to Y>, D, G, L)86; the inner loop has no exit to top level.87; the outer loop becomes divergent as its exiting branch in C is control-dependent on the inner loop's divergent loop exit in D.88define amdgpu_kernel void @hidden_nestedloop_diverge(i32 %n, i32 %a, i32 %b) #0 {89; CHECK-LABEL: for function 'hidden_nestedloop_diverge':90; CHECK-NOT: DIVERGENT: %uni.91; CHECK-NOT: DIVERGENT: br i1 %uni.92 93entry:94 %tid = call i32 @llvm.amdgcn.workitem.id.x()95 %uni.cond = icmp slt i32 %a, 096 %div.exitx = icmp slt i32 %tid, 097 br i1 %uni.cond, label %X, label %H98 99H:100 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %D ]101 br i1 %uni.cond, label %G, label %B102; CHECK: DIVERGENT: %div.exitx =103 104B:105 br i1 %uni.cond, label %X, label %C106 107C:108 br i1 %uni.cond, label %Y, label %D109 110D:111 %uni.inc = add i32 %uni.merge.h, 1112 br label %H113 114G:115 br i1 %div.exitx, label %C, label %L116; CHECK: DIVERGENT: br i1 %div.exitx,117 118L:119 br i1 %uni.cond, label %D, label %G120 121X:122 %uni.merge.x = phi i32 [ %a, %entry ], [ %uni.merge.h, %B ]123 br i1 %uni.cond, label %Y, label %exit124 125Y:126 %div.merge.y = phi i32 [ 42, %X ], [ %b, %C ]127 br label %exit128; CHECK: DIVERGENT: %div.merge.y =129 130exit:131 %div.merge.exit = phi i32 [ %a, %X ], [ %b, %Y ]132 ret void133; CHECK: DIVERGENT: %div.merge.exit =134}135 136; divergent loop (G<header>, L<exiting to X>) in divergent loop (H<header>, B<exiting to C>, C, G, L)137; the outer loop has no immediately divergent exiting edge.138; the inner exiting edge is exiting to top-level through the outer loop causing both to become divergent.139define amdgpu_kernel void @hidden_doublebreak_diverge(i32 %n, i32 %a, i32 %b) #0 {140; CHECK-LABEL: for function 'hidden_doublebreak_diverge':141; CHECK-NOT: DIVERGENT: %uni.142; CHECK-NOT: DIVERGENT: br i1 %uni.143 144entry:145 %tid = call i32 @llvm.amdgcn.workitem.id.x()146 %uni.cond = icmp slt i32 %a, 0147 %div.exitx = icmp slt i32 %tid, 0148 br i1 %uni.cond, label %X, label %H149 150H:151 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc, %C ]152 br i1 %uni.cond, label %G, label %B153; CHECK: DIVERGENT: %div.exitx =154 155B:156 br i1 %uni.cond, label %Y, label %C157 158C:159 %uni.inc = add i32 %uni.merge.h, 1160 br label %H161 162G:163 br i1 %div.exitx, label %X, label %L ; two-level break164; CHECK: DIVERGENT: br i1 %div.exitx,165 166L:167 br i1 %uni.cond, label %C, label %G168 169X:170 %div.merge.x = phi i32 [ %a, %entry ], [ %uni.merge.h, %G ] ; temporal divergence171 br label %Y172; CHECK: DIVERGENT: %div.merge.x =173 174Y:175 %div.merge.y = phi i32 [ 42, %X ], [ %b, %B ]176 ret void177; CHECK: DIVERGENT: %div.merge.y =178}179 180; divergent loop (G<header>, L<exiting to D>) contained inside a uniform loop (H<header>, B, G, L , D<exiting to x>)181define amdgpu_kernel void @hidden_containedloop_diverge(i32 %n, i32 %a, i32 %b) #0 {182; CHECK-LABEL: for function 'hidden_containedloop_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 %uni.cond = icmp slt i32 %a, 0189 %div.exitx = icmp slt i32 %tid, 0190 br i1 %uni.cond, label %X, label %H191 192H:193 %uni.merge.h = phi i32 [ 0, %entry ], [ %uni.inc.d, %D ]194 br i1 %uni.cond, label %G, label %B195; CHECK: DIVERGENT: %div.exitx =196 197B:198 %div.merge.b = phi i32 [ 42, %H ], [ %uni.merge.g, %G ]199 br label %D200; CHECK: DIVERGENT: %div.merge.b =201 202G:203 %uni.merge.g = phi i32 [ 123, %H ], [ %uni.inc.l, %L ]204 br i1 %div.exitx, label %B, label %L205; CHECK: DIVERGENT: br i1 %div.exitx,206 207L:208 %uni.inc.l = add i32 %uni.merge.g, 1209 br i1 %uni.cond, label %G, label %D210 211D:212 %uni.inc.d = add i32 %uni.merge.h, 1213 br i1 %uni.cond, label %X, label %H214 215X:216 %uni.merge.x = phi i32 [ %a, %entry ], [ %uni.inc.d, %D ]217 ret void218}219 220declare i32 @llvm.amdgcn.workitem.id.x() #0221 222attributes #0 = { nounwind readnone }223