This is the bootstrap comparison failure on IA-64 after -frename-registers was
enabled at -O2, but the issue has nothing to do with the pass. It comes from
the speculation support in the scheduler, namely from estimate_dep_weak:
/* Estimate the weakness of dependence between MEM1 and MEM2. */
dw_t
estimate_dep_weak (rtx mem1, rtx mem2)
{
rtx r1, r2;
if (mem1 == mem2)
/* MEMs are the same - don't speculate. */
return MIN_DEP_WEAK;
r1 = XEXP (mem1, 0);
r2 = XEXP (mem2, 0);
if (r1 == r2
|| (REG_P (r1) && REG_P (r2)
&& REGNO (r1) == REGNO (r2)))
/* Again, MEMs are the same. */
return MIN_DEP_WEAK;
The pointer comparison is not stable for VALUEs when cselib is used (this is
the business of canonical cselib values). I tried rtx_equal_for_cselib_p here
but this doesn't work because there are dangling VALUEs during scheduling
(VALUEs whose associated cselib value has been reclaimed but still referenced
as addresses of MEMs on lists). Hence the attached patch, which canonicalizes
the cselib values manually and fixes the comparison failure.
Bootstrapped/regtested on IA-64/Linux. The patch also contains an unrelated
micro-optimization for rtx_equal_for_cselib_p. Thoughts?
2016-05-02 Eric Botcazou <ebotca...@adacore.com>
PR rtl-optimization/70886
* sched-deps.c (estimate_dep_weak): Canonicalize cselib values.
* cselib.h (rtx_equal_for_cselib_1): Declare.
(rtx_equal_for_cselib_p: New inline function.
* cselib.c (rtx_equal_for_cselib_p): Delete.
(rtx_equal_for_cselib_1): Make public.
--
Eric Botcazou
Index: cselib.c
===================================================================
--- cselib.c (revision 235678)
+++ cselib.c (working copy)
@@ -49,7 +49,6 @@ static void unchain_one_value (cselib_va
static void unchain_one_elt_list (struct elt_list **);
static void unchain_one_elt_loc_list (struct elt_loc_list **);
static void remove_useless_values (void);
-static int rtx_equal_for_cselib_1 (rtx, rtx, machine_mode);
static unsigned int cselib_hash_rtx (rtx, int, machine_mode);
static cselib_val *new_cselib_val (unsigned int, machine_mode, rtx);
static void add_mem_for_addr (cselib_val *, cselib_val *, rtx);
@@ -788,15 +787,6 @@ cselib_reg_set_mode (const_rtx x)
return GET_MODE (REG_VALUES (REGNO (x))->elt->val_rtx);
}
-/* Return nonzero if we can prove that X and Y contain the same value, taking
- our gathered information into account. */
-
-int
-rtx_equal_for_cselib_p (rtx x, rtx y)
-{
- return rtx_equal_for_cselib_1 (x, y, VOIDmode);
-}
-
/* If x is a PLUS or an autoinc operation, expand the operation,
storing the offset, if any, in *OFF. */
@@ -843,7 +833,7 @@ autoinc_split (rtx x, rtx *off, machine_
addressing modes. If X and Y are not (known to be) part of
addresses, MEMMODE should be VOIDmode. */
-static int
+int
rtx_equal_for_cselib_1 (rtx x, rtx y, machine_mode memmode)
{
enum rtx_code code;
Index: cselib.h
===================================================================
--- cselib.h (revision 235678)
+++ cselib.h (working copy)
@@ -82,7 +82,7 @@ extern void cselib_finish (void);
extern void cselib_process_insn (rtx_insn *);
extern bool fp_setter_insn (rtx_insn *);
extern machine_mode cselib_reg_set_mode (const_rtx);
-extern int rtx_equal_for_cselib_p (rtx, rtx);
+extern int rtx_equal_for_cselib_1 (rtx, rtx, machine_mode);
extern int references_value_p (const_rtx, int);
extern rtx cselib_expand_value_rtx (rtx, bitmap, int);
typedef rtx (*cselib_expand_callback)(rtx, bitmap, int, void *);
@@ -125,4 +125,16 @@ canonical_cselib_val (cselib_val *val)
return canon;
}
+/* Return nonzero if we can prove that X and Y contain the same value, taking
+ our gathered information into account. */
+
+static inline int
+rtx_equal_for_cselib_p (rtx x, rtx y)
+{
+ if (x == y)
+ return 1;
+
+ return rtx_equal_for_cselib_1 (x, y, VOIDmode);
+}
+
#endif /* GCC_CSELIB_H */
Index: sched-deps.c
===================================================================
--- sched-deps.c (revision 235678)
+++ sched-deps.c (working copy)
@@ -4182,22 +4182,29 @@ finish_deps_global (void)
dw_t
estimate_dep_weak (rtx mem1, rtx mem2)
{
- rtx r1, r2;
-
if (mem1 == mem2)
/* MEMs are the same - don't speculate. */
return MIN_DEP_WEAK;
- r1 = XEXP (mem1, 0);
- r2 = XEXP (mem2, 0);
+ rtx r1 = XEXP (mem1, 0);
+ rtx r2 = XEXP (mem2, 0);
+
+ if (sched_deps_info->use_cselib)
+ {
+ /* We cannot call rtx_equal_for_cselib_p because the VALUEs might be
+ dangling at this point, since we never preserve them. Instead we
+ canonicalize manually to get stable VALUEs out of hashing. */
+ if (GET_CODE (r1) == VALUE && CSELIB_VAL_PTR (r1))
+ r1 = canonical_cselib_val (CSELIB_VAL_PTR (r1))->val_rtx;
+ if (GET_CODE (r2) == VALUE && CSELIB_VAL_PTR (r2))
+ r2 = canonical_cselib_val (CSELIB_VAL_PTR (r2))->val_rtx;
+ }
if (r1 == r2
- || (REG_P (r1) && REG_P (r2)
- && REGNO (r1) == REGNO (r2)))
+ || (REG_P (r1) && REG_P (r2) && REGNO (r1) == REGNO (r2)))
/* Again, MEMs are the same. */
return MIN_DEP_WEAK;
- else if ((REG_P (r1) && !REG_P (r2))
- || (!REG_P (r1) && REG_P (r2)))
+ else if ((REG_P (r1) && !REG_P (r2)) || (!REG_P (r1) && REG_P (r2)))
/* Different addressing modes - reason to be more speculative,
than usual. */
return NO_DEP_WEAK - (NO_DEP_WEAK - UNCERTAIN_DEP_WEAK) / 2;