summaryrefslogtreecommitdiff
path: root/gcc/builtins.cc
diff options
context:
space:
mode:
authorTamar Christina <tamar.christina@arm.com>2022-07-08 07:37:20 +0100
committerTamar Christina <tamar.christina@arm.com>2022-07-08 07:39:33 +0100
commit13f44099bcc64ddb50a6dbd462bf79b258dfd02c (patch)
tree7ea840cf4915eabc7761e0c1bc3989a9c3859bba /gcc/builtins.cc
parentbf3695691f4fc964a3b1c8274a6949d844e3edff (diff)
downloadgcc-13f44099bcc64ddb50a6dbd462bf79b258dfd02c.tar.gz
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/builtins.cc')
-rw-r--r--gcc/builtins.cc8
1 files changed, 4 insertions, 4 deletions
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index e6816d5c865..35b9197945f 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -6029,8 +6029,8 @@ expand_ifn_atomic_compare_exchange_into_call (gcall *call, machine_mode mode)
if (GET_MODE (boolret) != mode)
boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
x = force_reg (mode, x);
- write_complex_part (target, boolret, true);
- write_complex_part (target, x, false);
+ write_complex_part (target, boolret, true, true);
+ write_complex_part (target, x, false, false);
}
}
@@ -6085,8 +6085,8 @@ expand_ifn_atomic_compare_exchange (gcall *call)
rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
if (GET_MODE (boolret) != mode)
boolret = convert_modes (mode, GET_MODE (boolret), boolret, 1);
- write_complex_part (target, boolret, true);
- write_complex_part (target, oldval, false);
+ write_complex_part (target, boolret, true, true);
+ write_complex_part (target, oldval, false, false);
}
}