diff options
author | Julian Brown <julian@codesourcery.com> | 2010-10-04 14:59:30 +0000 |
---|---|---|
committer | Julian Brown <jules@gcc.gnu.org> | 2010-10-04 14:59:30 +0000 |
commit | c452684d45087cb02bf3a9ebe973682a3b946a56 (patch) | |
tree | b1fa492abbca688528392350fda6e82bd301c1e9 /gcc/config | |
parent | a3f2babd42c1b52ec313dec8af4eaa0386182d64 (diff) | |
download | gcc-c452684d45087cb02bf3a9ebe973682a3b946a56.zip gcc-c452684d45087cb02bf3a9ebe973682a3b946a56.tar.gz gcc-c452684d45087cb02bf3a9ebe973682a3b946a56.tar.bz2 |
expr.c (expand_assignment): Add assertion to prevent emitting null rtx for movmisalign pattern.
gcc/
* expr.c (expand_assignment): Add assertion to prevent emitting
null rtx for movmisalign pattern.
(expand_expr_real_1): Likewise.
* config/arm/arm.c (arm_builtin_support_vector_misalignment): New.
(TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT): New. Use above.
(arm_vector_alignment_reachable): New.
(TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE): New. Use above.
(neon_vector_mem_operand): Disallow PRE_DEC for misaligned loads.
(arm_print_operand): Include alignment qualifier in %A.
* config/arm/neon.md (UNSPEC_MISALIGNED_ACCESS): New constant.
(movmisalign<mode>): New expander.
(movmisalign<mode>_neon_store, movmisalign<mode>_neon_load): New
insn patterns.
gcc/testsuite/
* gcc.dg/vect/vect-42.c: Use vect_element_align instead of
vect_hw_misalign.
* gcc.dg/vect/vect-60.c: Likewise.
* gcc.dg/vect/vect-56.c: Likewise.
* gcc.dg/vect/vect-93.c: Likewise.
* gcc.dg/vect/no-scevccp-outer-8.c: Likewise.
* gcc.dg/vect/vect-95.c: Likewise.
* gcc.dg/vect/vect-96.c: Likewise.
* gcc.dg/vect/vect-outer-5.c: Use quad-word vectors when available.
* gcc.dg/vect/slp-25.c: Likewise.
* gcc.dg/vect/slp-3.c: Likewise.
* gcc.dg/vect/vect-multitypes-1.c: Likewise.
* gcc.dg/vect/no-vfa-pr29145.c: Likewise.
* gcc.dg/vect/vect-multitypes-4.c: Likewise. Use vect_element_align.
* gcc.dg/vect/vect-109.c: Likewise.
* gcc.dg/vect/vect-peel-1.c: Likewise.
* gcc.dg/vect/vect-peel-2.c: Likewise.
* lib/target-supports.exp
(check_effective_target_arm_vect_no_misalign): New.
(check_effective_target_vect_no_align): Use above.
(check_effective_target_vect_element_align): New.
(add_options_for_quad_vectors): New.
From-SVN: r164941
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/arm/arm.c | 81 | ||||
-rw-r--r-- | gcc/config/arm/neon.md | 47 |
2 files changed, 126 insertions, 2 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 2ff010b..7a8155d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -242,6 +242,11 @@ static bool cortex_a9_sched_adjust_cost (rtx, rtx, rtx, int *); static bool xscale_sched_adjust_cost (rtx, rtx, rtx, int *); static unsigned int arm_units_per_simd_word (enum machine_mode); static bool arm_class_likely_spilled_p (reg_class_t); +static bool arm_vector_alignment_reachable (const_tree type, bool is_packed); +static bool arm_builtin_support_vector_misalignment (enum machine_mode mode, + const_tree type, + int misalignment, + bool is_packed); /* Table of machine attributes. */ @@ -557,6 +562,14 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_CLASS_LIKELY_SPILLED_P #define TARGET_CLASS_LIKELY_SPILLED_P arm_class_likely_spilled_p +#undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE +#define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \ + arm_vector_alignment_reachable + +#undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT +#define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \ + arm_builtin_support_vector_misalignment + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -8834,7 +8847,8 @@ neon_vector_mem_operand (rtx op, int type) return arm_address_register_rtx_p (ind, 0); /* Allow post-increment with Neon registers. */ - if (type != 1 && (GET_CODE (ind) == POST_INC || GET_CODE (ind) == PRE_DEC)) + if ((type != 1 && GET_CODE (ind) == POST_INC) + || (type == 0 && GET_CODE (ind) == PRE_DEC)) return arm_address_register_rtx_p (XEXP (ind, 0), 0); /* FIXME: vld1 allows register post-modify. */ @@ -16317,6 +16331,8 @@ arm_print_operand (FILE *stream, rtx x, int code) { rtx addr; bool postinc = FALSE; + unsigned align, modesize, align_bits; + gcc_assert (GET_CODE (x) == MEM); addr = XEXP (x, 0); if (GET_CODE (addr) == POST_INC) @@ -16324,7 +16340,29 @@ arm_print_operand (FILE *stream, rtx x, int code) postinc = 1; addr = XEXP (addr, 0); } - asm_fprintf (stream, "[%r]", REGNO (addr)); + asm_fprintf (stream, "[%r", REGNO (addr)); + + /* We know the alignment of this access, so we can emit a hint in the + instruction (for some alignments) as an aid to the memory subsystem + of the target. */ + align = MEM_ALIGN (x) >> 3; + modesize = GET_MODE_SIZE (GET_MODE (x)); + + /* Only certain alignment specifiers are supported by the hardware. */ + if (modesize == 16 && (align % 32) == 0) + align_bits = 256; + else if ((modesize == 8 || modesize == 16) && (align % 16) == 0) + align_bits = 128; + else if ((align % 8) == 0) + align_bits = 64; + else + align_bits = 0; + + if (align_bits != 0) + asm_fprintf (stream, ":%d", align_bits); + + asm_fprintf (stream, "]"); + if (postinc) fputs("!", stream); } @@ -23145,4 +23183,43 @@ arm_expand_sync (enum machine_mode mode, } } +static bool +arm_vector_alignment_reachable (const_tree type, bool is_packed) +{ + /* Vectors which aren't in packed structures will not be less aligned than + the natural alignment of their element type, so this is safe. */ + if (TARGET_NEON && !BYTES_BIG_ENDIAN) + return !is_packed; + + return default_builtin_vector_alignment_reachable (type, is_packed); +} + +static bool +arm_builtin_support_vector_misalignment (enum machine_mode mode, + const_tree type, int misalignment, + bool is_packed) +{ + if (TARGET_NEON && !BYTES_BIG_ENDIAN) + { + HOST_WIDE_INT align = TYPE_ALIGN_UNIT (type); + + if (is_packed) + return align == 1; + + /* If the misalignment is unknown, we should be able to handle the access + so long as it is not to a member of a packed data structure. */ + if (misalignment == -1) + return true; + + /* Return true if the misalignment is a multiple of the natural alignment + of the vector's element type. This is probably always going to be + true in practice, since we've already established that this isn't a + packed access. */ + return ((misalignment % align) == 0); + } + + return default_builtin_support_vector_misalignment (mode, type, misalignment, + is_packed); +} + #include "gt-arm.h" diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 3bb74a2..cd91573b 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -141,6 +141,7 @@ (UNSPEC_VUZP2 202) (UNSPEC_VZIP1 203) (UNSPEC_VZIP2 204) + (UNSPEC_MISALIGNED_ACCESS 205) (UNSPEC_VCLE 206) (UNSPEC_VCLT 207)]) @@ -369,6 +370,52 @@ neon_disambiguate_copy (operands, dest, src, 4); }) +(define_expand "movmisalign<mode>" + [(set (match_operand:VDQX 0 "nonimmediate_operand" "") + (unspec:VDQX [(match_operand:VDQX 1 "general_operand" "")] + UNSPEC_MISALIGNED_ACCESS))] + "TARGET_NEON && !BYTES_BIG_ENDIAN" +{ + /* This pattern is not permitted to fail during expansion: if both arguments + are non-registers (e.g. memory := constant, which can be created by the + auto-vectorizer), force operand 1 into a register. */ + if (!s_register_operand (operands[0], <MODE>mode) + && !s_register_operand (operands[1], <MODE>mode)) + operands[1] = force_reg (<MODE>mode, operands[1]); +}) + +(define_insn "*movmisalign<mode>_neon_store" + [(set (match_operand:VDX 0 "memory_operand" "=Um") + (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")] + UNSPEC_MISALIGNED_ACCESS))] + "TARGET_NEON && !BYTES_BIG_ENDIAN" + "vst1.<V_sz_elem>\t{%P1}, %A0" + [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) + +(define_insn "*movmisalign<mode>_neon_load" + [(set (match_operand:VDX 0 "s_register_operand" "=w") + (unspec:VDX [(match_operand:VDX 1 "memory_operand" " Um")] + UNSPEC_MISALIGNED_ACCESS))] + "TARGET_NEON && !BYTES_BIG_ENDIAN" + "vld1.<V_sz_elem>\t{%P0}, %A1" + [(set_attr "neon_type" "neon_vld1_1_2_regs")]) + +(define_insn "*movmisalign<mode>_neon_store" + [(set (match_operand:VQX 0 "memory_operand" "=Um") + (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")] + UNSPEC_MISALIGNED_ACCESS))] + "TARGET_NEON && !BYTES_BIG_ENDIAN" + "vst1.<V_sz_elem>\t{%q1}, %A0" + [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) + +(define_insn "*movmisalign<mode>_neon_load" + [(set (match_operand:VQX 0 "s_register_operand" "=w") + (unspec:VQX [(match_operand:VQX 1 "memory_operand" " Um")] + UNSPEC_MISALIGNED_ACCESS))] + "TARGET_NEON && !BYTES_BIG_ENDIAN" + "vld1.<V_sz_elem>\t{%q0}, %A1" + [(set_attr "neon_type" "neon_vld1_1_2_regs")]) + (define_insn "vec_set<mode>_internal" [(set (match_operand:VD 0 "s_register_operand" "=w") (vec_merge:VD |