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