@@ -2388,6 +2388,16 @@ noce_mem_write_may_trap_or_fault_p (const_rtx mem)
return false;
}
+/* Return TRUE if INSN is a volatile insn or a non const call. */
+
+static inline bool
+volatile_or_non_const_call (rtx insn)
+{
+ return (INSN_P (insn)
+ && (volatile_insn_p (PATTERN (insn))
+ || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))));
+}
+
/* Return whether we can use store speculation for MEM. TOP_BB is the
basic block above the conditional block where we are considering
doing the speculative store. We look for whether MEM is set
@@ -2410,13 +2420,47 @@ noce_can_store_speculate_p (basic_block top_bb, const_rtx mem)
have to stop looking. Even if the MEM is set later in
the function, we still don't want to set it
unconditionally before the barrier. */
- if (INSN_P (insn)
- && (volatile_insn_p (PATTERN (insn))
- || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
+ if (volatile_or_non_const_call (insn))
return false;
+ /* We can speculate if the MEM will be set on every path out
+ of TOP_BB, but we must be careful that there is no
+ intervening call/volatile between TOP_BB and the set.
+
+ For the intervening call/volatile case, We are looking
+ for something akin to:
+
+ location of considered if-conversion on mem
+ if (condition)
+ call ();
+ mem = something; */
if (memory_must_be_modified_in_insn_p (mem, insn))
- return true;
+ {
+ if (!dom_info_available_p (CDI_DOMINATORS))
+ calculate_dominance_info (CDI_DOMINATORS);
+
+ /* Get all blocks that are post-dominated by the SET. */
+ VEC (basic_block, heap) *bbs =
+ get_all_dominated_blocks (CDI_POST_DOMINATORS,
+ BLOCK_FOR_INSN (insn));
+ while (VEC_length (basic_block, bbs))
+ {
+ rtx call;
+ basic_block bb = VEC_pop (basic_block, bbs);
+
+ /* If there is an intervening volatile/call between
+ TOP_BB and the SET of MEM, bail. */
+ FOR_BB_INSNS (bb, call)
+ if (volatile_or_non_const_call (call)
+ && dominated_by_p (CDI_DOMINATORS,
+ BLOCK_FOR_INSN (call),
+ top_bb))
+ return false;
+ }
+ VEC_free (basic_block, heap, bbs);
+ return true;
+ }
+
if (modified_in_p (XEXP (mem, 0), insn))
return false;