Blame SOURCES/gcc8-rh2028609.patch

da1516
The cprop_hardreg pass is built around the assumption that accessing a
da1516
register in a narrower mode is the same as accessing the lowpart of
da1516
the register.  This unfortunately is not true for vector registers on
da1516
IBM Z. This caused a miscompile of LLVM with GCC 8.5. The problem
da1516
could not be reproduced with upstream GCC unfortunately but we have to
da1516
assume that it is latent there. The right fix would require
da1516
substantial changes to the cprop pass and is certainly something we
da1516
would want for our platform. But since this would not be acceptable
da1516
for older GCCs I'll go with what Vladimir proposed in the RedHat BZ
da1516
and introduce a hopefully temporary and undocumented target hook to
da1516
disable that specific transformation in regcprop.c.
da1516
da1516
--- a/gcc/config/s390/s390.c
da1516
+++ b/gcc/config/s390/s390.c
da1516
@@ -10488,6 +10488,18 @@ s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
da1516
   return false;
da1516
 }
da1516
 
da1516
+/* Implement TARGET_NARROW_MODE_REFERS_LOW_PART_P.  */
da1516
+
da1516
+static bool
da1516
+s390_narrow_mode_refers_low_part_p (unsigned int regno)
da1516
+{
da1516
+  if (reg_classes_intersect_p (VEC_REGS, REGNO_REG_CLASS (regno)))
da1516
+    return false;
da1516
+
da1516
+  return true;
da1516
+}
da1516
+
da1516
+
da1516
 /* Implement TARGET_MODES_TIEABLE_P.  */
da1516
 
da1516
 static bool
da1516
@@ -16956,6 +16968,9 @@ s390_case_values_threshold (void)
da1516
 #undef TARGET_CASE_VALUES_THRESHOLD
da1516
 #define TARGET_CASE_VALUES_THRESHOLD s390_case_values_threshold
da1516
 
da1516
+#undef TARGET_NARROW_MODE_REFERS_LOW_PART_P
da1516
+#define TARGET_NARROW_MODE_REFERS_LOW_PART_P s390_narrow_mode_refers_low_part_p
da1516
+
da1516
 struct gcc_target targetm = TARGET_INITIALIZER;
da1516
 
da1516
 #include "gt-s390.h"
da1516
--- a/gcc/regcprop.c
da1516
+++ b/gcc/regcprop.c
da1516
@@ -426,7 +426,8 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
da1516
 
da1516
   if (orig_mode == new_mode)
da1516
     return gen_raw_REG (new_mode, regno);
da1516
-  else if (mode_change_ok (orig_mode, new_mode, regno))
da1516
+  else if (mode_change_ok (orig_mode, new_mode, regno)
da1516
+	   && targetm.narrow_mode_refers_low_part_p (copy_regno))
da1516
     {
da1516
       int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
da1516
       int use_nregs = hard_regno_nregs (copy_regno, new_mode);
da1516
--- a/gcc/target.def
da1516
+++ b/gcc/target.def
da1516
@@ -5446,6 +5446,16 @@ value that the middle-end intended.",
da1516
  bool, (machine_mode from, machine_mode to, reg_class_t rclass),
da1516
  hook_bool_mode_mode_reg_class_t_true)
da1516
 
da1516
+/* This hook is used to work around a problem in regcprop. Hardcoded
da1516
+assumptions currently prevent it from working correctly for targets
da1516
+where the low part of a multi-word register doesn't align to accessing
da1516
+the register with a narrower mode.  */
da1516
+DEFHOOK_UNDOC
da1516
+(narrow_mode_refers_low_part_p,
da1516
+"",
da1516
+bool, (unsigned int regno),
da1516
+hook_bool_uint_true)
da1516
+
da1516
 /* Change pseudo allocno class calculated by IRA.  */
da1516
 DEFHOOK
da1516
 (ira_change_pseudo_allocno_class,
da1516
--- a/gcc/hooks.h
da1516
+++ b/gcc/hooks.h
da1516
@@ -86,6 +86,7 @@ extern void hook_void_tree (tree);
da1516
 extern void hook_void_tree_treeptr (tree, tree *);
da1516
 extern void hook_void_int_int (int, int);
da1516
 extern void hook_void_gcc_optionsp (struct gcc_options *);
da1516
+extern bool hook_bool_uint_true (unsigned int);
da1516
 extern bool hook_bool_uint_uintp_false (unsigned int, unsigned int *);
da1516
 
da1516
 extern int hook_int_uint_mode_1 (unsigned int, machine_mode);
da1516
--- a/gcc/hooks.c
da1516
+++ b/gcc/hooks.c
da1516
@@ -498,6 +498,14 @@ hook_void_gcc_optionsp (struct gcc_optio
da1516
 {
da1516
 }
da1516
 
da1516
+/* Generic hook that takes an unsigned int and returns true.  */
da1516
+
da1516
+bool
da1516
+hook_bool_uint_true (unsigned int)
da1516
+{
da1516
+  return true;
da1516
+}
da1516
+
da1516
 /* Generic hook that takes an unsigned int, an unsigned int pointer and
da1516
    returns false.  */
da1516