Hi all,

I believe the decision to use UNSPEC_CMP and UNSPEC_CMPU for microblaze
compare instructions stems from the conversation in this thread from 2009;

http://gcc.gnu.org/ml/gcc/2009-12/msg00283.html

This makes sense, because if I use code attributes and iterators to extend the
compare insn as so;

(define_code_iterator any_cmp [gt ge lt le gtu geu ltu leu])

;; <u> expands to an empty string when doing a signed operation and
;; "u" when doing an unsigned operation.
(define_code_attr u [(gt "") (gtu "u")
         (ge "") (geu "u")
         (lt "") (ltu "u")
         (le "") (leu "u")])

(define_insn "cmp<u>_<code>"
  [(set (match_operand:SI 0 "register_operand" "=d")
    (any_cmp:SI
         (match_operand:SI 1 "register_operand")
         (match_operand:SI 2 "register_operand")))]
  ""
  "cmp<u>\t%0,%1,%2"
  [(set_attr "type" "arith")
  (set_attr "mode"  "SI")
  (set_attr "length"  "4")])

They look ok;

(insn 29 27 30 5 (set (reg:SI 67)
        (gt:SI (reg/v:SI 55 [ N ])
            (reg/v:SI 51 [ j ]))) ../core_matrix_min.c:6 63 {cmp_gt}
     (nil))
(jump_insn 30 29 31 5 (set (pc)
        (if_then_else (lt:SI (reg:SI 67)
                (const_int 0 [0]))
            (label_ref 28)
            (pc))) ../core_matrix_min.c:6 72 {branch_zero}
     (expr_list:REG_BR_PROB (const_int 9100 [0x238c])
        (nil))
 -> 28)

and code generated at -O0 is correct. But then I see that during
CSE optimization, the instructions are trashed;

starting the processing of deferred insns
deleting insn with uid = 16.
deleting insn with uid = 17.
deleting insn with uid = 28.
deleting insn with uid = 29.
deleting insn with uid = 30.


Looking back at the gcc 4.1.2 implementation, we had a branch_compare which
carried out the compare and branching in one instruction;

(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")
                                         ])
                      (match_operand:SI 3 "pc_or_label_operand" "")
                      (match_operand:SI 4 "pc_or_label_operand" "")))
  (clobber(reg:SI R_TMP))]
  ""
  {

    if (operands[3] != pc_rtx)
    {                                                           /*
normal jump */
        switch (GET_CODE (operands[0]))
        {
            case GT: return  "cmp\tr18,%z1,%z2\;blti%?\tr18,%3 #GT";
            case LE: return  "cmp\tr18,%z1,%z2\;bgei%?\tr18,%3";
            case GE: return  "cmp\tr18,%z2,%z1\;bgei%?\tr18,%3";
            case LT: return  "cmp\tr18,%z2,%z1\;blti%?\tr18,%3 #LT";
            case GTU:return  "cmpu\tr18,%z1,%z2\;blti%?\tr18,%3 #GTU";
            case LEU:return  "cmpu\tr18,%z1,%z2\;bgei%?\tr18,%3";
            case GEU:return  "cmpu\tr18,%z2,%z1\;bgei%?\tr18,%3";
            case LTU:return  "cmpu\tr18,%z2,%z1\;blti%?\tr18,%3 #LTU";
....

Is this method still valid and considered acceptable in a modern gcc?

thanks,
David


On 8 January 2013 15:59, David Holsgrove <david.holsgr...@xilinx.com> wrote:
> Loop unrolling (-funroll-loops) for microblaze is ineffectual on the gcc
> 4.6/4.7/4.8 branches.
>
> This previously worked on an out of tree gcc 4.1.2, and I believe the relevant
> diff to be the use of UNSPEC_CMP and UNSPEC_CMPU to create two unique
> instructions for signed_compare and unsigned_compare in microblaze's machine
> description, which means that the iv_analyze_expr in loop-iv.c of the compare
> instruction is unable to understand the expression.
>
> Details follow below,
>
> thanks,
> David
>

Reply via email to