aarch64: Don't emit invalid zero/sign-extend syntax
authorAlex Coplan <alex.coplan@arm.com>
Mon, 7 Sep 2020 14:20:21 +0000 (15:20 +0100)
committerAlex Coplan <alex.coplan@arm.com>
Mon, 7 Sep 2020 14:20:21 +0000 (15:20 +0100)
Given the following C function:

double *f(double *p, unsigned x)
{
    return p + x;
}

prior to this patch, GCC at -O2 would generate:

f:
        add     x0, x0, x1, uxtw 3
        ret

but this add instruction uses architecturally-invalid syntax: the width
of the third operand conflicts with the width of the extension
specifier. The third operand is only permitted to be an x register when
the extension specifier is (u|s)xtx.

This instruction, and analogous insns for adds, sub, subs, and cmp, are
rejected by clang, but accepted by binutils. Assembling and
disassembling such an insn with binutils gives the architecturally-valid
version in the disassembly:

   0:   8b214c00        add     x0, x0, w1, uxtw #3

This patch fixes several patterns in the AArch64 backend to use the
standard syntax as specified in the Arm ARM such that GCC's output can
be assembled by assemblers other than GAS.

---

gcc/ChangeLog:

* config/aarch64/aarch64.md
(*adds_<optab><ALLX:mode>_<GPI:mode>): Ensure extended operand
agrees with width of extension specifier.
(*subs_<optab><ALLX:mode>_<GPI:mode>): Likewise.
(*adds_<optab><ALLX:mode>_shift_<GPI:mode>): Likewise.
(*subs_<optab><ALLX:mode>_shift_<GPI:mode>): Likewise.
(*add_<optab><ALLX:mode>_<GPI:mode>): Likewise.
(*add_<optab><ALLX:mode>_shft_<GPI:mode>): Likewise.
(*add_uxt<mode>_shift2): Likewise.
(*sub_<optab><ALLX:mode>_<GPI:mode>): Likewise.
(*sub_<optab><ALLX:mode>_shft_<GPI:mode>): Likewise.
(*sub_uxt<mode>_shift2): Likewise.
(*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>): Likewise.
(*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>): Likewise.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/adds3.c: Fix test w.r.t. new syntax.
* gcc.target/aarch64/cmp.c: Likewise.
* gcc.target/aarch64/subs3.c: Likewise.
* gcc.target/aarch64/subsp.c: Likewise.
* gcc.target/aarch64/extend-syntax.c: New test.

gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/adds3.c
gcc/testsuite/gcc.target/aarch64/cmp.c
gcc/testsuite/gcc.target/aarch64/extend-syntax.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/subs3.c
gcc/testsuite/gcc.target/aarch64/subsp.c

index 9b20dd0b1a0e917789da1d8db1152e2bb1f1b625..b1e83dfda788af2c3101d67b5df00673f88b4a75 100644 (file)
    (set (match_operand:GPI 0 "register_operand" "=r")
        (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
   ""
-  "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
+  "adds\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
   [(set_attr "type" "alus_ext")]
 )
 
    (set (match_operand:GPI 0 "register_operand" "=r")
        (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
   ""
-  "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
+  "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
   [(set_attr "type" "alus_ext")]
 )
 
                              (match_dup 2))
                  (match_dup 3)))]
   ""
-  "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
+  "adds\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
   [(set_attr "type" "alus_ext")]
 )
 
                   (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
                               (match_dup 3))))]
   ""
-  "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
+  "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
   [(set_attr "type" "alus_ext")]
 )
 
        (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
                  (match_operand:GPI 2 "register_operand" "r")))]
   ""
-  "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
+  "add\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
   [(set_attr "type" "alu_ext")]
 )
 
                              (match_operand 2 "aarch64_imm3" "Ui3"))
                  (match_operand:GPI 3 "register_operand" "r")))]
   ""
-  "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
+  "add\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
   [(set_attr "type" "alu_ext")]
 )
 
   "*
   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
                                           INTVAL (operands[3])));
-  return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
+  return \"add\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
   [(set_attr "type" "alu_ext")]
 )
 
                   (ANY_EXTEND:GPI
                    (match_operand:ALLX 2 "register_operand" "r"))))]
   ""
-  "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
+  "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
   [(set_attr "type" "alu_ext")]
 )
 
                                (match_operand:ALLX 2 "register_operand" "r"))
                               (match_operand 3 "aarch64_imm3" "Ui3"))))]
   ""
-  "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
+  "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
   [(set_attr "type" "alu_ext")]
 )
 
   "*
   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
                                           INTVAL (operands[3])));
-  return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
+  return \"sub\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
   [(set_attr "type" "alu_ext")]
 )
 
                         (match_operand:ALLX 0 "register_operand" "r"))
                        (match_operand:GPI 1 "register_operand" "r")))]
   ""
-  "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
+  "cmp\\t%<GPI:w>1, %w0, <su>xt<ALLX:size>"
   [(set_attr "type" "alus_ext")]
 )
 
                         (match_operand 1 "aarch64_imm3" "Ui3"))
        (match_operand:GPI 2 "register_operand" "r")))]
   ""
-  "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
+  "cmp\\t%<GPI:w>2, %w0, <su>xt<ALLX:size> %1"
   [(set_attr "type" "alus_ext")]
 )
 
index c5518bdcaf20bba797de394492558cb41840e4e2..e938c8049cf6326db52565dea807b174ea672c67 100644 (file)
@@ -58,4 +58,4 @@ int main ()
   return 0;
 }
 
-/* { dg-final { scan-assembler-times "adds\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw" 2 } } */
+/* { dg-final { scan-assembler-times "adds\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, sxtw" 2 } } */
index ee57dd283bf36e1ded718aa16a75f3a5efec234b..a6487a4f77acaaefc5f730411146dc6831fffa29 100644 (file)
@@ -58,4 +58,5 @@ cmp_di_test4 (int a, s64 b, s64 c)
 }
 
 /* { dg-final { scan-assembler-times "cmp\tw\[0-9\]+, w\[0-9\]+" 2 } } */
-/* { dg-final { scan-assembler-times "cmp\tx\[0-9\]+, x\[0-9\]+" 4 } } */
+/* { dg-final { scan-assembler-times "cmp\tx\[0-9\]+, x\[0-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "cmp\tx\[0-9\]+, w\[0-9\]+, sxtw" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/extend-syntax.c b/gcc/testsuite/gcc.target/aarch64/extend-syntax.c
new file mode 100644 (file)
index 0000000..23fa9f4
--- /dev/null
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+// Hits *add_uxtdi_shift2 (*add_uxt<mode>_shift2).
+/*
+** add1:
+**     add     x0, x0, w1, uxtw 3
+**     ret
+*/
+unsigned long long *add1(unsigned long long *p, unsigned x)
+{
+  return p + x;
+}
+
+// Hits *add_zero_extendsi_di (*add_<optab><ALLX:mode>_<GPI:mode>).
+/*
+** add2:
+**     add     x0, x0, w1, uxtw
+**     ret
+*/
+unsigned long long add2(unsigned long long x, unsigned y)
+{
+  return x + y;
+}
+
+// Hits *add_extendsi_shft_di (*add_<optab><ALLX:mode>_shft_<GPI:mode>).
+/*
+** add3:
+**     add     x0, x0, w1, sxtw 3
+**     ret
+*/
+double *add3(double *p, int x)
+{
+  return p + x;
+}
+
+// Hits *sub_zero_extendsi_di (*sub_<optab><ALLX:mode>_<GPI:mode>).
+/*
+** sub1:
+**     sub     x0, x0, w1, uxtw
+**     ret
+*/
+unsigned long long sub1(unsigned long long x, unsigned n)
+{
+    return x - n;
+}
+
+// Hits *sub_uxtdi_shift2 (*sub_uxt<mode>_shift2).
+/*
+** sub2:
+**     sub     x0, x0, w1, uxtw 3
+**     ret
+*/
+double *sub2(double *x, unsigned n)
+{
+  return x - n;
+}
+
+// Hits *sub_extendsi_shft_di (*sub_<optab><ALLX:mode>_shft_<GPI:mode>).
+/*
+** sub3:
+**     sub     x0, x0, w1, sxtw 3
+**     ret
+*/
+double *sub3(double *p, int n)
+{
+  return p - n;
+}
+
+// Hits *adds_zero_extendsi_di (*adds_<optab><ALLX:mode>_<GPI:mode>).
+int adds1(unsigned long long x, unsigned y)
+{
+  /* { dg-final { scan-assembler-times "adds\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, uxtw" 1 } } */
+  unsigned long long l = x + y;
+  return !!l;
+}
+
+// Hits *adds_extendsi_shift_di (*adds_<optab><ALLX:mode>_shift_<GPI:mode>).
+int adds2(long long x, int y)
+{
+  /* { dg-final { scan-assembler-times "adds\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, sxtw 3" 1 } } */
+  long long t = x + ((long long)y << 3);
+  return !!t;
+}
+
+// Hits *subs_zero_extendsi_di (*subs_<optab><ALLX:mode>_<GPI:mode>).
+unsigned long long z;
+int subs1(unsigned long long x, unsigned y)
+{
+  /* { dg-final { scan-assembler-times "subs\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, uxtw" 1 } } */
+  unsigned long long t = x - y;
+  z = t;
+  return !!t;
+}
+
+// Hits *subs_extendsi_shift_di (*subs_<optab><ALLX:mode>_shift_<GPI:mode>).
+unsigned long long *w;
+int subs2(unsigned long long *x, int y)
+{
+  /* { dg-final { scan-assembler-times "subs\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, sxtw 3" 1 } } */
+  unsigned long long *t = x - y;
+  w = t;
+  return !!t;
+}
+
+// Hits *cmp_swp_zero_extendsi_regdi (*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>).
+int cmp(unsigned long long x, unsigned y)
+{
+  /* { dg-final { scan-assembler-times "cmp\tx\[0-9\]+, w\[0-9\]+, uxtw" 1 } } */
+  return !!(x - y);
+}
+
+// Hits *cmp_swp_extendsi_shft_di (*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>).
+int cmp2(unsigned long long x, int y)
+{
+  /* { dg-final { scan-assembler-times "cmp\tx\[0-9\]+, w\[0-9\]+, sxtw 3" 1 } } */
+  return x == ((unsigned long long)y << 3);
+}
+
+/* { dg-final { check-function-bodies "**" "" "" } } */
index 59581bf1ab790b06a9be4489d7e02ee889519447..0470a3bde343aeefdbcbb729a0211a03a0c2c543 100644 (file)
@@ -58,4 +58,4 @@ int main ()
   return 0;
 }
 
-/* { dg-final { scan-assembler-times "subs\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw" 2 } } */
+/* { dg-final { scan-assembler-times "subs\tx\[0-9\]+, x\[0-9\]+, w\[0-9\]+, sxtw" 2 } } */
index 6ef6b2c90ae694055749a94b68cbba5ee4aea882..341b83dca863cb3b9097bbd09c8d0997f981a2a4 100644 (file)
@@ -16,4 +16,4 @@ f2 (int *x, int y)
 }
 
 /* { dg-final { scan-assembler "sub\tsp, sp, x\[0-9\]*\n" } } */
-/* { dg-final { scan-assembler "sub\tsp, sp, x\[0-9\]*, sxtw 4\n" } } */
+/* { dg-final { scan-assembler "sub\tsp, sp, w\[0-9\]*, sxtw 4\n" } } */