ipa/109652 - ICE in modification phase of IPA SRA

There's another questionable IL transform by IPA SRA, replacing
foo (p_1(D)->x) with foo (VIEW_CONVERT <union type> (ISRA.PARM.1))
where ISRA.PARM.1 is a register.  Conversion of a register to
an aggregate type is questionable but not entirely unreasonable
and not within the set of IL I am rejecting when fixing PR109644.

The following lets this slip through in IPA SRA transform by
restricting re-gimplification to the case of register type
results.  To not break the previous testcase again we need to
optimize the BIT_FIELD_REF <VIEW_CONVERT <...>, ...> case
to elide the conversion.

	PR ipa/109652
	* ipa-param-manipulation.cc
	(ipa_param_body_adjustments::modify_expression): Allow
	conversion of a register to a non-register type.  Elide
	conversions inside BIT_FIELD_REFs.

	* gcc.dg/torture/pr109652.c: New testcase.
This commit is contained in:
Richard Biener 2023-04-28 08:40:07 +02:00
parent cacf65d744
commit a94dcac59e
2 changed files with 45 additions and 2 deletions

View file

@ -1836,9 +1836,11 @@ ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert,
|| TREE_CODE (expr) == IMAGPART_EXPR
|| TREE_CODE (expr) == REALPART_EXPR)
{
/* For a BIT_FIELD_REF do not bother to VIEW_CONVERT the base,
instead reference the replacement directly. */
convert = TREE_CODE (expr) != BIT_FIELD_REF;
expr_p = &TREE_OPERAND (expr, 0);
expr = *expr_p;
convert = true;
}
ipa_param_body_replacement *pbr = get_expr_replacement (expr, false);
@ -1861,7 +1863,8 @@ ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert,
gcc_checking_assert (tree_to_shwi (TYPE_SIZE (TREE_TYPE (expr)))
== tree_to_shwi (TYPE_SIZE (TREE_TYPE (repl))));
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), repl);
if (is_gimple_reg (repl))
if (is_gimple_reg (repl)
&& is_gimple_reg_type (TREE_TYPE (expr)))
{
gcc_assert (extra_stmts);
vce = force_gimple_operand (vce, extra_stmts, true, NULL_TREE);

View file

@ -0,0 +1,40 @@
/* { dg-do compile } */
typedef int UInt;
UInt skeletal_RI5_instr;
__attribute__((__noreturn__)) void vex_assert_fail();
typedef struct {
union {
struct {
UInt imm5;
} I5;
} ARMri5;
} ARMRI5;
typedef enum { ARMin_Alu, ARMin_Shift } ARMInstrTag;
void iregEnc();
static UInt skeletal_RI5(ARMRI5 *ri) {
UInt imm5 = ri->ARMri5.I5.imm5;
__builtin_expect(imm5, 1) ?: vex_assert_fail();
iregEnc(ri->ARMri5);
return skeletal_RI5_instr;
}
ARMInstrTag emit_ARMInstr_i_0;
void *emit_ARMInstr_disp_cp_chain_me_to_slowEP() {
switch (emit_ARMInstr_i_0) {
case ARMin_Alu:
UInt instr, subopc;
UInt rD, rN;
goto bad;
instr |= subopc | rN;
case ARMin_Shift:
rD = 0;
UInt rM = 0;
ARMRI5 argR;
instr = skeletal_RI5(&argR);
instr |= rD | rM;
goto done;
}
bad:
done:
return 0;
}