question about lshiftrt:DI when there are no 64bits in the processor

Georg Lay avr@gjlay.de
Wed Sep 15 21:18:00 GMT 2010


fanqifei schrieb:
> Hi all,
> 
> I am porting gcc to a microprocessor. There are no 64bits instructions
> in it. I added a small logical shift right optimization to the md
> file(see below).
> For the statement “k>>32” in which k is 64bits integer, the
> “define_expand” should fail because op2 is 32, not 1.
> However, I can see the lshiftrt:DI is still generated in rtl dumps
> even if I commented out the “define_expand”. If both “define_expand”
> and “define_isns” are commented out, the result is correct.
> 
> .md file:
> 
>     ;; Special case for long x>>1, which can be expanded
>     ;; using the carry bit shift-in instructions.  x<<1 is already
>     ;; expanded by the compiler into x+x, so no rules for long leftshift
>     ;; necessary.
>     ;;
> 
>     (define_expand "lshrdi3"
>       [(set (match_operand:DI 0 "register_operand" )
>             (lshiftrt:DI (match_operand:DI 1 "register_operand")
>                     (match_operand:QI 2 "immediate_operand")))]
>       ""
>     {
>         if ( GET_CODE(operands[2]) != CONST_INT ) { FAIL; }
>         if ( INTVAL(operands[2])        !=                  1 ) { FAIL; }
>     })
> 
>     (define_insn "*lshrdi3S1"
>       [(set (match_operand:DI 0 "register_operand"                     "=r")
>             (lshiftrt:DI (match_operand:DI 1 "register_operand"         "r")
>                     (match_operand:QI 2 "immediate_operand"        "i")))]
>       ""
>       "lsr.w %H0 %H1 1;\;lsrc.w %M0 %M1 1;"
>       [(set_attr "cc" "clobber")])
[...]
> Why the instructions (47-51) are replaced by lshiftrt:DI when there is
> no lshrdi3 insn defined in md file?

You actually /have/ defined an insn that allows lshiftrt:DI patterns for any
constant (even constants that are not known at compile time), namely your
"*lshrdi3S1" insn. Note that many passes construct new RTL out of RTL already
generated and try to match these constructs against some insns, most notably
pass insn-combine, insn splitters. If there is no match nothing happens. If
there is a match (and costs are lower etc.) the old pattern gets replaced by the
new one. In your case that means that you have to disallow anything that has op2
not equal to 1. So you couls rewrite the insn in question to

(define_insn "*lshrdi3S1"
  [(set (match_operand:DI 0 "register_operand"                     "=r")
        (lshiftrt:DI (match_operand:DI 1 "register_operand"         "r")
                     (const_int 1)))]
  ""
  ...)

or

(define_insn "*lshrdi3S1"
  [(set (match_operand:DI 0 "register_operand"                     "=r")
        (lshiftrt:DI (match_operand:DI 1 "register_operand"         "r")
                     (match_operand:QI 2 "const_int_operand"        "n")))]
  "operands[2] == const1_rtx"
  ...)

or any formulation you prefer.



More information about the Gcc mailing list