@@ -4605,6 +4605,12 @@ to return a nonzero value when it is required, the compiler will run out
of spill registers and print a fatal error message.
@end deftypefn
+@deftypefn {Target Hook} rtx TARGET_GEN_RTX_COMPLEX (machine_mode @var{mode}, rtx @var{real_part}, rtx @var{imag_part})
+This hook should return an rtx representing a complex of mode @var{machine_mode} built from @var{real_part} and @var{imag_part}.
+ If both arguments are @code{NULL}, create them as registers.
+ The default is @code{gen_rtx_CONCAT}.
+@end deftypefn
+
@deftypefn {Target Hook} rtx TARGET_READ_COMPLEX_PART (rtx @var{cplx}, complex_part_t @var{part})
This hook should return the rtx representing the specified @var{part} of the complex given by @var{cplx}.
@var{part} can be the real part, the imaginary part, or both of them.
@@ -3390,6 +3390,8 @@ stack.
@hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
+@hook TARGET_GEN_RTX_COMPLEX
+
@hook TARGET_READ_COMPLEX_PART
@hook TARGET_WRITE_COMPLEX_PART
@@ -1190,19 +1190,7 @@ gen_reg_rtx (machine_mode mode)
if (generating_concat_p
&& (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
|| GET_MODE_CLASS (mode) == MODE_COMPLEX_INT))
- {
- /* For complex modes, don't make a single pseudo.
- Instead, make a CONCAT of two pseudos.
- This allows noncontiguous allocation of the real and imaginary parts,
- which makes much better code. Besides, allocating DCmode
- pseudos overstrains reload on some machines like the 386. */
- rtx realpart, imagpart;
- machine_mode partmode = GET_MODE_INNER (mode);
-
- realpart = gen_reg_rtx (partmode);
- imagpart = gen_reg_rtx (partmode);
- return gen_rtx_CONCAT (mode, realpart, imagpart);
- }
+ return targetm.gen_rtx_complex (mode, NULL, NULL);
/* Do not call gen_reg_rtx with uninitialized crtl. */
gcc_assert (crtl->emit.regno_pointer_align_length);
@@ -6274,14 +6262,18 @@ init_emit_once (void)
FOR_EACH_MODE_IN_CLASS (mode, MODE_COMPLEX_INT)
{
- rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
- const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
+ machine_mode imode = GET_MODE_INNER (mode);
+ rtx inner = const_tiny_rtx[0][(int) imode];
+ const_tiny_rtx[0][(int) mode] =
+ targetm.gen_rtx_complex (mode, inner, inner);
}
FOR_EACH_MODE_IN_CLASS (mode, MODE_COMPLEX_FLOAT)
{
- rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
- const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
+ machine_mode imode = GET_MODE_INNER (mode);
+ rtx inner = const_tiny_rtx[0][(int) imode];
+ const_tiny_rtx[0][(int) mode] =
+ targetm.gen_rtx_complex (mode, inner, inner);
}
FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
@@ -400,7 +400,7 @@ flip_storage_order (machine_mode mode, rtx x)
real = flip_storage_order (GET_MODE_INNER (mode), real);
imag = flip_storage_order (GET_MODE_INNER (mode), imag);
- return gen_rtx_CONCAT (mode, real, imag);
+ return targetm.gen_rtx_complex (mode, real, imag);
}
if (UNLIKELY (reverse_storage_order_supported < 0))
@@ -1001,16 +1001,18 @@ expand_doubleword_mod (machine_mode mode, rtx op0, rtx op1, bool unsignedp)
machine_mode cmode = TYPE_MODE (ctype);
rtx op00 = operand_subword_force (op0, 0, mode);
rtx op01 = operand_subword_force (op0, 1, mode);
- rtx cres = gen_rtx_CONCAT (cmode, gen_reg_rtx (word_mode),
- gen_reg_rtx (word_mode));
+ rtx cres = targetm.gen_rtx_complex (cmode, gen_reg_rtx (word_mode),
+ gen_reg_rtx (word_mode));
tree lhs = make_tree (ctype, cres);
tree arg0 = make_tree (wtype, op00);
tree arg1 = make_tree (wtype, op01);
expand_addsub_overflow (UNKNOWN_LOCATION, PLUS_EXPR, lhs, arg0,
arg1, true, true, true, false, NULL);
- sum = expand_simple_binop (word_mode, PLUS, XEXP (cres, 0),
- XEXP (cres, 1), NULL_RTX, 1,
- OPTAB_DIRECT);
+ sum =
+ expand_simple_binop (word_mode, PLUS,
+ read_complex_part (cres, REAL_P),
+ read_complex_part (cres, IMAG_P), NULL_RTX,
+ 1, OPTAB_DIRECT);
if (sum == NULL_RTX)
return NULL_RTX;
}
@@ -3306,6 +3306,16 @@ a pointer to int.",
bool, (ao_ref *ref),
default_ref_may_alias_errno)
+/* Return the rtx representation of a complex with a specified mode. */
+DEFHOOK
+(gen_rtx_complex,
+ "This hook should return an rtx representing a complex of mode @var{machine_mode} built from @var{real_part} and @var{imag_part}.\n\
+ If both arguments are @code{NULL}, create them as registers.\n\
+ The default is @code{gen_rtx_CONCAT}.",
+ rtx,
+ (machine_mode mode, rtx real_part, rtx imag_part),
+ default_gen_rtx_complex)
+
/* Returns the value corresponding to the specified part of a complex. */
DEFHOOK
(read_complex_part,
@@ -1532,6 +1532,33 @@ default_preferred_simd_mode (scalar_mode)
return word_mode;
}
+/* By default, call gen_rtx_CONCAT. */
+
+rtx
+default_gen_rtx_complex (machine_mode mode, rtx real_part, rtx imag_part)
+{
+ /* For complex modes, don't make a single pseudo.
+ Instead, make a CONCAT of two pseudos.
+ This allows noncontiguous allocation of the real and imaginary parts,
+ which makes much better code. Besides, allocating DCmode
+ pseudos overstrains reload on some machines like the 386. */
+ machine_mode imode = GET_MODE_INNER (mode);
+
+ if (real_part == NULL)
+ real_part = gen_reg_rtx (imode);
+ else
+ gcc_assert ((GET_MODE (real_part) == imode)
+ || (GET_MODE (real_part) == E_VOIDmode));
+
+ if (imag_part == NULL)
+ imag_part = gen_reg_rtx (imode);
+ else
+ gcc_assert ((GET_MODE (imag_part) == imode)
+ || (GET_MODE (imag_part) == E_VOIDmode));
+
+ return gen_rtx_CONCAT (mode, real_part, imag_part);
+}
+
/* By default, extract one of the components of the complex value CPLX. Extract the
real part if part is REAL_P, and the imaginary part if it is IMAG_P. If part is
BOTH_P, return cplx directly*/
@@ -124,6 +124,8 @@ extern opt_machine_mode default_get_mask_mode (machine_mode);
extern bool default_empty_mask_is_expensive (unsigned);
extern vector_costs *default_vectorize_create_costs (vec_info *, bool);
+extern rtx default_gen_rtx_complex (machine_mode mode, rtx real_part,
+ rtx imag_part);
extern rtx default_read_complex_part (rtx cplx, complex_part_t part);
extern void default_write_complex_part (rtx cplx, rtx val,
complex_part_t part,