* target.def (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New.
        * targhooks.h (default_addr_space_zero_address_valid): Declare.
        * targhooks.c (default_addr_space_zero_address_valid): New.
        * doc/tm.texi, doc/tm.texi.in: Update.
        * config/i386/i386.c (ix86_addr_space_zero_address_valid): New.
        (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New.
        * fold-const.c (const_unop) [ADDR_SPACE_CONVERT_EXPR]: Disable
        folding of 0 when it is a valid address for the source space.
        * gimple.c (check_loadstore): Disable noticing dereference when
        0 is a valid address for the space.
---
 gcc/config/i386/i386.c | 10 ++++++++++
 gcc/doc/tm.texi        |  5 +++++
 gcc/doc/tm.texi.in     |  2 ++
 gcc/fold-const.c       |  6 +++++-
 gcc/gimple.c           | 12 +++++++++---
 gcc/target.def         |  9 +++++++++
 gcc/targhooks.c        |  9 +++++++++
 gcc/targhooks.h        |  1 +
 8 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f7abb00..e2dec2a 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -53669,6 +53669,16 @@ ix86_addr_space_convert (rtx op, tree from_type, tree 
to_type)
 #undef TARGET_ADDR_SPACE_CONVERT
 #define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert
 
+/* All use of segmentation is assumed to make address 0 valid.  */
+
+static bool
+ix86_addr_space_zero_address_valid (addr_space_t as)
+{
+  return as != ADDR_SPACE_GENERIC;
+}
+#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
+#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 72366b9..238f5f5 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10312,6 +10312,11 @@ arithmetic operations.  Pointers to a superset address 
space can be
 converted to pointers to a subset address space via explicit casts.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID 
(addr_space_t @var{as})
+Define this to modify the default handling of address 0 for the
+address space.  Return true if 0 should be considered a valid address.
+@end deftypefn
+
 @deftypefn {Target Hook} rtx TARGET_ADDR_SPACE_CONVERT (rtx @var{op}, tree 
@var{from_type}, tree @var{to_type})
 Define this to convert the pointer expression represented by the RTL
 @var{op} with type @var{from_type} that points to a named address
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index d8d0087..9230fb2 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7432,6 +7432,8 @@ c_register_addr_space ("__ea", ADDR_SPACE_EA);
 
 @hook TARGET_ADDR_SPACE_SUBSET_P
 
+@hook TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
+
 @hook TARGET_ADDR_SPACE_CONVERT
 
 @node Misc
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 2851a29..2e06217 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1564,7 +1564,11 @@ const_unop (enum tree_code code, tree type, tree arg0)
       return fold_convert_const (code, type, arg0);
 
     case ADDR_SPACE_CONVERT_EXPR:
-      if (integer_zerop (arg0))
+      /* If the source address is 0, and the source address space
+        cannot have a valid object at 0, fold to dest type null.  */
+      if (integer_zerop (arg0)
+         && !(targetm.addr_space.zero_address_valid
+              (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))))))
        return fold_convert_const (code, type, arg0);
       break;
 
diff --git a/gcc/gimple.c b/gcc/gimple.c
index c3762e1..e551dac 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2618,9 +2618,15 @@ nonfreeing_call_p (gimple *call)
 static bool
 check_loadstore (gimple *, tree op, tree, void *data)
 {
-  if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
-      && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
-    return true;
+  if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+    {
+      /* Some address spaces may legitimately dereference zero.  */
+      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
+      if (targetm.addr_space.zero_address_valid (as))
+       return false;
+
+      return operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0);
+    }
   return false;
 }
 
diff --git a/gcc/target.def b/gcc/target.def
index d29aad5..f75ce97 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3185,6 +3185,15 @@ converted to pointers to a subset address space via 
explicit casts.",
  bool, (addr_space_t subset, addr_space_t superset),
  default_addr_space_subset_p)
 
+/* True if 0 is a valid address in the address space, or false if
+   0 is a NULL in the address space.  */
+DEFHOOK
+(zero_address_valid,
+ "Define this to modify the default handling of address 0 for the\n\
+address space.  Return true if 0 should be considered a valid address.",
+ bool, (addr_space_t as),
+ default_addr_space_zero_address_valid)
+
 /* Function to convert an rtl expression from one address space to another.  */
 DEFHOOK
 (convert,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index a8a243c..c78a540 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1256,6 +1256,15 @@ default_addr_space_subset_p (addr_space_t subset, 
addr_space_t superset)
   return (subset == superset);
 }
 
+/* The default hook for determining if 0 within a named address
+   space is a valid address.  */
+
+bool
+default_addr_space_zero_address_valid (addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
 /* The default hook for TARGET_ADDR_SPACE_CONVERT. This hook should never be
    called for targets with only a generic address space.  */
 
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 77c284a..ade3327 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -173,6 +173,7 @@ extern bool default_addr_space_legitimate_address_p 
(machine_mode, rtx,
 extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
                                                  addr_space_t);
 extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
+extern bool default_addr_space_zero_address_valid (addr_space_t);
 extern rtx default_addr_space_convert (rtx, tree, tree);
 extern unsigned int default_case_values_threshold (void);
 extern bool default_have_conditional_execution (void);
-- 
2.4.3

Reply via email to