(AARCH64_FUSE_ADRP_LDR): Likewise.
(AARCH64_FUSE_CMP_BRANCH): Likewise.
+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
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,
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)
case SYMBOL_REF:
- if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
+ if (aarch64_cmodel == AARCH64_CMODEL_LARGE
+ || aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC)
{
/* LDR. */
if (speed)
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",
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;
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:
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;
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
#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"
UNSPEC_FRINTX
UNSPEC_FRINTZ
UNSPEC_GOTSMALLPIC
+ UNSPEC_GOTSMALLPIC28K
UNSPEC_GOTSMALLTLS
UNSPEC_GOTTINYPIC
UNSPEC_LD1
[(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")]