diff options
author | Jing Yu <jingyu@google.com> | 2011-01-30 22:18:29 -0800 |
---|---|---|
committer | Jing Yu <jingyu@google.com> | 2011-01-30 22:18:29 -0800 |
commit | 4a66e756636cb8364582ea503abd10d76f5b4aa3 (patch) | |
tree | 9660204ec085888a0601a6460c967b204a63d5f3 /gcc-4.4.3/gcc/tree-ssa-uninit.c | |
parent | b6be42e837844cce5283f42fcfac31e6d66a277d (diff) | |
download | toolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.tar.gz toolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.tar.bz2 toolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.zip |
Upgrade gcc-4.4.3 for Android toolchain.
- Backport upstream patches to support arm hardfp.
- Backport gcc-4.5 patches to support -march=atom. Now it is
able to build atom toolchain with glibc from this branch
- Develop a bunch of optimizations
- Fix a few arm dejagnu failures
To-do list:
- Support Android/atom
- Fix ia32 bootstrap failure
Change-Id: I5e10dcd21620d4d8ca984d1d1707a76067e61691
Diffstat (limited to 'gcc-4.4.3/gcc/tree-ssa-uninit.c')
-rw-r--r-- | gcc-4.4.3/gcc/tree-ssa-uninit.c | 219 |
1 files changed, 170 insertions, 49 deletions
diff --git a/gcc-4.4.3/gcc/tree-ssa-uninit.c b/gcc-4.4.3/gcc/tree-ssa-uninit.c index 41437b962..6edd89e87 100644 --- a/gcc-4.4.3/gcc/tree-ssa-uninit.c +++ b/gcc-4.4.3/gcc/tree-ssa-uninit.c @@ -215,7 +215,7 @@ find_control_equiv_block (basic_block bb) } #define MAX_NUM_CHAINS 8 -#define MAX_CHAIN_LEN 5 +#define MAX_CHAIN_LEN 8 /* Computes the control dependence chains (paths of edges) for DEP_BB up to the dominating basic block BB (the head node of a @@ -728,6 +728,160 @@ is_use_properly_guarded (gimple use_stmt, sbitmap uninit_opnds, struct pointer_set_t *visited_phis); +/* A helper function for prune_uninit_phi_opnds_in_unrealizable_paths. + Returns true if FLAG_ARG is defined by another phi node, and + the I th operand of PHI is also defined by another phi in the same + basic block of FLAG_ARG def's bb; returns false otherwise. If it + returns true, the defining statements for the flag and phi arg + are stored in *FLAG_ARG_DEF and *PHI_ARG_DEF. */ + +static bool +is_phi_arg_defined_by_phi (tree flag_arg, gimple phi, unsigned i, + gimple *flag_arg_def, gimple *phi_arg_def) +{ + tree phi_arg; + + if (TREE_CODE (flag_arg) != SSA_NAME) + return false; + + *flag_arg_def = SSA_NAME_DEF_STMT (flag_arg); + if (gimple_code (*flag_arg_def) != GIMPLE_PHI) + return false; + + phi_arg = gimple_phi_arg_def (phi, i); + if (TREE_CODE (phi_arg) != SSA_NAME) + return false; + + *phi_arg_def = SSA_NAME_DEF_STMT (phi_arg); + if (gimple_code (*phi_arg_def) != GIMPLE_PHI) + return false; + + if (gimple_bb (*phi_arg_def) != gimple_bb (*flag_arg_def)) + return false; + + return true; +} + +/* Returns true if all uninitialized opnds are pruned. Returns false + otherwise. PHI is the phi node with uninitialized operands, + UNINIT_OPNDS is the bitmap of the uninitialize operand positions, + FLAG_DEF is the statement defining the flag guarding the use of the + PHI output, BOUNDARY_CST is the const value used in the predicate + associated with the flag, CMP_CODE is the comparison code used in + the predicate, VISITED_PHIS is the pointer set of phis visited, and + VISITED_FLAG_PHIS is the pointer to the pointer set of flag definitions + that are also phis. + + Example scenario: + + BB1: + flag_1 = phi <0, 1> // (1) + var_1 = phi <undef, some_val> + + + BB2: + flag_2 = phi <0, flag_1, flag_1> // (2) + var_2 = phi <undef, var_1, var_1> + if (flag_2 == 1) + goto BB3; + + BB3: + use of var_2 // (3) + + Because some flag arg in (1) is not constant, if we do not look into the + flag phis recursively, it is conservatively treated as unknown and var_1 + is thought to be flowed into use at (3). Since var_1 is potentially uninitialized + a false warning will be emitted. Checking recursively into (1), the compiler can + find out that only some_val (which is defined) can flow into (3) which is OK. */ + +static bool +prune_uninit_phi_opnds_in_unrealizable_paths ( + gimple phi, sbitmap uninit_opnds, + gimple flag_def, tree boundary_cst, + enum tree_code cmp_code, + struct pointer_set_t *visited_phis, + struct pointer_set_t **visited_flag_phis) +{ + sbitmap_iterator sbi; + unsigned i; + + EXECUTE_IF_SET_IN_SBITMAP (uninit_opnds, 0, i, sbi) + { + tree flag_arg; + + flag_arg = gimple_phi_arg_def (flag_def, i); + + if (!is_gimple_constant (flag_arg)) + { + gimple flag_arg_def, phi_arg_def; + sbitmap uninit_opnds_arg_phi; + + if (!is_phi_arg_defined_by_phi (flag_arg, + phi, i, + &flag_arg_def, + &phi_arg_def)) + return false; + + if (!*visited_flag_phis) + *visited_flag_phis = pointer_set_create (); + + if (pointer_set_insert (*visited_flag_phis, flag_arg_def)) + return false; + + /* Now recursively prune the uninitialized phi args. */ + uninit_opnds_arg_phi = compute_uninit_opnds_pos (phi_arg_def); + if (!prune_uninit_phi_opnds_in_unrealizable_paths ( + phi_arg_def, uninit_opnds_arg_phi, + flag_arg_def, boundary_cst, cmp_code, + visited_phis, visited_flag_phis)) + { + sbitmap_free (uninit_opnds_arg_phi); + return false; + } + sbitmap_free (uninit_opnds_arg_phi); + pointer_set_delete (*visited_flag_phis, flag_arg_def); + continue; + } + + /* Now check if the constant is in the guarded range. */ + if (is_value_included_in (flag_arg, boundary_cst, cmp_code)) + { + tree opnd; + gimple opnd_def; + + /* Now that we know that this undefined edge is not + pruned. If the operand is defined by another phi, + we can further prune the incoming edges of that + phi by checking the predicates of this operands. */ + + opnd = gimple_phi_arg_def (phi, i); + opnd_def = SSA_NAME_DEF_STMT (opnd); + if (gimple_code (opnd_def) == GIMPLE_PHI) + { + edge opnd_edge; + sbitmap uninit_opnds2 + = compute_uninit_opnds_pos (opnd_def); + gcc_assert (!sbitmap_empty_p (uninit_opnds2)); + opnd_edge = gimple_phi_arg_edge (phi, i); + if (!is_use_properly_guarded (phi, + opnd_edge->src, + opnd_def, + uninit_opnds2, + visited_phis)) + { + sbitmap_free (uninit_opnds2); + return false; + } + sbitmap_free (uninit_opnds2); + } + else + return false; + } + } + + return true; +} + /* A helper function that determines if the predicate set of the use is not overlapping with that of the uninit paths. The most common senario of guarded use is in Example 1: @@ -816,7 +970,8 @@ use_pred_not_overlap_with_undef_path_pred ( bool swap_cond = false; bool invert = false; VEC(use_pred_info_t, heap) *the_pred_chain; - sbitmap_iterator sbi; + struct pointer_set_t *visited_flag_phis = NULL; + bool all_pruned = false; gcc_assert (num_preds > 0); /* Find within the common prefix of multiple predicate chains @@ -879,51 +1034,17 @@ use_pred_not_overlap_with_undef_path_pred ( if (cmp_code == ERROR_MARK) return false; - EXECUTE_IF_SET_IN_SBITMAP (uninit_opnds, 0, i, sbi) - { - tree flag_arg; - - flag_arg = gimple_phi_arg_def (flag_def, i); - if (!is_gimple_constant (flag_arg)) - return false; - - /* Now check if the constant is in the guarded range. */ - if (is_value_included_in (flag_arg, boundary_cst, cmp_code)) - { - tree opnd; - gimple opnd_def; - - /* Now that we know that this undefined edge is not - pruned. If the operand is defined by another phi, - we can further prune the incoming edges of that - phi by checking the predicates of this operands. */ - - opnd = gimple_phi_arg_def (phi, i); - opnd_def = SSA_NAME_DEF_STMT (opnd); - if (gimple_code (opnd_def) == GIMPLE_PHI) - { - edge opnd_edge; - sbitmap uninit_opnds2 - = compute_uninit_opnds_pos (opnd_def); - gcc_assert (!sbitmap_empty_p (uninit_opnds2)); - opnd_edge = gimple_phi_arg_edge (phi, i); - if (!is_use_properly_guarded (phi, - opnd_edge->src, - opnd_def, - uninit_opnds2, - visited_phis)) - { - sbitmap_free (uninit_opnds2); - return false; - } - sbitmap_free (uninit_opnds2); - } - else - return false; - } - } - - return true; + all_pruned = prune_uninit_phi_opnds_in_unrealizable_paths (phi, + uninit_opnds, + flag_def, + boundary_cst, + cmp_code, + visited_phis, + &visited_flag_phis); + + if (visited_flag_phis) + pointer_set_destroy (visited_flag_phis); + return all_pruned; } /* Returns true if TC is AND or OR */ @@ -1639,7 +1760,7 @@ warn_uninitialized_phi (gimple phi, VEC(gimple, heap) **worklist, } uninit_op = gimple_phi_arg_def (phi, sbitmap_first_set_bit (uninit_opnds)); - warn_uninit (uninit_op, + warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, "%qD may be used uninitialized in this function", uninit_use_stmt); @@ -1701,7 +1822,7 @@ execute_late_warn_uninitialized (void) cur_phi = VEC_pop (gimple, worklist); warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist); } - + VEC_free (gimple, heap, worklist); pointer_set_destroy (added_to_worklist); pointer_set_destroy (possibly_undefined_names); |