+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
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 *);
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)
{
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
(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")
(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
--- /dev/null
+/* { 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;
+}