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:
parent
9fbb94f227
commit
d5a19af1be
@ -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>
|
||||
|
||||
|
@ -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[])
|
||||
{
|
||||
|
@ -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
|
||||
;;----------------------------------------------------------------
|
||||
|
@ -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"))
|
||||
|
Loading…
Reference in New Issue
Block a user