sensible default. */
max_size = SRA_MAX_STRUCTURE_SIZE
? SRA_MAX_STRUCTURE_SIZE
- : MOVE_RATIO * UNITS_PER_WORD;
+ : MOVE_RATIO (optimize_function_for_speed_p (cfun)) * UNITS_PER_WORD;
max_count = SRA_MAX_STRUCTURE_COUNT
? SRA_MAX_STRUCTURE_COUNT
- : MOVE_RATIO;
+ : MOVE_RATIO (optimize_function_for_speed_p (cfun));
full_size = tree_low_cst (size_tree, 1);
full_count = count_type_elements (elt->type, false);
sra_build_assignment (tree dst, tree src)
{
gimple stmt;
- gimple_seq seq = NULL;
+ gimple_seq seq = NULL, seq2 = NULL;
/* Turning BIT_FIELD_REFs into bit operations enables other passes
to do a much better job at optimizing the code.
From dst = BIT_FIELD_REF <var, sz, off> we produce
if (scalar_bitfield_p (src))
{
tree var, shift, width;
- tree utype, stype, stmp, utmp, dtmp;
+ tree utype, stype;
bool unsignedp = (INTEGRAL_TYPE_P (TREE_TYPE (src))
? TYPE_UNSIGNED (TREE_TYPE (src)) : true);
+ struct gimplify_ctx gctx;
var = TREE_OPERAND (src, 0);
width = TREE_OPERAND (src, 1);
else if (!TYPE_UNSIGNED (utype))
utype = unsigned_type_for (utype);
- stmp = make_rename_temp (stype, "SR");
-
/* Convert the base var of the BIT_FIELD_REF to the scalar type
we use for computation if we cannot use it directly. */
- if (!useless_type_conversion_p (stype, TREE_TYPE (var)))
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- stmt = gimple_build_assign (stmp, fold_convert (stype, var));
- else
- stmt = gimple_build_assign (stmp, fold_build1 (VIEW_CONVERT_EXPR,
- stype, var));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
- }
+ if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
+ var = fold_convert (stype, var);
+ else
+ var = fold_build1 (VIEW_CONVERT_EXPR, stype, var);
if (!integer_zerop (shift))
- {
- stmt = gimple_build_assign (stmp, fold_build2 (RSHIFT_EXPR, stype,
- var, shift));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
- }
+ var = fold_build2 (RSHIFT_EXPR, stype, var, shift);
/* If we need a masking operation, produce one. */
if (TREE_INT_CST_LOW (width) == TYPE_PRECISION (stype))
tree one = build_int_cst_wide (stype, 1, 0);
tree mask = int_const_binop (LSHIFT_EXPR, one, width, 0);
mask = int_const_binop (MINUS_EXPR, mask, one, 0);
-
- stmt = gimple_build_assign (stmp, fold_build2 (BIT_AND_EXPR, stype,
- var, mask));
- gimple_seq_add_stmt (&seq, stmt);
- var = stmp;
+ var = fold_build2 (BIT_AND_EXPR, stype, var, mask);
}
/* After shifting and masking, convert to the target type. */
- utmp = stmp;
- if (!useless_type_conversion_p (utype, stype))
- {
- utmp = make_rename_temp (utype, "SR");
-
- stmt = gimple_build_assign (utmp, fold_convert (utype, var));
- gimple_seq_add_stmt (&seq, stmt);
-
- var = utmp;
- }
+ var = fold_convert (utype, var);
/* Perform sign extension, if required.
??? This should never be necessary. */
size_binop (MINUS_EXPR, width,
bitsize_int (1)), 0);
- stmt = gimple_build_assign (utmp, fold_build2 (BIT_XOR_EXPR, utype,
- var, signbit));
- gimple_seq_add_stmt (&seq, stmt);
-
- stmt = gimple_build_assign (utmp, fold_build2 (MINUS_EXPR, utype,
- utmp, signbit));
- gimple_seq_add_stmt (&seq, stmt);
-
- var = utmp;
+ var = fold_build2 (BIT_XOR_EXPR, utype, var, signbit);
+ var = fold_build2 (MINUS_EXPR, utype, var, signbit);
}
/* fold_build3 (BIT_FIELD_REF, ...) sometimes returns a cast. */
STRIP_NOPS (dst);
/* Finally, move and convert to the destination. */
- if (!useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (var)))
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
- var = fold_convert (TREE_TYPE (dst), var);
- else
- var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
+ var = fold_convert (TREE_TYPE (dst), var);
+ else
+ var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
- /* If the destination is not a register the conversion needs
- to be a separate statement. */
- if (!is_gimple_reg (dst))
- {
- dtmp = make_rename_temp (TREE_TYPE (dst), "SR");
- stmt = gimple_build_assign (dtmp, var);
- gimple_seq_add_stmt (&seq, stmt);
- var = dtmp;
- }
- }
- stmt = gimple_build_assign (dst, var);
- gimple_seq_add_stmt (&seq, stmt);
+ push_gimplify_context (&gctx);
+ gctx.into_ssa = true;
+ gctx.allow_rhs_cond_expr = true;
+
+ gimplify_assign (dst, var, &seq);
+
+ if (gimple_referenced_vars (cfun))
+ for (var = gctx.temps; var; var = TREE_CHAIN (var))
+ add_referenced_var (var);
+ pop_gimplify_context (NULL);
return seq;
}
&& !useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (src)))
src = fold_convert (TREE_TYPE (dst), src);
+ /* ??? Only call the gimplifier if we need to. Otherwise we may
+ end up substituting with DECL_VALUE_EXPR - see PR37380. */
+ if (!handled_component_p (src)
+ && !SSA_VAR_P (src))
+ {
+ src = force_gimple_operand (src, &seq2, false, NULL_TREE);
+ gimple_seq_add_seq (&seq, seq2);
+ }
stmt = gimple_build_assign (dst, src);
gimple_seq_add_stmt (&seq, stmt);
return seq;
tmp = var;
if (!is_gimple_variable (tmp))
tmp = unshare_expr (var);
+ else
+ TREE_NO_WARNING (var) = true;
tmp2 = make_rename_temp (utype, "SR");
if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- stmt = gimple_build_assign (tmp2, fold_convert (utype, tmp));
+ tmp = fold_convert (utype, tmp);
else
- stmt = gimple_build_assign (tmp2, fold_build1 (VIEW_CONVERT_EXPR,
- utype, tmp));
+ tmp = fold_build1 (VIEW_CONVERT_EXPR, utype, tmp);
+
+ stmt = gimple_build_assign (tmp2, tmp);
gimple_seq_add_stmt (&seq, stmt);
}
else
t = build2 (COMPLEX_EXPR, elt->type, r, i);
tmp_seq = sra_build_bf_assignment (expr, t);
- gcc_assert (gimple_seq_singleton_p (tmp_seq));
- SSA_NAME_DEF_STMT (expr) = gimple_seq_first_stmt (tmp_seq);
+ SSA_NAME_DEF_STMT (expr) = gimple_seq_last_stmt (tmp_seq);
gimple_seq_add_seq (seq_p, tmp_seq);
}
else if (elt->replacement)
}
else if (TREE_CODE (fld->element) == INTEGER_CST)
{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (fld->parent->element));
flen = fold_convert (bitsizetype, TYPE_SIZE (fld->type));
fpos = fold_convert (bitsizetype, fld->element);
+ if (domain_type && TYPE_MIN_VALUE (domain_type))
+ fpos = size_binop (MINUS_EXPR, fpos,
+ fold_convert (bitsizetype,
+ TYPE_MIN_VALUE (domain_type)));
fpos = size_binop (MULT_EXPR, flen, fpos);
}
else
infld = fld->replacement;
- type = TREE_TYPE (infld);
+ type = unsigned_type_for (TREE_TYPE (infld));
if (TYPE_PRECISION (type) != TREE_INT_CST_LOW (flen))
- type = lang_hooks.types.type_for_size (TREE_INT_CST_LOW (flen), 1);
- else
- type = unsigned_type_for (type);
+ type = build_nonstandard_integer_type (TREE_INT_CST_LOW (flen), 1);
if (TREE_CODE (infld) == BIT_FIELD_REF)
{
if (!elt->use_block_copy)
{
tree type = TREE_TYPE (bfexpr);
- tree var, vpos;
+ tree var = make_rename_temp (type, "SR"), tmp, vpos;
+ gimple st = NULL;
- if (!TYPE_UNSIGNED (type))
- type = unsigned_type_for (type);
+ gimple_assign_set_rhs1 (stmt, var);
+ update = true;
- var = make_rename_temp (type, "SR");
+ if (!TYPE_UNSIGNED (type))
+ {
+ type = unsigned_type_for (type);
+ tmp = make_rename_temp (type, "SR");
+ st = gimple_build_assign (var,
+ fold_convert (TREE_TYPE (var), tmp));
+ var = tmp;
+ }
gimple_seq_add_stmt (&seq,
gimple_build_assign
sra_explode_bitfield_assignment
(var, vpos, true, &seq, blen, bpos, elt);
- gimple_assign_set_rhs1 (stmt, var);
- update = true;
+ if (st)
+ gimple_seq_add_stmt (&seq, st);
}
else
sra_sync_for_bitfield_assignment