This is an archive of the discontinued LLVM Phabricator instance.

[mips] Add support for -modd-spreg/-mno-odd-spreg
ClosedPublic

Authored by dsanders on Jul 4 2014, 1:52 AM.

Details

Summary

When -mno-odd-spreg is in effect, 32-bit floating point values are not
permitted in odd FPU registers. The option also prohibits 32-bit and 64-bit
floating point comparison results from being written to odd registers.

This option has three purposes:

  • It allows support for certain MIPS implementations such as loongson-3a that do not allow the use of odd registers for single precision arithmetic.
  • When using -mfpxx, -mno-odd-spreg is the default and this allows us to statically check that code is compliant with the O32 FPXX ABI since mtc1/mfc1 instructions to/from odd registers are guaranteed not to appear for any reason. Once this has been established, the user can then re-enable -modd-spreg to regain the use of all 32 single-precision registers.
  • When using -mfp64 and -mno-odd-spreg together, an O32 extension named O32 FP64A is used as the ABI. This is intended to provide almost all functionality of an FR=1 processor but can also be executed on a FR=0 core with the assistance of a hardware compatibility mode which emulates FR=0 behaviour on an FR=1 processor.
  • Added '.module oddspreg' and '.module nooddspreg' each of which update the .MIPS.abiflags section appropriately
  • Moved setFpABI() call inside emitDirectiveModuleFP() so that the caller doesn't have to remember to do it.
  • MipsABIFlags now calculates the flags1 and flags2 member on demand rather than trying to maintain them in the same format they will be emitted in.

Diff Detail

Event Timeline

dsanders updated this revision to Diff 11078.Jul 4 2014, 1:52 AM
dsanders retitled this revision from to [mips] Add support for -modd-spreg/-mno-odd-spreg.
dsanders updated this object.
dsanders edited the test plan for this revision. (Show Details)
dsanders added reviewers: mpf, vmedic.
mpf edited edge metadata.Jul 4 2014, 3:56 AM

You will probably need to add two further test cases.

  1. nooddspreg with n32 or n64 raises an error
  2. nooddspreg with O32 FP32 behaves in a similar fashion to the O32 FP64 test cases

I have not applied and checked the overall behaviour of these patches. I'll hold off until the FP64A fpabi is set correctly when fp64 nooddspreg is set.

lib/Target/Mips/Mips.td
76

This seems somehow inconstant. One option is "nooddspreg" but everything else is postitive phrased as enable 'oddspreg'. Is this correct?

lib/Target/Mips/MipsAsmPrinter.cpp
710

Change to test for O32

lib/Target/Mips/MipsRegisterInfo.cpp
204

change to test for O32 instead of FP64.

lib/Target/Mips/MipsSubtarget.cpp
155

Can you change this to check for !O32 instead of !FP64.

dsanders updated this revision to Diff 11089.Jul 4 2014, 8:18 AM
dsanders edited edge metadata.

Add an error message to CodeGen and AsmParser paths. This is unfriendly message
is concealed by a nicer message in the AsmParser and will be concealed by
clang for the CodeGen path.

Test for O32 where requested.

Added the requested test cases.

Tidied a couple inconsistencies I noticed along the way.

dsanders updated this revision to Diff 11090.Jul 4 2014, 8:20 AM

Forgot to explain the fixme in nooddspreg.s

nooddspreg with n32 or n64 raises an error

I think it's best we raise that error in the frontend for the CodeGen path. I've added a last-chance error to the backend and a nicer error to the assembly parser.

lib/Target/Mips/Mips.td
76

Unfortunately it seems so. If I can find a way to do it consistently with the others then I'll change it. The problem is that the default feature string is empty and the constructors of MipsSubtarget don't consistently provide a way to enable a feature by default.

The alternative was to require -mattr=+oddspreg on all invocations.

dsanders updated this revision to Diff 11146.Jul 8 2014, 2:43 AM

Rebased and extracted from my branch. This removes the AFL_FLAGS1 enum which will
return (with Matthews comments taken into account) in my -modd-spreg patch

dsanders updated this revision to Diff 11147.Jul 8 2014, 2:49 AM

Formatting.

dsanders updated this revision to Diff 11149.Jul 8 2014, 2:51 AM

Undo the last two updates. They were meant for D4384

vmedic accepted this revision.Jul 8 2014, 3:36 AM
vmedic edited edge metadata.

LGTM with a nit

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
2823

We could have a check here for the end of a statement.

This revision is now accepted and ready to land.Jul 8 2014, 3:36 AM
dsanders updated this revision to Diff 11161.Jul 8 2014, 6:04 AM
dsanders edited edge metadata.

Rebased.

Fixed -modd-spreg/-mno-odd-spreg not updating subtarget features.

Added a simple check for off FPU registers to the assembler. It ought to be
checked for -integrated-as without -via-file-asm too. I just lack a good place
to put it at the moment.

dsanders updated this revision to Diff 11162.Jul 8 2014, 6:13 AM

Add test for the odd FPU register error

mpf added a comment.Jul 9 2014, 4:46 AM

The FP64A extension needs to prevent direct moves from odd-numbered double precision registers and GPRs as the lower half of the move will use mtc1 or mfc1 which are single precision instructions which would therefore actually be accessing odd single-precision registers. The logic to achieve this will be very similar to the logic needed for FPXX and arch <= mips32r1 where all double precision moves between FPR and GPR have to go via memory.

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
576

-mno-odd-spreg

lib/Target/Mips/MipsSubtarget.cpp
155

This does not do what the error says. The condition is that the ABI is not O32 and no-odd-spreg is given which is different from prohibiting mno-odd-spreg with O32 FP32.

dsanders updated this revision to Diff 11197.Jul 9 2014, 7:26 AM

Fix both error messages that Matthew mentioned.

dsanders updated this revision to Diff 11198.Jul 9 2014, 7:38 AM

Added check for end of statement as Vladimir suggested.

In D4383#22, @mpf wrote:

The FP64A extension needs to prevent direct moves from odd-numbered double precision registers and GPRs as the lower half of the move will use mtc1 or mfc1 which are single precision instructions which would therefore actually be accessing odd single-precision registers. The logic to achieve this will be very similar to the logic needed for FPXX and arch <= mips32r1 where all double precision moves between FPR and GPR have to go via memory.

I'd like to add this bit in a follow up patch if possible. As you say the functionality is very similar to a remaining part of the FPXX so it makes sense to wait for that patch rather than independently develop the same thing.

The changes LGTM

dsanders closed this revision.Jul 10 2014, 6:46 AM