This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Problem with reloading in a new backend...


[Putting the gcc-list back in CC:, ]

Le mardi 08 avril 2008 Ã 18:24 -0400, DJ Delorie a Ãcrit :

> Do you have one insn for each pair of src/dest that movqi supports?
> If so, this isn't the best way to do it - you should have one insn
> with multiple constraint alternativess, not multiple insns.
[...]
> reload deals with selecting among constraint
> options, it doesn't usually have the choice about which pattern to
> choose - the first that matches is used.  If you have a list of
> patterns that all match, only the first is available to reload.  Plus,
> reload gets confused when the predicates are used to choose among
> otherwise identical patterns.  So, it's best to have a more general
> predicate (like general_operand) and use the constraints to tell
> reload how to implement that insn in hardware.

Thanks to your suggestion, I changed my movqi pattern to look like:

(define_insn "*movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,y,y,m,r")
        (match_operand:QI 1 "general_operand" "r,n,s,r,m"))]
  ""  
  {
        switch (which_alternative) {
        case 0:                         /* register to register */
                return "tfr %0,%1";
        case 1:                         /* immediate to register */
                output_asm_insn ("ldih %0, hi(%1)", operands);
                output_asm_insn ("ldil %0, lo(%1)", operands);
                return "";
        case 2:                         /* immediate symbol to register */
                output_asm_insn ("ldih %0, hi(%c1)", operands);
                output_asm_insn ("ldil %0, lo(%c1)", operands);
                return "";
        case 3:                         /* register to memory */
                if (GET_CODE (XEXP(operands[0], 0)) == REG) {
                        operands[0] = XEXP(operands[0], 0);
                        return "st %1,(%0)";
                }
                fatal_insn ("Incorrect operand:", operands[0]);
        case 4:                         /* memory to register */
                if (GET_CODE (XEXP(operands[1], 0)) == REG) {
                        operands[1] = XEXP(operands[1], 0);
                        return "ld %0,(%1)";
                }
                fatal_insn ("Incorrect operand:", operands[1]);
        }
        return ""; 
  }
  [(set_attr "cc" "none")]
)

Does this look ok ? The 'fatal_insn' should not happen, because if I see
such a pattern in the define_expand "movqi" I force the use of a register:

(define_expand "movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
  ""
  {
        if (!reload_in_progress
            && !reload_completed) {

		if (GET_CODE (operands[0]) == MEM
                    && (GET_CODE (operands[1]) != REG)) {
                	operands[1] = force_reg (QImode, operands[1]);
                }
        	else if (GET_CODE(operands[1]) == MEM
	                && GET_CODE(XEXP(operands[1], 0)) == PLUS
	                && GET_CODE(XEXP(XEXP(operands[1], 0), 0)) == REG
	                && GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT) {
	                  /* indirect load */
	                  XEXP(operands[1], 0) = force_reg (QImode, XEXP (operands[1], 0));
		}
		else if (GET_CODE(operands[0]) == MEM
	                && GET_CODE(XEXP(operands[0], 0)) == PLUS
	                && GET_CODE(XEXP(XEXP(operands[0], 0), 0)) == REG
	                && GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT) {
	                  /* indirect store */
	                  XEXP(operands[0], 0) = force_reg (QImode, XEXP (operands[0], 0));
		}
        }
  }
)

This seems to work ok, but I still have issues at reload time, because
of the base register addressing mode: in the reload pass gcc generates
moves from/to the stack:

	Reloads for insn # 3
	Reload 0: reload_in (QI) = (reg/f:QI 31 r31) 
	        EVEN_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) 
	        reload_in_reg: (reg/f:QI 31 r31) 
	        reload_reg_rtx: (reg:QI 0 r0)
	Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 31 r31) 
	                                               (const_int -3 [0xfffffffd])) [10 S1 A16])
        EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
        reload_out_reg: (reg:QI 109 [ u ]) 

But those moves are illegal because there is no offset allowed in the
base register addressing mode (see the definition of my GO_IF_LEGITIMATE_ADDRESS() ),
so gcc crashes with 'unrecognizable insn'.

So what's the proper way to tell that indirect addressing is allowed,
but not with an offset ? Should I define an extra define_expand to deal
with those insns ?

Thanks again,

Stelian.
-- 
Stelian Pop <stelian@popies.net>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]