[AArch64][2/2] Implement -fpic for -mcmodel=small
authorJiong Wang <jiong.wang@arm.com>
Fri, 26 Jun 2015 14:00:56 +0000 (14:00 +0000)
committerJiong Wang <jiwang@gcc.gnu.org>
Fri, 26 Jun 2015 14:00:56 +0000 (14:00 +0000)
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

gcc/ChangeLog
gcc/config/aarch64/aarch64-opts.h
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/pic-small.c [new file with mode: 0644]

index e1827899a46e42cd2d351f21bbec82d2b848ce98..bf2d02c8c3c2b935499310ab491ca971a318356d 100644 (file)
        (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
index ea64cf4a1e7da6249b78649af0c37cc617a9b6b3..24bfd9fd1506abf64478e3cf7abb29c573861435 100644 (file)
@@ -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
index 4522f9c4b2fb711abfc10e480bf3bd4dd2d449ad..2c623cc145cbdbf195a2dff35aada15c454905b0 100644 (file)
@@ -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,
index 8533e1d2f7ff9d9a98871706db2a3bf9bfc23f54..a11d8568e31d99f31f97e4323c60e05d53b186b3 100644 (file)
@@ -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"
index dbc4d1fbfee85bc8bc686babc63b82ff8371dfc4..a1722684bc5b2e4bd982c0e6002505e0494c7a1c 100644 (file)
@@ -87,6 +87,7 @@
     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")]
index 498358a6354fe3afc3032d5be7526d942d1ec3ac..b19d3d743a733303371341d9f323f47ed83618c3 100644 (file)
 
 (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
 ;; -------------------------------------------------------------------
index 55fa18f1dc499e806ff4c07627e4b9e9147c7feb..610650edef7d6fff3ede7b5ca77c6b4188e152af 100644 (file)
@@ -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 (file)
index 0000000..874f81b
--- /dev/null
@@ -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 } } */