[llvm-commits] [llvm-gcc-4.2] r55796 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp

Dale Johannesen dalej at apple.com
Tue Sep 9 11:48:22 PDT 2008


I am not planning to do a complete rewrite of the intrinsic handling.
My high-level thoughts on how it should work, fwiw:

Language dependencies are the job of the FE.

Target dependencies are the job of the BE.

One issue is c89 handling, which requires errno and has a lot less  
other stuff specified.  Because of errno c89 libm calls cannot be  
implemented correctly on Darwin.   My feeling is that probably every  
target would find c99 intrinsic handling acceptable at this point, as  
regards errno, rounding mode, etc., so we shouldn't worry about c89 in  
this area.

Applying these principles results in some differences from what you  
have:

Whether an intrinsic reads the rounding mode is a language property.   
AFAIK there is no need for "pow that doesn't read rounding mode"  
because no language has such functionality.  It may be that a  
particular implementation doesn't need the rounding mode;  the BE is  
permitted to do target-dependent optimizations if it knows that.

Whether an implementation sets errno (as Darwin does not) is a target  
dependency.  c99 does not require it.  Again a target may do target- 
dependent optimizations if it wants.  (Of course this property may be  
shared by many targets so some abstraction would be useful; I am not  
saying these optimizations belong in the X86-specific code, for  
example.)

So, I don't think it's necessary to represent either of these  
properties in the IR as such; some abstraction such as "readnone" is  
useful on the intrinsic definitions since there is much commonality,  
but that would not be strictly necessary either.

If you're interested in working in this area, IMO the most useful  
thing would be to add a real representation for rounding mode in the  
BE.  Typically it is read by many instructions and intrinsics, and  
changed by only a few.  Once we can deal with "reads rounding mode but  
not memory" intelligently we can get somewhere with optimizations.

On Sep 9, 2008, at 1:07 AMPDT, Duncan Sands wrote:

>>> Hi Dale, thinking about this more, I started wondering
>>> why you want to produce llvm.pow and friends at all.
>>> Does it actually bring any advantage?
>>
>> Functionally, no, the point is to get C semantics out of the  
>> optimizers.
>
> Well, given that you have several versions of each routine
> (eg: pow that writes errno, pow that does not write errno
> but uses the rounding mode, pow that does not write errno
> and does not use the rounding mode), that makes for a lot
> of intrinsics!  Don't forget that SimplifyLibcalls performs
> simplifications that apply to all those different pow variants.
>
> That said, I think it is useful to distinguish between
> SimplifyLibcalls (SLC) and the rest of the compiler.
> The SLC pass is special in that it only exists to muck
> around with the standard system library, so it's not
> unreasonable that it recognizes standard library functions.
> It can always be turned off (llvm-gcc has logic for that).
>
> So, excluding SLC, what about the rest of the compiler?
>
> Well, ConstantFolding.cpp will constant fold a range of
> libcalls too.  That's not so great - something should be
> done about this (not sure what).  Probably llvm-gcc's
> logic should turn this off too, but it currently doesn't...
>
> The other place is codegen:
> SelectionDAGBuild.cpp turns several things into SDNodes:
> not just pow and cos intrinsics but also functions called
> "cos".  Two comments about this: (1) it implies that the
> llvm intrinsics must be readnone and not readonly; (2) I
> think the recognizing of names like "sin" should be dropped
> and only intrinsics used here (this is maybe what you had in
> mind). Let me explain (1): why an SDNode shouldn't be generated
> unless the function is readnone.  Consider the following
> program:
>
> declare double @cos( double ) readonly nounwind
> declare void @change_the_rounding_mode() nounwind
>
> define double @f(double %X) readonly nounwind {
>  %a = call double @cos( double %X ) readonly nounwind
>  call void @change_the_rounding_mode() nounwind
>  %b = call double @cos( double %X ) readonly nounwind
>  %c = add double %a, %b
>  ret double %c
> }
>
> Then the bitcode optimizers like GVN (correctly) do not
> remove the second call, even though it is the same as the
> first, because the change_rounding_mode call may change
> the result.  But codegen does!  Here is the result:
>
> f:
>        subq    $8, %rsp
>        movsd   %xmm0, (%rsp)
>        call    change_the_rounding_mode
>        movsd   (%rsp), %xmm0
>        call    cos
>        addsd   %xmm0, %xmm0
>        addq    $8, %rsp
>        ret
>
> The reason is simple enough: the call to "cos" is turned
> into an SDNode, then CSE collapses the two "cos" calls
> into one.  This is only correct if "cos" is readnone.
>
> I think things should work like this:
> (a) codegen should only turn llvm math intrinsics into SDNodes
> (b) llvm math intrinsics should be readnone
> (c) llvm-gcc should generate an llvm intrinsic for a gcc builtin
> only when the builtin is "const" (= readnone).
> (d) maybe SimplifyLibcalls should also automagically turn readnone
> calls to "cos" etc into calls to llvm.cos etc.
>
> Ciao,
>
> Duncan.




More information about the llvm-commits mailing list