microblaze unroll loops optimization
David Holsgrove
david.holsgrove@xilinx.com
Sat Jan 12 02:54:00 GMT 2013
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.holsgrove@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
>
More information about the Gcc
mailing list