[llvm-dev] Hoisting convergent function calls

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[llvm-dev] Hoisting convergent function calls

Matthias Braun via llvm-dev

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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] Hoisting convergent function calls

Matthias Braun via llvm-dev
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
<[hidden email]> 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
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev