#include "flags.h"
#include "df.h"
#include "hashtab.h"
+#include "except.h"
/* The data stored for the loop. */
struct df_ref *def;
basic_block bb = BLOCK_FOR_INSN (use->insn), def_bb;
+ if (use->flags & DF_REF_READ_WRITE)
+ return NULL;
+
defs = DF_REF_CHAIN (use);
if (!defs || defs->next)
return NULL;
for (j = 0; j < XVECLEN (x, i); j++)
val ^= hash_invariant_expr_1 (insn, XVECEXP (x, i, j));
}
+ else if (fmt[i] == 'i' || fmt[i] == 'n')
+ val ^= XINT (x, i);
}
return val;
return false;
}
}
+ else if (fmt[i] == 'i' || fmt[i] == 'n')
+ {
+ if (XINT (e1, i) != XINT (e2, i))
+ return false;
+ }
+ /* Unhandled type of subexpression, we fail conservatively. */
+ else
+ return false;
}
return true;
if (dump_file && inv->eqto != inv->invno)
fprintf (dump_file,
- "Invariant %d is equivalent to invariant %d.\n ",
+ "Invariant %d is equivalent to invariant %d.\n",
inv->invno, inv->eqto);
}
static bool
may_assign_reg_p (rtx x)
{
- return (can_copy_p (GET_MODE (x))
+ return (GET_MODE (x) != VOIDmode
+ && GET_MODE (x) != BLKmode
+ && can_copy_p (GET_MODE (x))
&& (!REG_P (x)
|| !HARD_REGISTER_P (x)
|| REGNO_REG_CLASS (REGNO (x)) != NO_REGS));
}
/* Finds the invariants INSN depends on and store them to the DEPENDS_ON
- bitmap. */
+ bitmap. Returns true if all dependencies of INSN are known to be
+ loop invariants, false otherwise. */
static bool
check_dependencies (rtx insn, bitmap depends_on)
for (use = DF_INSN_GET (df, insn)->uses; use; use = use->next_ref)
{
+ if (use->flags & DF_REF_READ_WRITE)
+ return false;
+
defs = DF_REF_CHAIN (use);
if (!defs)
continue;
|| !check_maybe_invariant (SET_SRC (set)))
return;
- if (may_trap_p (PATTERN (insn)))
- {
- if (!always_reached)
- return;
+ /* If the insn can throw exception, we cannot move it at all without changing
+ cfg. */
+ if (can_throw_internal (insn))
+ return;
- /* Unless the exceptions are handled, the behavior is undefined
- if the trap occurs. */
- if (flag_non_call_exceptions)
- return;
- }
+ /* We cannot make trapping insn executed, unless it was executed before. */
+ if (may_trap_after_code_motion_p (PATTERN (insn)) && !always_reached)
+ return;
depends_on = BITMAP_ALLOC (NULL);
if (!check_dependencies (insn, depends_on))
(*regs_needed)++;
(*comp_cost) += inv->cost;
+#ifdef STACK_REGS
+ {
+ /* Hoisting constant pool constants into stack regs may cost more than
+ just single register. On x87, the balance is affected both by the
+ small number of FP registers, and by its register stack organisation,
+ that forces us to add compensation code in and around the loop to
+ shuffle the operands to the top of stack before use, and pop them
+ from the stack after the loop finishes.
+
+ To model this effect, we increase the number of registers needed for
+ stack registers by two: one register push, and one register pop.
+ This usually has the effect that FP constant loads from the constant
+ pool are not moved out of the loop.
+
+ Note that this also means that dependent invariants can not be moved.
+ However, the primary purpose of this pass is to move loop invariant
+ address arithmetic out of loops, and address arithmetic that depends
+ on floating point constants is unlikely to ever occur. */
+ rtx set = single_set (inv->insn);
+ if (set
+ && IS_STACK_MODE (GET_MODE (SET_SRC (set)))
+ && constant_pool_constant_p (SET_SRC (set)))
+ (*regs_needed) += 2;
+ }
+#endif
+
EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
{
dep = VEC_index (invariant_p, invariants, depno);
struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto);
unsigned i;
basic_block preheader = loop_preheader_edge (loop)->src;
- rtx reg, set;
+ rtx reg, set, seq, op;
struct use *use;
bitmap_iterator bi;
}
else
{
- emit_insn_after (gen_move_insn (reg, SET_SRC (set)), BB_END (preheader));
+ start_sequence ();
+ op = force_operand (SET_SRC (set), reg);
+ if (op != reg)
+ emit_move_insn (reg, op);
+ seq = get_insns ();
+ end_sequence ();
+
+ emit_insn_after (seq, BB_END (preheader));
delete_insn (inv->insn);
}
}