[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 <[EMAIL PROTECTED]>

Reply via email to