diff options
author | Jan Hubicka <jh@suse.cz> | 2005-11-12 18:35:06 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2005-11-12 17:35:06 +0000 |
commit | 230dedb3272fa440ac35dcfb607c56221b1f18fa (patch) | |
tree | 143398328b5dba39ed717e534f55c159e0cba4b7 /gcc | |
parent | df25924573df78683f948a6fda74ece056746268 (diff) | |
download | gcc-230dedb3272fa440ac35dcfb607c56221b1f18fa.zip gcc-230dedb3272fa440ac35dcfb607c56221b1f18fa.tar.gz gcc-230dedb3272fa440ac35dcfb607c56221b1f18fa.tar.bz2 |
expr.c (expand_expr_real_1): <MAX_EXPR, MIN_EXPR>: Canonicalize to compare against 0 when possible.
* expr.c (expand_expr_real_1): <MAX_EXPR, MIN_EXPR>: Canonicalize
to compare against 0 when possible.
* gcc.target/i386/minmax-1.c: New.
* gcc.target/i386/minmax-2.c: New.
From-SVN: r106827
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/expr.c | 131 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/minmax-1.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/minmax-2.c | 9 |
5 files changed, 105 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 395df13..3c01cf7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-11-12 Jan Hubicka <jh@suse.cz> + + * expr.c (expand_expr_real_1): <MAX_EXPR, MIN_EXPR>: Canonicalize + to compare against 0 when possible. + 2005-11-12 Jie Zhang <jie.zhang@analog.com> * config/bfin/bfin.h (REGISTER_NAMES, SHORT_REGISTER_NAMES, @@ -8020,69 +8020,92 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (! CONSTANT_P (op1)) op1 = force_reg (mode, op1); -#ifdef HAVE_conditional_move - /* Use a conditional move if possible. */ - if (can_conditionally_move_p (mode)) - { - enum rtx_code comparison_code; - rtx insn; + { + enum rtx_code comparison_code; + rtx cmpop1 = op1; - if (code == MAX_EXPR) - comparison_code = unsignedp ? GEU : GE; - else - comparison_code = unsignedp ? LEU : LE; + if (code == MAX_EXPR) + comparison_code = unsignedp ? GEU : GE; + else + comparison_code = unsignedp ? LEU : LE; - /* ??? Same problem as in expmed.c: emit_conditional_move - forces a stack adjustment via compare_from_rtx, and we - lose the stack adjustment if the sequence we are about - to create is discarded. */ - do_pending_stack_adjust (); + /* Canonicalize to comparsions against 0. */ + if (op1 == const1_rtx) + { + /* Converting (a >= 1 ? a : 1) into (a > 0 ? a : 1) + or (a != 0 ? a : 1) for unsigned. + For MIN we are safe converting (a <= 1 ? a : 1) + into (a <= 0 ? a : 1) */ + cmpop1 = const0_rtx; + if (code == MAX_EXPR) + comparison_code = unsignedp ? NE : GT; + } + if (op1 == constm1_rtx && !unsignedp) + { + /* Converting (a >= -1 ? a : -1) into (a >= 0 ? a : -1) + and (a <= -1 ? a : -1) into (a < 0 ? a : -1) */ + cmpop1 = const0_rtx; + if (code == MIN_EXPR) + comparison_code = LT; + } +#ifdef HAVE_conditional_move + /* Use a conditional move if possible. */ + if (can_conditionally_move_p (mode)) + { + rtx insn; - start_sequence (); + /* ??? Same problem as in expmed.c: emit_conditional_move + forces a stack adjustment via compare_from_rtx, and we + lose the stack adjustment if the sequence we are about + to create is discarded. */ + do_pending_stack_adjust (); - /* Try to emit the conditional move. */ - insn = emit_conditional_move (target, comparison_code, - op0, op1, mode, - op0, op1, mode, - unsignedp); + start_sequence (); - /* If we could do the conditional move, emit the sequence, - and return. */ - if (insn) - { - rtx seq = get_insns (); - end_sequence (); - emit_insn (seq); - return target; - } + /* Try to emit the conditional move. */ + insn = emit_conditional_move (target, comparison_code, + op0, cmpop1, mode, + op0, op1, mode, + unsignedp); - /* Otherwise discard the sequence and fall back to code with - branches. */ - end_sequence (); - } + /* If we could do the conditional move, emit the sequence, + and return. */ + if (insn) + { + rtx seq = get_insns (); + end_sequence (); + emit_insn (seq); + return target; + } + + /* Otherwise discard the sequence and fall back to code with + branches. */ + end_sequence (); + } #endif - if (target != op0) - emit_move_insn (target, op0); + if (target != op0) + emit_move_insn (target, op0); - temp = gen_label_rtx (); + temp = gen_label_rtx (); - /* If this mode is an integer too wide to compare properly, - compare word by word. Rely on cse to optimize constant cases. */ - if (GET_MODE_CLASS (mode) == MODE_INT - && ! can_compare_p (GE, mode, ccp_jump)) - { - if (code == MAX_EXPR) - do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1, - NULL_RTX, temp); - else - do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target, - NULL_RTX, temp); - } - else - { - do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE, - unsignedp, mode, NULL_RTX, NULL_RTX, temp); - } + /* If this mode is an integer too wide to compare properly, + compare word by word. Rely on cse to optimize constant cases. */ + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (GE, mode, ccp_jump)) + { + if (code == MAX_EXPR) + do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1, + NULL_RTX, temp); + else + do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target, + NULL_RTX, temp); + } + else + { + do_compare_rtx_and_jump (target, cmpop1, comparison_code, + unsignedp, mode, NULL_RTX, NULL_RTX, temp); + } + } emit_move_insn (target, op1); emit_label (temp); return target; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aabc14b..2767bb5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-11-12 Jan Hubicka <jh@suse.cz> + + * gcc.target/i386/minmax-1.c: New. + * gcc.target/i386/minmax-2.c: New. + 2005-11-12 Kaz Kojima <kkojima@gcc.gnu.org> * gcc.dg/pr24445.c: Fix for 64-bit targets. diff --git a/gcc/testsuite/gcc.target/i386/minmax-1.c b/gcc/testsuite/gcc.target/i386/minmax-1.c new file mode 100644 index 0000000..ca7fb6a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/minmax-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=opteron" } */ +/* { dg-final { scan-assembler "test" } } */ +/* { dg-final { scan-assembler-not "cmp" } } */ +#define max(a,b) (((a) > (b))? (a) : (b)) +t(int a) +{ + return (max(a,1)); +} diff --git a/gcc/testsuite/gcc.target/i386/minmax-2.c b/gcc/testsuite/gcc.target/i386/minmax-2.c new file mode 100644 index 0000000..2021aaa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/minmax-2.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "test" } } */ +/* { dg-final { scan-assembler-not "cmp" } } */ +#define max(a,b) (((a) > (b))? (a) : (b)) +t(unsigned int a) +{ + return (max(a,1)); +} |