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