Commit 5554928d by H.J. Lu Committed by H.J. Lu

Revert revision 164552.

gcc/

2010-11-03  H.J. Lu  <hongjiu.lu@intel.com>

	PR rtl-optimization/45865
	* Makefile.in (df-problems.o): Revert revision 164552.
	* basic-block.h (enum bb_flags): Likewise.
	* cfgcleanup.c (block_was_dirty): Likewise.
	(try_forward_edges): Likewise.
	(try_crossjump_bb): Likewise.
	(try_head_merge_bb): Likewise.
	(try_optimize_cfg): Likewise.
	(cleanup_cfg): Likewise.
	* df-core.c (df_set_bb_dirty): Likewise.
	* df-problems.c: Likewise.
	(df_simulate_find_uses): Likewise.
	(MEMREF_NORMAL, MEMREF_VOLATILE): Likewise.
	(find_memory, find_memory_store): Likewise.
	(can_move_insns_across): Likewise.
	* df.h (can_move_insns_across): Likewise.
	* ifcvt.c (find_memory): Likewise.
	(dead_or_predicable): Likewise.

gcc/testsuite/

2010-11-03  H.J. Lu  <hongjiu.lu@intel.com>

	PR rtl-optimization/45865
	* gcc.dg/pr45865.c: New.
	* gcc.dg/torture/pr45865.c: Likewise.

	* gcc.target/arm/headmerge-1.c: Revert revision 164552.
	* gcc.target/arm/headmerge-2.c: Likewise.
	* gcc.target/i386/headmerge-1.c: Likewise.
	* gcc.target/i386/headmerge-2.c: Likewise.

From-SVN: r166259
parent 44cb6d4d
2010-11-03 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/45865
* Makefile.in (df-problems.o): Revert revision 164552.
* basic-block.h (enum bb_flags): Likewise.
* cfgcleanup.c (block_was_dirty): Likewise.
(try_forward_edges): Likewise.
(try_crossjump_bb): Likewise.
(try_head_merge_bb): Likewise.
(try_optimize_cfg): Likewise.
(cleanup_cfg): Likewise.
* df-core.c (df_set_bb_dirty): Likewise.
* df-problems.c: Likewise.
(df_simulate_find_uses): Likewise.
(MEMREF_NORMAL, MEMREF_VOLATILE): Likewise.
(find_memory, find_memory_store): Likewise.
(can_move_insns_across): Likewise.
* df.h (can_move_insns_across): Likewise.
* ifcvt.c (find_memory): Likewise.
(dead_or_predicable): Likewise.
2010-11-03 Richard Guenther <rguenther@suse.de> 2010-11-03 Richard Guenther <rguenther@suse.de>
PR middle-end/46288 PR middle-end/46288
...@@ -3168,7 +3168,7 @@ df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ ...@@ -3168,7 +3168,7 @@ df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \ $(RTL_H) insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \
$(TM_P_H) $(TARGET_H) $(FLAGS_H) output.h $(EXCEPT_H) dce.h vecprim.h $(TM_P_H) $(FLAGS_H) output.h $(EXCEPT_H) dce.h vecprim.h
df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \ insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \
......
...@@ -246,13 +246,7 @@ enum bb_flags ...@@ -246,13 +246,7 @@ enum bb_flags
/* Set on blocks that cannot be threaded through. /* Set on blocks that cannot be threaded through.
Only used in cfgcleanup.c. */ Only used in cfgcleanup.c. */
BB_NONTHREADABLE_BLOCK = 1 << 11, BB_NONTHREADABLE_BLOCK = 1 << 11
/* Set on blocks that were modified in some way. This bit is set in
df_set_bb_dirty, but not cleared by df_analyze, so it can be used
to test whether a block has been modified prior to a df_analyze
call. */
BB_MODIFIED = 1 << 12
}; };
/* Dummy flag for convenience in the hot/cold partitioning code. */ /* Dummy flag for convenience in the hot/cold partitioning code. */
......
...@@ -1413,7 +1413,6 @@ df_get_bb_dirty (basic_block bb) ...@@ -1413,7 +1413,6 @@ df_get_bb_dirty (basic_block bb)
void void
df_set_bb_dirty (basic_block bb) df_set_bb_dirty (basic_block bb)
{ {
bb->flags |= BB_MODIFIED;
if (df) if (df)
{ {
int p; int p;
......
...@@ -971,9 +971,7 @@ extern void df_simulate_one_insn_backwards (basic_block, rtx, bitmap); ...@@ -971,9 +971,7 @@ extern void df_simulate_one_insn_backwards (basic_block, rtx, bitmap);
extern void df_simulate_finalize_backwards (basic_block, bitmap); extern void df_simulate_finalize_backwards (basic_block, bitmap);
extern void df_simulate_initialize_forwards (basic_block, bitmap); extern void df_simulate_initialize_forwards (basic_block, bitmap);
extern void df_simulate_one_insn_forwards (basic_block, rtx, bitmap); extern void df_simulate_one_insn_forwards (basic_block, rtx, bitmap);
extern void simulate_backwards_to_point (basic_block, regset, rtx);
extern bool can_move_insns_across (rtx, rtx, rtx, rtx, basic_block, regset,
regset, rtx *);
/* Functions defined in df-scan.c. */ /* Functions defined in df-scan.c. */
extern void df_scan_alloc (bitmap); extern void df_scan_alloc (bitmap);
......
...@@ -103,6 +103,7 @@ static int noce_find_if_block (basic_block, edge, edge, int); ...@@ -103,6 +103,7 @@ static int noce_find_if_block (basic_block, edge, edge, int);
static int cond_exec_find_if_block (ce_if_block_t *); static int cond_exec_find_if_block (ce_if_block_t *);
static int find_if_case_1 (basic_block, edge, edge); static int find_if_case_1 (basic_block, edge, edge);
static int find_if_case_2 (basic_block, edge, edge); static int find_if_case_2 (basic_block, edge, edge);
static int find_memory (rtx *, void *);
static int dead_or_predicable (basic_block, basic_block, basic_block, static int dead_or_predicable (basic_block, basic_block, basic_block,
basic_block, int); basic_block, int);
static void noce_emit_move_insn (rtx, rtx); static void noce_emit_move_insn (rtx, rtx);
...@@ -3975,6 +3976,15 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) ...@@ -3975,6 +3976,15 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
return TRUE; return TRUE;
} }
/* A subroutine of dead_or_predicable called through for_each_rtx.
Return 1 if a memory is found. */
static int
find_memory (rtx *px, void *data ATTRIBUTE_UNUSED)
{
return MEM_P (*px);
}
/* Used by the code above to perform the actual rtl transformations. /* Used by the code above to perform the actual rtl transformations.
Return TRUE if successful. Return TRUE if successful.
...@@ -4076,38 +4086,131 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, ...@@ -4076,38 +4086,131 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
earliest = jump; earliest = jump;
} }
#endif #endif
/* If we allocated new pseudos (e.g. in the conditional move
expander called from noce_emit_cmove), we must resize the
array first. */
if (max_regno < max_reg_num ())
max_regno = max_reg_num ();
/* Try the NCE path if the CE path did not result in any changes. */ /* Try the NCE path if the CE path did not result in any changes. */
if (n_validated_changes == 0) if (n_validated_changes == 0)
{ {
rtx cond;
regset live;
bool success;
/* In the non-conditional execution case, we have to verify that there /* In the non-conditional execution case, we have to verify that there
are no trapping operations, no calls, no references to memory, and are no trapping operations, no calls, no references to memory, and
that any registers modified are dead at the branch site. */ that any registers modified are dead at the branch site. */
if (!any_condjump_p (jump)) rtx insn, cond, prev;
bitmap merge_set, merge_set_noclobber, test_live, test_set;
unsigned i, fail = 0;
bitmap_iterator bi;
/* Check for no calls or trapping operations. */
for (insn = head; ; insn = NEXT_INSN (insn))
{
if (CALL_P (insn))
return FALSE;
if (NONDEBUG_INSN_P (insn))
{
if (may_trap_p (PATTERN (insn)))
return FALSE;
/* ??? Even non-trapping memories such as stack frame
references must be avoided. For stores, we collect
no lifetime info; for reads, we'd have to assert
true_dependence false against every store in the
TEST range. */
if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
return FALSE;
}
if (insn == end)
break;
}
if (! any_condjump_p (jump))
return FALSE; return FALSE;
/* Find the extent of the conditional. */ /* Find the extent of the conditional. */
cond = noce_get_condition (jump, &earliest, false); cond = noce_get_condition (jump, &earliest, false);
if (!cond) if (! cond)
return FALSE; return FALSE;
live = BITMAP_ALLOC (&reg_obstack); /* Collect:
simulate_backwards_to_point (merge_bb, live, end); MERGE_SET = set of registers set in MERGE_BB
success = can_move_insns_across (head, end, earliest, jump, MERGE_SET_NOCLOBBER = like MERGE_SET, but only includes registers
merge_bb, live, that are really set, not just clobbered.
df_get_live_in (other_bb), NULL); TEST_LIVE = set of registers live at EARLIEST
BITMAP_FREE (live); TEST_SET = set of registers set between EARLIEST and the
if (!success) end of the block. */
merge_set = BITMAP_ALLOC (&reg_obstack);
merge_set_noclobber = BITMAP_ALLOC (&reg_obstack);
test_live = BITMAP_ALLOC (&reg_obstack);
test_set = BITMAP_ALLOC (&reg_obstack);
/* ??? bb->local_set is only valid during calculate_global_regs_live,
so we must recompute usage for MERGE_BB. Not so bad, I suppose,
since we've already asserted that MERGE_BB is small. */
/* If we allocated new pseudos (e.g. in the conditional move
expander called from noce_emit_cmove), we must resize the
array first. */
if (max_regno < max_reg_num ())
max_regno = max_reg_num ();
FOR_BB_INSNS (merge_bb, insn)
{
if (NONDEBUG_INSN_P (insn))
{
df_simulate_find_defs (insn, merge_set);
df_simulate_find_noclobber_defs (insn, merge_set_noclobber);
}
}
/* For small register class machines, don't lengthen lifetimes of
hard registers before reload. */
if (! reload_completed
&& targetm.small_register_classes_for_mode_p (VOIDmode))
{
EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi)
{
if (i < FIRST_PSEUDO_REGISTER
&& ! fixed_regs[i]
&& ! global_regs[i])
fail = 1;
}
}
/* For TEST, we're interested in a range of insns, not a whole block.
Moreover, we're interested in the insns live from OTHER_BB. */
/* The loop below takes the set of live registers
after JUMP, and calculates the live set before EARLIEST. */
bitmap_copy (test_live, df_get_live_in (other_bb));
df_simulate_initialize_backwards (test_bb, test_live);
for (insn = jump; ; insn = prev)
{
if (INSN_P (insn))
{
df_simulate_find_defs (insn, test_set);
df_simulate_one_insn_backwards (test_bb, insn, test_live);
}
prev = PREV_INSN (insn);
if (insn == earliest)
break;
}
/* We can perform the transformation if
MERGE_SET_NOCLOBBER & TEST_SET
and
MERGE_SET & TEST_LIVE)
and
TEST_SET & DF_LIVE_IN (merge_bb)
are empty. */
if (bitmap_intersect_p (test_set, merge_set_noclobber)
|| bitmap_intersect_p (test_live, merge_set)
|| bitmap_intersect_p (test_set, df_get_live_in (merge_bb)))
fail = 1;
BITMAP_FREE (merge_set_noclobber);
BITMAP_FREE (merge_set);
BITMAP_FREE (test_live);
BITMAP_FREE (test_set);
if (fail)
return FALSE; return FALSE;
} }
......
2010-11-03 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/45865
* gcc.dg/pr45865.c: New.
* gcc.dg/torture/pr45865.c: Likewise.
* gcc.target/arm/headmerge-1.c: Revert revision 164552.
* gcc.target/arm/headmerge-2.c: Likewise.
* gcc.target/i386/headmerge-1.c: Likewise.
* gcc.target/i386/headmerge-2.c: Likewise.
2010-11-03 Richard Guenther <rguenther@suse.de> 2010-11-03 Richard Guenther <rguenther@suse.de>
PR middle-end/46288 PR middle-end/46288
......
/* PR rtl-optimization/45865 */
/* { dg-do compile } */
/* { dg-options "-O2 -fcompare-debug" } */
typedef union tree_node *tree;
enum ix86_builtin_type {
IX86_BT_LAST_VECT,
IX86_BT_LAST_PTR
};
extern const enum ix86_builtin_type ix86_builtin_type_ptr_base[];
extern tree build_qualified_type (tree, int);
extern tree build_pointer_type (tree);
tree
ix86_get_builtin_type (enum ix86_builtin_type tcode, unsigned int index)
{
tree type, itype;
int quals;
if (tcode <= IX86_BT_LAST_PTR)
quals = 0x0;
else
quals = 0x1;
itype = ix86_get_builtin_type (ix86_builtin_type_ptr_base[index],
index);
if (quals != 0x0)
itype = build_qualified_type (itype, quals);
type = build_pointer_type (itype);
return type;
}
/* { dg-do compile } */
typedef struct rtx_def *rtx;
enum machine_mode {
VOIDmode,
CCFPmode,
CCFPUmode,
MAX_MACHINE_MODE
};
enum mode_class {
MODE_CC,
MODE_FLOAT,
MODE_COMPLEX_FLOAT,
MODE_VECTOR_FLOAT
};
extern const enum mode_class mode_class[(int) MAX_MACHINE_MODE];
enum rtx_code {
UNKNOWN,
GEU,
ORDERED,
CONST_INT
};
struct rtx_def {
unsigned int code: 16;
unsigned int mode : 8;
};
extern enum rtx_code reverse_condition (enum rtx_code);
enum rtx_code
reversed_comparison_code_parts (enum rtx_code code, rtx insn, rtx arg0,
rtx arg1)
{
enum machine_mode mode;
mode = (enum machine_mode) (arg0)->mode;
if (mode == VOIDmode)
mode = (enum machine_mode) (arg1)->mode;
if ((mode_class[(int) (mode)]) == MODE_CC)
return (mode != CCFPmode && mode != CCFPUmode
? reverse_condition (code)
: reverse_condition_maybe_unordered (code));
switch (code)
{
case GEU:
return reverse_condition (code);
case ORDERED:
return UNKNOWN;
}
if (((enum rtx_code) (arg0)->code) == CONST_INT
|| (((enum machine_mode) (arg0)->mode) != VOIDmode
&& ! ((mode_class[(int) (mode)]) == MODE_FLOAT
|| (mode_class[(int) (mode)]) == MODE_COMPLEX_FLOAT
|| (mode_class[(int) (mode)]) == MODE_VECTOR_FLOAT)))
return reverse_condition (code);
return UNKNOWN;
}
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "#120" 1 } } */
extern void foo1 (int);
extern void foo2 (int);
void t (int x, int y)
{
if (y < 5)
foo1 (120);
else
foo2 (120);
}
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "120" 1 } } */
extern void foo1 (int);
extern void foo2 (int);
extern void foo3 (int);
extern void foo4 (int);
extern void foo5 (int);
extern void foo6 (int);
void t (int x, int y)
{
switch (y)
{
case 1:
foo1 (120);
break;
case 5:
foo2 (120);
break;
case 7:
foo3 (120);
break;
case 10:
foo4 (120);
break;
case 13:
foo5 (120);
break;
default:
foo6 (120);
break;
}
}
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "120" 1 } } */
extern void foo1 (int);
extern void foo2 (int);
void t (int x, int y)
{
if (y < 5)
foo1 (120);
else
foo2 (120);
}
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "120" 1 } } */
extern void foo1 (int);
extern void foo2 (int);
extern void foo3 (int);
extern void foo4 (int);
extern void foo5 (int);
extern void foo6 (int);
void t (int x, int y)
{
switch (y)
{
case 1:
foo1 (120);
break;
case 5:
foo2 (120);
break;
case 7:
foo3 (120);
break;
case 10:
foo4 (120);
break;
case 13:
foo5 (120);
break;
default:
foo6 (120);
break;
}
}
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