Patchwork [AArch64] Allow symbol+offset as symbolic constant expression

login
register
mail settings
Submitter Ian Bolton
Date July 6, 2012, 3:31 p.m.
Message ID <000001cd5b8c$6bf379c0$43da6d40$@bolton@arm.com>
Download mbox | patch
Permalink /patch/169482/
State New
Headers show

Comments

Ian Bolton - July 6, 2012, 3:31 p.m.
Hi,

This patch reduces codesize for cases such as this one:

 int arr[100];
 int foo () { return arr[10]; }

Before the patch, the code looked like this:

 adrp x0, arr
 add x0, x0, :lo12:arr
 ldr w0, [x0,40]

Now, it looks like this:
 
 adrp x0, arr+40
 ldr w0, [x0,#:lo12:arr+40]

Some workloads have seen up to 1K reduction in code size.

OK to commit?

Cheers,
Ian



2012-07-06  Ian Bolton  <ian.bolton@arm.com>

	* gcc/config/aarch64/aarch64.c (aarch64_print_operand): Use
	aarch64_classify_symbolic_expression for classifying operands.

	* gcc/config/aarch64/aarch64.c
	(aarch64_classify_symbolic_expression): New function.

	* gcc/config/aarch64/aarch64.c (aarch64_symbolic_constant_p):
	New function.

	* gcc/config/aarch64/predicates.md (aarch64_valid_symref):
	Symbol with constant offset is a valid symbol reference.
Marcus Shawcroft - July 23, 2012, 9:51 a.m.
On 06/07/12 16:31, Ian Bolton wrote:
> Hi,
>
> This patch reduces codesize for cases such as this one:
>
>   int arr[100];
>   int foo () { return arr[10]; }
>
> Before the patch, the code looked like this:
>
>   adrp x0, arr
>   add x0, x0, :lo12:arr
>   ldr w0, [x0,40]
>
> Now, it looks like this:
>
>   adrp x0, arr+40
>   ldr w0, [x0,#:lo12:arr+40]
>
> Some workloads have seen up to 1K reduction in code size.
>
> OK to commit?
>
> Cheers,
> Ian
>
>
>
> 2012-07-06  Ian Bolton<ian.bolton@arm.com>
>
> 	* gcc/config/aarch64/aarch64.c (aarch64_print_operand): Use
> 	aarch64_classify_symbolic_expression for classifying operands.
>
> 	* gcc/config/aarch64/aarch64.c
> 	(aarch64_classify_symbolic_expression): New function.
>
> 	* gcc/config/aarch64/aarch64.c (aarch64_symbolic_constant_p):
> 	New function.
>
> 	* gcc/config/aarch64/predicates.md (aarch64_valid_symref):
> 	Symbol with constant offset is a valid symbol reference.

OK

Patch

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 542c1e0..53c238a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2820,6 +2820,17 @@  aarch64_symbolic_address_p (rtx x)
   return GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF;
 }
 
+/* Classify the base of symbolic expression X, given that X appears in
+   context CONTEXT.  */
+static enum aarch64_symbol_type
+aarch64_classify_symbolic_expression (rtx x, enum aarch64_symbol_context context)
+{
+  rtx offset;
+  split_const (x, &x, &offset);
+  return aarch64_classify_symbol (x, context);
+}
+
+
 /* Return TRUE if X is a legitimate address for accessing memory in
    mode MODE.  */
 static bool
@@ -3227,7 +3238,7 @@  aarch64_print_operand (FILE *f, rtx x, char code)
       if (GET_CODE (x) == HIGH)
 	x = XEXP (x, 0);
 
-      switch (aarch64_classify_symbol (x, SYMBOL_CONTEXT_ADR))
+      switch (aarch64_classify_symbolic_expression (x, SYMBOL_CONTEXT_ADR))
 	{
 	case SYMBOL_SMALL_GOT:
 	  asm_fprintf (asm_out_file, ":got:");
@@ -3256,7 +3267,7 @@  aarch64_print_operand (FILE *f, rtx x, char code)
       break;
 
     case 'L':
-      switch (aarch64_classify_symbol (x, SYMBOL_CONTEXT_ADR))
+      switch (aarch64_classify_symbolic_expression (x, SYMBOL_CONTEXT_ADR))
 	{
 	case SYMBOL_SMALL_GOT:
 	  asm_fprintf (asm_out_file, ":lo12:");
@@ -3285,7 +3296,8 @@  aarch64_print_operand (FILE *f, rtx x, char code)
       break;
 
     case 'G':
-      switch (aarch64_classify_symbol (x, SYMBOL_CONTEXT_ADR))
+
+      switch (aarch64_classify_symbolic_expression (x, SYMBOL_CONTEXT_ADR))
 	{
 	case SYMBOL_SMALL_TPREL:
 	  asm_fprintf (asm_out_file, ":tprel_hi12:");
@@ -4746,6 +4758,8 @@  aarch64_classify_tls_symbol (rtx x)
     }
 }
 
+/* Return the method that should be used to access SYMBOL_REF or
+   LABEL_REF X in context CONTEXT.  */
 enum aarch64_symbol_type
 aarch64_classify_symbol (rtx x,
 			 enum aarch64_symbol_context context ATTRIBUTE_UNUSED)
@@ -4817,7 +4831,23 @@  aarch64_classify_symbol (rtx x,
   return SYMBOL_FORCE_TO_MEM;
 }
 
+/* Return true if X is a symbolic constant that can be used in context
+   CONTEXT.  If it is, store the type of the symbol in *SYMBOL_TYPE.  */
+
+bool
+aarch64_symbolic_constant_p (rtx x, enum aarch64_symbol_context context,
+			     enum aarch64_symbol_type *symbol_type)
+{
+  rtx offset;
+  split_const (x, &x, &offset);
+  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+    *symbol_type = aarch64_classify_symbol (x, context);
+  else
+    return false;
 
+  /* No checking of offset at this point.  */
+  return true;
+}
 
 bool
 aarch64_constant_address_p (rtx x)
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 7089e8b..328e5cf 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -114,8 +114,12 @@ 
        (match_test "mode == DImode && CONSTANT_ADDRESS_P (op)")))
 
 (define_predicate "aarch64_valid_symref"
-  (and (match_code "symbol_ref, label_ref")
-	(match_test "aarch64_classify_symbol (op, SYMBOL_CONTEXT_ADR) != SYMBOL_FORCE_TO_MEM")))
+  (match_code "const, symbol_ref, label_ref")
+{
+  enum aarch64_symbol_type symbol_type;
+  return (aarch64_symbolic_constant_p (op, SYMBOL_CONTEXT_ADR, &symbol_type)
+	 && symbol_type != SYMBOL_FORCE_TO_MEM);
+})
 
 (define_predicate "aarch64_tls_ie_symref"
   (match_code "symbol_ref, label_ref")