Commit 1b1e81f8 by Jiong Wang Committed by Jiong Wang

[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
parent b175b679
......@@ -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.
......
......@@ -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
......
......@@ -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,
......
......@@ -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"
......@@ -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")]
......
......@@ -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
;; -------------------------------------------------------------------
......
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.
......
/* { 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 } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment