@@ -263,14 +263,14 @@ static void swap_to_top (rtx_insn *, sta
static bool move_for_stack_reg (rtx_insn *, stack_ptr, rtx);
static bool move_nan_for_stack_reg (rtx_insn *, stack_ptr, rtx);
static int swap_rtx_condition_1 (rtx);
-static int swap_rtx_condition (rtx_insn *);
+static int swap_rtx_condition (rtx_insn *, int &);
static void compare_for_stack_reg (rtx_insn *, stack_ptr, rtx, bool);
static bool subst_stack_regs_pat (rtx_insn *, stack_ptr, rtx);
static void subst_asm_stack_regs (rtx_insn *, stack_ptr);
static bool subst_stack_regs (rtx_insn *, stack_ptr);
static void change_stack (rtx_insn *, stack_ptr, stack_ptr, enum emit_where);
static void print_stack (FILE *, stack_ptr);
-static rtx_insn *next_flags_user (rtx_insn *);
+static rtx_insn *next_flags_user (rtx_insn *, int &);
/* Return nonzero if any stack register is mentioned somewhere within PAT. */
@@ -336,7 +336,7 @@ stack_regs_mentioned (const_rtx insn)
static rtx ix86_flags_rtx;
static rtx_insn *
-next_flags_user (rtx_insn *insn)
+next_flags_user (rtx_insn *insn, int &debug_seen)
{
/* Search forward looking for the first use of this value.
Stop at block boundaries. */
@@ -346,7 +346,14 @@ next_flags_user (rtx_insn *insn)
insn = NEXT_INSN (insn);
if (INSN_P (insn) && reg_mentioned_p (ix86_flags_rtx, PATTERN (insn)))
- return insn;
+ {
+ if (DEBUG_INSN_P (insn) && debug_seen >= 0)
+ {
+ debug_seen = 1;
+ continue;
+ }
+ return insn;
+ }
if (CALL_P (insn))
return NULL;
@@ -1248,8 +1255,22 @@ swap_rtx_condition_1 (rtx pat)
return r;
}
+/* This function swaps condition in cc users and returns true
+ if successful. It is invoked in 2 different modes, one with
+ DEBUG_SEEN set initially to 0. In this mode, next_flags_user
+ will skip DEBUG_INSNs that it would otherwise return and just
+ sets DEBUG_SEEN to 1 in that case. If DEBUG_SEEN is 0 at
+ the end of toplevel swap_rtx_condition which returns true,
+ it means no problematic DEBUG_INSNs were seen and all changes
+ have been applied. If it returns true but DEBUG_SEEN is 1,
+ it means some problematic DEBUG_INSNs were seen and no changes
+ have been applied so far. In that case one needs to call
+ swap_rtx_condition again with DEBUG_SEEN set to -1, in which
+ case it doesn't skip DEBUG_INSNs, but instead adjusts the
+ flags related condition in them or resets them as needed. */
+
static int
-swap_rtx_condition (rtx_insn *insn)
+swap_rtx_condition (rtx_insn *insn, int &debug_seen)
{
rtx pat = PATTERN (insn);
@@ -1259,7 +1280,7 @@ swap_rtx_condition (rtx_insn *insn)
&& REG_P (SET_DEST (pat))
&& REGNO (SET_DEST (pat)) == FLAGS_REG)
{
- insn = next_flags_user (insn);
+ insn = next_flags_user (insn, debug_seen);
if (insn == NULL_RTX)
return 0;
pat = PATTERN (insn);
@@ -1281,7 +1302,18 @@ swap_rtx_condition (rtx_insn *insn)
{
insn = NEXT_INSN (insn);
if (INSN_P (insn) && reg_mentioned_p (dest, insn))
- break;
+ {
+ if (DEBUG_INSN_P (insn))
+ {
+ if (debug_seen >= 0)
+ debug_seen = 1;
+ else
+ /* Reset the DEBUG insn otherwise. */
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+ continue;
+ }
+ break;
+ }
if (CALL_P (insn))
return 0;
}
@@ -1301,7 +1333,7 @@ swap_rtx_condition (rtx_insn *insn)
return 0;
/* Now we are prepared to handle this. */
- insn = next_flags_user (insn);
+ insn = next_flags_user (insn, debug_seen);
if (insn == NULL_RTX)
return 0;
pat = PATTERN (insn);
@@ -1310,23 +1342,25 @@ swap_rtx_condition (rtx_insn *insn)
if (swap_rtx_condition_1 (pat))
{
int fail = 0;
- INSN_CODE (insn) = -1;
- if (recog_memoized (insn) == -1)
- fail = 1;
- /* In case the flags don't die here, recurse to try fix
- following user too. */
- else if (! dead_or_set_p (insn, ix86_flags_rtx))
+ if (DEBUG_INSN_P (insn))
+ gcc_assert (debug_seen < 0);
+ else
{
- insn = next_flags_user (insn);
- if (!insn || !swap_rtx_condition (insn))
+ INSN_CODE (insn) = -1;
+ if (recog_memoized (insn) == -1)
fail = 1;
}
- if (fail)
+ /* In case the flags don't die here, recurse to try fix
+ following user too. */
+ if (!fail && !dead_or_set_p (insn, ix86_flags_rtx))
{
- swap_rtx_condition_1 (pat);
- return 0;
+ insn = next_flags_user (insn, debug_seen);
+ if (!insn || !swap_rtx_condition (insn, debug_seen))
+ fail = 1;
}
- return 1;
+ if (fail || debug_seen == 1)
+ swap_rtx_condition_1 (pat);
+ return !fail;
}
return 0;
}
@@ -1345,6 +1379,7 @@ compare_for_stack_reg (rtx_insn *insn, s
{
rtx *src1, *src2;
rtx src1_note, src2_note;
+ int debug_seen = 0;
src1 = get_true_reg (&XEXP (pat_src, 0));
src2 = get_true_reg (&XEXP (pat_src, 1));
@@ -1354,8 +1389,17 @@ compare_for_stack_reg (rtx_insn *insn, s
if ((! STACK_REG_P (*src1)
|| (STACK_REG_P (*src2)
&& get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))
- && swap_rtx_condition (insn))
+ && swap_rtx_condition (insn, debug_seen))
{
+ /* If swap_rtx_condition succeeded but some debug insns
+ were seen along the way, it has actually reverted all the
+ changes. Rerun swap_rtx_condition in a mode where DEBUG_ISNSs
+ will be adjusted as well. */
+ if (debug_seen)
+ {
+ debug_seen = -1;
+ swap_rtx_condition (insn, debug_seen);
+ }
std::swap (XEXP (pat_src, 0), XEXP (pat_src, 1));
src1 = get_true_reg (&XEXP (pat_src, 0));
@@ -0,0 +1,12 @@
+/* PR target/107183 */
+/* { dg-do compile } */
+/* { dg-options "-O -fsanitize=float-cast-overflow -fcompare-debug" } */
+
+long double a, b, c;
+
+int
+foo (void)
+{
+ unsigned u = b || __builtin_rintl (c);
+ return u + (unsigned) a;
+}