This is the mail archive of the gcc-bugs@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]

[Bug rtl-optimization/35604] New: Label references are not updated after edge insertion


This problem can be seen by compiling testsuite/gfortran.dg/g77/ndrm2.f. The
label reference (after x87 stack compensation edge is inserted) is updated only
in final jump insn, but other references to the same label are left untouched.

We enter stack pass with:

(insn:TI 19 20 18 4 dnrm2.f:33 (set (reg/v/f:SI 1 dx [orig:73 next.2 ] [73])
        (label_ref:SI 53)) 47 {*movsi_1} (expr_list:REG_EQUAL (label_ref:SI 53)
        (insn_list:REG_LABEL_OPERAND 53 (nil))))

...

(insn 23 137 17 4 dnrm2.f:40 (set (reg:CCZ 17 flags)
        (compare:CCZ (reg/v/f:SI 1 dx [orig:73 next.2 ] [73])
            (label_ref:SI 53))) 5 {*cmpsi_1_insn} (insn_list:REG_LABEL_OPERAND
53 (nil)))

...

(jump_insn 24 245 355 4 dnrm2.f:40 (set (pc)
        (if_then_else (eq (reg:CCZ 17 flags)
                (const_int 0 [0x0]))
            (label_ref 53)
            (pc))) 579 {*jcc_1} (expr_list:REG_DEAD (reg:CCZ 17 flags)
        (expr_list:REG_BR_PROB (const_int 1500 [0x5dc])
            (nil))))

;; End of basic block 4 -> ( 13 5)
;; lr  out       1 [dx] 3 [bx] 4 [si] 6 [bp] 7 [sp] 11 [st(3)] 12 [st(4)] 20
[frame]
;; live  out     1 [dx] 3 [bx] 4 [si] 6 [bp] 7 [sp] 12 [st(4)] 20 [frame]

;; Succ edge  13 [15.0%]  (can_fallthru)
;; Succ edge  5 [85.0%]  (fallthru,can_fallthru)


Where the target code label is in BB13:

;; Pred edge  4 [15.0%]  (can_fallthru)
;; Pred edge  12 [15.0%]  (fallthru,can_fallthru)
(code_label/s:HI 53 325 54 13 3 ("__label_000030") [6 uses])

(note:HI 54 53 59 13 [bb 13] NOTE_INSN_BASIC_BLOCK)

====

The BB is inserted on edge between bb4 and bb13, the target code label is now
label 435 in bb37:

;; Start of basic block ( 4) -> 37
;; bb 37 artificial_defs: { }
;; bb 37 artificial_uses: { u-1(6){ }u-1(7){ }}

;; Pred edge  4 [15.0%]  (can_fallthru)
(code_label 435 433 434 37 31 "" [1 uses])

(note 434 435 381 37 [bb 37] NOTE_INSN_BASIC_BLOCK)

(insn 381 434 380 37 (set (reg:DF 9 st(1))
        (reg:DF 8 st)) -1 (expr_list:REG_DEAD (reg:DF 8 st)
        (nil)))

(note 380 381 53 37 NOTE_INSN_DELETED)
;; End of basic block 37 -> ( 13)


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

===

However, the problem is, that (insn 19) and (insn 23) still point to old label,
producing effectively wrong code:

>>      movl    $.L3, %edx      #, next.2
        movl    $1, %ebx        #, ix
        sall    $3, %eax        #,
>>      cmpl    $.L3, %edx      #, next.2
        movl    $1, -28(%ebp)   #, i
        fldz
        movl    %eax, -20(%ebp) #,
>>      je      .L31    #,

This works only by pure luck.

However, with my experimental patch that produces fused compare-and-branch (a
feature of core2 processor), we enter stack pass with:

(jump_insn:TI 24 245 354 4 dnrm2.f:40 (set (pc)
        (if_then_else (eq (reg/v/f:SI 1 dx [orig:73 next.2 ] [73])
                (label_ref:SI 53))
            (label_ref 53)
            (pc))) 581 {*jcc_fused_1} (insn_list:REG_LABEL_OPERAND 53
(expr_list:REG_BR_PROB (const_int 1500 [0x5dc])
            (nil))))

All label references are updated in a fused jump insn after edge insertion, so
this partially updated sequence is produced:

(insn 19 137 17 4 dnrm2.f:33 (set (reg/v/f:SI 1 dx [orig:73 next.2 ] [73])
        (label_ref:SI 53)) 47 {*movsi_1} (expr_list:REG_EQUAL (label_ref:SI 53)
        (insn_list:REG_LABEL_OPERAND 53 (nil))))

...

(jump_insn:TI 24 245 354 4 dnrm2.f:40 (set (pc)
        (if_then_else (eq (reg/v/f:SI 1 dx [orig:73 next.2 ] [73])
                (label_ref:SI 434))
            (label_ref:SI 434)
            (pc))) 581 {*jcc_fused_1} (insn_list:REG_LABEL_OPERAND 53
(expr_list:REG_BR_PROB (const_int 1500 [0x5dc])
            (nil))))


leading to:

>>>     movl    $.L3, %edx
        movl    $1, -28(%ebp)
        movl    $1, %ebx
        fldz
        movl    %eax, -20(%ebp)
        .p2align 4,,7
>>>     cmpl    $.L31, %edx
>>>     je      .L31    # fused

This is still wrong code, but triggers a testsuite failure. And by changing
$.L3 into $.L31, the test succeeds also with fused compare and branch.

The conclusion is, that updating only jump insn is not enough, but all label
references should be updated to newly inserted label when edge is inserted into
control flow.


-- 
           Summary: Label references are not updated after edge insertion
           Product: gcc
           Version: 4.4.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: ubizjak at gmail dot com
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35604


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