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
This commit is contained in:
parent
2044a4c3cc
commit
110e1ccc08
2 changed files with 113 additions and 45 deletions
|
@ -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
|
||||
|
|
|
@ -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")]
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue