This is an archive of the discontinued LLVM Phabricator instance.

[AArch64] Make .arch without extra features actually take effect
ClosedPublic

Authored by mstorsjo on Jun 2 2023, 2:53 AM.

Details

Summary

This fixes PR32873 / https://github.com/llvm/llvm-project/issues/32220.

@ab mentioned in that bug report that he would send a patch for the issue
soon, but that apparently didn't land at least, and I don't find any
from quickly browsing the mailing list archives after that time.

Diff Detail

Event Timeline

mstorsjo created this revision.Jun 2 2023, 2:53 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 2 2023, 2:53 AM
mstorsjo requested review of this revision.Jun 2 2023, 2:53 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 2 2023, 2:53 AM
lenary edited reviewers, added: pratlucas; removed: lenary.Jun 2 2023, 3:00 AM
pratlucas accepted this revision.Jun 2 2023, 5:43 AM

LGTM.

This revision is now accepted and ready to land.Jun 2 2023, 5:43 AM
  • Is there any use case for the previous behaviour that would be broken by this?
  • Is it worth adding a release note for? (regardless of the answer to the above)
  • Does gcc/gas actually behave in the way this patch implements?
  • Do you know if other backends have this problem? (does not need to be included in this patch however)

Besides that, no objections to fixing this.

  • Is there any use case for the previous behaviour that would be broken by this?

Not a direct use case per se, but this does affect how things do work out in some cases.

https://patchwork.ffmpeg.org/project/ffmpeg/patch/20230530123043.52940-1-martin@martin.st/ is a patch for ffmpeg, that tries to allow assembling the dotprod/i8mm extensions (in handwritten assembly) even if the baseline target doesn't include those extensions. Support for those extensions will be detected at runtime, and functions that rely on those extensions will be used if supported, while the binaries in general can run on anything from ARMv8.0 upwards.

To achieve this, the patch detects whether .arch armv8.2-a is supported, and whether .arch_extension i8mm is supported. The .arch directive is required, since binutils refuses to enable those extensions unless the base architecture level is >= 8.2.

So for most cases, we're expected to end up with this:

.arch armv8.2-a
.arch_extension dotprod
.arch_extension i8mm
<dotprod/i8mm instructions>

However dotprod and i8mm aren't supported in .arch_extension right now (fixed by D151981), but .arch armv8.2-a is. Now if we're building with -march=armv8.6-a, we do support those extensions without any directives.

So with current released Clang, we get this, if building without -march=armv8.6-a:

.arch armv8.2-a
// No dotprod/i8mm instructions used, LLVM is unable to enable them via assembly source

If building with -march=armv8.6-a, we get this:

.arch armv8.2-a
// Dotprod/i8mm instructions used since the .arch doesn't have any effect

With this patch applied, we wouldn't be able to use those instructions here. But coupled with D151981 we can, and we can also make use of them without -march=armv8.6-a.

But this patch also makes it possible to enable the use of those instructions with .arch armv8.6-a in the assembly source, which didn't work before.

So TL;DR, this patch _does_ change how things behave. But it does change things towards a more correct and expected behaviour - I don't see the previous behaviour as an expected behaviour that anyone would rely on, especially if they expect to assemble with binutils too.

  • Is it worth adding a release note for? (regardless of the answer to the above)

I guess so

  • Does gcc/gas actually behave in the way this patch implements?

Yes; this patch makes LLVM behave like binutils gas in all of those cases as mentioned above.

  • Do you know if other backends have this problem? (does not need to be included in this patch however)

Not sure offhand, dunno if .arch (or other similar directives) behaves in a similar way on other architectures.

especially if they expect to assemble with binutils too.

Didn't think about it that way, this makes sense.

Not sure offhand, dunno if .arch (or other similar directives) behaves in a similar way on other architectures.

I forgot this is somewhat Arm specific. I see https://sourceware.org/binutils/docs/as/ARM-Directives.html, I'll check what we do for that.

Arm works as expected:

void fn() {
    __asm__ volatile (".arch_extension sec\n"
                      ".arch thumbv7\n"
                      "smc #0\n");
}

<source>:4:24: error: instruction requires: TrustZone
                      "smc #0\n");
                       ^

.arch then .arch_extension compiles without error.

Intel does recognise the directive but it (deliberately) ignores it.

mstorsjo updated this revision to Diff 527855.Jun 2 2023, 7:15 AM

Added a release note.

This revision was landed with ongoing or failed builds.Jun 6 2023, 1:50 AM
This revision was automatically updated to reflect the committed changes.