This is an archive of the discontinued LLVM Phabricator instance.

[FastISel][X86] If selectFNeg fails, fall back to SelectionDAG not treating it as an fsub.
ClosedPublic

Authored by craig.topper on May 6 2019, 4:40 PM.

Details

Summary

If fneg lowering for fsub -0.0, x fails we currently fall back to treating it as an fsub. This has different behavior for nans than the xor with sign bit trick we normally try to do. On X86, the xor trick for double fails fast-isel in 32-bit mode with sse2 due to 64 bit integer types not being available. With -O2 we would always use an xorpd for this case. If we use subsd, this creates an observable behavior difference between -O0 and -O2. So fall back to SelectionDAG if we can't fast-isel it, that way SelectionDAG will use the xorpd.

I believe this patch is restoring the behavior prior to r345295 from last October. This was missed then because our fast isel case in 32-bit mode aborted fast-isel earlier for another reason. But I've added new tests to cover that.

Diff Detail

Event Timeline

craig.topper created this revision.May 6 2019, 4:40 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 6 2019, 4:40 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
llvm/test/CodeGen/X86/fast-isel-fneg.ll
68

The general idea is good, but I'm failing to see how this instruction changed from subsd to xorps. Am I missing something subtle?

craig.topper marked an inline comment as done.May 6 2019, 5:58 PM
craig.topper added inline comments.
llvm/test/CodeGen/X86/fast-isel-fneg.ll
68

The subsd was being emited by selectBinary after selectFNeg returned false. With this change we don't go into selectBinary there anymore for fsub -0.0, x. Instead we return false from selectOperator when selectFNeg fails. This causes fast instruction selection to abort and we'll instead generate a SelectionDAG for the fneg and everything that comes before it. Then we go through normal DAG combines and operation legalization on the SelectionDAG. This causes the LowerFNEGOrFABS code in X86ISelLowering.cpp to execute. This will generate a vector xor. This bad for compile time since we SelectionDAG is slower than just emitting the fsub, but its more correct for this case.

I think once we fail out of SelectOperator we may have another chance to handle this via the target specific fastSelectInstruction hook. We might be able to generate the xorps code manually from there and avoid the SelectionDAG fallback. But I wanted to get a correct implementation first before an optimal one.

Ah, I see it now. Thanks for the explanation.

I'd like to review this, but the FastISel code under the hood is outside of my domain. If no one else chimes in, I'll dig into it tomorrow.

cameron.mcinally accepted this revision.May 6 2019, 6:16 PM

Actually, I take that back. Was just doing a post-mortem on D53650 and this makes perfect sense now. I tried to combine a isFNeg(...) and getFNegArgument(...) into one match, but I botched it. Sorry you had to track that down.

This LGTM!

This revision is now accepted and ready to land.May 6 2019, 6:16 PM

Ah, I see it now. Thanks for the explanation.

I'd like to review this, but the FastISel code under the hood is outside of my domain. If no one else chimes in, I'll dig into it tomorrow.

If nothing else, I think you can at least confirm this returns things back to the behavior that would have existed prior to r345295

Ah, I see it now. Thanks for the explanation.

I'd like to review this, but the FastISel code under the hood is outside of my domain. If no one else chimes in, I'll dig into it tomorrow.

If nothing else, I think you can at least confirm this returns things back to the behavior that would have existed prior to r345295

And by behavior I mean from a control flow perspective in this file.

I approved it. Yeah, I see the bug now. selectFNeg(...) should have just returned false and not continued on to selectBinaryOp(...). That was a dumb mistake.

This revision was automatically updated to reflect the committed changes.