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]

Reload generates wrong spill


The following code is a testcase for avr where reload generates wrong
code:

struct S
{
    unsigned char a, b;
} ab = {12, 34};

void yoo (struct S y)
{
    __asm volatile ("ldi %B0, 56" : "+y" (y));
    y.a = 0;
    __asm volatile ("; y = %0" : "+y" (y));
    ab = y;
}

The asm just serves to direct struct S into register Y.
Y is a 16-bit reg that consists of two 8-bit regs r28 and r29.

The bug also occurs without inline asm for complex code, but this test
case is easier and the problem can be better reproduced.

Y also serves as frame pointer. avr_hard_regno_mode_ok allows
HImode=Pmode to go into Y but rejects QImode.

The program is compiled with -Os, there is no frame pointer needed and
Y can be allocated for ordinary data.

The line y.a = 0 reads in pass .asmcons

(insn 7 6 8 2 (set (subreg:QI (reg/v:HI 43 [ y ]) 0)
        (const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
     (nil))

This is the only insn between the two asms. After .ira this reads

(insn 7 6 17 2 (set (reg:QI 24 r24)
        (const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
     (nil))

(insn 17 7 8 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
        (reg:HI 24 r24)) pr46779-1.c:34 10 {*movhi}
     (nil))

so that r29 gets messed up, i.e. there is a

(set (reg:HI 24) (reg:HI 29))

missing before insn 7. Reload fails to generate this insn. This is the
case for current trunk (last snapshot) and 4.5. In 4.3, reload
generates correct code (at least for this test case).

gcc configured (SVN 172597, last 4.7 snapshot):
  --target=avr --disable-nls --disable-shared --enable-languages=c
  --prefix=...

avr-gcc command line: -c -dp -save-temps -Os -da

Thanks for any hints on this, especially if it's a reload bug or
complete abuse of HARD_REGNO_MODE_OK.

FYI, I attached the two dumps.

A complete test case is located in
 gcc.target/avr/pr46779-1.c

Johann

;; Function yoo (yoo)

deferring rescan insn with uid = 15.
deferring rescan insn with uid = 6.


yoo

Dataflow summary:
;;  invalidated by call 	 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35 [argH]
;;  hardware regs used 	 28 [r28] 32 [__SP_L__] 34 [argL]
;;  regular block artificial uses 	 28 [r28] 32 [__SP_L__] 34 [argL]
;;  eh block artificial uses 	 28 [r28] 32 [__SP_L__] 34 [argL]
;;  entry block defs 	 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;;  exit block uses 	 28 [r28] 32 [__SP_L__]
;;  regs ever live 	 24[r24] 25[r25]
;;  ref usage 	r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d} r21={1d} r22={1d} r23={1d} r24={1d,1u} r25={1d,1u} r28={1d,2u} r32={1d,2u} r34={1d,1u} r43={3d,4u} 
;;    total ref usage 35{24d,11u,0e} in 6{6 regular + 0 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)

;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u0(28){ }u1(32){ }u2(34){ }}
;; lr  in  	 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; lr  use 	 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; lr  def 	 43
;; live  in  	 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; live  gen 	 43
;; live  kill	

;; Pred edge  ENTRY [100.0%]  (fallthru)
(note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(note 2 4 3 2 NOTE_INSN_DELETED)

(note 3 2 15 2 NOTE_INSN_FUNCTION_BEG)

(insn 15 3 6 2 (set (reg/v:HI 43 [ y ])
        (reg:HI 24 r24 [ y ])) pr46779-1.c:32 -1
     (nil))

(insn 6 15 7 2 (set (reg/v:HI 43 [ y ])
        (asm_operands/v:HI ("ldi %B0, 56") ("=y") 0 [
                (reg/v:HI 43 [ y ])
            ]
             [
                (asm_input:HI ("0") (null):0)
            ]
             [] pr46779-1.c:36)) pr46779-1.c:32 -1
     (nil))

(insn 7 6 8 2 (set (subreg:QI (reg/v:HI 43 [ y ]) 0)
        (const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
     (nil))

(insn 8 7 10 2 (set (reg/v:HI 43 [ y ])
        (asm_operands/v:HI ("; y = %0") ("=y") 0 [
                (reg/v:HI 43 [ y ])
            ]
             [
                (asm_input:HI ("0") (null):0)
            ]
             [] pr46779-1.c:36)) pr46779-1.c:34 -1
     (nil))

(insn 10 8 12 2 (set (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
        (reg/v:HI 43 [ y ])) pr46779-1.c:35 10 {*movhi}
     (nil))

(insn 12 10 0 2 (set (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
        (subreg:QI (reg/v:HI 43 [ y ]) 0)) pr46779-1.c:35 4 {*movqi}
     (expr_list:REG_DEAD (reg/v:HI 43 [ y ])
        (nil)))
;; End of basic block 2 -> ( 1)
;; lr  out 	 28 [r28] 32 [__SP_L__] 34 [argL]
;; live  out 	 28 [r28] 32 [__SP_L__] 34 [argL]


;; Succ edge  EXIT [100.0%]  (fallthru)

starting the processing of deferred insns
rescanning insn with uid = 6.
deleting insn with uid = 6.
rescanning insn with uid = 15.
deleting insn with uid = 15.
ending the processing of deferred insns
;; Function yoo (yoo)

starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 (    1)
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 (    1)
Building IRA IR
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called

Pass 0 for finding pseudo/allocno costs

    a0 (r43,l0) best POINTER_Y_REGS, allocno POINTER_Y_REGS

  a0(r43,l0) costs: POINTER_X_REGS:8000,8000 POINTER_Y_REGS:0,0 POINTER_Z_REGS:8000,8000 BASE_POINTER_REGS:8000,8000 POINTER_REGS:8000,8000 ADDW_REGS:8000,8000 SIMPLE_LD_REGS:8000,8000 LD_REGS:8000,8000 NO_LD_REGS:8000,8000 GENERAL_REGS:8000,8000 ALL_REGS:8000,8000 MEM:28000,28000


Pass 1 for finding pseudo/allocno costs

    r43: preferred POINTER_Y_REGS, alternative GENERAL_REGS, allocno GENERAL_REGS

  a0(r43,l0) costs: POINTER_X_REGS:8000,8000 POINTER_Y_REGS:0,0 POINTER_Z_REGS:8000,8000 BASE_POINTER_REGS:8000,8000 POINTER_REGS:8000,8000 ADDW_REGS:8000,8000 SIMPLE_LD_REGS:8000,8000 LD_REGS:8000,8000 NO_LD_REGS:8000,8000 GENERAL_REGS:8000,8000 ALL_REGS:8000,8000 MEM:28000,28000

   Insn 12(l0): point = 0
   Insn 10(l0): point = 2
   Insn 8(l0): point = 4
   Insn 7(l0): point = 6
   Insn 6(l0): point = 8
   Insn 15(l0): point = 10
 a0(r43 [0]): [1..10]
 a0(r43 [1]): [3..10]
Compressing live ranges: from 13 to 2 - 15%
Ranges after the compression:
 a0(r43 [0]): [0..1]
 a0(r43 [1]): [0..1]
+++Allocating 8 bytes for conflict table (uncompressed size 8)
;; a0(r43,l0) conflicts:
;;   subobject 0:
;;     total conflict hard regs:
;;     conflict hard regs:


;;   subobject 1:
;;     total conflict hard regs:
;;     conflict hard regs:

  regions=1, blocks=3, points=2
    allocnos=1 (big 1), copies=0, conflicts=0, ranges=2

**** Allocnos coloring:


  Loop 0 (parent -1, header bb0, depth 0)
    bbs: 2
    all: 0r43
    modified regnos: 43
    border:
    Pressure: GENERAL_REGS=3
    Hard reg set forest:
      0:( 2-31)@112000
      Allocno a0r43 of GENERAL_REGS(30) has 29 avail. regs obj 0 2-31 (confl regs =  0 1 32-34 ) node:  2-31,  obj 1 2-31 (confl regs =  0 1 32-34 ) node:  2-31
      Pushing a0(r43,l0)(cost 0)
      Popping a0(r43,l0)  -- assign reg 28
Disposition:
    0:r43  l0    28
New iteration of spill/restore move
+++Costs: overall 0, reg 0, mem 0, ld 0, st 0, move 0
+++       move loops 0, new jumps 0
insn=15, live_throughout: 32, dead_or_set: 24, 25, 43
insn=6, live_throughout: 32, dead_or_set: 43
insn=7, live_throughout: 32, 43, dead_or_set: 43
insn=8, live_throughout: 32, dead_or_set: 43
insn=10, live_throughout: 32, 43, dead_or_set: 
insn=12, live_throughout: 32, dead_or_set: 43
changing reg in insn 15
changing reg in insn 6
changing reg in insn 8
changing reg in insn 6
changing reg in insn 10
changing reg in insn 8
changing reg in insn 7
Spilling for insn 7.
Using reg 24 for reload 0
Spilling for insn 10.
Spilling for insn 12.
Using reg 24 for reload 1

Reloads for insn # 7
Reload 0: reload_out (HI) = (reg/v:HI 28 r28 [orig:43 y ] [43])
	GENERAL_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
	reload_out_reg: (reg/v:HI 28 r28 [orig:43 y ] [43])
	reload_reg_rtx: (reg:HI 24 r24)

Reloads for insn # 10
Reload 0: reload_out (HI) = (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
	NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
	reload_out_reg: (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])

Reloads for insn # 12
Reload 0: reload_out (QI) = (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
	NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
	reload_out_reg: (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
Reload 1: reload_in (HI) = (reg/v:HI 28 r28 [orig:43 y ] [43])
	GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1)
	reload_in_reg: (reg/v:HI 28 r28 [orig:43 y ] [43])
	reload_reg_rtx: (reg:HI 24 r24)


try_optimize_cfg iteration 1

starting the processing of deferred insns
ending the processing of deferred insns
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 (    1)
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 (    1)


yoo

Dataflow summary:
;;  invalidated by call 	 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35 [argH]
;;  hardware regs used 	 32 [__SP_L__]
;;  regular block artificial uses 	 32 [__SP_L__]
;;  eh block artificial uses 	 32 [__SP_L__] 34 [argL]
;;  entry block defs 	 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14 [r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;;  exit block uses 	 32 [__SP_L__]
;;  regs ever live 	 24[r24] 25[r25] 28[r28] 29[r29]
;;  ref usage 	r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d} r21={1d} r22={1d} r23={1d} r24={3d,3u} r25={2d,2u} r28={4d,4u} r29={4d,4u} r32={1d,2u} 
;;    total ref usage 45{30d,15u,0e} in 8{8 regular + 0 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)

;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(32){ }}
;; lr  in  	 24 [r24] 25 [r25] 32 [__SP_L__]
;; lr  use 	 24 [r24] 25 [r25] 32 [__SP_L__]
;; lr  def 	 24 [r24] 25 [r25] 28 [r28] 29 [r29]
;; live  in  	 24 [r24] 25 [r25] 32 [__SP_L__]
;; live  gen 	 24 [r24] 25 [r25] 28 [r28] 29 [r29]
;; live  kill	

;; Pred edge  ENTRY [100.0%]  (fallthru)
(note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(note 2 4 3 2 NOTE_INSN_DELETED)

(note 3 2 15 2 NOTE_INSN_FUNCTION_BEG)

(insn 15 3 6 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
        (reg:HI 24 r24 [ y ])) pr46779-1.c:32 10 {*movhi}
     (nil))

(insn 6 15 7 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
        (asm_operands/v:HI ("ldi %B0, 56") ("=y") 0 [
                (reg/v:HI 28 r28 [orig:43 y ] [43])
            ]
             [
                (asm_input:HI ("0") (null):0)
            ]
             [] pr46779-1.c:36)) pr46779-1.c:32 -1
     (nil))

(insn 7 6 17 2 (set (reg:QI 24 r24)
        (const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
     (nil))

(insn 17 7 8 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
        (reg:HI 24 r24)) pr46779-1.c:34 10 {*movhi}
     (nil))

(insn 8 17 10 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
        (asm_operands/v:HI ("; y = %0") ("=y") 0 [
                (reg/v:HI 28 r28 [orig:43 y ] [43])
            ]
             [
                (asm_input:HI ("0") (null):0)
            ]
             [] pr46779-1.c:36)) pr46779-1.c:34 -1
     (nil))

(insn 10 8 18 2 (set (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
        (reg/v:HI 28 r28 [orig:43 y ] [43])) pr46779-1.c:35 10 {*movhi}
     (nil))

(insn 18 10 12 2 (set (reg:HI 24 r24)
        (reg/v:HI 28 r28 [orig:43 y ] [43])) pr46779-1.c:35 10 {*movhi}
     (nil))

(insn 12 18 16 2 (set (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2]  <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
        (reg:QI 24 r24)) pr46779-1.c:35 4 {*movqi}
     (nil))
;; End of basic block 2 -> ( 1)
;; lr  out 	 32 [__SP_L__]
;; live  out 	 32 [__SP_L__]


;; Succ edge  EXIT [100.0%]  (fallthru)

(note 16 12 0 NOTE_INSN_DELETED)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]