Woo, David J via llvm-dev
2017-Aug-18 18:37 UTC
[llvm-dev] Hoisting convergent function calls
Hi, Is it a bug for optimization passes to hoist calls to convergent functions out of control flow? If I run SimplifyCFG on test/Transforms/GVNHoist/hoist-convergent.ll it will do this and EarlyCSE does it as well when run on the following LLVM IR: define float @no_convergent_func_hoisting(float %d, float %min, float %max, float %a) { entry: %div = fdiv float 1.000000e+00, %d %cmp = fcmp oge float %div, 0.000000e+00 %sub1 = fsub float %max, %a %c = call float @convergent_func(float %sub1, float %div) br i1 %cmp, label %if.then, label %if.else if.then: %mul2 = call float @convergent_func(float %sub1, float %div) br label %if.end if.else: %mul6 = call float @convergent_func(float %sub1, float %div) br label %if.end if.end: %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] %add = fadd float %tmax.0, %c ret float %add } declare float @convergent_func(float, float) #0 attributes #0 = { nounwind readnone convergent } The LLVM language reference says this behavior isn't a bug since it only forbids making functions control-dependent on additional values, and this is removing a control dependence. However, the hoist-convergent test seems to indicate that convergent functions should not be hoisted, and this is necessary for implementing cross-invocation operations like OpenGL's ballotARB() since it could affect which invocations are active when the function is called. Thanks, David -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170818/cd352b72/attachment.html>
Connor Abbott via llvm-dev
2017-Aug-19 21:54 UTC
[llvm-dev] Hoisting convergent function calls
Hi, Yes, convergent function calls are allowed to be hoisted. They're supposed to model operations like derivatives and readInvocation() that give the same result as long as the set of active invocations is only ever enlarged. For ballotARB() and friends which can't be hoisted, you need to add something else. RadeonSI, which supports the ARB_shader_ballot GL extension with ballotARB(), adds a side-effecting inline asm instruction beforehand to keep LLVM from hoisting the call: https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/radeonsi/si_shader.c#n3475 but that's obviously pretty bad, and won't work at all if the function calling ballotARB() isn't the entrypoint. Maybe just removing IsSpeculatable will work? Athough I don't know if I fully understand that attribute to be honest. The test you referenced seems wrong to me. At the very least, whether the function can be hoisted has nothing to do with whether it's convergent or not. Seems like Matt added it a long time ago. maybe he can explain if there's some subtlety I missed. Connor On Fri, Aug 18, 2017 at 2:37 PM, Woo, David J via llvm-dev <llvm-dev at lists.llvm.org> wrote:> Hi, > > Is it a bug for optimization passes to hoist calls to convergent functions > out of control flow? If I run SimplifyCFG on > test/Transforms/GVNHoist/hoist-convergent.ll it will do this and EarlyCSE > does it as well when run on the following LLVM IR: > > define float @no_convergent_func_hoisting(float %d, float %min, float %max, > float %a) { > > entry: > > %div = fdiv float 1.000000e+00, %d > > %cmp = fcmp oge float %div, 0.000000e+00 > > %sub1 = fsub float %max, %a > > %c = call float @convergent_func(float %sub1, float %div) > > br i1 %cmp, label %if.then, label %if.else > > if.then: > > %mul2 = call float @convergent_func(float %sub1, float %div) > > br label %if.end > > if.else: > > %mul6 = call float @convergent_func(float %sub1, float %div) > > br label %if.end > > if.end: > > %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] > > %add = fadd float %tmax.0, %c > > ret float %add > > } > > declare float @convergent_func(float, float) #0 > > attributes #0 = { nounwind readnone convergent } > > The LLVM language reference says this behavior isn’t a bug since it only > forbids making functions control-dependent on additional values, and this is > removing a control dependence. However, the hoist-convergent test seems to > indicate that convergent functions should not be hoisted, and this is > necessary for implementing cross-invocation operations like OpenGL’s > ballotARB() since it could affect which invocations are active when the > function is called. > > Thanks, > > David > > > > > > > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >