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