diff options
author | Jiong Wang <jiong.wang@arm.com> | 2015-06-26 14:00:56 +0000 |
---|---|---|
committer | Jiong Wang <jiwang@gcc.gnu.org> | 2015-06-26 14:00:56 +0000 |
commit | 1b1e81f847a651bef0fff52d4dc5d09d9e521bcc (patch) | |
tree | 64b16d72cff8de0a9ba7d3f8cb5d1b43cdde3f87 | |
parent | b175b679a4ec31502b1eb6752265f7be09ba9c08 (diff) | |
download | gcc-1b1e81f847a651bef0fff52d4dc5d09d9e521bcc.zip gcc-1b1e81f847a651bef0fff52d4dc5d09d9e521bcc.tar.gz gcc-1b1e81f847a651bef0fff52d4dc5d09d9e521bcc.tar.bz2 |
[AArch64][2/2] Implement -fpic for -mcmodel=small
2015-06-26 Jiong Wang <jiong.wang@arm.com>
gcc/
* config/aarch64/aarch64-protos.h (aarch64_symbol_type): New type
SYMBOL_SMALL_GOT_28K.
* config/aarch64/aarch64.md: (ldr_got_small_<mode>): Support new GOT
relocation modifiers.
(unspec): New enum "UNSPEC_GOTMALLPIC28K.
(ldr_got_small_28k_<mode>): New.
(ldr_got_small_28k_sidi): New.
* config/aarch64/iterators.md (got_modifier): New mode iterator.
* config/aarch64/aarch64-otps.h (aarch64_code_model): New model.
* config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Support
SYMBOL_SMALL_GOT_28K.
(aarch64_rtx_costs): Add costs for new instruction sequences.
(initialize_aarch64_code_model): Initialize new model.
(aarch64_classify_symbol): Recognize new model and new symbol classification.
(aarch64_asm_preferred_eh_data_format): Support new model.
(aarch64_load_symref_appropriately): Generate new instruction
sequences for -fpic.
(TARGET_USE_PSEUDO_PIC_REG): New definition.
(aarch64_use_pseudo_pic_reg): New function.
gcc/testsuite/
* gcc.target/aarch64/pic-small.c: New testcase.
From-SVN: r225017
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-opts.h | 3 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 8 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 86 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 24 | ||||
-rw-r--r-- | gcc/config/aarch64/iterators.md | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/pic-small.c | 26 |
8 files changed, 174 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e182789..bf2d02c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -69,6 +69,28 @@ 2015-06-26 Jiong Wang <jiong.wang@arm.com> + * config/aarch64/aarch64-protos.h (aarch64_symbol_type): New type + SYMBOL_SMALL_GOT_28K. + * config/aarch64/aarch64.md: (ldr_got_small_<mode>): Support new GOT + relocation modifiers. + (unspec): New enum "UNSPEC_GOTMALLPIC28K. + (ldr_got_small_28k_<mode>): New. + (ldr_got_small_28k_sidi): New. + * config/aarch64/iterators.md (got_modifier): New mode iterator. + * config/aarch64/aarch64-otps.h (aarch64_code_model): New model. + * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Support + SYMBOL_SMALL_GOT_28K. + (aarch64_rtx_costs): Add costs for new instruction sequences. + (initialize_aarch64_code_model): Initialize new model. + (aarch64_classify_symbol): Recognize new model and new symbol classification. + (aarch64_asm_preferred_eh_data_format): Support new model. + (aarch64_load_symref_appropriately): Generate new instruction + sequences for -fpic. + (TARGET_USE_PSEUDO_PIC_REG): New definition. + (aarch64_use_pseudo_pic_reg): New function. + +2015-06-26 Jiong Wang <jiong.wang@arm.com> + * config/aarch64/aarch64-protos.h (aarch64_symbol_type): Rename SYMBOL_SMALL_GOT to SYMBOL_SMALL_GOT_4G. * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Ditto. diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index ea64cf4..24bfd9f 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -56,6 +56,9 @@ enum aarch64_code_model { /* Static code, data and GOT/PLT fit within a 4GB region. The default PIC code model. */ AARCH64_CMODEL_SMALL_PIC, + /* -fpic for small memory model. + GOT size to 28KiB (4K*8-4K) or 3580 entries. */ + AARCH64_CMODEL_SMALL_SPIC, /* No assumptions about addresses of code and data. The PIC variant is not yet implemented. */ AARCH64_CMODEL_LARGE diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 4522f9c..2c623cc 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -62,6 +62,13 @@ enum aarch64_symbol_context This corresponds to the small PIC model of the compiler. + SYMBOL_SMALL_GOT_28K: Similar to SYMBOL_SMALL_GOT_4G, but used for symbol + restricted within 28K GOT table size. + + ldr reg, [gp, #:gotpage_lo15:sym] + + This corresponds to -fpic model for small memory model of the compiler. + SYMBOL_SMALL_TLSGD SYMBOL_SMALL_TLSDESC SYMBOL_SMALL_GOTTPREL @@ -95,6 +102,7 @@ enum aarch64_symbol_context enum aarch64_symbol_type { SYMBOL_SMALL_ABSOLUTE, + SYMBOL_SMALL_GOT_28K, SYMBOL_SMALL_GOT_4G, SYMBOL_SMALL_TLSGD, SYMBOL_SMALL_TLSDESC, diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 8533e1d..a11d856 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -846,6 +846,66 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, emit_insn (gen_rtx_SET (dest, imm)); return; + case SYMBOL_SMALL_GOT_28K: + { + machine_mode mode = GET_MODE (dest); + rtx gp_rtx = pic_offset_table_rtx; + + /* NOTE: pic_offset_table_rtx can be NULL_RTX, because we can reach + here before rtl expand. Tree IVOPT will generate rtl pattern to + decide rtx costs, in which case pic_offset_table_rtx is not + initialized. For that case no need to generate the first adrp + instruction as the the final cost for global variable access is + one instruction. */ + if (gp_rtx != NULL) + { + /* -fpic for -mcmodel=small allow 32K GOT table size (but we are + using the page base as GOT base, the first page may be wasted, + in the worst scenario, there is only 28K space for GOT). + + The generate instruction sequence for accessing global variable + is: + + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym] + + Only one instruction needed. But we must initialize + pic_offset_table_rtx properly. We generate initialize insn for + every global access, and allow CSE to remove all redundant. + + The final instruction sequences will look like the following + for multiply global variables access. + + adrp pic_offset_table_rtx, _GLOBAL_OFFSET_TABLE_ + + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym1] + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym2] + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym3] + ... */ + + rtx s = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); + crtl->uses_pic_offset_table = 1; + emit_move_insn (gp_rtx, gen_rtx_HIGH (Pmode, s)); + + if (mode != GET_MODE (gp_rtx)) + gp_rtx = simplify_gen_subreg (mode, gp_rtx, GET_MODE (gp_rtx), 0); + } + + if (mode == ptr_mode) + { + if (mode == DImode) + emit_insn (gen_ldr_got_small_28k_di (dest, gp_rtx, imm)); + else + emit_insn (gen_ldr_got_small_28k_si (dest, gp_rtx, imm)); + } + else + { + gcc_assert (mode == Pmode); + emit_insn (gen_ldr_got_small_28k_sidi (dest, gp_rtx, imm)); + } + + return; + } + case SYMBOL_SMALL_GOT_4G: { /* In ILP32, the mode of dest can be either SImode or DImode, @@ -1498,6 +1558,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) case SYMBOL_SMALL_TLSGD: case SYMBOL_SMALL_TLSDESC: case SYMBOL_SMALL_GOTTPREL: + case SYMBOL_SMALL_GOT_28K: case SYMBOL_SMALL_GOT_4G: case SYMBOL_TINY_GOT: if (offset != const0_rtx) @@ -6441,7 +6502,8 @@ cost_plus: case SYMBOL_REF: - if (aarch64_cmodel == AARCH64_CMODEL_LARGE) + if (aarch64_cmodel == AARCH64_CMODEL_LARGE + || aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC) { /* LDR. */ if (speed) @@ -7295,7 +7357,9 @@ initialize_aarch64_code_model (void) aarch64_cmodel = AARCH64_CMODEL_TINY_PIC; break; case AARCH64_CMODEL_SMALL: - aarch64_cmodel = AARCH64_CMODEL_SMALL_PIC; + aarch64_cmodel = (flag_pic == 2 + ? AARCH64_CMODEL_SMALL_PIC + : AARCH64_CMODEL_SMALL_SPIC); break; case AARCH64_CMODEL_LARGE: sorry ("code model %qs with -f%s", "large", @@ -7376,6 +7440,7 @@ aarch64_classify_symbol (rtx x, rtx offset, case AARCH64_CMODEL_TINY: return SYMBOL_TINY_ABSOLUTE; + case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: return SYMBOL_SMALL_ABSOLUTE; @@ -7423,9 +7488,11 @@ aarch64_classify_symbol (rtx x, rtx offset, return SYMBOL_TINY_GOT; return SYMBOL_TINY_ABSOLUTE; + case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: if (!aarch64_symbol_binds_local_p (x)) - return SYMBOL_SMALL_GOT_4G; + return (aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC + ? SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G); return SYMBOL_SMALL_ABSOLUTE; default: @@ -9299,6 +9366,7 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global) case AARCH64_CMODEL_TINY_PIC: case AARCH64_CMODEL_SMALL: case AARCH64_CMODEL_SMALL_PIC: + case AARCH64_CMODEL_SMALL_SPIC: /* text+got+data < 4Gb. 4-byte signed relocs are sufficient for everything. */ type = DW_EH_PE_sdata4; @@ -11594,6 +11662,15 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, return true; } +/* Return 1 if pseudo register should be created and used to hold + GOT address for PIC code. */ + +bool +aarch64_use_pseudo_pic_reg (void) +{ + return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC; +} + #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST aarch64_address_cost @@ -11872,6 +11949,9 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, #undef TARGET_SCHED_FUSION_PRIORITY #define TARGET_SCHED_FUSION_PRIORITY aarch64_sched_fusion_priority +#undef TARGET_USE_PSEUDO_PIC_REG +#define TARGET_USE_PSEUDO_PIC_REG aarch64_use_pseudo_pic_reg + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-aarch64.h" diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index dbc4d1f..a172268 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -87,6 +87,7 @@ UNSPEC_FRINTX UNSPEC_FRINTZ UNSPEC_GOTSMALLPIC + UNSPEC_GOTSMALLPIC28K UNSPEC_GOTSMALLTLS UNSPEC_GOTTINYPIC UNSPEC_LD1 @@ -4360,6 +4361,29 @@ [(set_attr "type" "load1")] ) +(define_insn "ldr_got_small_28k_<mode>" + [(set (match_operand:PTR 0 "register_operand" "=r") + (unspec:PTR [(mem:PTR (lo_sum:PTR + (match_operand:PTR 1 "register_operand" "r") + (match_operand:PTR 2 "aarch64_valid_symref" "S")))] + UNSPEC_GOTSMALLPIC28K))] + "" + "ldr\\t%<w>0, [%1, #:<got_modifier>:%a2]" + [(set_attr "type" "load1")] +) + +(define_insn "ldr_got_small_28k_sidi" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (unspec:SI [(mem:SI (lo_sum:DI + (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "aarch64_valid_symref" "S")))] + UNSPEC_GOTSMALLPIC28K)))] + "TARGET_ILP32" + "ldr\\t%w0, [%1, #:gotpage_lo14:%a2]" + [(set_attr "type" "load1")] +) + (define_insn "ldr_got_tiny" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 498358a..b19d3d7 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -657,6 +657,10 @@ (define_mode_attr insn_count [(OI "8") (CI "12") (XI "16")]) +;; -fpic small model GOT reloc modifers: gotpage_lo15/lo14 for ILP64/32. +;; No need of iterator for -fPIC as it use got_lo12 for both modes. +(define_mode_attr got_modifier [(SI "gotpage_lo14") (DI "gotpage_lo15")]) + ;; ------------------------------------------------------------------- ;; Code Iterators ;; ------------------------------------------------------------------- diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 55fa18f..610650e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-06-26 Jiong Wang <jiong.wang@arm.com> + + * gcc.target/aarch64/pic-small.c: New testcase. + 2015-06-26 Richard Biener <rguenther@suse.de> * gcc.dg/tree-ssa/forwprop-25.c: Adjust. diff --git a/gcc/testsuite/gcc.target/aarch64/pic-small.c b/gcc/testsuite/gcc.target/aarch64/pic-small.c new file mode 100644 index 0000000..874f81b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pic-small.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fpic -fno-inline --save-temps" } */ + +void abort (); +int global_a; + +int +initialize (void) +{ + global_a = 0x10; + return global_a - 1; +} + +int +main (int argc, char **argv) +{ + int a = initialize (); + + if (a != global_a - 1) + abort (); + + return 0; +} + +/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, _GLOBAL_OFFSET_TABLE" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ |