aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2015-06-26 14:00:56 +0000
committerJiong Wang <jiwang@gcc.gnu.org>2015-06-26 14:00:56 +0000
commit1b1e81f847a651bef0fff52d4dc5d09d9e521bcc (patch)
tree64b16d72cff8de0a9ba7d3f8cb5d1b43cdde3f87
parentb175b679a4ec31502b1eb6752265f7be09ba9c08 (diff)
downloadgcc-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/ChangeLog22
-rw-r--r--gcc/config/aarch64/aarch64-opts.h3
-rw-r--r--gcc/config/aarch64/aarch64-protos.h8
-rw-r--r--gcc/config/aarch64/aarch64.c86
-rw-r--r--gcc/config/aarch64/aarch64.md24
-rw-r--r--gcc/config/aarch64/iterators.md4
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pic-small.c26
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 } } */