Commit 4c81f958 by James Greenhalgh Committed by James Greenhalgh

[Patch AArch64] Reinstate CANNOT_CHANGE_MODE_CLASS to fix pr67609

gcc/

	PR rtl-optimization/67609
	* config/aarch64/aarch64-protos.h
	(aarch64_cannot_change_mode_class): Bring back.
	* config/aarch64/aarch64.c
	(aarch64_cannot_change_mode_class): Likewise.
	* config/aarch64/aarch64.h (CANNOT_CHANGE_MODE_CLASS): Likewise.
	* config/aarch64/aarch64.md (aarch64_movdi_<mode>low): Use
	zero_extract rather than truncate.
	(aarch64_movdi_<mode>high): Likewise.

gcc/testsuite/

	PR rtl-optimization/67609
	* gcc.dg/torture/pr67609.c: New.

From-SVN: r231455
parent 08554c26
2015-12-09 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64-protos.h
(aarch64_cannot_change_mode_class): Bring back.
* config/aarch64/aarch64.c
(aarch64_cannot_change_mode_class): Likewise.
* config/aarch64/aarch64.h (CANNOT_CHANGE_MODE_CLASS): Likewise.
* config/aarch64/aarch64.md (aarch64_movdi_<mode>low): Use
zero_extract rather than truncate.
(aarch64_movdi_<mode>high): Likewise.
2015-12-09 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/68786
......@@ -269,6 +269,9 @@ int aarch64_get_condition_code (rtx);
bool aarch64_bitmask_imm (HOST_WIDE_INT val, machine_mode);
int aarch64_branch_cost (bool, bool);
enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx);
bool aarch64_cannot_change_mode_class (machine_mode,
machine_mode,
enum reg_class);
bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
bool aarch64_constant_address_p (rtx);
bool aarch64_expand_movmem (rtx *);
......
......@@ -12712,6 +12712,24 @@ aarch64_vectorize_vec_perm_const_ok (machine_mode vmode,
return ret;
}
/* Implement target hook CANNOT_CHANGE_MODE_CLASS. */
bool
aarch64_cannot_change_mode_class (machine_mode from,
machine_mode to,
enum reg_class rclass)
{
/* We cannot allow word_mode subregs of full vector modes.
Otherwise the middle-end will assume it's ok to store to
(subreg:DI (reg:TI 100) 0) in order to modify only the low 64 bits
of the 128-bit register. However, after reload the subreg will
be dropped leaving a plain DImode store. See PR67609 for a more
detailed dicussion. In all other cases, we want to be permissive
and return false. */
return (reg_classes_intersect_p (FP_REGS, rclass)
&& GET_MODE_SIZE (to) == UNITS_PER_WORD
&& GET_MODE_SIZE (from) > UNITS_PER_WORD);
}
rtx
aarch64_reverse_mask (enum machine_mode mode)
{
......
......@@ -828,6 +828,9 @@ do { \
extern void __aarch64_sync_cache_range (void *, void *); \
__aarch64_sync_cache_range (beg, end)
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
aarch64_cannot_change_mode_class (FROM, TO, CLASS)
#define SHIFT_COUNT_TRUNCATED !TARGET_SIMD
/* Choose appropriate mode for caller saves, so we do the minimum
......
......@@ -4681,7 +4681,8 @@
(define_insn "aarch64_movdi_<mode>low"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI (match_operand:TX 1 "register_operand" "w")))]
(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
(const_int 64) (const_int 0)))]
"TARGET_FLOAT && (reload_completed || reload_in_progress)"
"fmov\\t%x0, %d1"
[(set_attr "type" "f_mrc")
......@@ -4690,9 +4691,8 @@
(define_insn "aarch64_movdi_<mode>high"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TX (match_operand:TX 1 "register_operand" "w")
(const_int 64))))]
(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
(const_int 64) (const_int 64)))]
"TARGET_FLOAT && (reload_completed || reload_in_progress)"
"fmov\\t%x0, %1.d[1]"
[(set_attr "type" "f_mrc")
......
2015-12-09 James Greenhalgh <james.greenhalgh@arm.com>
PR rtl-optimization/67609
* gcc.dg/torture/pr67609.c: New.
2015-12-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/68583
......
/* { dg-do run } */
typedef union
{
double v[2];
double s __attribute__ ((vector_size (16)));
} data;
data reg;
void __attribute__ ((noinline))
set_lower (double b)
{
data stack_var;
double __attribute__ ((vector_size (16))) one = { 1.0, 1.0 };
stack_var.s = reg.s;
stack_var.s += one;
stack_var.v[0] += b;
reg.s = stack_var.s;
}
int
main (int argc, char ** argv)
{
reg.v[0] = 1.0;
reg.v[1] = 1.0;
/* reg should contain { 1.0, 1.0 }. */
set_lower (2.0);
/* reg should contain { 4.0, 2.0 }. */
if ((int) reg.v[0] != 4 || (int) reg.v[1] != 2)
__builtin_abort ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment