This is an archive of the discontinued LLVM Phabricator instance.

[LLVM - ARM/AArch64] Add ACLE special register intrinsics (10.1)
ClosedPublic

Authored by LukeCheeseman on May 12 2015, 2:49 AM.

Details

Summary

This patch implements LLVM support for the ACLE special register intrinsics in section 10.1, __arm_{w,r}sr{,p,64}.

This patch is intended to lower the read/write_register instrinsics, used to implement the special register intrinsics in the clang patch for special register intrinsics (see http://reviews.llvm.org/D9697), to ARM specific instructions MRC,MCR,MSR etc. to allow reading an writing of coprocessor registers in AArch32 and AArch64. This is done by inspecting the register string passed to the intrinsic and then lowering to the appropriate instruction.

Diff Detail

Repository
rL LLVM

Event Timeline

LukeCheeseman retitled this revision from to [LLVM - ARM/AArch64] Add ACLE special register intrinsics (10.1).
LukeCheeseman updated this object.
LukeCheeseman edited the test plan for this revision. (Show Details)
LukeCheeseman added a subscriber: Unknown Object (MLST).

Hi Luke,

Nice patch! I have some early inline comments, but I'll review the bulk of it later.

I also noticed you have added no new tests, did you forget to "git add" the files?

cheers,
--renato

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
4029 ↗(On Diff #25565)

Good catch! This could even be moved inside the DAG.setRoot() call below, like the others.

lib/Target/ARM/ARMISelLowering.cpp
4119 ↗(On Diff #25565)

Maybe an assert on Op.getValueType() being 64-bits would be good here.

6542 ↗(On Diff #25565)

I'm a bit rusty in SelectionDAG, but can we always guarantee that we'll only have 64-bit types here?

rengolin added inline comments.May 12 2015, 7:55 AM
lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
2142 ↗(On Diff #25565)

Missing assert(AllIntFields) ?

Adding extra assertions to check the types provided when trying to expand/lower read/write_register. Added tests for the lowering of read/write_register.

Thanks for pointing out the tests, I had forgotten to write some for the lowering of the read/write_register.

Hi Luke,

Thanks for the changes. I think the two main functions to lower read/write register calls need some cleaning (see inline), but the tests are good.

cheers,
--renato

lib/Target/ARM/ARMISelDAGToDAG.cpp
3360 ↗(On Diff #25593)

Aren't there ARM::* register enums for those? You seem to be using a similar technique for VFP registers below, why can't you do the same for these?

3505 ↗(On Diff #25593)

This block seems lost... and it's parsing the string again, when you already had it to enum up there. Maybe also add "cpsr" into the string switch and add a new switch to continue on specific cases and emit the call on default:

3522 ↗(On Diff #25593)

This one as well.

Would be good if you could use ARM:: enum values for the register names here, too.

3534 ↗(On Diff #25593)

Same things can be said about this function, as the one above.

In addition, there are too many nested blocks here, with a lot of magic constants. Would be good to split these into smaller functions, static if necessary, that deal with the gory details of masks and register names/IDs.

LukeCheeseman added inline comments.May 13 2015, 8:10 AM
lib/Target/ARM/ARMISelDAGToDAG.cpp
3360 ↗(On Diff #25593)

The values here are masks for the MSR/MRS (Banked Register) instructions and not actual registers, as such there isn't an enum that I found for these values. Also, the values for VFP instructions aren't registers but opcodes, this is because the different registers get read/written from/to using VMRS/VMSR by creating SelctionDAG nodes with an opcode corresponding to the register. Thanks for highlighting this, I'll change the name of this function to better match what it is supposed to do and improve my comments around these.

Reduced the size of the main functions in this patch (the lowering of read and write register) by adding calls to some helper function to help reduce nesting and improve the clarity of the functions. Also, added some more tests.

Renato,

Thanks for the suggestions, I've tried to tidy up the main functions by extracting some of the code for setting the masks into some helper functions, I could perhaps do more to completely extract the setting of the masks (for example in the later part of the write lowering). I haven't placed the parsing of apsr, cpsr and spsr into the switch as I thought it wasn't part of what either switch was trying to do as it wasn't trying to get a mask value and so I've left it in the main part of the lowering. I'd welcome any more suggestions you have.

Thanks,
Luke

Fully extracted constructing each mask into a separate helper functions. Renamed helpers to be more consistent in their names. Changed the M class mask constructor to return the mask not a node so that the helpers were more consistent.

Sorry for the delay. The changes you did are good. Some minor comments inline.

lib/Target/ARM/ARMISelDAGToDAG.cpp
3618 ↗(On Diff #25707)

Shouldn't it be an error if (Opcode && !Subtarget->hasVFP3()) ?

Maybe something like:

if (Opcode) {
  if (!Subtarget->hasVFP3())
    return nullptr;
  Ops ...
}
3711 ↗(On Diff #25707)

Same comment about hasVFP3()

3740 ↗(On Diff #25707)

What about ARMv6 and older?

Added early exits when a VFP opcode has been found but the target doesn't support the operation. Changes to comment when constructing a mask for AR class register string.

rengolin accepted this revision.May 18 2015, 6:11 AM
rengolin added a reviewer: rengolin.

LGTM, Thanks!

This revision is now accepted and ready to land.May 18 2015, 6:11 AM
This revision was automatically updated to reflect the committed changes.