predicates.md: Add cmp_op predicate.

2014-02-23  David Holsgrove <david.holsgrove@xilinx.com>

	* config/microblaze/predicates.md: Add cmp_op predicate.
	* config/microblaze/microblaze.md: Add branch_compare instruction 
	which uses cmp_op predicate and emits cmp insn before branch.
	* config/microblaze/microblaze.c (microblaze_emit_compare): Rename 
	to microblaze_expand_conditional_branch and consolidate logic.
	(microblaze_expand_conditional_branch): emit branch_compare
	insn instead of handling cmp op separate from branch insn.

From-SVN: r208055
This commit is contained in:
David Holsgrove 2014-02-23 18:36:38 +00:00 committed by Michael Eager
parent 9fbb94f227
commit d5a19af1be
4 changed files with 94 additions and 81 deletions

View File

@ -1,3 +1,13 @@
2014-02-23 David Holsgrove <david.holsgrove@xilinx.com>
* config/microblaze/predicates.md: Add cmp_op predicate.
* config/microblaze/microblaze.md: Add branch_compare instruction
which uses cmp_op predicate and emits cmp insn before branch.
* config/microblaze/microblaze.c (microblaze_emit_compare): Rename
to microblaze_expand_conditional_branch and consolidate logic.
(microblaze_expand_conditional_branch): emit branch_compare
insn instead of handling cmp op separate from branch insn.
2014-02-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_emit_le_vsx_move): Relax assert
@ -5,16 +15,16 @@
2014-02-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
define_insn with define_expand and new define_insn
*altivec_lve<VI_char>x_internal.
(altivec_stve<VI_char>x): Replace define_insn with define_expand
and new define_insn *altivec_stve<VI_char>x_internal.
* config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
prototype.
* config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
lve*x built-ins.
(altivec_expand_stvex_be): New function.
* config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
define_insn with define_expand and new define_insn
*altivec_lve<VI_char>x_internal.
(altivec_stve<VI_char>x): Replace define_insn with define_expand
and new define_insn *altivec_stve<VI_char>x_internal.
* config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
prototype.
* config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
lve*x built-ins.
(altivec_expand_stvex_be): New function.
2014-02-22 Joern Rennecke <joern.rennecke@embecosm.com>

View File

@ -3257,51 +3257,6 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
emit_move_insn (mem, fnaddr);
}
/* Emit instruction to perform compare.
cmp is (compare_op op0 op1). */
static rtx
microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
{
rtx cmp_op0 = XEXP (cmp, 0);
rtx cmp_op1 = XEXP (cmp, 1);
rtx comp_reg = gen_reg_rtx (SImode);
enum rtx_code code = *cmp_code;
gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
/* If comparing against zero, just test source reg. */
if (cmp_op1 == const0_rtx)
return cmp_op0;
if (code == EQ || code == NE)
{
/* Use xor for equal/not-equal comparison. */
emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
}
else if (code == GT || code == GTU || code == LE || code == LEU)
{
/* MicroBlaze compare is not symmetrical. */
/* Swap argument order. */
cmp_op1 = force_reg (mode, cmp_op1);
if (code == GT || code == LE)
emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
else
emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
/* Translate test condition. */
*cmp_code = swap_condition (code);
}
else /* if (code == GE || code == GEU || code == LT || code == LTU) */
{
cmp_op1 = force_reg (mode, cmp_op1);
if (code == GE || code == LT)
emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
else
emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
}
return comp_reg;
}
/* Generate conditional branch -- first, generate test condition,
second, generate correct branch instruction. */
@ -3309,14 +3264,39 @@ void
microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
{
enum rtx_code code = GET_CODE (operands[0]);
rtx comp;
rtx cmp_op0 = operands[1];
rtx cmp_op1 = operands[2];
rtx label1 = operands[3];
rtx comp_reg = gen_reg_rtx (SImode);
rtx condition;
comp = microblaze_emit_compare (mode, operands[0], &code);
condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
emit_jump_insn (gen_condjump (condition, operands[3]));
gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
/* If comparing against zero, just test source reg. */
if (cmp_op1 == const0_rtx)
{
comp_reg = cmp_op0;
condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
emit_jump_insn (gen_condjump (condition, label1));
}
else if (code == EQ || code == NE)
{
/* Use xor for equal/not-equal comparison. */
emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
emit_jump_insn (gen_condjump (condition, label1));
}
else
{
/* Generate compare and branch in single instruction. */
cmp_op1 = force_reg (mode, cmp_op1);
condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1));
}
}
void
microblaze_expand_conditional_branch_sf (rtx operands[])
{

View File

@ -1635,28 +1635,6 @@
(set_attr "length" "4")]
)
(define_insn "signed_compare"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]
""
"cmp\t%0,%1,%2"
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "4")])
(define_insn "unsigned_compare"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]
""
"cmpu\t%0,%1,%2"
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "4")])
;;----------------------------------------------------------------
;; Setting a register from an floating point comparison.
;;----------------------------------------------------------------
@ -1730,6 +1708,47 @@
(set_attr "length" "4")]
)
(define_insn "branch_compare"
[(set (pc)
(if_then_else (match_operator:SI 0 "cmp_op"
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")
])
(label_ref (match_operand 3))
(pc)))
(clobber(reg:SI R_TMP))]
""
{
operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
enum rtx_code code = GET_CODE (operands[0]);
if (code == GT || code == LE)
{
output_asm_insn ("cmp\tr18,%z1,%z2", operands);
code = swap_condition (code);
}
else if (code == GTU || code == LEU)
{
output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
code = swap_condition (code);
}
else if (code == GE || code == LT)
{
output_asm_insn ("cmp\tr18,%z2,%z1", operands);
}
else if (code == GEU || code == LTU)
{
output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
}
operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
return "b%C0i%?\tr18,%3";
}
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "12")]
)
;;----------------------------------------------------------------
;; Unconditional branches
;;----------------------------------------------------------------

View File

@ -123,3 +123,7 @@
;; Test for valid PIC call operand
(define_predicate "call_insn_plt_operand"
(match_test "PLT_ADDR_P (op)"))
;; Return if the code of this rtx pattern is a comparison.
(define_predicate "cmp_op"
(match_code "gt,ge,gtu,geu,lt,le,ltu,leu"))