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]

Problem with reloading in a new backend...


Hi,

I'm working on a GCC (4.3.0) backend for a custom 16 bit microcontroller
we're designing at work, and I'm facing a reload problem. After having
lost many hours trying to make it work, I decided to ask for some
help :)

I'll try to summarize the situation below, but by all means please ask
for more if something is missing.

The error I'm encountering happens when compiling _divdi3 in libgcc
(note that before compiling this one, several functions from libgcc
compiled fine):

../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c: In function â__divhi3â:
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: error: insn does not satisfy its constraints:
(insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10)
        (const_int 24 [0x18])) 1 {*movqi_imm} (nil))
../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: internal compiler error: in reload_cse_simplify_operands, at postreload.c:395

The microcontroller in question is a 16 bit one, and addresses the
memory only in 16 bit words:
	#define BITS_PER_UNIT	16
	#define UNITS_PER_WORD	1

This microcontroller has 32 hard registers. Immediate constants can only
be loaded into the first 8 registers. There are no index registers. All
the even registers can serve as a base register. However, the base
register addressing is reduced to its simplest form, where the offset is
always 0.

Based on the above, I have defined:
	enum reg_class
	{
	  NO_REGS,
	  STACK_REGS,
	  EIGHT_REGS,
	  EVEN_REGS,
	  ALL_REGS,
	  LIM_REG_CLASSES
	};

	#define GENERAL_REGS ALL_REGS

	...

	#define REG_CLASS_CONTENTS                      \
	{                                               \
	  { 0x00000000 },                               \
	  { 0x80000000 },                               \
	  { 0x000000FF },                               \
	  { 0x55555555 },                               \
	  { (1LL << FIRST_PSEUDO_REGISTER) - 1 }        \
	}

	#define REGNO_REG_CLASS(REGNO)                  \
	  ((REGNO) > 30   ? STACK_REGS                  \
	   : (REGNO) < 8  ? EIGHT_REGS                  \
	   : (REGNO % 2) == 0  ? EVEN_REGS              \
	   : GENERAL_REGS)

	#define BASE_REG_CLASS EVEN_REGS

	#define INDEX_REG_CLASS NO_REGS

	#define REGNO_OK_FOR_BASE_P(NUM) (NUM % 2 == 0)

	#define REGNO_OK_FOR_INDEX_P(NUM) 0

	#define PREFERRED_RELOAD_CLASS(X, CLASS)        \
	  ((CONSTANT_P(X)) ? EIGHT_REGS :               \
	   (MEM_P(X)) ? EVEN_REGS : CLASS)

	#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \
	  ((CONSTANT_P(X)) ? EIGHT_REGS :               \
	   (MEM_P(X)) ? EVEN_REGS : CLASS)

	...

	#define STACK_POINTER_REGNUM 31

	#define FRAME_POINTER_REGNUM 30

	....

	#ifdef REG_OK_STRICT
	#define REG_OK_FOR_BASE_P(X)                            \
	        (REGNO_OK_FOR_BASE_P (REGNO (X)) && (REGNO (X) <FIRST_PSEUDO_REGISTER))
	#else
	#define REG_OK_FOR_BASE_P(X)                            \
        	(REGNO_OK_FOR_BASE_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
	#endif

	#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)        \
	do {                                                    \
	  if (GET_CODE (X) == REG && (REG_OK_FOR_BASE_P(X)))    \
	    goto LABEL;                                         \
	  else if (GET_CODE(X) == PLUS &&                       \
	           REG_OK_FOR_BASE_P (XEXP (X, 0)) &&           \
	           GET_CODE(XEXP(X,1)) == CONST_INT &&          \
	           INTVAL(XEXP(X,1)) == 0)                      \
	    goto LABEL;                                         \
	} while (0)


I also defined some constraints for the register classes:

	(define_register_constraint "x" "STACK_REGS"
	  "Stack registers (r30--r31)")

	(define_register_constraint "y" "EIGHT_REGS"
	  "Low eight registers (r0--r7)")

	(define_register_constraint "z" "EVEN_REGS"
	  "Even registers (r0,r2,r4, @dots{} r30)")


The movqi_imm pattern which constraints doesn't match has been defined
with (note the 'y' constrant):

	(define_insn "*movqi_imm"
	  [(set (match_operand:QI 0 "register_operand" "=y")
	        (match_operand:QI 1 "const_int_operand" ""))]
	  ""  
	  {
	        output_asm_insn ("ldih %0, hi(%1)", operands);
	        output_asm_insn ("ldil %0, lo(%1)", operands);
	        return "";
	  }
	  [(set_attr "cc" "none")]
	)

Now, I'm trying to figure out why the error happens, with GCC choosing
to put an immediate into r10 instead of an EIGHT_REGS. It all seems to
come (I do not know why) from insn 16 in libgcc2.c.175r.lreg:

	Register 453 costs: EIGHT_REGS:0 EVEN_REGS:0 ALL_REGS:0 MEM:4175
	Register 466 costs: EIGHT_REGS:600 EVEN_REGS:600 ALL_REGS:600 MEM:5200
	...
	Register 453 pref EVEN_REGS
	Register 466 pref EVEN_REGS
	...
	(insn 16 15 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 453 [ uu+1 ])
	        (reg:QI 466 [ v ])) 0 {*movqi_reg} (nil))

In libgcc2.c.176.greg I see:

	Reloads for insn # 16
	Reload 0: reload_in (QI) = (plus:QI (reg/f:QI 30 r30)
	                                                    (const_int 24 [0x18]))
	        EVEN_REGS, RELOAD_FOR_OUTPUT_ADDRESS (opnum = 0), can't combine 
	        reload_in_reg: (plus:QI (reg/f:QI 30 r30)
                                                    (const_int 24 [0x18]))
	        reload_reg_rtx: (reg:QI 10 r10)
	Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 30 r30)
        	                                                (const_int 24 [0x18])) [31 S1 A16])
	        EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
	        reload_out_reg: (reg:QI 453 [ uu+1 ])
	        reload_reg_rtx: (reg:QI 14 r14)


	...

	(insn 16 1115 1117 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 14 r14)
	        (reg:QI 2 r2 [orig:466 v ] [466])) 0 {*movqi_reg} (nil))

	(insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10)
	        (const_int 24 [0x18])) 1 {*movqi_imm} (nil))

	(insn 1118 1117 1119 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10)
	        (plus:QI (reg:QI 10 r10)
	            (reg/f:QI 30 r30))) 13 {addqi3} (expr_list:REG_EQUIV (plus:QI (reg/f:QI 30 r30)
	            (const_int 24 [0x18]))
	        (nil)))

	(insn 1119 1118 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (mem/c:QI (reg:QI 10 r10) [31 S1 A16])
	        (reg:QI 14 r14)) 8 {*movqi_tomem} (nil))

I tried playing with different definitions for PREFERRED_RELOAD_CLASS,
PREFERRED_OUTPUT_RELOAD_CLASS, TARGET_SECONDARY_RELOAD, with no luck.

Thanks to anybody who can explain to me what's wrong here, and give a clue
on what I must do to fix it.

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]