diff options
author | Tamar Christina <tamar.christina@arm.com> | 2022-07-08 07:37:20 +0100 |
---|---|---|
committer | Tamar Christina <tamar.christina@arm.com> | 2022-07-08 07:39:33 +0100 |
commit | 13f44099bcc64ddb50a6dbd462bf79b258dfd02c (patch) | |
tree | 7ea840cf4915eabc7761e0c1bc3989a9c3859bba /gcc/expmed.cc | |
parent | bf3695691f4fc964a3b1c8274a6949d844e3edff (diff) | |
download | gcc-13f44099bcc64ddb50a6dbd462bf79b258dfd02c.zip gcc-13f44099bcc64ddb50a6dbd462bf79b258dfd02c.tar.gz gcc-13f44099bcc64ddb50a6dbd462bf79b258dfd02c.tar.bz2 |
middle-end: Use subregs to expand COMPLEX_EXPR to set the lowpart.
When lowering COMPLEX_EXPR we currently emit two VEC_EXTRACTs. One for the
lowpart and one for the highpart.
The problem with this is that in RTL the lvalue of the RTX is the only thing
tying the two instructions together.
This means that e.g. combine is unable to try to combine the two instructions
for setting the lowpart and highpart.
For ISAs that have bit extract instructions we can eliminate one of the extracts
if, and only if we're setting the entire complex number.
This change changes the expand code when we're setting the entire complex number
to generate a subreg for the lowpart instead of a vec_extract.
This allows us to optimize sequences such as:
_Complex int f(int a, int b) {
_Complex int t = a + b * 1i;
return t;
}
from:
f:
bfi x2, x0, 0, 32
bfi x2, x1, 32, 32
mov x0, x2
ret
into:
f:
bfi x0, x1, 32, 32
ret
I have also confirmed the codegen for x86_64 did not change.
gcc/ChangeLog:
* expmed.cc (store_bit_field_1): Add parameter that indicates if value is
still undefined and if so emit a subreg move instead.
(store_integral_bit_field): Likewise.
(store_bit_field): Likewise.
* expr.h (write_complex_part): Likewise.
* expmed.h (store_bit_field): Add new parameter.
* builtins.cc (expand_ifn_atomic_compare_exchange_into_call): Use new
parameter.
(expand_ifn_atomic_compare_exchange): Likewise.
* calls.cc (store_unaligned_arguments_into_pseudos): Likewise.
* emit-rtl.cc (validate_subreg): Likewise.
* expr.cc (emit_group_store): Likewise.
(copy_blkmode_from_reg): Likewise.
(copy_blkmode_to_reg): Likewise.
(clear_storage_hints): Likewise.
(write_complex_part): Likewise.
(emit_move_complex_parts): Likewise.
(expand_assignment): Likewise.
(store_expr): Likewise.
(store_field): Likewise.
(expand_expr_real_2): Likewise.
* ifcvt.cc (noce_emit_move_insn): Likewise.
* internal-fn.cc (expand_arith_set_overflow): Likewise.
(expand_arith_overflow_result_store): Likewise.
(expand_addsub_overflow): Likewise.
(expand_neg_overflow): Likewise.
(expand_mul_overflow): Likewise.
(expand_arith_overflow): Likewise.
gcc/testsuite/ChangeLog:
* g++.target/aarch64/complex-init.C: New test.
Diffstat (limited to 'gcc/expmed.cc')
-rw-r--r-- | gcc/expmed.cc | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/gcc/expmed.cc b/gcc/expmed.cc index c3e4aa8..9b01b5a 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -738,13 +738,16 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0, If FALLBACK_P is true, fall back to store_fixed_bit_field if we have no other way of implementing the operation. If FALLBACK_P is false, - return false instead. */ + return false instead. + + if UNDEFINED_P is true then STR_RTX is undefined and may be set using + a subreg instead. */ static bool store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, poly_uint64 bitregion_start, poly_uint64 bitregion_end, machine_mode fieldmode, - rtx value, bool reverse, bool fallback_p) + rtx value, bool reverse, bool fallback_p, bool undefined_p) { rtx op0 = str_rtx; @@ -805,8 +808,9 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, return true; } } - else if (constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, ®num) - && multiple_p (bitsize, regsize * BITS_PER_UNIT) + else if (((constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, ®num) + && multiple_p (bitsize, regsize * BITS_PER_UNIT)) + || undefined_p) && known_ge (GET_MODE_BITSIZE (GET_MODE (op0)), bitsize)) { sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), @@ -869,7 +873,7 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, GET_MODE_SIZE (GET_MODE (op0))); emit_move_insn (temp, op0); store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value, - reverse, fallback_p); + reverse, fallback_p, undefined_p); emit_move_insn (op0, temp); return true; } @@ -994,7 +998,7 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, bitnum + bit_offset, bitregion_start, bitregion_end, word_mode, - value_word, reverse, fallback_p)) + value_word, reverse, fallback_p, false)) { delete_insns_since (last); return false; @@ -1084,7 +1088,7 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, rtx tempreg = copy_to_reg (xop0); if (store_bit_field_1 (tempreg, bitsize, bitpos, bitregion_start, bitregion_end, - fieldmode, orig_value, reverse, false)) + fieldmode, orig_value, reverse, false, false)) { emit_move_insn (xop0, tempreg); return true; @@ -1112,13 +1116,15 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, FIELDMODE is the machine-mode of the FIELD_DECL node for this field. - If REVERSE is true, the store is to be done in reverse order. */ + If REVERSE is true, the store is to be done in reverse order. + + If UNDEFINED_P is true then STR_RTX is currently undefined. */ void store_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, poly_uint64 bitregion_start, poly_uint64 bitregion_end, machine_mode fieldmode, - rtx value, bool reverse) + rtx value, bool reverse, bool undefined_p) { /* Handle -fstrict-volatile-bitfields in the cases where it applies. */ unsigned HOST_WIDE_INT ibitsize = 0, ibitnum = 0; @@ -1151,7 +1157,7 @@ store_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, gcc_assert (ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode)); temp = copy_to_reg (str_rtx); if (!store_bit_field_1 (temp, ibitsize, ibitnum, 0, 0, - int_mode, value, reverse, true)) + int_mode, value, reverse, true, undefined_p)) gcc_unreachable (); emit_move_insn (str_rtx, temp); @@ -1186,7 +1192,7 @@ store_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, if (!store_bit_field_1 (str_rtx, bitsize, bitnum, bitregion_start, bitregion_end, - fieldmode, value, reverse, true)) + fieldmode, value, reverse, true, undefined_p)) gcc_unreachable (); } |