OSDN Git Service

PR c++/24686
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index d74d945..e7eec87 100644 (file)
@@ -1485,7 +1485,7 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
       rtx prev_insn;
 
       /* First, look to see if we put a constant in a register.  */
-      prev_insn = PREV_INSN (if_info->cond_earliest);
+      prev_insn = prev_nonnote_insn (if_info->cond_earliest);
       if (prev_insn
          && INSN_P (prev_insn)
          && GET_CODE (PATTERN (prev_insn)) == SET)
@@ -1697,7 +1697,9 @@ noce_try_abs (struct noce_if_info *if_info)
   if (no_new_pseudos)
     return FALSE;
 
-  /* Recognize A and B as constituting an ABS or NABS.  */
+  /* Recognize A and B as constituting an ABS or NABS.  The canonical
+     form is a branch around the negation, taken when the object is the
+     first operand of a comparison against 0 that evaluates to true.  */
   a = if_info->a;
   b = if_info->b;
   if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
@@ -1718,25 +1720,30 @@ noce_try_abs (struct noce_if_info *if_info)
   if (rtx_equal_p (XEXP (cond, 0), b))
     c = XEXP (cond, 1);
   else if (rtx_equal_p (XEXP (cond, 1), b))
-    c = XEXP (cond, 0);
+    {
+      c = XEXP (cond, 0);
+      negate = !negate;
+    }
   else
     return FALSE;
 
-  /* Verify that C is zero.  Search backward through the block for
-     a REG_EQUAL note if necessary.  */
+  /* Verify that C is zero.  Search one step backward for a
+     REG_EQUAL note or a simple source if necessary.  */
   if (REG_P (c))
     {
-      rtx insn, note = NULL;
-      for (insn = earliest;
-          insn != BB_HEAD (if_info->test_bb);
-          insn = PREV_INSN (insn))
-       if (INSN_P (insn)
-           && ((note = find_reg_note (insn, REG_EQUAL, c))
-               || (note = find_reg_note (insn, REG_EQUIV, c))))
-         break;
-      if (! note)
+      rtx set, insn = prev_nonnote_insn (earliest);
+      if (insn
+         && (set = single_set (insn))
+         && rtx_equal_p (SET_DEST (set), c))
+       {
+         rtx note = find_reg_equal_equiv_note (insn);
+         if (note)
+           c = XEXP (note, 0);
+         else
+           c = SET_SRC (set);
+       }
+      else
        return FALSE;
-      c = XEXP (note, 0);
     }
   if (MEM_P (c)
       && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
@@ -2025,6 +2032,59 @@ noce_operand_ok (rtx op)
   return ! may_trap_p (op);
 }
 
+/* Return true if a write into MEM may trap or fault.  */
+
+static bool
+noce_mem_write_may_trap_or_fault_p (rtx mem)
+{
+  rtx addr;
+
+  if (MEM_READONLY_P (mem))
+    return true;
+
+  if (may_trap_or_fault_p (mem))
+    return true;
+
+  addr = XEXP (mem, 0);
+
+  /* Call target hook to avoid the effects of -fpic etc....  */
+  addr = targetm.delegitimize_address (addr);
+
+  while (addr)
+    switch (GET_CODE (addr))
+      {
+      case CONST:
+      case PRE_DEC:
+      case PRE_INC:
+      case POST_DEC:
+      case POST_INC:
+      case POST_MODIFY:
+       addr = XEXP (addr, 0);
+       break;
+      case LO_SUM:
+      case PRE_MODIFY:
+       addr = XEXP (addr, 1);
+       break;
+      case PLUS:
+       if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+         addr = XEXP (addr, 0);
+       else
+         return false;
+       break;
+      case LABEL_REF:
+       return true;
+      case SYMBOL_REF:
+       if (SYMBOL_REF_DECL (addr)
+           && decl_readonly_section (SYMBOL_REF_DECL (addr), 0))
+         return true;
+       return false;
+      default:
+       return false;
+      }
+
+  return false;
+}
+
 /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
    without using conditional execution.  Return TRUE if we were
    successful at converting the block.  */
@@ -2136,14 +2196,6 @@ noce_process_if_block (struct ce_if_block * ce_info)
   if (side_effects_p (x))
     return FALSE;
 
-  /* If x is a read-only memory, then the program is valid only if we
-     avoid the store into it.  If there are stores on both the THEN and
-     ELSE arms, then we can go ahead with the conversion; either the 
-     program is broken, or the condition is always false such that the
-     other memory is selected.  */
-  if (!set_b && MEM_P (x) && MEM_READONLY_P (x))
-    return FALSE;
-
   b = (set_b ? SET_SRC (set_b) : x);
 
   /* Only operate on register destinations, and even then avoid extending
@@ -2211,23 +2263,16 @@ noce_process_if_block (struct ce_if_block * ce_info)
     }
 
   /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
-     for most optimizations if writing to x may trap, i.e. it's a memory
-     other than a static var or a stack slot.  */
-  if (! set_b
-      && MEM_P (orig_x)
-      && ! MEM_NOTRAP_P (orig_x)
-      && rtx_addr_can_trap_p (XEXP (orig_x, 0)))
-    {
-      if (HAVE_conditional_move)
-       {
-         if (noce_try_cmove (&if_info))
-           goto success;
-         if (! HAVE_conditional_execution
-             && noce_try_cmove_arith (&if_info))
-           goto success;
-       }
-      return FALSE;
-    }
+     for optimizations if writing to x may trap or fault, i.e. it's a memory
+     other than a static var or a stack slot, is misaligned on strict
+     aligned machines or is read-only.
+     If x is a read-only memory, then the program is valid only if we
+     avoid the store into it.  If there are stores on both the THEN and
+     ELSE arms, then we can go ahead with the conversion; either the
+     program is broken, or the condition is always false such that the
+     other memory is selected.  */
+  if (!set_b && MEM_P (orig_x) && noce_mem_write_may_trap_or_fault_p (orig_x))
+    return FALSE;
 
   if (noce_try_move (&if_info))
     goto success;