Hello,

I'm currently writing a gcc backend for a microcontroller architecture which 
can only handle indirect memory accesses.
In normal cases all works fine, but there is a special case where the reload 
pass (<- not sure) produces a direct memory access in -O2 optimization mode 
which causes the postreload pass to abort.

The relevant c-code uses a constant memory address:

#define IO_BASE         (0x34000)
#define UART2OFF        (0x08)
#define UART2BASE       ((void *)(IO_BASE+(UART2OFF*2)))

u = (struct uart *)UART2BASE;

So basically u has the constant address 0x34010 which is known at compile time.

The instruction where the error occurs is the following:
u->tx_data = tx;

In the source.c.128r.expand dump file this line looks like this:
(insn 40 39 41 5 ../uart2sim/uart2i_3.c:272 (set (reg/f:HI 46)
        (symbol_ref:HI ("tx") [flags 0x2] <var_decl 0xb7ca7268 tx>)) -1 (nil))

(insn 41 40 42 5 ../uart2sim/uart2i_3.c:272 (set (reg:HI 28 [ tx.44 ])
        (zero_extend:HI (mem/c/i:QI (reg/f:HI 46) [0 tx+0 S1 A9]))) -1 (nil))

(insn 42 41 43 5 ../uart2sim/uart2i_3.c:272 (set (reg:HI 27 [ D.1392 ])
        (reg:HI 28 [ tx.44 ])) -1 (nil))

(insn 43 42 44 5 ../uart2sim/uart2i_3.c:272 (set (reg/f:HI 47)
        (const_int -49136 [0xffffffffffff4010])) -1 (nil))

(insn 44 43 45 5 ../uart2sim/uart2i_3.c:272 (set (mem/s:HI (plus:HI (reg/f:HI 
47)
                (const_int 4 [0x4])) [2 <variable>.tx_data+0 S2 A18])
        (reg:HI 27 [ D.1392 ])) -1 (nil))

So basically its like it should be. An indirect store operation using pseudo 
register 47 as base register. The fact that the constant 0x34010 is negative is 
due to the fact that our pmode is only 18 bit wide. It shouldn't be a problem 
if the constant gets loaded into a register.

The above insns change a bit during the following passes. In the 
source.c.168r.asmcons dump file it basically looks like this:

(insn 171 36 43 2 ../uart2sim/uart2i_3.c:272 (set (reg/f:HI 104)
        (reg/f:HI 85)) 2 {movhi} (expr_list:REG_EQUAL (symbol_ref:HI ("tx") 
[flags 0x2] <var_decl 0xb7ca7268 tx>)
        (nil)))

(insn 43 171 49 2 ../uart2sim/uart2i_3.c:272 (set (reg/f:HI 105)
        (reg/f:HI 35)) 2 {movhi} (expr_list:REG_DEAD (reg/f:HI 35)
        (expr_list:REG_EQUAL (const_int -49136 [0xffffffffffff4010])
            (nil))))

(insn 41 39 44 4 ../uart2sim/uart2i_3.c:272 (set (reg:HI 28 [ tx.44 ])
        (zero_extend:HI (mem/c/i:QI (reg/f:HI 85) [0 tx+0 S1 A9]))) 26 
{zero_extendqihi2} (expr_list:REG_EQUAL (zero_extend:HI (mem/c/i:QI 
(symbol_ref:HI ("tx") [flags 0x2] <var_decl 0xb7ca7268 tx>) [0 tx+0 S1 A9]))
        (nil)))

(insn 44 41 45 4 ../uart2sim/uart2i_3.c:272 (set (mem/s:HI (plus:HI (reg/f:HI 
105)
                (const_int 4 [0x4])) [2 <variable>.tx_data+0 S2 A18])
        (reg:HI 28 [ tx.44 ])) 2 {movhi} (nil))

So the memory instruction is still indirect. But after the ira/reload pass the 
following is found in the source.c.172r.ira dump file:

(insn 41 39 44 4 ../uart2sim/uart2i_3.c:272 (set (reg:HI 7 r7 [orig:28 tx.44 ] 
[28])
        (zero_extend:HI (mem/c/i:QI (reg/f:HI 9 r9 [85]) [0 tx+0 S1 A9]))) 26 
{zero_extendqihi2} (expr_list:REG_EQUAL (zero_extend:HI (mem/c/i:QI 
(symbol_ref:HI ("tx") [flags 0x2] <var_decl 0xb7ca7268 tx>) [0 tx+0 S1 A9]))
        (nil)))

(insn 44 41 45 4 ../uart2sim/uart2i_3.c:272 (set (mem/s:HI (plus:HI (const_int 
-49136 [0xffffffffffff4010])
                (const_int 4 [0x4])) [2 <variable>.tx_data+0 S2 A18])
        (reg:HI 7 r7 [orig:28 tx.44 ] [28])) 2 {movhi} (nil))

So NOW it is a direct store operation. And the compiler crashes with the 
following error message:

../uart2sim/uart2i_3.c: In Funktion »main«:
../uart2sim/uart2i_3.c:307: Fehler: Befehl erfüllt nicht seine Bedingungen:
(insn 44 41 45 4 ../uart2sim/uart2i_3.c:272 (set (mem/s:HI (plus:HI (const_int 
-49136 [0xffffffffffff4010])
                (const_int 4 [0x4])) [2 <variable>.tx_data+0 S2 A18])
        (reg:HI 7 r7 [orig:28 tx.44 ] [28])) 2 {movhi} (nil))
../uart2sim/uart2i_3.c:307: interner Compiler-Fehler: in 
reload_cse_simplify_operands, bei postreload.c:396

Its German output. In English it sais that the instruction doesn't match its 
constraints which are tested in line 396 in postreload.c which looks like this:
  /* Figure out which alternative currently matches.  */
  if (! constrain_operands (1))
    fatal_insn_not_found (insn);

Obviously this line asks the GO_IF_LEGITIMATE_ADDRESS macro. If I allow direct 
addresses there, the postreload pass doesn't crash.
The GO_IF_LEGITIMATE_ADDRESS helper function looks like this:

int valid = 0;
switch (GET_CODE (x))
{
        case REG:
                valid = REG_OK_FOR_BASE_P (x);
                break;
                        
        case PLUS:
        {
                rtx base = XEXP (x, 0);
                rtx offset = XEXP (x, 1);
                        
                valid = (REG == GET_CODE (base) &&
                         REGNO_OK_FOR_BASE_P (base) &&
                         CONST_INT == GET_CODE (offset) &&
                         GET_CODE(offset) != SYMBOL_REF &&
                         x_const_ok_for_base (mode, REGNO (base), INTVAL 
(offset)));
                break;
        }
        default:
                valid = 0;
}
return valid;   

So the macro only allows register and register+offset indirect memory 
addresses. But it looks like only postreload checks this, not the ira/reload 
pass.

With -O0 and -O1 optimization modes the error doesn't occur.

I have no idea which target macro could have the right influence on the reload 
pass to prohibit this instruction merging and creation of a direct memory 
access.

You guys helped me once, hope you can help me again :)

Thanks in advance!
Eric Neumann


Reply via email to