How do I expand a move immediate into two RTL expressions?

Tabony, Charles ctabony@qualcomm.com
Wed Jul 13 19:46:00 GMT 2005


Hi,

I am trying to alter a machine description to produce efficient
instruction scheduling.  Towards that goal, I am trying to eliminate
every instance where a define_insn outputs more than one assembly
instruction for given constraints.  One of the operations that takes two
assembly instructions is moving an immediate value that is represented
by more than 16 bits into a 32 bit register.  It is done by assigning
the high and low halfwords each with unsigned 16 bit immediates.  I
tried to expand the single RTL move expression into two using the
following define expand:

(define_expand "movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
  ""
  {
    if(GET_CODE(operands[0]) != REG){
      operands[1] = force_reg(SImode, operands[1]);
    }
    if(REG_P(operands[0]) && CONSTANT_P(operands[1])
       && (-0x8000 > INTVAL(operands[1]) || INTVAL(operands[1]) >
0x7FFF)){
      emit_move_insn(gen_rtx_SUBREG(HImode, operands[0], 2),
                     GEN_INT((INTVAL(operands[1]) >> 16) & 0xFFFF));
      emit_move_insn(gen_rtx_SUBREG(HImode, operands[0], 0),
                     GEN_INT(INTVAL(operands[1]) & 0xFFFF));
      DONE;
    }
  }
)

I also added the following define_insn's to match the resulting RTL to
assembly.

(define_insn "movhi_subreg0"
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
        (match_operand:HI 1 "immediate_operand"            "I"))]
  ""
  "%0.l = #%1"
)

(define_insn "movhi_subreg1"
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
        (match_operand:HI 1 "immediate_operand"            "I"))]
  ""
  "%0.h = #%1"
)

When I try to build, I get the following error when the cross compiler
tries to compile a file for the target:

internal compiler error: in do_SUBST, at combine.c:446

>From what I can tell, it does not like when the low 16 bits have a 1 in
the most significant bit.

Can anyone tell me why this does not work?  How could I get it to work?
Is this the right approach at all?  If what I am trying will not work,
then how can I avoid outputting multiple assembly instructions at once?

Thank you,
Charles J. Tabony



More information about the Gcc-help mailing list