diff options
author | Richard Biener <rguenther@suse.de> | 2023-04-28 08:40:07 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2023-04-28 13:35:22 +0200 |
commit | a94dcac59ee4c99b523ae593cb1c0ad43d4a110b (patch) | |
tree | d91a1169d3d009e4b782b4bef5e2850a734a10a6 | |
parent | cacf65d74463600815773255e8b82b4043432bd7 (diff) | |
download | gcc-a94dcac59ee4c99b523ae593cb1c0ad43d4a110b.zip gcc-a94dcac59ee4c99b523ae593cb1c0ad43d4a110b.tar.gz gcc-a94dcac59ee4c99b523ae593cb1c0ad43d4a110b.tar.bz2 |
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.
-rw-r--r-- | gcc/ipa-param-manipulation.cc | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr109652.c | 40 |
2 files changed, 45 insertions, 2 deletions
diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc index 33dcab9..a286af7 100644 --- a/gcc/ipa-param-manipulation.cc +++ b/gcc/ipa-param-manipulation.cc @@ -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); diff --git a/gcc/testsuite/gcc.dg/torture/pr109652.c b/gcc/testsuite/gcc.dg/torture/pr109652.c new file mode 100644 index 0000000..8a6524d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr109652.c @@ -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; +} |