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