FW: clarification needed for the constrained fp implementation.

Copying the list on a discussion of potentially general interest….

double someFunc(double A, double B, bool ForceRoundUp) {

I think that, however we do this, we’ll need a way of dealing with “live in” and “live out” FP-environment state. Moreover, any external call can change these as well (unless we prove/know that it doesn’t). Translating these calls into intrinsics so that the optimizer can reason about them seems like a reasonable plan. -Hal

A little bit of curiously. What if user doesn’t restore the OldRM like this:

double someFunc(double A, double B, bool ForceRoundUp) {

#pragma STDC FENV_ACCESS ON

double Result;

if (ForceRoundUp) {

int OldRM = fegetround();

fesetround(FE_UPWARD);

Result = A/B;

// fesetround(OldRM);

} else {

Result = A/B;

}

return Result;

}

Are we still going to generate llvm.begin.local.roundingmode/llvm.end.local.roundingmode?

I was actually thinking that fegetround and fesetround would always be translated into llvm.get.roundingmode and llvm.set.roundingmode at least initially, because it’s a bit of trouble to prove that they are being used to implement the local rounding mode idiom. Certainly recognizing that kind of usage is more work than a front end should be doing.

I would propose the begin/end local rounding mode intrinsics as a convenience for cases where some user (probably never clang) specifically knew that this was the intended behavior. I believe Wei has a use case like that, and I’ve also spoken to someone working on the Julia language who would like to be able to do this.

That does still leave the problem of what happens if there is a function call inside a pair of begin/end local rounding mode intrinsics. I’m not entirely sure the best way to handle this. Do we try to restrict calls that might change the rounding mode or do we leave it up to the front end and/or user to make sure things are safe.

As for the C/FENV_ACCESS case, I seriously feel like the way that pragma is defined leaves users with a huge amount of room to shoot themselves in the foot. If I’m reading the specifications correctly, it says that changing from a scope with FENV_ACCESS on to a scope with FENV_ACCESS off or vice versa without the FP environment in its default state is undefined behavior. At some point it would probably be nice to have a sanitizer that checks this.

-Andy

I was actually thinking that fegetround and fesetround would always be
translated into llvm.get.roundingmode and llvm.set.roundingmode at least
initially, because it’s a bit of trouble to prove that they are being used
to implement the local rounding mode idiom. Certainly recognizing that kind
of usage is more work than a front end should be doing.

I would propose the begin/end local rounding mode intrinsics as a
convenience for cases where some user (probably never clang) specifically
knew that this was the intended behavior. I believe Wei has a use case
like that, and I’ve also spoken to someone working on the Julia language
who would like to be able to do this.

Okay.

That does still leave the problem of what happens if there is a function
call inside a pair of begin/end local rounding mode intrinsics. I’m not
entirely sure the best way to handle this. Do we try to restrict calls
that might change the rounding mode or do we leave it up to the front end
and/or user to make sure things are safe.

​From the 2011 discussion thread on Intel Forum [1], seems the pragma only
affects the function containing it. That sounds reasonable to me.

[1] Software - Intel Communities

As for the C/FENV_ACCESS case, I seriously feel like the way that pragma
is defined leaves users with a huge amount of room to shoot themselves in
the foot. If I’m reading the specifications correctly, it says that
changing from a scope with FENV_ACCESS on to a scope with FENV_ACCESS off
or vice versa without the FP environment in its default state is undefined
behavior. At some point it would probably be nice to have a sanitizer that
checks this.

I think you can just implement the pragma without worrying too much about
how user might mis-use them. Leave the front-end or sanitizer to take care
of those issues.

From the 2011 discussion thread on Intel Forum [1], seems the pragma only affects the function containing it. That sounds reasonable to me.

[1] Software - Intel Communities

The discussion there is a bit unclear and seems to at least in part refer to how the pragma is implemented by the Intel compiler. According to the C99 standard the FENV_ACCESS pragma can appear either outside of any function scope or within the body of a function. If it occurs outside of any function then it applies until another FENV_ACCESS pragma appears to change the state or until the end of the translation unit.

If it occurs within the body of a function, the standard says it only applies from the point where it appears until the end of the compound statement (or until another instance of the pragma is seen). However, in practice this would be fairly difficult to implement. In an earlier discussion (http://lists.llvm.org/pipermail/cfe-dev/2017-August/055309.html) we agreed that the LLVM implementation would use the constrained intrinsics for all floating point operations within a function if the “FENV_ACCESS ON” state applied anywhere in the function. This is basically what the discussion above says happens in the Intel compiler. It’s more than the standard requires, but it still results in correct code.

If you were saying that the pragma does not apply to functions that are called from within an FENV_ACCESS ON state unless the pragma was also used for the called function, I think that’s correct. It just isn’t necessarily obvious and might trip some people up. My understanding is that it is the user’s responsibility to ensure that the FP environment is in the correct state.

I think you can just implement the pragma without worrying too much about how user might mis-use them. Leave the front-end or sanitizer to take care of those issues.

I agree. I’ve just been starting to think about ways we can help users figure out what they did wrong, so I wanted to mention it.

-Andy