rtx cond = noce_get_condition (jump, &cond_earliest, false);
rtx cc_cmp = cond_exec_get_condition (jump);
+ if (cc_cmp)
+ cc_cmp = copy_rtx (cc_cmp);
rtx rev_cc_cmp = cond_exec_get_condition (jump, /* get_reversed */ true);
+ if (rev_cc_cmp)
+ rev_cc_cmp = copy_rtx (rev_cc_cmp);
rtx_insn *insn;
int count = 0;
unsigned cost1 = 0, cost2 = 0;
rtx_insn *seq, *seq1, *seq2;
rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
+ bool read_comparison = false;
seq1 = try_emit_cmove_seq (if_info, temp, cond,
new_val, old_val, need_cmov,
as well. This allows the backend to emit a cmov directly without
creating an additional compare for each. If successful, costing
is easier and this sequence is usually preferred. */
- seq2 = try_emit_cmove_seq (if_info, target, cond,
+ seq2 = try_emit_cmove_seq (if_info, temp, cond,
new_val, old_val, need_cmov,
&cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
+ /* The backend might have created a sequence that uses the
+ condition. Check this. */
+ rtx_insn *walk = seq2;
+ while (walk)
+ {
+ rtx set = single_set (walk);
+
+ if (!set || !SET_SRC (set))
+ {
+ walk = NEXT_INSN (walk);
+ continue;
+ }
+
+ rtx src = SET_SRC (set);
+
+ if (XEXP (set, 1) && GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE)
+ ; /* We assume that this is the cmove created by the backend that
+ naturally uses the condition. Therefore we ignore it. */
+ else
+ {
+ if (reg_mentioned_p (XEXP (cond, 0), src)
+ || reg_mentioned_p (XEXP (cond, 1), src))
+ {
+ read_comparison = true;
+ break;
+ }
+ }
+
+ walk = NEXT_INSN (walk);
+ }
+
/* Check which version is less expensive. */
if (seq1 != NULL_RTX && (cost1 <= cost2 || seq2 == NULL_RTX))
{
{
seq = seq2;
temp_dest = temp_dest2;
+ if (!second_try && read_comparison)
+ *last_needs_comparison = count;
}
else
{
unmodified_insns->safe_push (insn);
}
+ /* Even if we did not actually need the comparison, we want to make sure
+ to try a second time in order to get rid of the temporaries. */
+ if (*last_needs_comparison == -1)
+ *last_needs_comparison = 0;
+
+
return true;
}
--- /dev/null
+/* Make sure if conversion for two instructions does not break
+ anything (if it runs). */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -std=c99" } */
+
+#include <limits.h>
+#include <assert.h>
+
+__attribute__ ((noinline))
+int foo (int *a, int n)
+{
+ int min = 999999;
+ int bla = 0;
+ for (int i = 0; i < n; i++)
+ {
+ if (a[i] < min)
+ {
+ min = a[i];
+ bla = 1;
+ }
+ }
+
+ if (bla)
+ min += 1;
+ return min;
+}
+
+int main()
+{
+ int a[] = {2, 1, -13, INT_MAX, INT_MIN, 0};
+
+ int res = foo (a, sizeof (a) / sizeof (a[0]));
+
+ assert (res == (INT_MIN + 1));
+}