From 6997dd683bb3e21b4b9480c163fb015b105f5d8e Mon Sep 17 00:00:00 2001 From: Yvan Roux Date: Mon, 30 Nov 2015 11:01:17 +0100 Subject: gcc/ Backport from trunk r227748. 2015-09-14 Ramana Radhakrishnan PR target/63304 * config/aarch64/aarch64.c (aarch64_expand_mov_immediate): Handle nopcrelative_literal_loads. (aarch64_classify_address): Likewise. (aarch64_constant_pool_reload_icode): Define. (aarch64_secondary_reload): Handle secondary reloads for literal pools. (aarch64_override_options): Handle nopcrelative_literal_loads. (aarch64_classify_symbol): Handle nopcrelative_literal_loads. * config/aarch64/aarch64.md (aarch64_reload_movcp): Define. (aarch64_reload_movcp): Likewise. * config/aarch64/aarch64.opt (mpc-relative-literal-loads): New option. * config/aarch64/predicates.md (aarch64_constant_pool_symref): New predicate. * doc/invoke.texi (mpc-relative-literal-loads): Document. gcc/ Backport from trunk r229160. 2015-10-22 Ramana Radhakrishnan PR target/63304 * config/aarch64/aarch64.c (aarch64_nopcrelative_literal_loads): New. (aarch64_expand_mov_immediate): Use aarch64_nopcrelative_literal_loads. (aarch64_classify_address): Likewise. (aarch64_secondary_reload): Likewise. (aarch64_override_options_after_change_1): Adjust. * config/aarch64/aarch64.md (aarch64_reload_movcp): Use aarch64_nopcrelative_literal_loads. (aarch64_reload_movcp): Likewise. * config/aarch64/aarch64-protos.h (aarch64_nopcrelative_literal_loads): Declare gcc/testsuite/ Backport from trunk r229160. 2015-10-22 Jiong Wang Ramana Radhakrishnan PR target/63304 * gcc.target/aarch64/pr63304_1.c: New test. gcc/testsuite/ Backport from trunk r229161. 2015-10-22 Andre Vieira PR testsuite/67948 * gcc.target/arm/xor-and.c: Adjust test to check for eor instead of orr. Change-Id: I939fdc89b6a545d8f60971f4bbfb1f5f901c20b6 --- gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64.c | 114 +++++++++++++++++++++++++-- gcc/config/aarch64/aarch64.md | 26 ++++++ gcc/config/aarch64/aarch64.opt | 4 + gcc/config/aarch64/iterators.md | 3 + gcc/config/aarch64/predicates.md | 4 + gcc/doc/invoke.texi | 8 ++ gcc/testsuite/gcc.target/aarch64/pr63304_1.c | 47 +++++++++++ gcc/testsuite/gcc.target/arm/xor-and.c | 2 +- 9 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr63304_1.c diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 3c46222d659..75c0161a870 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -401,4 +401,5 @@ int aarch64_ccmp_mode_to_code (enum machine_mode mode); bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset); bool aarch64_operands_ok_for_ldpstp (rtx *, bool, enum machine_mode); bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, enum machine_mode); +extern bool aarch64_nopcrelative_literal_loads; #endif /* GCC_AARCH64_PROTOS_H */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 0eba6a9372e..7a5a2312201 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -183,6 +183,9 @@ enum aarch64_processor aarch64_tune = cortexa53; /* Mask to specify which instruction scheduling options should be used. */ unsigned long aarch64_tune_flags = 0; +/* Global flag for PC relative loads. */ +bool aarch64_nopcrelative_literal_loads; + /* Support for command line parsing of boolean flags in the tuning structures. */ struct aarch64_flag_desc @@ -1566,11 +1569,27 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) aarch64_emit_move (dest, base); return; } + mem = force_const_mem (ptr_mode, imm); gcc_assert (mem); + + /* If we aren't generating PC relative literals, then + we need to expand the literal pool access carefully. + This is something that needs to be done in a number + of places, so could well live as a separate function. */ + if (aarch64_nopcrelative_literal_loads) + { + gcc_assert (can_create_pseudo_p ()); + base = gen_reg_rtx (ptr_mode); + aarch64_expand_mov_immediate (base, XEXP (mem, 0)); + mem = gen_rtx_MEM (ptr_mode, base); + } + if (mode != ptr_mode) mem = gen_rtx_ZERO_EXTEND (mode, mem); + emit_insn (gen_rtx_SET (VOIDmode, dest, mem)); + return; case SYMBOL_SMALL_TLSGD: @@ -3681,9 +3700,10 @@ aarch64_classify_address (struct aarch64_address_info *info, rtx sym, addend; split_const (x, &sym, &addend); - return (GET_CODE (sym) == LABEL_REF - || (GET_CODE (sym) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (sym))); + return ((GET_CODE (sym) == LABEL_REF + || (GET_CODE (sym) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (sym) + && !aarch64_nopcrelative_literal_loads))); } return false; @@ -4864,12 +4884,69 @@ aarch64_legitimize_reload_address (rtx *x_p, } +/* Return the reload icode required for a constant pool in mode. */ +static enum insn_code +aarch64_constant_pool_reload_icode (machine_mode mode) +{ + switch (mode) + { + case SFmode: + return CODE_FOR_aarch64_reload_movcpsfdi; + + case DFmode: + return CODE_FOR_aarch64_reload_movcpdfdi; + + case TFmode: + return CODE_FOR_aarch64_reload_movcptfdi; + + case V8QImode: + return CODE_FOR_aarch64_reload_movcpv8qidi; + + case V16QImode: + return CODE_FOR_aarch64_reload_movcpv16qidi; + + case V4HImode: + return CODE_FOR_aarch64_reload_movcpv4hidi; + + case V8HImode: + return CODE_FOR_aarch64_reload_movcpv8hidi; + + case V2SImode: + return CODE_FOR_aarch64_reload_movcpv2sidi; + + case V4SImode: + return CODE_FOR_aarch64_reload_movcpv4sidi; + + case V2DImode: + return CODE_FOR_aarch64_reload_movcpv2didi; + + case V2DFmode: + return CODE_FOR_aarch64_reload_movcpv2dfdi; + + default: + gcc_unreachable (); + } + + gcc_unreachable (); +} static reg_class_t aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, reg_class_t rclass, machine_mode mode, secondary_reload_info *sri) { + + /* If we have to disable direct literal pool loads and stores because the + function is too big, then we need a scratch register. */ + if (MEM_P (x) && GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) + && (SCALAR_FLOAT_MODE_P (GET_MODE (x)) + || targetm.vector_mode_supported_p (GET_MODE (x))) + && aarch64_nopcrelative_literal_loads) + { + sri->icode = aarch64_constant_pool_reload_icode (mode); + return NO_REGS; + } + /* Without the TARGET_SIMD instructions we cannot move a Q register to a Q register directly. We need a scratch. */ if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x) @@ -7511,7 +7588,7 @@ aarch64_override_options_after_change_1 (struct gcc_options *opts) else if (opts->x_flag_omit_leaf_frame_pointer) opts->x_flag_omit_frame_pointer = true; - /* If not opzimizing for size, set the default + /* If not optimizing for size, set the default alignment to what the target wants. */ if (!opts->x_optimize_size) { @@ -7522,6 +7599,24 @@ aarch64_override_options_after_change_1 (struct gcc_options *opts) if (opts->x_align_functions <= 0) opts->x_align_functions = aarch64_tune_params.function_align; } + + /* If nopcrelative_literal_loads is set on the command line, this + implies that the user asked for PC relative literal loads. */ + if (opts->x_nopcrelative_literal_loads == 1) + aarch64_nopcrelative_literal_loads = false; + + /* If it is not set on the command line, we default to no + pc relative literal loads. */ + if (opts->x_nopcrelative_literal_loads == 2) + aarch64_nopcrelative_literal_loads = true; + + /* In the tiny memory model it makes no sense + to disallow non PC relative literal pool loads + as many other things will break anyway. */ + if (opts->x_nopcrelative_literal_loads + && (aarch64_cmodel == AARCH64_CMODEL_TINY + || aarch64_cmodel == AARCH64_CMODEL_TINY_PIC)) + aarch64_nopcrelative_literal_loads = false; } /* 'Unpack' up the internal tuning structs and update the options @@ -8710,7 +8805,16 @@ aarch64_classify_symbol (rtx x, rtx offset) if (GET_CODE (x) == SYMBOL_REF) { if (aarch64_cmodel == AARCH64_CMODEL_LARGE) - return SYMBOL_FORCE_TO_MEM; + { + /* This is alright even in PIC code as the constant + pool reference is always PC relative and within + the same translation unit. */ + if (nopcrelative_literal_loads + && CONSTANT_POOL_ADDRESS_P (x)) + return SYMBOL_SMALL_ABSOLUTE; + else + return SYMBOL_FORCE_TO_MEM; + } if (aarch64_tls_symbol_p (x)) return aarch64_classify_tls_symbol (x); diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 9751999ccfc..7503cfd4dd4 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4485,6 +4485,32 @@ ;; ------------------------------------------------------------------- ;; Reload support ;; ------------------------------------------------------------------- +;; Reload Scalar Floating point modes from constant pool. +;; The AArch64 port doesn't have __int128 constant move support. +(define_expand "aarch64_reload_movcp" + [(set (match_operand:GPF_TF 0 "register_operand" "=w") + (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S"))) + (clobber (match_operand:P 2 "register_operand" "=&r"))] + "TARGET_FLOAT && aarch64_nopcrelative_literal_loads" + { + aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0)); + emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2])); + DONE; + } +) + +;; Reload Vector modes from constant pool. +(define_expand "aarch64_reload_movcp" + [(set (match_operand:VALL 0 "register_operand" "=w") + (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S"))) + (clobber (match_operand:P 2 "register_operand" "=&r"))] + "TARGET_FLOAT && aarch64_nopcrelative_literal_loads" + { + aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0)); + emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2])); + DONE; + } +) (define_expand "aarch64_reload_mov" [(set (match_operand:TX 0 "register_operand" "=w") diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 8642bdb74f3..a1ce58d4ea8 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -144,3 +144,7 @@ Enum(aarch64_abi) String(ilp32) Value(AARCH64_ABI_ILP32) EnumValue Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64) + +mpc-relative-literal-loads +Target Report Save Var(nopcrelative_literal_loads) Init(2) Save +PC relative literal loads. diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 9232e8e7b92..964f8f1af68 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -44,6 +44,9 @@ ;; Double vector modes. (define_mode_iterator VDF [V2SF V4HF]) +;; Iterator for all scalar floating point modes (SF, DF and TF) +(define_mode_iterator GPF_TF [SF DF TF]) + ;; Integer vector modes. (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI]) diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index ee16dc88bd0..7841378a5da 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -362,3 +362,7 @@ (define_predicate "aarch64_simd_shift_imm_bitsize_di" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 0, 64)"))) + +(define_predicate "aarch64_constant_pool_symref" + (and (match_code "symbol_ref") + (match_test "CONSTANT_POOL_ADDRESS_P (op)"))) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8d27c3ffe52..3996518204f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12412,6 +12412,14 @@ for @var{string} in this option are not guaranteed to be consistent across releases. This option is only intended to be useful when developing GCC. + +@item -mpc-relative-literal-loads +@opindex mpcrelativeliteralloads +Enable PC relative literal loads. If this option is used, literal +pools are assumed to have a range of up to 1MiB and an appropriate +instruction sequence is used. This option has no impact when used +with @option{-mcmodel=tiny}. + @end table @subsubsection @option{-march} and @option{-mcpu} Feature Modifiers diff --git a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c new file mode 100644 index 00000000000..fa0fb56d9e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c @@ -0,0 +1,47 @@ +/* { dg-do assemble } */ +/* { dg-options "-O1 --save-temps" } */ +#pragma GCC push_options +#pragma GCC target ("+nothing+simd, cmodel=small") + +int +cal (float a) +{ + float b = 1.2; + float c = 2.2; + if ((a + b) != c) + return 0; + else + return 1; +} + +#pragma GCC push_options + +#pragma GCC target ("cmodel=large") + +int +cal2 (float a) +{ + + float b = 1.2; + float c = 2.2; + if ((a + b) != c) + return 0; + else + return 1; +} + +#pragma GCC pop_options + +int +cal3 (float a) +{ + + float b = 1.2; + float c = 2.2; + if ((a + b) != c) + return 0; + else + return 1; +} + +/* { dg-final { scan-assembler-times "adrp" 6 } } */ diff --git a/gcc/testsuite/gcc.target/arm/xor-and.c b/gcc/testsuite/gcc.target/arm/xor-and.c index 53dff85f8f7..3715530cd7b 100644 --- a/gcc/testsuite/gcc.target/arm/xor-and.c +++ b/gcc/testsuite/gcc.target/arm/xor-and.c @@ -10,6 +10,6 @@ unsigned short foo (unsigned short x) return x; } -/* { dg-final { scan-assembler "orr" } } */ +/* { dg-final { scan-assembler "eor" } } */ /* { dg-final { scan-assembler-not "mvn" } } */ /* { dg-final { scan-assembler-not "uxth" } } */ -- cgit v1.2.3