diff options
Diffstat (limited to 'gcc/config/alpha/alpha.c')
-rw-r--r-- | gcc/config/alpha/alpha.c | 196 |
1 files changed, 119 insertions, 77 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index cad90e1adce..a4d3bf1f150 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -5803,38 +5803,34 @@ alpha_build_builtin_va_list (void) /* Helper function for alpha_stdarg_optimize_hook. Skip over casts and constant additions. */ -static tree +static gimple va_list_skip_additions (tree lhs) { - tree rhs, stmt; - - if (TREE_CODE (lhs) != SSA_NAME) - return lhs; + gimple stmt; for (;;) { + enum tree_code code; + stmt = SSA_NAME_DEF_STMT (lhs); - if (TREE_CODE (stmt) == PHI_NODE) + if (gimple_code (stmt) == GIMPLE_PHI) return stmt; - if (TREE_CODE (stmt) != MODIFY_EXPR - || TREE_OPERAND (stmt, 0) != lhs) - return lhs; - - rhs = TREE_OPERAND (stmt, 1); - if (TREE_CODE (rhs) == WITH_SIZE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + if (!is_gimple_assign (stmt) + || gimple_assign_lhs (stmt) != lhs) + return NULL; - if (((!CONVERT_EXPR_P (rhs)) - && ((TREE_CODE (rhs) != PLUS_EXPR - && TREE_CODE (rhs) != POINTER_PLUS_EXPR) - || TREE_CODE (TREE_OPERAND (rhs, 1)) != INTEGER_CST - || !host_integerp (TREE_OPERAND (rhs, 1), 1))) - || TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME) - return rhs; + if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME) + return stmt; + code = gimple_assign_rhs_code (stmt); + if (!CONVERT_EXPR_CODE_P (code) + && ((code != PLUS_EXPR && code != POINTER_PLUS_EXPR) + || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST + || !host_integerp (gimple_assign_rhs2 (stmt), 1))) + return stmt; - lhs = TREE_OPERAND (rhs, 0); + lhs = gimple_assign_rhs1 (stmt); } } @@ -5859,36 +5855,49 @@ va_list_skip_additions (tree lhs) static bool alpha_stdarg_optimize_hook (struct stdarg_info *si, const_gimple stmt) { - tree base, offset, arg1, arg2; + tree base, offset, rhs; int offset_arg = 1; + gimple base_stmt; -#if 1 - /* FIXME tuples. */ - (void) si; - (void) stmt; - return false; -#else + if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) + != GIMPLE_SINGLE_RHS) + return false; + + rhs = gimple_assign_rhs1 (stmt); while (handled_component_p (rhs)) rhs = TREE_OPERAND (rhs, 0); if (TREE_CODE (rhs) != INDIRECT_REF || TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME) return false; - lhs = va_list_skip_additions (TREE_OPERAND (rhs, 0)); - if (lhs == NULL_TREE - || TREE_CODE (lhs) != POINTER_PLUS_EXPR) + stmt = va_list_skip_additions (TREE_OPERAND (rhs, 0)); + if (stmt == NULL + || !is_gimple_assign (stmt) + || gimple_assign_rhs_code (stmt) != POINTER_PLUS_EXPR) return false; - base = TREE_OPERAND (lhs, 0); + base = gimple_assign_rhs1 (stmt); if (TREE_CODE (base) == SSA_NAME) - base = va_list_skip_additions (base); + { + base_stmt = va_list_skip_additions (base); + if (base_stmt + && is_gimple_assign (base_stmt) + && gimple_assign_rhs_code (base_stmt) == COMPONENT_REF) + base = gimple_assign_rhs1 (base_stmt); + } if (TREE_CODE (base) != COMPONENT_REF || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node)) { - base = TREE_OPERAND (lhs, 0); + base = gimple_assign_rhs2 (stmt); if (TREE_CODE (base) == SSA_NAME) - base = va_list_skip_additions (base); + { + base_stmt = va_list_skip_additions (base); + if (base_stmt + && is_gimple_assign (base_stmt) + && gimple_assign_rhs_code (base_stmt) == COMPONENT_REF) + base = gimple_assign_rhs1 (base_stmt); + } if (TREE_CODE (base) != COMPONENT_REF || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node)) @@ -5902,55 +5911,88 @@ alpha_stdarg_optimize_hook (struct stdarg_info *si, const_gimple stmt) || !bitmap_bit_p (si->va_list_vars, DECL_UID (base))) return false; - offset = TREE_OPERAND (lhs, offset_arg); + offset = gimple_op (stmt, 1 + offset_arg); if (TREE_CODE (offset) == SSA_NAME) - offset = va_list_skip_additions (offset); - - if (TREE_CODE (offset) == PHI_NODE) { - HOST_WIDE_INT sub; - - if (PHI_NUM_ARGS (offset) != 2) - goto escapes; + gimple offset_stmt = va_list_skip_additions (offset); - arg1 = va_list_skip_additions (PHI_ARG_DEF (offset, 0)); - arg2 = va_list_skip_additions (PHI_ARG_DEF (offset, 1)); - if (TREE_CODE (arg2) != MINUS_EXPR && TREE_CODE (arg2) != PLUS_EXPR) + if (offset_stmt + && gimple_code (offset_stmt) == GIMPLE_PHI) { - tree tem = arg1; - arg1 = arg2; - arg2 = tem; + HOST_WIDE_INT sub; + gimple arg1_stmt, arg2_stmt; + tree arg1, arg2; + enum tree_code code1, code2; - if (TREE_CODE (arg2) != MINUS_EXPR && TREE_CODE (arg2) != PLUS_EXPR) + if (gimple_phi_num_args (offset_stmt) != 2) goto escapes; - } - if (!host_integerp (TREE_OPERAND (arg2, 1), 0)) - goto escapes; - sub = tree_low_cst (TREE_OPERAND (arg2, 1), 0); - if (TREE_CODE (arg2) == MINUS_EXPR) - sub = -sub; - if (sub < -48 || sub > -32) - goto escapes; + arg1_stmt + = va_list_skip_additions (gimple_phi_arg_def (offset_stmt, 0)); + arg2_stmt + = va_list_skip_additions (gimple_phi_arg_def (offset_stmt, 1)); + if (arg1_stmt == NULL + || !is_gimple_assign (arg1_stmt) + || arg2_stmt == NULL + || !is_gimple_assign (arg2_stmt)) + goto escapes; - arg2 = va_list_skip_additions (TREE_OPERAND (arg2, 0)); - if (arg1 != arg2) - goto escapes; + code1 = gimple_assign_rhs_code (arg1_stmt); + code2 = gimple_assign_rhs_code (arg2_stmt); + if (code1 == COMPONENT_REF + && (code2 == MINUS_EXPR || code2 == PLUS_EXPR)) + /* Do nothing. */; + else if (code2 == COMPONENT_REF + && (code1 == MINUS_EXPR || code1 == PLUS_EXPR)) + { + gimple tem = arg1_stmt; + code2 = code1; + arg1_stmt = arg2_stmt; + arg2_stmt = tem; + } + else + goto escapes; - if (TREE_CODE (arg1) == SSA_NAME) - arg1 = va_list_skip_additions (arg1); + if (!host_integerp (gimple_assign_rhs2 (arg2_stmt), 0)) + goto escapes; - if (TREE_CODE (arg1) != COMPONENT_REF - || TREE_OPERAND (arg1, 1) != va_list_gpr_counter_field - || get_base_address (arg1) != base) - goto escapes; + sub = tree_low_cst (gimple_assign_rhs2 (arg2_stmt), 0); + if (code2 == MINUS_EXPR) + sub = -sub; + if (sub < -48 || sub > -32) + goto escapes; - /* Need floating point regs. */ - cfun->va_list_fpr_size |= 2; + arg1 = gimple_assign_rhs1 (arg1_stmt); + arg2 = gimple_assign_rhs1 (arg2_stmt); + if (TREE_CODE (arg2) == SSA_NAME) + { + arg2_stmt = va_list_skip_additions (arg2); + if (arg2_stmt == NULL + || !is_gimple_assign (arg2_stmt) + || gimple_assign_rhs_code (arg2_stmt) != COMPONENT_REF) + goto escapes; + arg2 = gimple_assign_rhs1 (arg2_stmt); + } + if (arg1 != arg2) + goto escapes; + + if (TREE_CODE (arg1) != COMPONENT_REF + || TREE_OPERAND (arg1, 1) != va_list_gpr_counter_field + || get_base_address (arg1) != base) + goto escapes; + + /* Need floating point regs. */ + cfun->va_list_fpr_size |= 2; + return false; + } + if (offset_stmt + && is_gimple_assign (offset_stmt) + && gimple_assign_rhs_code (offset_stmt) == COMPONENT_REF) + offset = gimple_assign_rhs1 (offset_stmt); } - else if (TREE_CODE (offset) != COMPONENT_REF - || TREE_OPERAND (offset, 1) != va_list_gpr_counter_field - || get_base_address (offset) != base) + if (TREE_CODE (offset) != COMPONENT_REF + || TREE_OPERAND (offset, 1) != va_list_gpr_counter_field + || get_base_address (offset) != base) goto escapes; else /* Need general regs. */ @@ -5960,7 +6002,6 @@ alpha_stdarg_optimize_hook (struct stdarg_info *si, const_gimple stmt) escapes: si->va_list_escapes = true; return false; -#endif } #endif @@ -6126,10 +6167,11 @@ alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) } static tree -alpha_gimplify_va_arg_1 (tree type, tree base, gimple_seq offset, +alpha_gimplify_va_arg_1 (tree type, tree base, tree offset, gimple_seq *pre_p) { - tree type_size, ptr_type, addend, t, addr, internal_post; + tree type_size, ptr_type, addend, t, addr; + gimple_seq internal_post; /* If the type could not be passed in registers, skip the block reserved for the registers. */ @@ -6177,7 +6219,7 @@ alpha_gimplify_va_arg_1 (tree type, tree base, gimple_seq offset, fold_convert (sizetype, addend)); internal_post = NULL; gimplify_expr (&addr, pre_p, &internal_post, is_gimple_val, fb_rvalue); - append_to_statement_list (internal_post, pre_p); + gimple_seq_add_seq (pre_p, internal_post); /* Update the offset field. */ type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); @@ -6230,7 +6272,7 @@ alpha_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, r = alpha_gimplify_va_arg_1 (type, base, offset, pre_p); /* Stuff the offset temporary back into its field. */ - gimplify_assign (offset_field, + gimplify_assign (unshare_expr (offset_field), fold_convert (TREE_TYPE (offset_field), offset), pre_p); if (indirect) |