MIN/MAX codegen tweek (regression relative to 3.4)
Jan Hubicka
jh@suse.cz
Fri Nov 11 16:51:00 GMT 2005
Hi,
with tree-level MIN/MAX discovery we've lost ability to optimize cmp $1 into
test reg,reg in these cases. This (quite surprisingly) cause about 2%
regression on VPR benchmark.
The patch looks rather large due to re-indenting. Only real change is the code
dealing with cmpop1.
Bootstrapped/regtested i686-pc-gnu-linux, OK?
Honza
/* { 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));
}
/* { 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));
}
2005-11-11 Jan Hubicka <jh@suse.cz>
* expr.c (expand_expr_real_1): Be more curefull to arrange cmp 0 on
MIN/MAX exprs.
Index: expr.c
===================================================================
-cp -L expr.c (revision 106319) -L expr.c (working copy) .svn/text-base/expr.c.svn-base expr.c
*** expr.c (revision 106319)
--- expr.c (working copy)
*************** expand_expr_real_1 (tree exp, rtx target
*** 8020,8088 ****
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;
! 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 ();
!
! start_sequence ();
!
! /* Try to emit the conditional move. */
! insn = emit_conditional_move (target, comparison_code,
! op0, op1, mode,
! op0, op1, mode,
! unsignedp);
!
! /* 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);
! 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);
! }
emit_move_insn (target, op1);
emit_label (temp);
return target;
--- 8020,8111 ----
if (! CONSTANT_P (op1))
op1 = force_reg (mode, op1);
+ {
+ enum rtx_code comparison_code;
+ rtx cmpop1 = op1;
+
+ if (code == MAX_EXPR)
+ comparison_code = unsignedp ? GEU : GE;
+ else
+ comparison_code = unsignedp ? LEU : LE;
+
+ /* 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;
! /* ??? 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 ();
! start_sequence ();
!
! /* Try to emit the conditional move. */
! insn = emit_conditional_move (target, comparison_code,
! op0, cmpop1, mode,
! op0, op1, mode,
! unsignedp);
!
! /* 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);
! 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, cmpop1, comparison_code,
! unsignedp, mode, NULL_RTX, NULL_RTX, temp);
! }
! }
emit_move_insn (target, op1);
emit_label (temp);
return target;
More information about the Gcc-patches
mailing list