Richard Sandiford wrote: > > You might as well make the first operand a register_operand and > avoid the REG_P check. I agree. I implemented this change and it works as expected.
>More importantly: > >> operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); >> operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); > > ..this code is designed to handle REGs and CONST_INTs correctly, > and avoid the problem you were seeing. (As Eric says, gen_int_mode > is the canonical way of generating a correct CONST_INT in cases where > you do need to create one manually. In this case it's simpler to use > simplify_gen_subreg though.) I modified the code as below and now I do not have the problems I had before. else if (CONST_INT == GET_CODE (operands[1]) || REG_P (operands[1])) { operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); } > I notice you're generating subregs of symbolic constants, > but I'm not sure that's really supported. I did this so that I can generate rtl code that I can latter trap with the define_insn's below. (define_insn "movqi_hiword" [(set (match_operand:QI 0 "register_operand" "") (subreg:QI (match_operand:HI 1 "general_operand" "") 0))] "" "move\t%0,#HIWORD(%1)" ) (define_insn "*movqi_lowword" [(set (match_operand:QI 0 "register_operand" "") (subreg:QI (match_operand:HI 1 "general_operand" "") 1))] "" "move\t%0,#LOWWORD(%1)" ) Do you recommend a better way to do this? > As far as the MEM_P case goes: [...] > > you can use: > > operands[4] = adjust_address (operands[1], QImode, 1); > operands[5] = adjust_address (operands[1], QImode, 0); > I also implemented this and it works nicely. Many thanks! > The CONST handling looks suspicious here. CONSTs aren't memory references, > but you split them into memory references. In my debugging session, all cases I say CONSTs they were used for memory. I will look at this in more detail. > Also, you need to beware of cases in which operands[1] overlaps > operands[0]. The splitter says: > > [(set (match_dup 2) (match_dup 4)) > (set (match_dup 3) (match_dup 5))] > > and operands[2] is always the highpart: > > operands[2] = gen_highpart(QImode, operands[0]); > > but consider the case in which operands[1] (and thus operands[4]) > is a memory reference that uses the high part of operands[0] as > a base register. In that case, the base register will be modified > by the first split instruction and have the wrong value in the > second split instruction. See other ports for the canonical way > of handling this. Thanks for the heads up. Could you point me to a specific target/file? Best regards, -Omar