aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>2020-01-07 21:29:11 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2020-01-07 21:29:11 +0000
commit56eb4c70ea7a78a53fbb6e7597e74e7ba04d4570 (patch)
tree37a396422db852926736ee67a4599304dd79f155
parentcdf77151aa5a75e8967984fe3f457d4a23261cb6 (diff)
downloadgcc-56eb4c70ea7a78a53fbb6e7597e74e7ba04d4570.zip
gcc-56eb4c70ea7a78a53fbb6e7597e74e7ba04d4570.tar.gz
gcc-56eb4c70ea7a78a53fbb6e7597e74e7ba04d4570.tar.bz2
Restore patch reverted on trunk instead of a branch
From-SVN: r279972
-rw-r--r--gcc/config/rs6000/rs6000.c86
-rw-r--r--gcc/ipa-inline-analysis.c2
-rw-r--r--gcc/ipa-inline.c4
3 files changed, 89 insertions, 3 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 127927d..c212257 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -6753,6 +6753,90 @@ hard_reg_and_mode_to_addr_mask (rtx reg, machine_mode mode)
return addr_mask;
}
+/* Helper function to adjust a vector address (ADDR) to point to a given
+ element offset (ELEMENT_OFFSET). This function handles updating addresses
+ that use PLUS (i.e. a D_FORM address with an integer constant or an X_FORM
+ address adding two registers). If we can't update the address directly, we
+ can use the base register temporary (BASE_TMP) to form a valid address. The
+ mode of the element within the vector is SCALAR_MODE. */
+
+rtx
+adjust_vec_address_plus (rtx addr,
+ rtx element_offset,
+ rtx base_tmp,
+ machine_mode scalar_mode)
+{
+ gcc_assert (GET_CODE (addr) == PLUS);
+
+ rtx new_addr = NULL;
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+ rtx insn;
+
+ gcc_assert (REG_P (op0) || SUBREG_P (op0));
+
+ if (CONST_INT_P (op1) && CONST_INT_P (element_offset))
+ {
+ HOST_WIDE_INT offset = INTVAL (op1) + INTVAL (element_offset);
+ rtx offset_rtx = GEN_INT (offset);
+ new_addr = gen_rtx_PLUS (Pmode, op0, offset_rtx);
+
+ enum insn_form iform = address_to_insn_form (new_addr, scalar_mode,
+ NON_PREFIXED_DEFAULT);
+
+ /* If the address isn't valid, change REG+OFFSET into REG+REG. */
+ if (iform == INSN_FORM_BAD)
+ {
+ /* The offset either overflowed or it might not be a valid DS/DQ
+ offset, move offset to the temporary (which will likely be split),
+ and do X-FORM addressing. */
+ emit_move_insn (base_tmp, offset_rtx);
+ new_addr = gen_rtx_PLUS (Pmode, op0, base_tmp);
+ }
+ }
+
+ else
+ {
+ bool op1_reg_p = (REG_P (op1) || SUBREG_P (op1));
+ bool ele_reg_p = (REG_P (element_offset) || SUBREG_P (element_offset));
+
+ /* Note, ADDI requires the register being added to be a base
+ register. If the register was R0, load it up into the temporary
+ and do the add. */
+ if (op1_reg_p
+ && (ele_reg_p || reg_or_subregno (op1) != FIRST_GPR_REGNO))
+ {
+ insn = gen_add3_insn (base_tmp, op1, element_offset);
+ gcc_assert (insn != NULL_RTX);
+ emit_insn (insn);
+ }
+
+ else if (ele_reg_p
+ && reg_or_subregno (element_offset) != FIRST_GPR_REGNO)
+ {
+ insn = gen_add3_insn (base_tmp, element_offset, op1);
+ gcc_assert (insn != NULL_RTX);
+ emit_insn (insn);
+ }
+
+ /* Make sure we don't overwrite the temporary if the element being
+ extracted is variable, and we've put the offset into base_tmp
+ previously. */
+ else if (reg_mentioned_p (base_tmp, element_offset))
+ emit_insn (gen_add2_insn (base_tmp, op1));
+
+ else
+ {
+ emit_move_insn (base_tmp, op1);
+ emit_insn (gen_add2_insn (base_tmp, element_offset));
+ }
+
+ new_addr = gen_rtx_PLUS (Pmode, op0, base_tmp);
+ }
+
+ return new_addr;
+}
+
/* Adjust a memory address (MEM) of a vector type to point to a scalar field
within the vector (ELEMENT) with a mode (SCALAR_MODE). Use a base register
temporary (BASE_TMP) to fixup the address. Return the new memory address
@@ -6898,6 +6982,8 @@ rs6000_adjust_vec_address (rtx scalar_reg,
valid_addr_p = (addr_mask & RELOAD_REG_OFFSET) != 0;
}
+ /* An address that is a single register is always valid for either indexed or
+ offsettable loads. */
else if (REG_P (new_addr) || SUBREG_P (new_addr))
valid_addr_p = true;
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index eb42cae..8b400ff 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -462,7 +462,7 @@ offline_size (struct cgraph_node *node, ipa_size_summary *info)
return 0;
}
-/* Estimate the growth caused by inlining NODE into all callees. */
+/* Estimate the growth caused by inlining NODE into all callers. */
int
estimate_growth (struct cgraph_node *node)
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 3b68fc4..302badf 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -184,8 +184,8 @@ caller_growth_limits (struct cgraph_edge *e)
the function to shrink if it went over the limits by forced inlining. */
newsize = estimate_size_after_inlining (to, e);
if (newsize >= ipa_size_summaries->get (what)->size
- && newsize > opt_for_fn (to->decl, param_large_function_insns)
- && newsize > limit)
+ && (newsize > opt_for_fn (to->decl, param_large_function_insns)
+ || newsize > limit))
{
e->inline_failed = CIF_LARGE_FUNCTION_GROWTH_LIMIT;
return false;