aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-04-12 20:09:47 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2017-04-12 20:09:47 +0200
commitdeed3da9af697ecf073aea855ecce2d22d85ef71 (patch)
treeaa6adfa7b5640797147ae3695682ee34d546528a /gcc/optabs.c
parentb96a3e11572287992923065def1d64e8a2240f9b (diff)
downloadgcc-deed3da9af697ecf073aea855ecce2d22d85ef71.zip
gcc-deed3da9af697ecf073aea855ecce2d22d85ef71.tar.gz
gcc-deed3da9af697ecf073aea855ecce2d22d85ef71.tar.bz2
re PR tree-optimization/79390 (10% performance drop in SciMark2 LU after r242550)
PR tree-optimization/79390 * optabs.c (emit_conditional_move): If the preferred op2/op3 operand order does not result in usable sequence, retry with reversed operand order. * gcc.target/i386/pr70465-2.c: Xfail the scan-assembler-not test. From-SVN: r246882
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c80
1 files changed, 50 insertions, 30 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 1afd593..48e37f8 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4258,12 +4258,15 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
if (cmode == VOIDmode)
cmode = GET_MODE (op0);
+ enum rtx_code orig_code = code;
+ bool swapped = false;
if (swap_commutative_operands_p (op2, op3)
&& ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
!= UNKNOWN))
{
std::swap (op2, op3);
code = reversed;
+ swapped = true;
}
if (mode == VOIDmode)
@@ -4272,45 +4275,62 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
icode = direct_optab_handler (movcc_optab, mode);
if (icode == CODE_FOR_nothing)
- return 0;
+ return NULL_RTX;
if (!target)
target = gen_reg_rtx (mode);
- code = unsignedp ? unsigned_condition (code) : code;
- comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
-
- /* We can get const0_rtx or const_true_rtx in some circumstances. Just
- return NULL and let the caller figure out how best to deal with this
- situation. */
- if (!COMPARISON_P (comparison))
- return NULL_RTX;
-
- saved_pending_stack_adjust save;
- save_pending_stack_adjust (&save);
- last = get_last_insn ();
- do_pending_stack_adjust ();
- prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
- GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
- &comparison, &cmode);
- if (comparison)
+ for (int pass = 0; ; pass++)
{
- struct expand_operand ops[4];
+ code = unsignedp ? unsigned_condition (code) : code;
+ comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
- create_output_operand (&ops[0], target, mode);
- create_fixed_operand (&ops[1], comparison);
- create_input_operand (&ops[2], op2, mode);
- create_input_operand (&ops[3], op3, mode);
- if (maybe_expand_insn (icode, 4, ops))
+ /* We can get const0_rtx or const_true_rtx in some circumstances. Just
+ punt and let the caller figure out how best to deal with this
+ situation. */
+ if (COMPARISON_P (comparison))
{
- if (ops[0].value != target)
- convert_move (target, ops[0].value, false);
- return target;
+ saved_pending_stack_adjust save;
+ save_pending_stack_adjust (&save);
+ last = get_last_insn ();
+ do_pending_stack_adjust ();
+ prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
+ GET_CODE (comparison), NULL_RTX, unsignedp,
+ OPTAB_WIDEN, &comparison, &cmode);
+ if (comparison)
+ {
+ struct expand_operand ops[4];
+
+ create_output_operand (&ops[0], target, mode);
+ create_fixed_operand (&ops[1], comparison);
+ create_input_operand (&ops[2], op2, mode);
+ create_input_operand (&ops[3], op3, mode);
+ if (maybe_expand_insn (icode, 4, ops))
+ {
+ if (ops[0].value != target)
+ convert_move (target, ops[0].value, false);
+ return target;
+ }
+ }
+ delete_insns_since (last);
+ restore_pending_stack_adjust (&save);
}
+
+ if (pass == 1)
+ return NULL_RTX;
+
+ /* If the preferred op2/op3 order is not usable, retry with other
+ operand order, perhaps it will expand successfully. */
+ if (swapped)
+ code = orig_code;
+ else if ((reversed = reversed_comparison_code_parts (orig_code, op0, op1,
+ NULL))
+ != UNKNOWN)
+ code = reversed;
+ else
+ return NULL_RTX;
+ std::swap (op2, op3);
}
- delete_insns_since (last);
- restore_pending_stack_adjust (&save);
- return NULL_RTX;
}