GCC won`t emit my instriction

Jeff Law law@redhat.com
Fri Jun 7 04:50:00 GMT 2019


On 6/6/19 10:42 PM, Alex Hill via gcc-help wrote:
> 
> I need to reduce amount of branches in code. There is exist benchmark called median it have some code like:
>     if ( A < B )
>             return A = foo[i];
>         else
>             return B = foo[i];
> I wrote a pattern in machine description file *.md to avoid branches:
>     (define_insn "smin<GPR:mode>3"
>       [
>         (set 
>           (match_operand:GPR 0 "register_operand" "=r")
>             (if_then_else:GPR
>           (lt:GPR 
>             (match_operand:GPR 1 "register_operand" " r")
>             (match_operand:GPR 2 "register_operand" " r"))
>         (match_dup 1)
>         (match_dup 2)))
>       ]
>       ""
>       "min\t%0,%1,%2"
>       [(set_attr "type" "move")
>        (set_attr "mode" "<MODE>")]) 
> It works in case of simple comparison:
>     if ( A < B )
>             return A ;
>         else
>             return B;
> GCC emit:
>     min a0,a0,a1    # 9 smindi3 [length = 4]
>     ret # 21    simple_return   [length = 4]
> But if i try same, but with indexed variable( array ): it won`t works:
>     if ( A < B )
>             return A = foo[i];
>         else
>             return B = foo[i];
> GCC emit:
>     blt a0,a1,.L5   # 11    *branch_orderdi [length = 4]
>     sd  a1,8(a2)    # 18    *movdi_64bit/4  [length = 4]
>     mv  a0,a1   # 8 *movdi_64bit/1  [length = 4]
>     ret # 34    simple_return   [length = 4]
>     .L5:
>     sd  a0,8(a2)    # 13    *movdi_64bit/4  [length = 4]
>     ret # 28    simple_return   [length = 4]
> I need to GCC emit something like this:
>     min a0,a0,a1    # 9 smindi3 [length = 4]
>     sd  a0,8(a2)    # 18    *movdi_64bit/4  [length = 4]
>     ret # 34    simple_return   [length = 4]
> I appreciate any help, and i desperate to find a desicion, i tried to look into GIMPLE to change conditions of MIN_EXPR, but there is no(almost) any documentation, and sources are VERY puzzling((
Rather than using a match_dup which requires the exact same register
throughout the RTL pipeline, you might consider using a matching constraint.

    (define_insn "smin<GPR:mode>3"
      [
        (set
          (match_operand:GPR 0 "register_operand" "=r")
            (if_then_else:GPR
          (lt:GPR
            (match_operand:GPR 1 "register_operand" " r")
            (match_operand:GPR 2 "register_operand" " r"))
        (match_operand:GPR 3 "register_operand" "1")
        (match_operand:GPR 4 "register_operand" "2")))

I would also strongly recommnend reviewing the various dump files to see
if you're getting min/max as you leave gimple and if they're carried
through the RTL pipeline.

jeff



More information about the Gcc-help mailing list