From 110e1ccc08a859c62b672e3a8b697caff350de38 Mon Sep 17 00:00:00 2001 From: James Greenhalgh Date: Tue, 22 Apr 2014 10:49:48 +0000 Subject: [PATCH] Re: [AArch64] Fix possible wrong code generation when comparing DImode values. gcc/ * config/aarch64/aarch64-simd.md (aarch64_cmdi): Always split. (*aarch64_cmdi): New. (aarch64_cmtstdi): Always split. (*aarch64_cmtstdi): New. From-SVN: r209617 --- gcc/ChangeLog | 8 ++ gcc/config/aarch64/aarch64-simd.md | 150 ++++++++++++++++++++--------- 2 files changed, 113 insertions(+), 45 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e882ff81db8..b1850b9c4f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-04-22 James Greenhalgh + + * config/aarch64/aarch64-simd.md + (aarch64_cmdi): Always split. + (*aarch64_cmdi): New. + (aarch64_cmtstdi): Always split. + (*aarch64_cmtstdi): New. + 2014-04-22 Jakub Jelinek PR tree-optimization/60823 diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 7fa76be9ae8..995b4a81acd 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\t%d0, %d, %d - cm\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 (, operands[1], operands[2]); - rtx cc_reg = aarch64_gen_compare_reg (, operands[1], operands[2]); - rtx comparison = gen_rtx_ (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 (, operands[1], operands[2]); + rtx cc_reg = aarch64_gen_compare_reg (, operands[1], operands[2]); + rtx comparison = gen_rtx_ (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_cmdi" + [(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\t%d0, %d, %d + cm\t%d0, %d1, #0" + [(set_attr "type" "neon_compare, neon_compare_zero")] +) + ;; cm(hs|hi) (define_insn "aarch64_cm" @@ -3458,23 +3478,42 @@ ))) (clobber (reg:CC CC_REGNUM))] "TARGET_SIMD" - "@ - cm\t%d0, %d, %d - #" - "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 (, operands[1], operands[2]); - rtx comparison = gen_rtx_ (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 (, operands[1], operands[2]); + rtx comparison = gen_rtx_ (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_cmdi" + [(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\t%d0, %d, %d" + [(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")] )