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")])

I can find out that the the insn is generated in
pass_jump2(gcc/4.3.2/gcc/cfgcleanup.c).
in p_b.c.137r.into_cfglayout:

    ;; Start of basic block ( 6) -> 5
    ;; Pred edge  6 [97.1%]
    (code_label 69 44 47 5 57 "" [1 uses])

    (note 47 69 50 5 [bb 5] NOTE_INSN_BASIC_BLOCK)

    (insn 50 47 48 5 p_b.c:491 (clobber (reg:DI 42 [ D.1783 ])) -1
(insn_list:REG_LIBCALL 51 (nil)))

    (insn 48 50 49 5 p_b.c:491 (set (subreg:SI (reg:DI 42 [ D.1783 ]) 0)
            (lshiftrt:SI (subreg:SI (reg/v:DI 35 [ k ]) 4)
                (const_int 0 [0x0]))) 54 {lshrsi3}
(expr_list:REG_NO_CONFLICT (reg/v:DI 35 [ k ])
            (nil)))

    (insn 49 48 51 5 p_b.c:491 (set (subreg:SI (reg:DI 42 [ D.1783 ]) 4)
            (const_int 0 [0x0])) 3 {*mov_mode_insn}
(expr_list:REG_NO_CONFLICT (reg/v:DI 35 [ k ])
            (nil)))

    (insn 51 49 52 5 p_b.c:491 (set (reg:DI 42 [ D.1783 ])
            (reg:DI 42 [ D.1783 ])) 2 {movdi} (insn_list:REG_RETVAL 50
(expr_list:REG_EQUAL (lshiftrt:DI (reg/v:DI 35 [ k ])
                    (const_int 32 [0x20]))
                (nil))))

but in p_b.c.138r.jump, insns between 47 and 51 are removed and insn51
is changed.

    ;; Start of basic block ( 5) -> 4
    ;; Pred edge  5 [97.1%]
    (code_label 69 44 47 4 57 "" [1 uses])

    (note 47 69 51 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

    (insn 51 47 52 4 p_b.c:491 (set (reg:DI 42 [ D.1783 ])
            (lshiftrt:DI (reg/v:DI 35 [ k ])
                (const_int 32 [0x20]))) 58 {*lshrdi3S1} (nil))

I am wondering what’s the usage of REG_EQUAL? ( I have read gcc
internal, but still don’t quite understand).
Why the instructions (47-51) are replaced by lshiftrt:DI when there is
no lshrdi3 insn defined in md file?

Thanks.
-- 
-Qifei Fan

Reply via email to