diff options
author | James Greenhalgh <james.greenhalgh@arm.com> | 2014-04-22 10:49:48 +0000 |
---|---|---|
committer | James Greenhalgh <jgreenhalgh@gcc.gnu.org> | 2014-04-22 10:49:48 +0000 |
commit | 110e1ccc08a859c62b672e3a8b697caff350de38 (patch) | |
tree | 9b76b58e41be54e3bdf58a208239490cfec45044 | |
parent | 2044a4c3cc2db3697e62eea701c489378ad54947 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-simd.md | 150 |
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")] ) |