diff mbox

[aarch64] Fix target/70120

Message ID 56EB02B1.2030701@redhat.com
State New
Headers show

Commit Message

Richard Henderson March 17, 2016, 7:17 p.m. UTC
With -g, and a code section that ends unaligned, the assembler complains of
"unaligned opcodes detected".  Except there are no such unaligned opcodes, nor
dwarf2 code ranges covering the end of the section, which arguably makes this
an assembler bug.  However, it's reasonably easy to work around in the
compiler, which saves having to bump the required binutils version.

Tested on aarch64-linux.


r~
PR target/70120
	* varasm.c (for_each_section): New.
	* varasm.h (for_each_section): Declare.
	* config/aarch64/aarch64.c (aarch64_align_code_section): New.
	(aarch64_asm_file_end): New.
	(TARGET_ASM_FILE_END): Redefine.

testsuite/
	* gcc.target/aarch64/pr70120-1.c: New.
	* gcc.target/aarch64/pr70120-2.c: New.
	* gcc.target/aarch64/pr70120-3.c: New.

Comments

Bernd Schmidt March 21, 2016, 1:13 p.m. UTC | #1
On 03/17/2016 08:17 PM, Richard Henderson wrote:
> With -g, and a code section that ends unaligned, the assembler complains of
> "unaligned opcodes detected".  Except there are no such unaligned opcodes, nor
> dwarf2 code ranges covering the end of the section, which arguably makes this
> an assembler bug.  However, it's reasonably easy to work around in the
> compiler, which saves having to bump the required binutils version.
>
> Tested on aarch64-linux.

Ok for the varasm bits.


Bernd
Jiong Wang March 21, 2016, 1:40 p.m. UTC | #2
On 17/03/16 19:17, Richard Henderson wrote:
> PR target/70120
> 	* varasm.c (for_each_section): New.
> 	* varasm.h (for_each_section): Declare.
> 	* config/aarch64/aarch64.c (aarch64_align_code_section): New.
> 	(aarch64_asm_file_end): New.
> 	(TARGET_ASM_FILE_END): Redefine.

Will ASM_OUTPUT_POOL_EPILOGUE be a better place to fix this issue? which can
avoid the for_each_section traversal.

>
>
> r~
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index cf1239d..cca9bd9 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -13989,6 +13989,39 @@  aarch64_optab_supported_p (int op, machine_mode, machine_mode,
     }
 }
 
+/* A subroutine of aarch64_asm_file_end.  Callback to align the
+   given section if it contains code.  */
+
+static void
+aarch64_align_code_section (section *s)
+{
+  if (s->common.flags & SECTION_CODE)
+    {
+      switch_to_section (s);
+      ASM_OUTPUT_ALIGN (asm_out_file, 2);
+    }
+}
+
+/* Implement the TARGET_ASM_FILE_END hook.  */
+
+static void
+aarch64_asm_file_end (void)
+{
+  /* When using per-function literal pools, we must ensure that any code
+     section is aligned to the minimal instruction length, lest we get
+     errors from the assembler re "unaligned instructions".  */
+  if (aarch64_can_use_per_function_literal_pools_p ())
+    for_each_section (aarch64_align_code_section);
+
+  /* If a subtarget has already defined this hook, call it.  */
+#ifdef TARGET_ASM_FILE_END
+  TARGET_ASM_FILE_END ();
+#endif
+}
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END aarch64_asm_file_end
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
diff --git a/gcc/testsuite/gcc.target/aarch64/pr70120-1.c b/gcc/testsuite/gcc.target/aarch64/pr70120-1.c
new file mode 100644
index 0000000..31a5e94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr70120-1.c
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Og -fschedule-insns -mno-pc-relative-literal-loads -g" } */
+
+typedef short v32u16 __attribute__ ((vector_size (32)));
+typedef int v32u32 __attribute__ ((vector_size (32)));
+typedef long v32u64 __attribute__ ((vector_size (32)));
+typedef __int128 u128;
+typedef __int128 v32u128 __attribute__ ((vector_size (32)));
+
+int
+foo(int u16_0, int u32_0, int u64_0, u128 u128_0, int u16_1, int u32_1, int u64_1, u128 u128_1, v32u16 v32u16_0, v32u32 v32u32_0, v32u64 v32u64_0, v32u128 v32u128_0, v32u16 v32u16_1, v32u32 v32u32_1, v32u64 v32u64_1, v32u128 v32u128_1)
+{
+  v32u32_1 ^= (v32u32) ~ v32u64_0;
+  v32u32_1 %= (v32u32) - v32u16_1 | 1;
+  v32u16_1 -= (v32u16) v32u16_1;
+  v32u64_0 *= (v32u64){~ u128_0, v32u16_1[5], v32u16_0[15], v32u32_1[4]};
+  v32u16_0 /= (v32u16){0x574c, ~u128_1, v32u128_1[0], u64_1, v32u64_0[1], v32u64_1[2], 0, 0x8ce6, u128_1, 0x5e69} |1;
+  return v32u16_0[0] + v32u16_0[6] + v32u16_0[8] + v32u16_0[9] + v32u32_0[0] + v32u32_0[1] + v32u32_0[2] + v32u32_0[3] + v32u32_0[4] + v32u32_0[6] + v32u64_0[0] + v32u64_0[2] + v32u64_0[3] + v32u128_0[0] + v32u128_0[1] + v32u32_1[0] + v32u32_1[2] + v32u64_1[2] + v32u64_1[3] + v32u128_1[1];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr70120-2.c b/gcc/testsuite/gcc.target/aarch64/pr70120-2.c
new file mode 100644
index 0000000..0110224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr70120-2.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Og -freorder-functions -g3 -mcmodel=large" } */
+
+typedef short v32u16 __attribute__ ((vector_size (32)));
+typedef int v32u32 __attribute__ ((vector_size (32)));
+typedef long v32u64 __attribute__ ((vector_size (32)));
+typedef __int128 u128;
+typedef __int128 v32u128 __attribute__ ((vector_size (32)));
+
+int
+foo (int u16_0, int u32_0, int u64_0, u128 u128_0, int u16_1, int u32_1, v32u16 v32u16_0, v32u32 v32u32_0, v32u64 v32u64_0, v32u128 v32u128_0, v32u16 v32u16_1, v32u32 v32u32_1, v32u64 v32u64_1, v32u128 v32u128_1)
+{
+  u128_0 <<= 0x6c;
+  v32u16_1 %= (v32u16) { 1, 64, 0xf294, 0, u32_1, v32u32_1[6], ~u128_0, 0x2912, v32u32_0[2]} | 1;
+  v32u16_0 ^= (v32u16){-v32u16_1[11], -u32_1, 64, ~u128_0, 0, 1, 64, ~u64_0, 0};
+  return u16_0 + u32_0 + u16_1 + v32u16_0[0] + v32u32_0[1] + v32u32_0[2] + v32u32_0[4] + v32u32_0[6] + v32u64_0[0] + v32u64_0[1] + v32u64_0[2] + v32u64_0[3] + v32u128_0[0] + v32u128_0[1] + v32u16_1[0] + v32u32_1[7] + v32u64_1[0] + v32u64_1[1] + v32u64_1[2] + v32u64_1[3] + v32u128_1[0] + v32u128_1[1];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr70120-3.c b/gcc/testsuite/gcc.target/aarch64/pr70120-3.c
new file mode 100644
index 0000000..2b70df7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr70120-3.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -ffunction-sections -mno-pc-relative-literal-loads -g3" } */
+
+typedef unsigned short u16;
+typedef unsigned short v32u16 __attribute__((vector_size(32)));
+typedef unsigned int u32;
+typedef unsigned int v32u32 __attribute__((vector_size(32)));
+typedef unsigned long long u64;
+typedef unsigned long long v32u64 __attribute__((vector_size(32)));
+typedef unsigned __int128 u128;
+typedef unsigned __int128 v32u128 __attribute__((vector_size(32)));
+u128 __attribute__((noinline, noclone))
+foo(u16 u16_0, u32 u32_0, u64 u64_0, u128 u128_0, u16 u16_1, u32 u32_1, u64 u64_1, u128 u128_1, v32u16 v32u16_0, v32u32 v32u32_0, v32u64 v32u64_0, v32u128 v32u128_0, v32u16 v32u16_1, v32u32 v32u32_1, v32u64 v32u64_1, v32u128 v32u128_1)
+{
+ v32u128_1 %= (v32u128)v32u32_1 | 1;
+ u16_1 /= ((u32)~(u128)(((u128)0xa1 << 0))) | 1;
+ v32u32_0 += (v32u32){(u16)v32u16_1[9], (u16)v32u16_1[14], (u32)-v32u32_0[7], ((u64)(u32)(((u128)0x43bc59e9 << 0))), ((u32)(u32)(((u128)0x14a47ba8f240a6 << 0))), (u128)v32u128_1[1], (u16)u16_1, (u64)-u64_1};
+ return u16_0 + u32_0 + u64_0 + u128_0 + u16_1 + u32_1 + u64_1 + u128_1 + v32u16_0[0] + v32u16_0[1] + v32u16_0[2] + v32u16_0[3] + v32u16_0[4] + v32u16_0[5] + v32u16_0[6] + v32u16_0[7] + v32u16_0[8] + v32u16_0[9] + v32u16_0[10] + v32u16_0[11] + v32u16_0[12] + v32u16_0[13] + v32u16_0[14] + v32u16_0[15] + v32u32_0[0] + v32u32_0[1] + v32u32_0[2] + v32u32_0[3] + v32u32_0[4] + v32u32_0[5] + v32u32_0[6] + v32u32_0[7] + v32u64_0[0] + v32u64_0[1] + v32u64_0[2] + v32u64_0[3] + v32u128_0[0] + v32u128_0[1] + v32u16_1[0] + v32u16_1[1] + v32u16_1[2] + v32u16_1[3] + v32u16_1[4] + v32u16_1[5] + v32u16_1[6] + v32u16_1[7] + v32u16_1[8] + v32u16_1[9] + v32u16_1[10] + v32u16_1[11] + v32u16_1[12] + v32u16_1[13] + v32u16_1[14] + v32u16_1[15] + v32u32_1[0] + v32u32_1[1] + v32u32_1[2] + v32u32_1[3] + v32u32_1[4] + v32u32_1[5] + v32u32_1[6] + v32u32_1[7] + v32u64_1[0] + v32u64_1[1] + v32u64_1[2] + v32u64_1[3] + v32u128_1[0] + v32u128_1[1];
+}
+int main()
+{
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 3a3573e..d1fd6fa 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -849,6 +849,21 @@  mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
     }
   return readonly_data_section;
 }
+
+/* Iterate over all created sections.  */
+
+void
+for_each_section (void (*callback)(section *))
+{
+  hash_table<section_hasher>::iterator iter;
+  section *s;
+
+  for (s = unnamed_sections; s != NULL; s = s->unnamed.next)
+    callback(s);
+  FOR_EACH_HASH_TABLE_ELEMENT (*section_htab, s, section *s, iter)
+    callback(s);
+}
+
 
 /* Given NAME, a putative register name, discard any customary prefixes.  */
 
diff --git a/gcc/varasm.h b/gcc/varasm.h
index 51a5492..e928036 100644
--- a/gcc/varasm.h
+++ b/gcc/varasm.h
@@ -41,6 +41,7 @@  extern void process_pending_assemble_externals (void);
 extern bool decl_replaceable_p (tree);
 extern bool decl_binds_to_current_def_p (const_tree);
 extern enum tls_model decl_default_tls_model (const_tree);
+extern void for_each_section (void (*callback)(section *));
 
 /* Declare DECL to be a weak symbol.  */
 extern void declare_weak (tree);