This is an archive of the discontinued LLVM Phabricator instance.

[ARM,AArch64] Add a full set of -mtp= options.
ClosedPublic

Authored by simon_tatham on Jun 8 2023, 3:38 AM.

Details

Summary

AArch64 has five system registers intended to be useful as thread
pointers: one for each exception level which is RW at that level and
inaccessible to lower ones, and the special TPIDRRO_EL0 which is
readable but not writable at EL0. AArch32 has three, corresponding to
the AArch64 ones that aren't specific to EL2 or EL3.

Currently clang supports only a subset of these registers, and not
even a consistent subset between AArch64 and AArch32:

  • For AArch64, clang permits you to choose between the four TPIDR_ELn thread registers, but not the fifth one, TPIDRRO_EL0.
  • In AArch32, on the other hand, the only thread register you can choose (apart from 'none, use a function call') is TPIDRURO, which corresponds to (the bottom 32 bits of) AArch64's TPIDRRO_EL0.

So there is no thread register that you can currently use in both
targets!

For custom and bare-metal purposes, users might very reasonably want
to use any of these thread registers. There's no reason they shouldn't
all be supported as options, even if the default choices follow
existing practice on typical operating systems.

This commit extends the range of values acceptable to the -mtp=
clang option, so that you can specify any of these registers by (the
lower-case version of) their official names in the ArmARM:

  • For AArch64: tpidr_el0, tpidrro_el0, tpidr_el1, tpidr_el2, tpidr_el3
  • For AArch32: tpidrurw, tpidruro, tpidrprw

All existing values of the option are still supported and behave the
same as before. Defaults are also unchanged. No command line that
worked already should change behaviour as a result of this.

The new values for the -mtp= option have been agreed with Arm's gcc
developers (although I don't know whether they plan to implement them
in the near future).

Diff Detail

Event Timeline

simon_tatham created this revision.Jun 8 2023, 3:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 8 2023, 3:38 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
simon_tatham requested review of this revision.Jun 8 2023, 3:38 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 8 2023, 3:38 AM

The only minor visible difference is the removal of read-tp-hard option from the LLVM side, which could be used by other downstream implementations.

I personally don't think this is a big deal. First, we don't promise stability on that layer, and second, it would be trivial to find out what the option has changed to.

This looks good to me, perhaps clearing the potential confusion on the commit message (inline comment).

Give it some time for other people to see it.

Thanks!
Renato

clang/include/clang/Driver/Options.td
3601

From your comment:

"In AArch32, on the other hand, the _only_ thread register you can choose (apart from 'none, use a function call') is the one that's read-only at EL0."

I inferred the current alias el0 would map to the read-only version tpidrro_el0.

Looking at the implementation below (AArch64ExpandPseudoInsts.cpp), EL0 seems to be the default when choosing the thread pointer?

The only minor visible difference is the removal of read-tp-hard option from the LLVM side, which could be used by other downstream implementations.

Yes. I wasn't sure how much that mattered, and like you, I came down weakly on the side of not worrying about the change and keeping the names logical. I'll change it back without complaining if anyone else has a strong opinion, though!

clang/include/clang/Driver/Options.td
3601

If you inferred that, then I was unclear, and should reword :-)

el0 is a name only accepted on AArch64, and maps to the AArch64 register tpidr_el0.

The only hardware option in AArch32 (before this commit) is called cp15 (unhelpfully, since all three regs are in CP15), and is an alias for tpidruro, which is the AArch32 register that's readonly at EL0 and writable at EL1 (and in fact aliases the bottom 32 bits of tpidrro_el0).

Yes, the current defaults are different between AArch32 and 64 (unsurprisingly, since no register is currently supported on both), but that makes sense, since Linux also seems to do things differently. On AArch32 the code generation uses TPIDRURO, which unprivileged code can read but not write, and on AArch64 it uses TPIDR_EL0 which unprivileged code can overwrite if it wants to. I don't know why the defaults are different, but I have no plan to change them here!

simon_tatham edited the summary of this revision. (Show Details)Jun 8 2023, 4:11 AM
rengolin added inline comments.
clang/include/clang/Driver/Options.td
3601

Right! The confusion was on my side on the overloaded EL0 for both the register name in AArch64 and the processor state on both. I should have noticed the capitalisation difference. Now it makes sense, thanks!

I don't know why the defaults are different, but I have no plan to change them here!

Ack. First introduce functionality, then investigate why (on a separate patch).

@olista01 might remember something...

nickdesaulniers added inline comments.Jun 9 2023, 1:43 PM
llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
4941–4943

From the buildbot presubmit failure:

/var/lib/buildkite-agent/builds/llvm-project/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp:4942:23: error: no member named 'isReadTPSoft' in 'llvm::ARMSubtarget'
    assert(!Subtarget.isReadTPSoft() &&
            ~~~~~~~~~ ^
/usr/include/assert.h:93:27: note: expanded from macro 'assert'
     (static_cast <bool> (expr)                                         \
                          ^~~~

PTAL

MaskRay added inline comments.Jun 9 2023, 1:50 PM
clang/test/Driver/clang-translation.c
129

clang-translation.c's job is shifting, but I think it is mainly for testing common options. For Arm-specific testing, I think using a arm-*.c file will be more appropriate. Ideally we can find an existing file where new RUN lines seem appropriate, as a fallback we can introduce a new test file:)

Also, use --target= for new tests. -target has been deprecated (without a warning) since Clang 3.x era.

Fixed the isReadTPSoft predicate (sorry – I always get confused by when Tablegen autogenerates those predicates and when it doesn't), and reorganised the tests.

I couldn't find any existing test file, so I made a new pair arm-thread-pointer.c and aarch64-thread-pointer.c and moved all the TP tests out into there.

Rebased past rG34d7acd444b8 (which conflicted with it, though trivially) and attempted to fix the clang-format complaint in pre-merge checks.

Right, this seems to be passing tests now, so I think @nickdesaulniers's issue is fixed, and I've also split up the tests as @MaskRay suggested.

nickdesaulniers accepted this revision.Jun 14 2023, 9:15 AM

thanks for the patch!

This revision is now accepted and ready to land.Jun 14 2023, 9:15 AM
This revision was automatically updated to reflect the committed changes.