This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] use saturating FP casts when compiling with "no-strict-float-cast-overflow"
ClosedPublic

Authored by spatel on Dec 15 2021, 7:56 AM.

Details

Summary

We got an unintended consequence of the optimizer getting smarter when compiling in a non-standard mode, and there's no good way to inhibit those optimizations at a later stage. The test is based on an example linked from D92270.

We allow the "no-strict-float-cast-overflow" exception to normal C cast rules to preserve legacy code that does not expect overflowing casts from FP to int to produce UB. See D46236 for details.

Diff Detail

Event Timeline

spatel created this revision.Dec 15 2021, 7:56 AM
nikic added a comment.Dec 15 2021, 8:02 AM

Looks reasonable. Making float to int cast well defined is exactly why these intrinsics exist. Should we also drop the "string-float-cast-overflow" attribute, as UB is now prevented in a different way?

Looks reasonable. Making float to int cast well defined is exactly why these intrinsics exist. Should we also drop the "string-float-cast-overflow" attribute, as UB is now prevented in a different way?

Yes, that sounds like a good enhancement. The only in-tree use of the attribute is in DAGCombiner. Make that a follow-up patch or two since it crosses into LLVM?
If we care about perf of the generated code in those cases, then we need to add something to the optimizer or codegen to recognize patterns like this:

define float @s(float %x) {
  %i = call i32 @llvm.fptosi.sat.i32.f32(float %x)
  %f = sitofp i32 %i to float
  ret float %f
}

This sounds like a great fix to me! :)

nikic accepted this revision.Dec 16 2021, 3:28 AM

LGTM

Looks reasonable. Making float to int cast well defined is exactly why these intrinsics exist. Should we also drop the "string-float-cast-overflow" attribute, as UB is now prevented in a different way?

Yes, that sounds like a good enhancement. The only in-tree use of the attribute is in DAGCombiner. Make that a follow-up patch or two since it crosses into LLVM?

Followup sounds good.

This revision is now accepted and ready to land.Dec 16 2021, 3:28 AM
This revision was landed with ongoing or failed builds.Dec 16 2021, 6:26 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptDec 16 2021, 6:26 AM

What's the plan for constrained intrinsics versions of these intrinsics? The IRBuilder calls for CreateFPToSI and CreateFPToUI are strict FP aware, but this new code isn't.

What's the plan for constrained intrinsics versions of these intrinsics? The IRBuilder calls for CreateFPToSI and CreateFPToUI are strict FP aware, but this new code isn't.

Not sure. cc'ing @kpn @sepavloff @andrew.w.kaylor
The saturating intrinsics implement non-standard behavior for C languages AFAIK, so we might want to warn if someone tries to use "-fno-strict-float-cast-overflow" and "-ffp-exception-behavior=strict" at the same time? Or we try to support that corner case by adding even more FP intrinsics?

What's the plan for constrained intrinsics versions of these intrinsics? The IRBuilder calls for CreateFPToSI and CreateFPToUI are strict FP aware, but this new code isn't.

Not sure. cc'ing @kpn @sepavloff @andrew.w.kaylor
The saturating intrinsics implement non-standard behavior for C languages AFAIK, so we might want to warn if someone tries to use "-fno-strict-float-cast-overflow" and "-ffp-exception-behavior=strict" at the same time? Or we try to support that corner case by adding even more FP intrinsics?

Conversion float->int depends on rounding mode. At least on some ML cores this conversion is made with saturating semantics. So ability to specify rounding mode would be useful for such targets.

kpn added a comment.Dec 21 2021, 10:35 AM

What's the plan for constrained intrinsics versions of these intrinsics? The IRBuilder calls for CreateFPToSI and CreateFPToUI are strict FP aware, but this new code isn't.

Not sure. cc'ing @kpn @sepavloff @andrew.w.kaylor
The saturating intrinsics implement non-standard behavior for C languages AFAIK, so we might want to warn if someone tries to use "-fno-strict-float-cast-overflow" and "-ffp-exception-behavior=strict" at the same time? Or we try to support that corner case by adding even more FP intrinsics?

Conversion float->int depends on rounding mode. At least on some ML cores this conversion is made with saturating semantics. So ability to specify rounding mode would be useful for such targets.

What about the idea of using operand bundles? I think the idea there was to avoid having to add new intrinsics for every target-specific floating point intrinsic. But maybe the idea will work here as well?

I think we definitely need to warn when -ffp-exception-behavior=strict or =maytrap is given and incompatible options are also used with it. In that case we should also be disabling the -ffp-exception-behavior option and the related #pragmas plus warning about the disabling. We already disable+warn when our backend doesn't support strictfp, we can do the same here.

If someone in the future wants to implement the support then that'll be nice. But in the meantime we shouldn't be silently letting people use strictfp plus a contradictory option.