[PATCH] D152221: Avoid cross-section branches in AArch64 inline asm

Nick Desaulniers via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 6 13:32:24 PDT 2023


nickdesaulniers added a comment.

In D152221#4398628 <https://reviews.llvm.org/D152221#4398628>, @dhoekwater wrote:

> I'm adding this so that, once enabled, function splitting and basic block sections won't create link failures for AArch64.
>
> If we have two basic blocks: BB1 and BB2 where BB1 contains an inline assembly label and BB2 contains inline assembly that branches to that label, function splitting and `fbasic-block-sections=all` can both place BB1 and BB2 in different text sections. Ex: https://godbolt.org/z/z8KareGn7. With function splitting, if the `beq label1` instruction is rarely taken, `label1` will be placed in the `.text.split` section, while `beq label1` remains in `.text`. If the linker places the two sections more than 1MB away from each other, the program will fail to link because the offset doesn't fit in `beq` machine code instruction.

Perhaps the label should be defined in C, then `asm goto` should be used for the first inline asm statement: https://godbolt.org/z/4fMT4cWPG

  --- /tmp/x.c	2023-06-06 13:29:37.883592223 -0700
  +++ /tmp/y.c	2023-06-06 13:29:44.555615299 -0700
  @@ -3,13 +3,14 @@
   __attribute__((noinline))
   int abs_diff(volatile int a, volatile int b) {
       int result = -1;
  -    asm volatile (
  +    asm goto (
               "cmp %w0, %w1\n"      // Compare the values of a and b
  -            "beq label1\n"         // Branch if a == b
  +            "beq %l3\n"           // Branch if a == b
               "sub %w2, %w0, %w1\n" // Calculates a - b
               : "=r" (result)
               : "r" (a), "r" (b)
               : "cc"
  +            : label1
           );
       if (a > b) {
           result = a - b;
  @@ -17,8 +18,8 @@
       if (a < b) {
           result = b - a;
       }
  +label1: // Provide a target for the other inline asm
       asm volatile (
  -        "label1:\n"   // Provide a target for the other inline asm
           "mov %w0, #0\n"
           : "=r" (result) 
           : 

Then it's obvious to the compiler that `label1` has its address taken, and probably shouldn't be moved around (by whatever `basic-block-sections=all` is)?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152221/new/

https://reviews.llvm.org/D152221



More information about the llvm-commits mailing list