This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: add missing if-then-else optimization
- From: Dale Johannesen <dalej at apple dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Dale Johannesen <dalej at apple dot com>
- Date: Fri, 13 Sep 2002 11:39:52 -0700
- Subject: Patch: add missing if-then-else optimization
Compiling the following -O2 (ppc darwin):
int foo(int v, unsigned char *p1, unsigned char* p2) {
int s=0;
if ((v = p1[0]-p2[0]) < 0) v=-v;
s+=v;
if ((v = p1[1]-p2[1]) < 0) v=-v;
s+=v;
return s;
}
the first if-then is transformed into "abs", the second one is
not. This happens because, after the first "abs" substitution
is made, the code in if_convert does not reexamine the merged
block to see if another substitution can be made. This
patch addresses the problem. Bootstrapped and tested on Darwin.
(Note, to get this to work I also had to change various places
that insert inline substitutions to do the insertion before
"cond_earliest", rather than before "jump". The comments say
this is what is supposed to happen, and it seems to work.
Without this change you get breakage on this code:
x=0;
if (a>0) x=1;
if (a<0) x=1;
The first if-then is transformed to x=(a>0), and if the code for
this is placed before "jump" you get
x=0;
test for a vs 0 [was shared] <-cond_earliest
x=(a>0)
conditional branch <-jump
The code in noce_process_if_block gets insn_b from the instruction
before cond_earliest, so it misses the second store to x and invalid
code results.)
Attachment:
diffs
Description: Binary data
Index: ifcvt.c
===================================================================
RCS file: /cvs/Darwin/gcc3/gcc/ifcvt.c,v
retrieving revision 1.12
diff -u -d -b -w -c -3 -p -r1.12 ifcvt.c
cvs server: conflicting specifications of output style
*** ifcvt.c 2002/08/26 05:39:38 1.12
--- ifcvt.c 2002/09/13 17:47:15
*************** noce_try_store_flag (if_info)
*** 715,721 ****
seq = get_insns ();
end_sequence ();
! emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE
(if_info->insn_a));
return TRUE;
}
--- 715,722 ----
seq = get_insns ();
end_sequence ();
! emit_insn_before_scope (seq, if_info->cond_earliest,
! INSN_SCOPE (if_info->insn_a));
return TRUE;
}
*************** noce_try_store_flag_constants (if_info)
*** 850,856 ****
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE
(if_info->insn_a));
return TRUE;
}
--- 851,858 ----
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->cond_earliest,
! INSN_SCOPE (if_info->insn_a));
return TRUE;
}
*************** noce_try_store_flag_inc (if_info)
*** 910,916 ****
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->jump,
INSN_SCOPE (if_info->insn_a));
return TRUE;
--- 912,918 ----
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->cond_earliest,
INSN_SCOPE (if_info->insn_a));
return TRUE;
*************** noce_try_store_flag_mask (if_info)
*** 963,969 ****
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->jump,
INSN_SCOPE (if_info->insn_a));
return TRUE;
--- 965,971 ----
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->cond_earliest,
INSN_SCOPE (if_info->insn_a));
return TRUE;
*************** noce_try_cmove (if_info)
*** 1059,1065 ****
seq = get_insns ();
end_sequence ();
! emit_insn_before_scope (seq, if_info->jump,
INSN_SCOPE (if_info->insn_a));
return TRUE;
}
--- 1061,1067 ----
seq = get_insns ();
end_sequence ();
! emit_insn_before_scope (seq, if_info->cond_earliest,
INSN_SCOPE (if_info->insn_a));
return TRUE;
}
*************** noce_try_cmove_arith (if_info)
*** 1222,1228 ****
tmp = get_insns ();
end_sequence ();
! emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE
(if_info->insn_a));
return TRUE;
end_seq_and_fail:
--- 1224,1231 ----
tmp = get_insns ();
end_sequence ();
! emit_insn_before_scope (tmp, if_info->cond_earliest,
! INSN_SCOPE (if_info->insn_a));
return TRUE;
end_seq_and_fail:
*************** noce_try_minmax (if_info)
*** 1474,1480 ****
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE
(if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
--- 1477,1484 ----
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->cond_earliest,
! INSN_SCOPE (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
*************** noce_try_abs (if_info)
*** 1592,1598 ****
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE
(if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
--- 1596,1603 ----
if (seq_contains_jump (seq))
return FALSE;
! emit_insn_before_scope (seq, if_info->cond_earliest,
! INSN_SCOPE (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
*************** if_convert (x_life_data_ok)
*** 3115,3122 ****
FOR_EACH_BB (bb)
{
! basic_block new_bb = find_if_header (bb, pass);
! if (new_bb)
bb = new_bb;
}
--- 3120,3127 ----
FOR_EACH_BB (bb)
{
! basic_block new_bb;
! while ((new_bb = find_if_header (bb, pass)))
bb = new_bb;
}