aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Greenhalgh <james.greenhalgh@arm.com>2014-04-22 10:49:48 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2014-04-22 10:49:48 +0000
commit110e1ccc08a859c62b672e3a8b697caff350de38 (patch)
tree9b76b58e41be54e3bdf58a208239490cfec45044
parent2044a4c3cc2db3697e62eea701c489378ad54947 (diff)
downloadgcc-110e1ccc08a859c62b672e3a8b697caff350de38.zip
gcc-110e1ccc08a859c62b672e3a8b697caff350de38.tar.gz
gcc-110e1ccc08a859c62b672e3a8b697caff350de38.tar.bz2
Re: [AArch64] Fix possible wrong code generation when comparing DImode values.
gcc/ * config/aarch64/aarch64-simd.md (aarch64_cm<optab>di): Always split. (*aarch64_cm<optab>di): New. (aarch64_cmtstdi): Always split. (*aarch64_cmtstdi): New. From-SVN: r209617
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/aarch64/aarch64-simd.md150
2 files changed, 113 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e882ff8..b1850b9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-04-22 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64-simd.md
+ (aarch64_cm<optab>di): Always split.
+ (*aarch64_cm<optab>di): New.
+ (aarch64_cmtstdi): Always split.
+ (*aarch64_cmtstdi): New.
+
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/60823
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 7fa76be..995b4a8 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3415,26 +3415,46 @@
)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_SIMD"
- "@
- cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
- cm<optab>\t%d0, %d1, #0
- #"
- "reload_completed
- /* We need to prevent the split from
- happening in the 'w' constraint cases. */
- && GP_REGNUM_P (REGNO (operands[0]))
- && GP_REGNUM_P (REGNO (operands[1]))"
- [(const_int 0)]
+ "#"
+ "reload_completed"
+ [(set (match_operand:DI 0 "register_operand")
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero")
+ )))]
{
- enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
- rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
- rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
- emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
- DONE;
+ /* If we are in the general purpose register file,
+ we split to a sequence of comparison and store. */
+ if (GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1])))
+ {
+ enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ /* Otherwise, we expand to a similar pattern which does not
+ clobber CC_REGNUM. */
}
[(set_attr "type" "neon_compare, neon_compare_zero, multiple")]
)
+(define_insn "*aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w,w")
+ (neg:DI
+ (COMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w,w")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz")
+ )))]
+ "TARGET_SIMD && reload_completed"
+ "@
+ cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+ cm<optab>\t%d0, %d1, #0"
+ [(set_attr "type" "neon_compare, neon_compare_zero")]
+)
+
;; cm(hs|hi)
(define_insn "aarch64_cm<optab><mode>"
@@ -3458,23 +3478,42 @@
)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_SIMD"
- "@
- cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
- #"
- "reload_completed
- /* We need to prevent the split from
- happening in the 'w' constraint cases. */
- && GP_REGNUM_P (REGNO (operands[0]))
- && GP_REGNUM_P (REGNO (operands[1]))"
- [(const_int 0)]
+ "#"
+ "reload_completed"
+ [(set (match_operand:DI 0 "register_operand")
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero")
+ )))]
{
- enum machine_mode mode = CCmode;
- rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
- rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
- emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
- DONE;
+ /* If we are in the general purpose register file,
+ we split to a sequence of comparison and store. */
+ if (GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1])))
+ {
+ enum machine_mode mode = CCmode;
+ rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+ rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ /* Otherwise, we expand to a similar pattern which does not
+ clobber CC_REGNUM. */
}
- [(set_attr "type" "neon_compare, neon_compare_zero")]
+ [(set_attr "type" "neon_compare,multiple")]
+)
+
+(define_insn "*aarch64_cm<optab>di"
+ [(set (match_operand:DI 0 "register_operand" "=w")
+ (neg:DI
+ (UCOMPARISONS:DI
+ (match_operand:DI 1 "register_operand" "w")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w")
+ )))]
+ "TARGET_SIMD && reload_completed"
+ "cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>"
+ [(set_attr "type" "neon_compare")]
)
;; cmtst
@@ -3502,23 +3541,44 @@
(const_int 0))))
(clobber (reg:CC CC_REGNUM))]
"TARGET_SIMD"
- "@
- cmtst\t%d0, %d1, %d2
- #"
- "reload_completed
- /* We need to prevent the split from
- happening in the 'w' constraint cases. */
- && GP_REGNUM_P (REGNO (operands[0]))
- && GP_REGNUM_P (REGNO (operands[1]))"
- [(const_int 0)]
+ "#"
+ "reload_completed"
+ [(set (match_operand:DI 0 "register_operand")
+ (neg:DI
+ (ne:DI
+ (and:DI
+ (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "register_operand"))
+ (const_int 0))))]
{
- rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
- enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
- rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
- rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
- emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
- DONE;
+ /* If we are in the general purpose register file,
+ we split to a sequence of comparison and store. */
+ if (GP_REGNUM_P (REGNO (operands[0]))
+ && GP_REGNUM_P (REGNO (operands[1])))
+ {
+ rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
+ enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
+ rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
+ rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
+ emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+ DONE;
+ }
+ /* Otherwise, we expand to a similar pattern which does not
+ clobber CC_REGNUM. */
}
+ [(set_attr "type" "neon_tst,multiple")]
+)
+
+(define_insn "*aarch64_cmtstdi"
+ [(set (match_operand:DI 0 "register_operand" "=w")
+ (neg:DI
+ (ne:DI
+ (and:DI
+ (match_operand:DI 1 "register_operand" "w")
+ (match_operand:DI 2 "register_operand" "w"))
+ (const_int 0))))]
+ "TARGET_SIMD"
+ "cmtst\t%d0, %d1, %d2"
[(set_attr "type" "neon_tst")]
)