This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Medium model support in GCC


Hi,
here is updated patch, tested on x86_64-linux with and without MEDIUM
being default.  Sorry for the delays - there was power outage for the
machine I tested it on.

> >         if (GET_CODE (disp) == SYMBOL_REF
> > ! 	  && !SYMBOL_REF_FAR_ADDR_P (disp)
> >   	  && SYMBOL_REF_LOCAL_P (disp))
> 
> You made one change here ...
> 
> >   	  if (((GET_CODE (op0) == SYMBOL_REF
> > ! 		&& (ix86_cmodel == CM_SMALL_PIC
> > ! 		    || (ix86_cmodel == CM_MEDIUM_PIC
> > ! 		        && !SYMBOL_REF_FAR_ADDR_P (op0)))
> >   		&& SYMBOL_REF_LOCAL_P (op0))
> 
> ... but not all instances.  There are at least 3 more.

There are similar instances in predicates.md that are not quite same.
We test whteher the absolute address fits in and this is true only for
small/medium model, not for PIC models and for unsigned also not for
kernel model, so I kept the conditional in a way enumerating these 2/3
models as it seems cleaner than equivalent !SYMBOL_REF_FAR_ADDR_P (op0)
&& !flag_pic && ix86_model != CM_KERNEL especially when we will have to
exclude large model we will have to add shortly too.  But I can use this
form or something else if it sounds better  (this is still one test
shorter)
> 
> > + mlarge-data-treshold=
> 
> Misspelled "threshold", all instances.

Honza

	* output.h (enum section_category): Export from varasm.c
	(categorize_decl_for_section): Likewise.
	* varasm.c (enum section_category): Kill.
	(categorize_decl_for_section): Make global.
	* i386-protos.h (x86_output_aligned_bss, x86_elf_aligned_common):
	Declare.
	* i386.c (ix86_section_threshold): New static variable.
	(ix86_in_large_data_p, ix86_encode_section_info, x86_64_elf_unique_section,
	x86_64_elf_select_section): New functions.
	(TARGET_ENCODE_SECTION_INFO): Define
	(override_options): Enable medium model for PIC.
	(ix86_expand_prologue): Expand gen_set_got_rex64.
	(legitimate_constant_p): Handle new UNSPECs.
	(legitimate_pic_address_disp_p): Likewise.
	(legitimize_pic_address): Lower MEDIUM model addressing.
	* i386.h (PIC_OFFSET_TABLE_REGNUM): Set for medium model PIC.
	(enum cmodel): Add MEDIUM_PIC.
	(SYMBOL_REF_FAR_ADDR_P): New macro.
	(SYMBOL_FLAG_FAR_ADDR): New flag.
	* i386.md (movdi): Support medium model.
	(set_got_rex64): New pattern.
	* i386.opt (mlarge-data-threshold): New flag.
	* predicates.md (zext_operand/sext_operand): Deal with medium model.
	* x86-64.h (ASM_OUTPUT_ALIGNED_BSS): Use x86_output_aligned_bss.
	(ASM_OUTPUT_ALIGNED_COMMON, TARGET_ASM_SELECT_SECTION,
	TARGET_ASM_UNIQUE_SECTION): New.

	* invoke.texi (-mlarge_data_threshold): Document

	* x86-64-medium-?.c: New.
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.159
diff -c -3 -p -r1.159 output.h
*** output.h	25 Jun 2005 02:00:41 -0000	1.159
--- output.h	24 Jul 2005 14:36:43 -0000
*************** extern void no_asm_to_stream (FILE *);
*** 500,505 ****
--- 500,543 ----
  #define SECTION_NOTYPE	 0x80000	/* don't output @progbits */
  #define SECTION_MACH_DEP 0x100000	/* subsequent bits reserved for target */
  
+ /* A helper function for default_elf_select_section and
+    default_elf_unique_section.  Categorizes the DECL.  */
+ 
+ enum section_category
+ {
+   SECCAT_TEXT,
+ 
+   SECCAT_RODATA,
+   SECCAT_RODATA_MERGE_STR,
+   SECCAT_RODATA_MERGE_STR_INIT,
+   SECCAT_RODATA_MERGE_CONST,
+   SECCAT_SRODATA,
+ 
+   SECCAT_DATA,
+ 
+   /* To optimize loading of shared programs, define following subsections
+      of data section:
+ 	_REL	Contains data that has relocations, so they get grouped
+ 		together and dynamic linker will visit fewer pages in memory.
+ 	_RO	Contains data that is otherwise read-only.  This is useful
+ 		with prelinking as most relocations won't be dynamically
+ 		linked and thus stay read only.
+ 	_LOCAL	Marks data containing relocations only to local objects.
+ 		These relocations will get fully resolved by prelinking.  */
+   SECCAT_DATA_REL,
+   SECCAT_DATA_REL_LOCAL,
+   SECCAT_DATA_REL_RO,
+   SECCAT_DATA_REL_RO_LOCAL,
+ 
+   SECCAT_SDATA,
+   SECCAT_TDATA,
+ 
+   SECCAT_BSS,
+   SECCAT_SBSS,
+   SECCAT_TBSS
+ };
+ 
+ 
  extern bool set_named_section_flags (const char *, unsigned int);
  #define named_section_flags(NAME, FLAGS) \
    named_section_real((NAME), (FLAGS), /*decl=*/NULL_TREE)
*************** extern unsigned int default_section_type
*** 510,515 ****
--- 548,554 ----
  
  extern void default_no_named_section (const char *, unsigned int, tree);
  extern void default_elf_asm_named_section (const char *, unsigned int, tree);
+ extern enum section_category categorize_decl_for_section (tree, int, int);
  extern void default_coff_asm_named_section (const char *, unsigned int, tree);
  extern void default_pe_asm_named_section (const char *, unsigned int, tree);
  
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.522
diff -c -3 -p -r1.522 varasm.c
*** varasm.c	22 Jul 2005 17:40:29 -0000	1.522
--- varasm.c	24 Jul 2005 14:36:44 -0000
*************** default_select_section (tree decl, int r
*** 5012,5058 ****
      data_section ();
  }
  
- /* A helper function for default_elf_select_section and
-    default_elf_unique_section.  Categorizes the DECL.  */
- 
  enum section_category
- {
-   SECCAT_TEXT,
- 
-   SECCAT_RODATA,
-   SECCAT_RODATA_MERGE_STR,
-   SECCAT_RODATA_MERGE_STR_INIT,
-   SECCAT_RODATA_MERGE_CONST,
-   SECCAT_SRODATA,
- 
-   SECCAT_DATA,
- 
-   /* To optimize loading of shared programs, define following subsections
-      of data section:
- 	_REL	Contains data that has relocations, so they get grouped
- 		together and dynamic linker will visit fewer pages in memory.
- 	_RO	Contains data that is otherwise read-only.  This is useful
- 		with prelinking as most relocations won't be dynamically
- 		linked and thus stay read only.
- 	_LOCAL	Marks data containing relocations only to local objects.
- 		These relocations will get fully resolved by prelinking.  */
-   SECCAT_DATA_REL,
-   SECCAT_DATA_REL_LOCAL,
-   SECCAT_DATA_REL_RO,
-   SECCAT_DATA_REL_RO_LOCAL,
- 
-   SECCAT_SDATA,
-   SECCAT_TDATA,
- 
-   SECCAT_BSS,
-   SECCAT_SBSS,
-   SECCAT_TBSS
- };
- 
- static enum section_category
- categorize_decl_for_section (tree, int, int);
- 
- static enum section_category
  categorize_decl_for_section (tree decl, int reloc, int shlib)
  {
    enum section_category ret;
--- 5012,5018 ----
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.145
diff -c -3 -p -r1.145 i386-protos.h
*** config/i386/i386-protos.h	18 Jul 2005 06:39:18 -0000	1.145
--- config/i386/i386-protos.h	24 Jul 2005 14:36:45 -0000
*************** struct ix86_address
*** 259,264 ****
--- 259,268 ----
  
  extern int ix86_decompose_address (rtx, struct ix86_address *);
  extern int memory_address_length (rtx addr);
+ extern void x86_output_aligned_bss (FILE *, tree, const char *,
+ 				    unsigned HOST_WIDE_INT, int);
+ extern void x86_elf_aligned_common (FILE *, const char *,
+ 				    unsigned HOST_WIDE_INT, int);
  
  #ifdef RTX_CODE
  extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.843
diff -c -3 -p -r1.843 i386.c
*** config/i386/i386.c	18 Jul 2005 06:39:18 -0000	1.843
--- config/i386/i386.c	24 Jul 2005 14:36:46 -0000
*************** unsigned int ix86_preferred_stack_bounda
*** 812,817 ****
--- 812,822 ----
  /* Values 1-5: see jump.c */
  int ix86_branch_cost;
  
+ /* Variables which are this size or smaller are put in the data/bss
+    or ldata/lbss sections.  */
+ 
+ int ix86_section_threshold = 65536;
+ 
  /* Prefix built by ASM_GENERATE_INTERNAL_LABEL.  */
  char internal_label_prefix[16];
  int internal_label_prefix_len;
*************** static const char * const x86_64_reg_cla
*** 945,950 ****
--- 950,961 ----
  static REAL_VALUE_TYPE ext_80387_constants_table [5];
  static bool ext_80387_constants_init = 0;
  static void init_ext_80387_constants (void);
+ static bool ix86_in_large_data_p (tree);
+ static void ix86_encode_section_info (tree, rtx, int);
+ static void x86_64_elf_unique_section (tree decl, int reloc) ATTRIBUTE_UNUSED;
+ static void x86_64_elf_select_section (tree decl, int reloc,
+ 				       unsigned HOST_WIDE_INT align)
+ 				      ATTRIBUTE_UNUSED;
  
  /* Initialize the GCC target structure.  */
  #undef TARGET_ATTRIBUTE_TABLE
*************** static void init_ext_80387_constants (vo
*** 965,970 ****
--- 976,984 ----
  #undef TARGET_ASM_FUNCTION_EPILOGUE
  #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
  
+ #undef TARGET_ENCODE_SECTION_INFO
+ #define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
+ 
  #undef TARGET_ASM_OPEN_PAREN
  #define TARGET_ASM_OPEN_PAREN ""
  #undef TARGET_ASM_CLOSE_PAREN
*************** override_options (void)
*** 1291,1304 ****
      {
        if (!strcmp (ix86_cmodel_string, "small"))
  	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
        else if (flag_pic)
  	sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
        else if (!strcmp (ix86_cmodel_string, "32"))
  	ix86_cmodel = CM_32;
        else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
  	ix86_cmodel = CM_KERNEL;
-       else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
- 	ix86_cmodel = CM_MEDIUM;
        else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
  	ix86_cmodel = CM_LARGE;
        else
--- 1305,1318 ----
      {
        if (!strcmp (ix86_cmodel_string, "small"))
  	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+       else if (!strcmp (ix86_cmodel_string, "medium"))
+ 	ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM;
        else if (flag_pic)
  	sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
        else if (!strcmp (ix86_cmodel_string, "32"))
  	ix86_cmodel = CM_32;
        else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
  	ix86_cmodel = CM_KERNEL;
        else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
  	ix86_cmodel = CM_LARGE;
        else
*************** override_options (void)
*** 1502,1507 ****
--- 1516,1529 ----
        else
  	ix86_branch_cost = i;
      }
+   if (ix86_section_threshold_string)
+     {
+       i = atoi (ix86_section_threshold_string);
+       if (i < 0)
+ 	error ("-mlarge-data-threshold=%d is negative", i);
+       else
+ 	ix86_section_threshold = i;
+     }
  
    if (ix86_tls_dialect_string)
      {
*************** override_options (void)
*** 1641,1646 ****
--- 1663,1837 ----
      flag_schedule_insns_after_reload = flag_schedule_insns = 0;
  }
  
+ /* switch to the appropriate section for output of DECL.
+    DECL is either a `VAR_DECL' node or a constant of some sort.
+    RELOC indicates whether forming the initial value of DECL requires
+    link-time relocations.  */
+ 
+ static void
+ x86_64_elf_select_section (tree decl, int reloc,
+ 		         unsigned HOST_WIDE_INT align)
+ {
+   if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+       && ix86_in_large_data_p (decl))
+     {
+       const char *sname = NULL;
+       switch (categorize_decl_for_section (decl, reloc, flag_pic))
+ 	{
+ 	case SECCAT_DATA:
+ 	  sname = ".ldata";
+ 	  break;
+ 	case SECCAT_DATA_REL:
+ 	  sname = ".ldata.rel";
+ 	  break;
+ 	case SECCAT_DATA_REL_LOCAL:
+ 	  sname = ".ldata.rel.local";
+ 	  break;
+ 	case SECCAT_DATA_REL_RO:
+ 	  sname = ".ldata.rel.ro";
+ 	  break;
+ 	case SECCAT_DATA_REL_RO_LOCAL:
+ 	  sname = ".ldata.rel.ro.local";
+ 	  break;
+ 	case SECCAT_BSS:
+ 	  sname = ".lbss";
+ 	  break;
+ 	case SECCAT_RODATA:
+ 	case SECCAT_RODATA_MERGE_STR:
+ 	case SECCAT_RODATA_MERGE_STR_INIT:
+ 	case SECCAT_RODATA_MERGE_CONST:
+ 	  sname = ".lrodata";
+ 	  break;
+ 	case SECCAT_SRODATA:
+ 	case SECCAT_SDATA:
+ 	case SECCAT_SBSS:
+ 	  gcc_unreachable ();
+ 	case SECCAT_TEXT:
+ 	case SECCAT_TDATA:
+ 	case SECCAT_TBSS:
+ 	  /* We don't split these for medium model.  Place them into
+ 	     default sections and hope for best.  */
+ 	  break;
+ 	}
+       if (sname)
+ 	{
+           named_section (decl, sname, reloc);
+ 	  return;
+ 	}
+     }
+   default_elf_select_section (decl, reloc, align);
+ }
+ 
+ /* Build up a unique section name, expressed as a
+    STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
+    RELOC indicates whether the initial value of EXP requires
+    link-time relocations.  */
+ 
+ static void
+ x86_64_elf_unique_section (tree decl, int reloc)
+ {
+   if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+       && ix86_in_large_data_p (decl))
+     {
+       const char *prefix = NULL;
+       /* We only need to use .gnu.linkonce if we don't have COMDAT groups.  */
+       bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
+ 
+       switch (categorize_decl_for_section (decl, reloc, flag_pic))
+ 	{
+ 	case SECCAT_DATA:
+ 	case SECCAT_DATA_REL:
+ 	case SECCAT_DATA_REL_LOCAL:
+ 	case SECCAT_DATA_REL_RO:
+ 	case SECCAT_DATA_REL_RO_LOCAL:
+           prefix = one_only ? ".gnu.linkonce.ld." : ".ldata.";
+ 	  break;
+ 	case SECCAT_BSS:
+           prefix = one_only ? ".gnu.linkonce.lb." : ".lbss.";
+ 	  break;
+ 	case SECCAT_RODATA:
+ 	case SECCAT_RODATA_MERGE_STR:
+ 	case SECCAT_RODATA_MERGE_STR_INIT:
+ 	case SECCAT_RODATA_MERGE_CONST:
+           prefix = one_only ? ".gnu.linkonce.lr." : ".lrodata.";
+ 	  break;
+ 	case SECCAT_SRODATA:
+ 	case SECCAT_SDATA:
+ 	case SECCAT_SBSS:
+ 	  gcc_unreachable ();
+ 	case SECCAT_TEXT:
+ 	case SECCAT_TDATA:
+ 	case SECCAT_TBSS:
+ 	  /* We don't split these for medium model.  Place them into
+ 	     default sections and hope for best.  */
+ 	  break;
+ 	}
+       if (prefix)
+ 	{
+ 	  const char *name;
+ 	  size_t nlen, plen;
+ 	  char *string;
+ 	  plen = strlen (prefix);
+ 
+ 	  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ 	  name = targetm.strip_name_encoding (name);
+ 	  nlen = strlen (name);
+ 
+ 	  string = alloca (nlen + plen + 1);
+ 	  memcpy (string, prefix, plen);
+ 	  memcpy (string + plen, name, nlen + 1);
+ 
+ 	  DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
+ 	  return;
+ 	}
+     }
+   default_unique_section (decl, reloc);
+ }
+ 
+ /* This says how to output assembler code to declare an
+    uninitialized external linkage data object.
+ 
+    For medim model x86-64 we need to use .largecomm opcode for
+    large objects.  */
+ void
+ x86_elf_aligned_common (FILE *file,
+ 			const char *name, unsigned HOST_WIDE_INT size,
+ 			int align)
+ {
+   if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+       && size > (unsigned int)ix86_section_threshold)
+     fprintf (file, ".largecomm\t");
+   else
+     fprintf (file, "%s", COMMON_ASM_OP);
+   assemble_name (file, name);
+   fprintf (file, ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
+ 	   size, align / BITS_PER_UNIT);
+ }
+ 
+ /* Utility function for targets to use in implementing
+    ASM_OUTPUT_ALIGNED_BSS.  */
+ 
+ void
+ x86_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
+ 			const char *name, unsigned HOST_WIDE_INT size,
+ 			int align)
+ {
+   if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
+       && size > (unsigned int)ix86_section_threshold)
+     named_section (decl, ".lbss", 0);
+   else
+     bss_section ();
+   ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+ #ifdef ASM_DECLARE_OBJECT_NAME
+   last_assemble_variable_decl = decl;
+   ASM_DECLARE_OBJECT_NAME (file, name, decl);
+ #else
+   /* Standard thing is just output label for the object.  */
+   ASM_OUTPUT_LABEL (file, name);
+ #endif /* ASM_DECLARE_OBJECT_NAME */
+   ASM_OUTPUT_SKIP (file, size ? size : 1);
+ }
+ 
  void
  optimization_options (int level, int size ATTRIBUTE_UNUSED)
  {
*************** ix86_expand_prologue (void)
*** 4644,4650 ****
  
    if (pic_reg_used)
      {
!       insn = emit_insn (gen_set_got (pic_offset_table_rtx));
  
        /* Even with accurate pre-reload life analysis, we can wind up
  	 deleting all references to the pic register after reload.
--- 4835,4844 ----
  
    if (pic_reg_used)
      {
!       if (TARGET_64BIT)
!         insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
!       else
!         insn = emit_insn (gen_set_got (pic_offset_table_rtx));
  
        /* Even with accurate pre-reload life analysis, we can wind up
  	 deleting all references to the pic register after reload.
*************** legitimate_constant_p (rtx x)
*** 5173,5178 ****
--- 5367,5374 ----
        if (GET_CODE (x) == UNSPEC)
  	switch (XINT (x, 1))
  	  {
+ 	  case UNSPEC_GOTOFF:
+ 	    return true;
  	  case UNSPEC_TPOFF:
  	  case UNSPEC_NTPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
*************** legitimate_pic_operand_p (rtx x)
*** 5232,5242 ****
--- 5428,5443 ----
      {
      case CONST:
        inner = XEXP (x, 0);
+       if (GET_CODE (inner) == PLUS
+ 	  && GET_CODE (XEXP (inner, 1)) == CONST_INT)
+ 	inner = XEXP (inner, 0);
  
        /* Only some unspecs are valid as "constants".  */
        if (GET_CODE (inner) == UNSPEC)
  	switch (XINT (inner, 1))
  	  {
+ 	  case UNSPEC_GOTOFF:
+ 	    return true;
  	  case UNSPEC_TPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
  	  default:
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5269,5275 ****
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && ix86_cmodel == CM_SMALL_PIC
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
--- 5470,5476 ----
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && !SYMBOL_REF_FAR_ADDR_P (disp)
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5284,5290 ****
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& ix86_cmodel == CM_SMALL_PIC
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
--- 5485,5491 ----
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& !SYMBOL_REF_FAR_ADDR_P (op0)
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
*************** legitimate_pic_address_disp_p (rtx disp)
*** 5302,5308 ****
        /* We are unsafe to allow PLUS expressions.  This limit allowed distance
           of GOT tables.  We should not need these anyway.  */
        if (GET_CODE (disp) != UNSPEC
! 	  || XINT (disp, 1) != UNSPEC_GOTPCREL)
  	return 0;
  
        if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
--- 5503,5510 ----
        /* We are unsafe to allow PLUS expressions.  This limit allowed distance
           of GOT tables.  We should not need these anyway.  */
        if (GET_CODE (disp) != UNSPEC
! 	  || (XINT (disp, 1) != UNSPEC_GOTPCREL
! 	      && XINT (disp, 1) != UNSPEC_GOTOFF))
  	return 0;
  
        if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
*************** legitimize_pic_address (rtx orig, rtx re
*** 5632,5637 ****
--- 5834,5873 ----
  
    if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
      new = addr;
+   else if (TARGET_64BIT
+ 	   && ix86_cmodel != CM_SMALL_PIC
+ 	   && local_symbolic_operand (addr, Pmode))
+     {
+       rtx tmpreg;
+       /* This symbol may be referenced via a displacement from the PIC
+ 	 base address (@GOTOFF).  */
+ 
+       if (reload_in_progress)
+ 	regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+       if (GET_CODE (addr) == CONST)
+ 	addr = XEXP (addr, 0);
+       if (GET_CODE (addr) == PLUS)
+ 	  {
+             new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
+ 	    new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
+ 	  }
+ 	else
+           new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+       new = gen_rtx_CONST (Pmode, new);
+       if (!reg)
+         tmpreg = gen_reg_rtx (Pmode);
+       else
+ 	tmpreg = reg;
+       emit_move_insn (tmpreg, new);
+ 
+       if (reg != 0)
+ 	{
+ 	  new = expand_simple_binop (Pmode, PLUS, reg, pic_offset_table_rtx,
+ 				     tmpreg, 1, OPTAB_DIRECT);
+ 	  new = reg;
+ 	}
+       else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
+     }
    else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
      {
        /* This symbol may be referenced via a displacement from the PIC
*************** ix86_md_asm_clobbers (tree outputs ATTRI
*** 17545,17550 ****
--- 17781,17829 ----
    return clobbers;
  }
  
+ /* Return true if this goes in small data/bss.  */
+ 
+ static bool
+ ix86_in_large_data_p (tree exp)
+ {
+   if (ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC)
+     return false;
+ 
+   /* Functions are never large data.  */
+   if (TREE_CODE (exp) == FUNCTION_DECL)
+     return false;
+ 
+   if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+     {
+       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+       if (strcmp (section, ".ldata") == 0
+ 	  || strcmp (section, ".lbss") == 0)
+ 	return true;
+       return false;
+     }
+   else
+     {
+       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+ 
+       /* If this is an incomplete type with size 0, then we can't put it
+ 	 in data because it might be too big when completed.  */
+       if (!size || size > ix86_section_threshold)
+ 	return true;
+     }
+ 
+   return false;
+ }
+ static void
+ ix86_encode_section_info (tree decl, rtx rtl, int first)
+ {
+   default_encode_section_info (decl, rtl, first);
+ 
+   if (TREE_CODE (decl) == VAR_DECL
+       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+       && ix86_in_large_data_p (decl))
+     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FAR_ADDR;
+ }
+ 
  /* Worker function for REVERSE_CONDITION.  */
  
  enum rtx_code
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.442
diff -c -3 -p -r1.442 i386.h
*** config/i386/i386.h	18 Jul 2005 06:39:19 -0000	1.442
--- config/i386/i386.h	24 Jul 2005 14:36:47 -0000
*************** do {									\
*** 961,967 ****
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   (TARGET_64BIT || !flag_pic ? INVALID_REGNUM		\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
--- 961,968 ----
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   ((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC)	\
!    || !flag_pic ? INVALID_REGNUM			\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
*************** enum cmodel {
*** 2143,2149 ****
    CM_KERNEL,	/* Assumes all code and data fits in the high 31 bits.  */
    CM_MEDIUM,	/* Assumes code fits in the low 31 bits; data unlimited.  */
    CM_LARGE,	/* No assumptions.  */
!   CM_SMALL_PIC	/* Assumes code+data+got/plt fits in a 31 bit region.  */
  };
  
  extern enum cmodel ix86_cmodel;
--- 2144,2151 ----
    CM_KERNEL,	/* Assumes all code and data fits in the high 31 bits.  */
    CM_MEDIUM,	/* Assumes code fits in the low 31 bits; data unlimited.  */
    CM_LARGE,	/* No assumptions.  */
!   CM_SMALL_PIC,	/* Assumes code+data+got/plt fits in a 31 bit region.  */
!   CM_MEDIUM_PIC	/* Assumes code+got/plt fits in a 31 bit region.  */
  };
  
  extern enum cmodel ix86_cmodel;
*************** enum asm_dialect {
*** 2160,2166 ****
  
  extern enum asm_dialect ix86_asm_dialect;
  extern unsigned int ix86_preferred_stack_boundary;
! extern int ix86_branch_cost;
  
  /* Smallest class containing REGNO.  */
  extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER];
--- 2162,2168 ----
  
  extern enum asm_dialect ix86_asm_dialect;
  extern unsigned int ix86_preferred_stack_boundary;
! extern int ix86_branch_cost, ix86_section_threshold;
  
  /* Smallest class containing REGNO.  */
  extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER];
*************** struct machine_function GTY(())
*** 2281,2286 ****
--- 2283,2292 ----
  #define X86_FILE_START_VERSION_DIRECTIVE false
  #define X86_FILE_START_FLTUSED false
  
+ /* Flag to mark data that is in the large address area.  */
+ #define SYMBOL_FLAG_FAR_ADDR		(SYMBOL_FLAG_MACH_DEP << 0)
+ #define SYMBOL_REF_FAR_ADDR_P(X)	\
+ 	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
  /*
  Local variables:
  version-control: t
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.650
diff -c -3 -p -r1.650 i386.md
*** config/i386/i386.md	21 Jul 2005 19:55:03 -0000	1.650
--- config/i386/i386.md	24 Jul 2005 14:36:48 -0000
***************
*** 13781,13793 ****
  
  (define_insn "set_got"
    [(set (match_operand:SI 0 "register_operand" "=r")
  	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
     (clobber (reg:CC FLAGS_REG))]
    "!TARGET_64BIT"
    { return output_set_got (operands[0]); }
    [(set_attr "type" "multi")
     (set_attr "length" "12")])
  
  (define_expand "epilogue"
    [(const_int 1)]
    ""
--- 13781,13800 ----
  
  (define_insn "set_got"
    [(set (match_operand:SI 0 "register_operand" "=r")
  	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
     (clobber (reg:CC FLAGS_REG))]
    "!TARGET_64BIT"
    { return output_set_got (operands[0]); }
    [(set_attr "type" "multi")
     (set_attr "length" "12")])
  
+ (define_insn "set_got_rex64"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
+   "TARGET_64BIT"
+   "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+   [(set_attr "type" "lea")
+    (set_attr "length" "6")])
+ 
  (define_expand "epilogue"
    [(const_int 1)]
    ""
Index: config/i386/i386.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.opt,v
retrieving revision 1.4
diff -c -3 -p -r1.4 i386.opt
*** config/i386/i386.opt	11 Jul 2005 09:35:16 -0000	1.4
--- config/i386/i386.opt	24 Jul 2005 14:36:48 -0000
*************** mbranch-cost=
*** 87,92 ****
--- 87,96 ----
  Target RejectNegative Joined Var(ix86_branch_cost_string)
  Branches are this expensive (1-5, arbitrary units)
  
+ mlarge-data-threshold=
+ Target RejectNegative Joined Var(ix86_section_threshold_string)
+ Data greater than given threshold will go into .ldata section in x86-64 medium model
+ 
  mcmodel=
  Target RejectNegative Joined Var(ix86_cmodel_string)
  Use given x86-64 code model
Index: config/i386/predicates.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/predicates.md,v
retrieving revision 1.19
diff -c -3 -p -r1.19 predicates.md
*** config/i386/predicates.md	25 Jun 2005 01:21:24 -0000	1.19
--- config/i386/predicates.md	24 Jul 2005 14:36:48 -0000
***************
*** 110,116 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 110,117 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
! 	      || (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
***************
*** 150,156 ****
  		 end of 31bits boundary.  We may also accept pretty
  		 large negative constants knowing that all objects are
  		 in the positive half of address space.  */
! 	      if (ix86_cmodel == CM_SMALL
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
--- 151,159 ----
  		 end of 31bits boundary.  We may also accept pretty
  		 large negative constants knowing that all objects are
  		 in the positive half of address space.  */
! 	      if ((ix86_cmodel == CM_SMALL
! 		   || (ix86_cmodel == CM_MEDIUM
! 		       && !SYMBOL_REF_FAR_ADDR_P (op1)))
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
***************
*** 224,230 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return ix86_cmodel == CM_SMALL;
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 227,235 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL
! 	      || (ix86_cmodel == CM_MEDIUM
! 		  && !SYMBOL_REF_FAR_ADDR_P (op)));
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
***************
*** 247,253 ****
  		 offsets, since one bit is available for free.  Negative
  		 offsets are limited by the size of NULL pointer area
  		 specified by the ABI.  */
! 	      if (ix86_cmodel == CM_SMALL
  		  && GET_CODE (op2) == CONST_INT
  		  && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
  		  && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
--- 252,260 ----
  		 offsets, since one bit is available for free.  Negative
  		 offsets are limited by the size of NULL pointer area
  		 specified by the ABI.  */
! 	      if ((ix86_cmodel == CM_SMALL
! 		   || (ix86_cmodel == CM_MEDIUM
! 		       && !SYMBOL_REF_FAR_ADDR_P (op1)))
  		  && GET_CODE (op2) == CONST_INT
  		  && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
  		  && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
Index: config/i386/x86-64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/x86-64.h,v
retrieving revision 1.13
diff -c -3 -p -r1.13 x86-64.h
*** config/i386/x86-64.h	25 Jun 2005 01:21:24 -0000	1.13
--- config/i386/x86-64.h	24 Jul 2005 14:36:48 -0000
*************** Boston, MA 02110-1301, USA.  */
*** 52,58 ****
   %{Wa,*:%*} %{m32:--32} %{m64:--64}"
  
  #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
!   asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
  
  /* This is used to align code labels according to Intel recommendations.  */
  
--- 52,62 ----
   %{Wa,*:%*} %{m32:--32} %{m64:--64}"
  
  #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
!   x86_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
! 
! #undef  ASM_OUTPUT_ALIGNED_COMMON
! #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)		\
!   x86_elf_aligned_common (FILE, NAME, SIZE, ALIGN);
  
  /* This is used to align code labels according to Intel recommendations.  */
  
*************** Boston, MA 02110-1301, USA.  */
*** 75,77 ****
--- 79,87 ----
  
  #undef PREFERRED_DEBUGGING_TYPE
  #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+ #undef TARGET_ASM_SELECT_SECTION
+ #define TARGET_ASM_SELECT_SECTION  x86_64_elf_select_section
+ 
+ #undef TARGET_ASM_UNIQUE_SECTION
+ #define TARGET_ASM_UNIQUE_SECTION  x86_64_elf_unique_section
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.654
diff -c -3 -p -r1.654 invoke.texi
*** doc/invoke.texi	23 Jul 2005 08:36:41 -0000	1.654
--- doc/invoke.texi	24 Jul 2005 14:36:50 -0000
*************** Objective-C and Objective-C++ Dialects}.
*** 518,524 ****
  -m96bit-long-double  -mregparm=@var{num}  -msseregparm @gol
  -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
  -mcmodel=@var{code-model} @gol
! -m32  -m64}
  
  @emph{IA-64 Options}
  @gccoptlist{-mbig-endian  -mlittle-endian  -mgnu-as  -mgnu-ld  -mno-pic @gol
--- 518,524 ----
  -m96bit-long-double  -mregparm=@var{num}  -msseregparm @gol
  -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
  -mcmodel=@var{code-model} @gol
! -m32  -m64 -mlarge-data-threshold=@var{num}}
  
  @emph{IA-64 Options}
  @gccoptlist{-mbig-endian  -mlittle-endian  -mgnu-as  -mgnu-ld  -mno-pic @gol
*************** their size as well as function calling c
*** 9021,9026 ****
--- 9021,9031 ----
  @code{long double} will be modified.  Hence they will not be binary
  compatible with arrays or structures in code compiled without that switch.
  
+ @item -mmlarge-data-threshold=@var{number}
+ @opindex mlarge-data-threshold=@var{number}
+ When @option{-mcmodel=medium} is specified, the data greater than
+ @var{threshold} are placed in large data section.  This value must be the
+ same across all object linked into the binarry and defaults to 65535.
  
  @item -msvr3-shlib
  @itemx -mno-svr3-shlib


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]