Hi all, Here is an updated patch (attached) for __seg_fs and __seg_gs:
* added a target hook "default_pointer_address_modes" to avoid disabling a few gcc optimizations which, according to my reading of the documentation, should continue to work even in the presence of multiple address spaces as long as they all use the same mode for pointers. * account for the extra byte in "%gs:(...)" addresses. * added one test case (better than none!) using "scan-assembler". If people agree that this is the style of test that we need here, then I could add more of them. The diff is against trunk. The tests don't all pass; the failures really seem unrelated, but I guess I should grab the same revision without the patch, compile it, try to run all the tests on the same machine, and compare the list of failures... it just takes a serious amount of time to do so... I also reported the bug I got previously (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66768) and it seems to occur already in other targets with address spaces. A bientôt, Armin.
Index: gcc/config/i386/i386-c.c =================================================================== --- gcc/config/i386/i386-c.c (revision 225561) +++ gcc/config/i386/i386-c.c (working copy) @@ -576,6 +576,9 @@ ix86_target_macros (void) ix86_tune, ix86_fpmath, cpp_define); + + cpp_define (parse_in, "__SEG_FS"); + cpp_define (parse_in, "__SEG_GS"); } @@ -590,6 +593,9 @@ ix86_register_pragmas (void) /* Update pragma hook to allow parsing #pragma GCC target. */ targetm.target_option.pragma_parse = ix86_pragma_target_parse; + c_register_addr_space ("__seg_fs", ADDR_SPACE_SEG_FS); + c_register_addr_space ("__seg_gs", ADDR_SPACE_SEG_GS); + #ifdef REGISTER_SUBTARGET_PRAGMAS REGISTER_SUBTARGET_PRAGMAS (); #endif Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 225561) +++ gcc/config/i386/i386.c (working copy) @@ -16059,6 +16059,18 @@ ix86_print_operand (FILE *file, rtx x, i fputs (" PTR ", file); } + switch (MEM_ADDR_SPACE(x)) + { + case ADDR_SPACE_SEG_FS: + fputs (ASSEMBLER_DIALECT == ASM_ATT ? "%fs:" : "fs:", file); + break; + case ADDR_SPACE_SEG_GS: + fputs (ASSEMBLER_DIALECT == ASM_ATT ? "%gs:" : "gs:", file); + break; + default: + break; + } + x = XEXP (x, 0); /* Avoid (%rip) for call operands. */ if (CONSTANT_ADDRESS_P (x) && code == 'P' @@ -26133,6 +26145,7 @@ ix86_attr_length_address_default (rtx_in for (i = recog_data.n_operands - 1; i >= 0; --i) if (MEM_P (recog_data.operand[i])) { + int addr_space, len; constrain_operands_cached (insn, reload_completed); if (which_alternative != -1) { @@ -26148,7 +26161,15 @@ ix86_attr_length_address_default (rtx_in if (*constraints == 'X') continue; } - return memory_address_length (XEXP (recog_data.operand[i], 0), false); + + len = memory_address_length (XEXP (recog_data.operand[i], 0), false); + + /* account for one byte segment prefix for SEG_FS/SEG_GS addr spaces */ + addr_space = MEM_ADDR_SPACE(recog_data.operand[i]); + if (addr_space != ADDR_SPACE_GENERIC) + len++; + + return len; } return 0; } @@ -52205,6 +52226,126 @@ ix86_operands_ok_for_move_multiple (rtx return true; } + +/*** FS/GS segment register addressing mode ***/ + +static machine_mode +ix86_addr_space_pointer_mode (addr_space_t as) +{ + gcc_assert (as == ADDR_SPACE_GENERIC || + as == ADDR_SPACE_SEG_FS || + as == ADDR_SPACE_SEG_GS); + return ptr_mode; +} + +/* Return the appropriate mode for a named address address. */ +static machine_mode +ix86_addr_space_address_mode (addr_space_t as) +{ + gcc_assert (as == ADDR_SPACE_GENERIC || + as == ADDR_SPACE_SEG_FS || + as == ADDR_SPACE_SEG_GS); + return Pmode; +} + +/* Named address space version of valid_pointer_mode. */ +static bool +ix86_addr_space_valid_pointer_mode (machine_mode mode, addr_space_t as) +{ + gcc_assert (as == ADDR_SPACE_GENERIC || + as == ADDR_SPACE_SEG_FS || + as == ADDR_SPACE_SEG_GS); + return targetm.valid_pointer_mode (mode); +} + +/* Like ix86_legitimate_address_p, except with named addresses. */ +static bool +ix86_addr_space_legitimate_address_p (machine_mode mode, rtx x, + bool reg_ok_strict, addr_space_t as) +{ + gcc_assert (as == ADDR_SPACE_GENERIC || + as == ADDR_SPACE_SEG_FS || + as == ADDR_SPACE_SEG_GS); + return ix86_legitimate_address_p (mode, x, reg_ok_strict); +} + +/* Named address space version of LEGITIMIZE_ADDRESS. */ +static rtx +ix86_addr_space_legitimize_address (rtx x, rtx oldx, + machine_mode mode, addr_space_t as) +{ + gcc_assert (as == ADDR_SPACE_GENERIC || + as == ADDR_SPACE_SEG_FS || + as == ADDR_SPACE_SEG_GS); + return ix86_legitimize_address (x, oldx, mode); +} + +/* The default, SEG_FS and SEG_GS address spaces are all "subsets" of + each other. */ +bool static +ix86_addr_space_subset_p (addr_space_t subset, addr_space_t superset) +{ + gcc_assert (subset == ADDR_SPACE_GENERIC || + subset == ADDR_SPACE_SEG_FS || + subset == ADDR_SPACE_SEG_GS); + gcc_assert (superset == ADDR_SPACE_GENERIC || + superset == ADDR_SPACE_SEG_FS || + superset == ADDR_SPACE_SEG_GS); + return true; +} + +/* Convert from one address space to another: it is a no-op. + It is the C code's responsibility to write sensible casts. */ +static rtx +ix86_addr_space_convert (rtx op, tree from_type, tree to_type) +{ + addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); + addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); + + gcc_assert (from_as == ADDR_SPACE_GENERIC || + from_as == ADDR_SPACE_SEG_FS || + from_as == ADDR_SPACE_SEG_GS); + gcc_assert (to_as == ADDR_SPACE_GENERIC || + to_as == ADDR_SPACE_SEG_FS || + to_as == ADDR_SPACE_SEG_GS); + + return op; +} + +static bool +ix86_addr_space_default_pointer_address_modes_p (void) +{ + return true; /* all pointer and address modes are still Pmode/ptr_mode */ +} + +#undef TARGET_ADDR_SPACE_POINTER_MODE +#define TARGET_ADDR_SPACE_POINTER_MODE ix86_addr_space_pointer_mode + +#undef TARGET_ADDR_SPACE_ADDRESS_MODE +#define TARGET_ADDR_SPACE_ADDRESS_MODE ix86_addr_space_address_mode + +#undef TARGET_ADDR_SPACE_VALID_POINTER_MODE +#define TARGET_ADDR_SPACE_VALID_POINTER_MODE ix86_addr_space_valid_pointer_mode + +#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P +#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \ + ix86_addr_space_legitimate_address_p + +#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS +#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS \ + ix86_addr_space_legitimize_address + +#undef TARGET_ADDR_SPACE_SUBSET_P +#define TARGET_ADDR_SPACE_SUBSET_P ix86_addr_space_subset_p + +#undef TARGET_ADDR_SPACE_CONVERT +#define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert + +#undef TARGET_ADDR_SPACE_DEFAULT_POINTER_ADDRESS_MODES_P +#define TARGET_ADDR_SPACE_DEFAULT_POINTER_ADDRESS_MODES_P \ + ix86_addr_space_default_pointer_address_modes_p + + /* Initialize the GCC target structure. */ #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory Index: gcc/config/i386/i386.h =================================================================== --- gcc/config/i386/i386.h (revision 225561) +++ gcc/config/i386/i386.h (working copy) @@ -2572,6 +2572,11 @@ extern void debug_dispatch_window (int); #define TARGET_SUPPORTS_WIDE_INT 1 +enum { + ADDR_SPACE_SEG_FS = 1, + ADDR_SPACE_SEG_GS = 2 +}; + /* Local variables: version-control: t Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi (revision 225561) +++ gcc/doc/tm.texi (working copy) @@ -10321,6 +10321,17 @@ guaranteed that one of the two address s as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook. @end deftypefn +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_DEFAULT_POINTER_ADDRESS_MODES_P (void) +Some places still assume that all pointer or address modes are the +standard Pmode and ptr_mode. These optimizations become invalid if +the target actually supports multiple different modes. This hook returns +true if all pointers and addresses are Pmode and ptr_mode, and false +otherwise. Called via target_default_pointer_address_modes_p(). The +default NULL for the hook makes this function return true if the two hooks +@code{TARGET_ADDR_SPACE_POINTER_MODE}, @code{TARGET_ADDR_SPACE_ADDRESS_MODE} +are undefined, and false otherwise. +@end deftypefn + @node Misc @section Miscellaneous Parameters @cindex parameters, miscellaneous Index: gcc/doc/tm.texi.in =================================================================== --- gcc/doc/tm.texi.in (revision 225561) +++ gcc/doc/tm.texi.in (working copy) @@ -7450,6 +7450,8 @@ c_register_addr_space ("__ea", ADDR_SPAC @hook TARGET_ADDR_SPACE_CONVERT +@hook TARGET_ADDR_SPACE_DEFAULT_POINTER_ADDRESS_MODES_P + @node Misc @section Miscellaneous Parameters @cindex parameters, miscellaneous Index: gcc/target.def =================================================================== --- gcc/target.def (revision 225561) +++ gcc/target.def (working copy) @@ -3164,6 +3164,19 @@ as determined by the @code{TARGET_ADDR_S rtx, (rtx op, tree from_type, tree to_type), default_addr_space_convert) +/* True if all pointer or address modes are the standard Pmode and ptr_mode. */ +DEFHOOK +(default_pointer_address_modes_p, + "Some places still assume that all pointer or address modes are the\n\ +standard Pmode and ptr_mode. These optimizations become invalid if\n\ +the target actually supports multiple different modes. This hook returns\n\ +true if all pointers and addresses are Pmode and ptr_mode, and false\n\ +otherwise. Called via target_default_pointer_address_modes_p(). The\n\ +default NULL for the hook makes this function return true if the two hooks\n\ +@code{TARGET_ADDR_SPACE_POINTER_MODE}, @code{TARGET_ADDR_SPACE_ADDRESS_MODE}\n\ +are undefined, and false otherwise.", + bool, (void), NULL) + HOOK_VECTOR_END (addr_space) #undef HOOK_PREFIX Index: gcc/targhooks.c =================================================================== --- gcc/targhooks.c (revision 225561) +++ gcc/targhooks.c (working copy) @@ -1221,6 +1221,9 @@ default_addr_space_valid_pointer_mode (m bool target_default_pointer_address_modes_p (void) { + if (targetm.addr_space.default_pointer_address_modes_p != NULL) + return targetm.addr_space.default_pointer_address_modes_p(); + if (targetm.addr_space.address_mode != default_addr_space_address_mode) return false; if (targetm.addr_space.pointer_mode != default_addr_space_pointer_mode) Index: gcc/testsuite/gcc.target/i386/addr-space-1.c =================================================================== --- gcc/testsuite/gcc.target/i386/addr-space-1.c (revision 0) +++ gcc/testsuite/gcc.target/i386/addr-space-1.c (working copy) @@ -0,0 +1,11 @@ +/* { dg-do compile */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "movl\[ \t\]%gs:\\((%eax|%rax)\\), %eax" } } */ + +extern __seg_gs int *call_me (void); + +int +read_seg_gs (void) +{ + return *call_me(); +}