Commit 44fef04a by Kyrylo Tkachov Committed by Kyrylo Tkachov

[RTL-ifcvt] Improve conditional select ops on immediates

	* ifcvt.c (noce_try_store_flag_constants): Make logic of the case
	when diff == STORE_FLAG_VALUE or diff == -STORE_FLAG_VALUE more
	explicit.  Prefer to add the flag whenever possible.
	(noce_process_if_block): Try noce_try_store_flag_constants before
	noce_try_cmove.

	* gcc.target/aarch64/csel_bfx_1.c: New test.
	* gcc.target/aarch64/csel_imms_inc_1.c: Likewise.

From-SVN: r226491
parent 03038b8b
2015-08-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* ifcvt.c (noce_try_store_flag_constants): Make logic of the case
when diff == STORE_FLAG_VALUE or diff == -STORE_FLAG_VALUE more
explicit. Prefer to add the flag whenever possible.
(noce_process_if_block): Try noce_try_store_flag_constants before
noce_try_cmove.
2015-08-03 Richard Biener <rguenther@suse.de> 2015-08-03 Richard Biener <rguenther@suse.de>
* genmatch.c (struct sinfo, struct sinfo_hashmap_traits, sinfo_map_t): * genmatch.c (struct sinfo, struct sinfo_hashmap_traits, sinfo_map_t):
......
...@@ -1159,9 +1159,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1159,9 +1159,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
{ {
rtx target; rtx target;
rtx_insn *seq; rtx_insn *seq;
int reversep; bool reversep;
HOST_WIDE_INT itrue, ifalse, diff, tmp; HOST_WIDE_INT itrue, ifalse, diff, tmp;
int normalize, can_reverse; int normalize;
bool can_reverse;
machine_mode mode; machine_mode mode;
if (CONST_INT_P (if_info->a) if (CONST_INT_P (if_info->a)
...@@ -1170,6 +1171,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1170,6 +1171,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
mode = GET_MODE (if_info->x); mode = GET_MODE (if_info->x);
ifalse = INTVAL (if_info->a); ifalse = INTVAL (if_info->a);
itrue = INTVAL (if_info->b); itrue = INTVAL (if_info->b);
bool subtract_flag_p = false;
diff = (unsigned HOST_WIDE_INT) itrue - ifalse; diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
/* Make sure we can represent the difference between the two values. */ /* Make sure we can represent the difference between the two values. */
...@@ -1182,23 +1184,61 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1182,23 +1184,61 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump) can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
!= UNKNOWN); != UNKNOWN);
reversep = 0; reversep = false;
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE) if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
normalize = 0; {
normalize = 0;
/* We could collapse these cases but it is easier to follow the
diff/STORE_FLAG_VALUE combinations when they are listed
explicitly. */
/* test ? 3 : 4
=> 4 + (test != 0). */
if (diff < 0 && STORE_FLAG_VALUE < 0)
reversep = false;
/* test ? 4 : 3
=> can_reverse | 4 + (test == 0)
!can_reverse | 3 - (test != 0). */
else if (diff > 0 && STORE_FLAG_VALUE < 0)
{
reversep = can_reverse;
subtract_flag_p = !can_reverse;
}
/* test ? 3 : 4
=> can_reverse | 3 + (test == 0)
!can_reverse | 4 - (test != 0). */
else if (diff < 0 && STORE_FLAG_VALUE > 0)
{
reversep = can_reverse;
subtract_flag_p = !can_reverse;
}
/* test ? 4 : 3
=> 4 + (test != 0). */
else if (diff > 0 && STORE_FLAG_VALUE > 0)
reversep = false;
else
gcc_unreachable ();
}
else if (ifalse == 0 && exact_log2 (itrue) >= 0 else if (ifalse == 0 && exact_log2 (itrue) >= 0
&& (STORE_FLAG_VALUE == 1 && (STORE_FLAG_VALUE == 1
|| if_info->branch_cost >= 2)) || if_info->branch_cost >= 2))
normalize = 1; normalize = 1;
else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
&& (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2)) && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
normalize = 1, reversep = 1; {
normalize = 1;
reversep = true;
}
else if (itrue == -1 else if (itrue == -1
&& (STORE_FLAG_VALUE == -1 && (STORE_FLAG_VALUE == -1
|| if_info->branch_cost >= 2)) || if_info->branch_cost >= 2))
normalize = -1; normalize = -1;
else if (ifalse == -1 && can_reverse else if (ifalse == -1 && can_reverse
&& (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2)) && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2))
normalize = -1, reversep = 1; {
normalize = -1;
reversep = true;
}
else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1) else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
|| if_info->branch_cost >= 3) || if_info->branch_cost >= 3)
normalize = -1; normalize = -1;
...@@ -1223,9 +1263,9 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1223,9 +1263,9 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
=> x = 3 + (test == 0); */ => x = 3 + (test == 0); */
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE) if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
{ {
target = expand_simple_binop (mode, /* Always use ifalse here. It should have been swapped with itrue
(diff == STORE_FLAG_VALUE when appropriate when reversep is true. */
? PLUS : MINUS), target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
gen_int_mode (ifalse, mode), target, gen_int_mode (ifalse, mode), target,
if_info->x, 0, OPTAB_WIDEN); if_info->x, 0, OPTAB_WIDEN);
} }
...@@ -2731,13 +2771,14 @@ noce_process_if_block (struct noce_if_info *if_info) ...@@ -2731,13 +2771,14 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success; goto success;
if (noce_try_abs (if_info)) if (noce_try_abs (if_info))
goto success; goto success;
if (!targetm.have_conditional_execution ()
&& noce_try_store_flag_constants (if_info))
goto success;
if (HAVE_conditional_move if (HAVE_conditional_move
&& noce_try_cmove (if_info)) && noce_try_cmove (if_info))
goto success; goto success;
if (! targetm.have_conditional_execution ()) if (! targetm.have_conditional_execution ())
{ {
if (noce_try_store_flag_constants (if_info))
goto success;
if (noce_try_addcc (if_info)) if (noce_try_addcc (if_info))
goto success; goto success;
if (noce_try_store_flag_mask (if_info)) if (noce_try_store_flag_mask (if_info))
......
2015-08-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/aarch64/csel_bfx_1.c: New test.
* gcc.target/aarch64/csel_imms_inc_1.c: Likewise.
2015-08-02 Martin Sebor <msebor@redhat.com> 2015-08-02 Martin Sebor <msebor@redhat.com>
* g++.dg/Wframe-address-in-Wall.C: New test. * g++.dg/Wframe-address-in-Wall.C: New test.
......
/* { dg-do compile } */
/* { dg-options "-save-temps -O2" } */
int
foo (int a, int b)
{
return ((a & (1 << 25)) ? 5 : 4);
}
/* { dg-final { scan-assembler "ubfx\t\[xw\]\[0-9\]*.*" } } */
/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */
/* { dg-do run } */
/* { dg-options "-save-temps -O2 -fno-inline" } */
extern void abort (void);
int
fooinc (int x)
{
if (x)
return 1025;
else
return 1026;
}
int
fooinc2 (int x)
{
if (x)
return 1026;
else
return 1025;
}
int
main (void)
{
if (fooinc (0) != 1026)
abort ();
if (fooinc (1) != 1025)
abort ();
if (fooinc2 (0) != 1025)
abort ();
if (fooinc2 (1) != 1026)
abort ();
return 0;
}
/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment