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
* 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.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")