Commit 110e1ccc by James Greenhalgh Committed by James Greenhalgh

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
parent 2044a4c3
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")]
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment