static bool graphite_can_represent_init (tree e) { switch (TREE_CODE (e)) { case POLYNOMIAL_CHREC: return graphite_can_represent_init (CHREC_LEFT (e)) && graphite_can_represent_init (CHREC_RIGHT (e)); case MULT_EXPR: if (chrec_contains_symbols (TREE_OPERAND (e, 0))) return graphite_can_represent_init (TREE_OPERAND (e, 0)) && tree_fits_shwi_p (TREE_OPERAND (e, 1)); else return graphite_can_represent_init (TREE_OPERAND (e, 1)) && tree_fits_shwi_p (TREE_OPERAND (e, 0)); case PLUS_EXPR: case POINTER_PLUS_EXPR: case MINUS_EXPR: return graphite_can_represent_init (TREE_OPERAND (e, 0)) && graphite_can_represent_init (TREE_OPERAND (e, 1)); case NEGATE_EXPR: case BIT_NOT_EXPR: CASE_CONVERT: case NON_LVALUE_EXPR: return graphite_can_represent_init (TREE_OPERAND (e, 0)); default: break; } return true; }
Uint UI_From_gnu (tree Input) { tree gnu_type = TREE_TYPE (Input), gnu_base, gnu_temp; /* UI_Base is defined so that 5 Uint digits is sufficient to hold the largest possible signed 64-bit value. */ const int Max_For_Dint = 5; int v[Max_For_Dint], i; Vector_Template temp; Int_Vector vec; #if HOST_BITS_PER_WIDE_INT == 64 /* On 64-bit hosts, tree_fits_shwi_p tells whether the input fits in a signed 64-bit integer. Then a truncation tells whether it fits in a signed 32-bit integer. */ if (tree_fits_shwi_p (Input)) { HOST_WIDE_INT hw_input = tree_to_shwi (Input); if (hw_input == (int) hw_input) return UI_From_Int (hw_input); } else return No_Uint; #else /* On 32-bit hosts, tree_fits_shwi_p tells whether the input fits in a signed 32-bit integer. Then a sign test tells whether it fits in a signed 64-bit integer. */ if (tree_fits_shwi_p (Input)) return UI_From_Int (tree_to_shwi (Input)); gcc_assert (TYPE_PRECISION (gnu_type) <= 64); if (TYPE_UNSIGNED (gnu_type) && TYPE_PRECISION (gnu_type) == 64 && wi::neg_p (Input, SIGNED)) return No_Uint; #endif gnu_base = build_int_cst (gnu_type, UI_Base); gnu_temp = Input; for (i = Max_For_Dint - 1; i >= 0; i--) { v[i] = tree_to_shwi (fold_build1 (ABS_EXPR, gnu_type, fold_build2 (TRUNC_MOD_EXPR, gnu_type, gnu_temp, gnu_base))); gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base); } temp.Low_Bound = 1; temp.High_Bound = Max_For_Dint; vec.Bounds = &temp; vec.Array = v; return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0); }
bool compute_builtin_object_size (tree ptr, int object_size_type, unsigned HOST_WIDE_INT *psize) { gcc_assert (object_size_type >= 0 && object_size_type <= 3); /* Set to unknown and overwrite just before returning if the size could be determined. */ *psize = unknown[object_size_type]; if (! offset_limit) init_offset_limit (); if (TREE_CODE (ptr) == ADDR_EXPR) return addr_object_size (NULL, ptr, object_size_type, psize); if (TREE_CODE (ptr) != SSA_NAME || !POINTER_TYPE_P (TREE_TYPE (ptr))) return false; if (computed[object_size_type] == NULL) { if (optimize || object_size_type & 1) return false; /* When not optimizing, rather than failing, make a small effort to determine the object size without the full benefit of the (costly) computation below. */ gimple *def = SSA_NAME_DEF_STMT (ptr); if (gimple_code (def) == GIMPLE_ASSIGN) { tree_code code = gimple_assign_rhs_code (def); if (code == POINTER_PLUS_EXPR) { tree offset = gimple_assign_rhs2 (def); ptr = gimple_assign_rhs1 (def); if (tree_fits_shwi_p (offset) && compute_builtin_object_size (ptr, object_size_type, psize)) { /* Return zero when the offset is out of bounds. */ unsigned HOST_WIDE_INT off = tree_to_shwi (offset); *psize = off < *psize ? *psize - off : 0; return true; } } } return false; } if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr))) { struct object_size_info osi; bitmap_iterator bi; unsigned int i; if (num_ssa_names > object_sizes[object_size_type].length ()) object_sizes[object_size_type].safe_grow (num_ssa_names); if (dump_file) { fprintf (dump_file, "Computing %s %sobject size for ", (object_size_type & 2) ? "minimum" : "maximum", (object_size_type & 1) ? "sub" : ""); print_generic_expr (dump_file, ptr, dump_flags); fprintf (dump_file, ":\n"); } osi.visited = BITMAP_ALLOC (NULL); osi.reexamine = BITMAP_ALLOC (NULL); osi.object_size_type = object_size_type; osi.depths = NULL; osi.stack = NULL; osi.tos = NULL; /* First pass: walk UD chains, compute object sizes that can be computed. osi.reexamine bitmap at the end will contain what variables were found in dependency cycles and therefore need to be reexamined. */ osi.pass = 0; osi.changed = false; collect_object_sizes_for (&osi, ptr); /* Second pass: keep recomputing object sizes of variables that need reexamination, until no object sizes are increased or all object sizes are computed. */ if (! bitmap_empty_p (osi.reexamine)) { bitmap reexamine = BITMAP_ALLOC (NULL); /* If looking for minimum instead of maximum object size, detect cases where a pointer is increased in a loop. Although even without this detection pass 2 would eventually terminate, it could take a long time. If a pointer is increasing this way, we need to assume 0 object size. E.g. p = &buf[0]; while (cond) p = p + 4; */ if (object_size_type & 2) { osi.depths = XCNEWVEC (unsigned int, num_ssa_names); osi.stack = XNEWVEC (unsigned int, num_ssa_names); osi.tos = osi.stack; osi.pass = 1; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) check_for_plus_in_loops (&osi, ssa_name (i)); free (osi.depths); osi.depths = NULL; free (osi.stack); osi.stack = NULL; osi.tos = NULL; } do { osi.pass = 2; osi.changed = false; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) { collect_object_sizes_for (&osi, ssa_name (i)); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Reexamining "); print_generic_expr (dump_file, ssa_name (i), dump_flags); fprintf (dump_file, "\n"); } } } while (osi.changed); BITMAP_FREE (reexamine); }