diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7830f3b1c5d..6204106d470 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2014-02-23 David Holsgrove + + * 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 * config/rs6000/rs6000.c (rs6000_emit_le_vsx_move): Relax assert @@ -5,16 +15,16 @@ 2014-02-23 Bill Schmidt - * config/rs6000/altivec.md (altivec_lvex): Replace - define_insn with define_expand and new define_insn - *altivec_lvex_internal. - (altivec_stvex): Replace define_insn with define_expand - and new define_insn *altivec_stvex_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_lvex): Replace + define_insn with define_expand and new define_insn + *altivec_lvex_internal. + (altivec_stvex): Replace define_insn with define_expand + and new define_insn *altivec_stvex_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 diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index cd2a788caae..985d26a40ca 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -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[]) { diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md index 01c49e00279..0e43a65586a 100644 --- a/gcc/config/microblaze/microblaze.md +++ b/gcc/config/microblaze/microblaze.md @@ -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 ;;---------------------------------------------------------------- diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md index f34453ca8ee..bfdf4ea810b 100644 --- a/gcc/config/microblaze/predicates.md +++ b/gcc/config/microblaze/predicates.md @@ -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"))