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]

ICE on 2.6.7-rc1 kernel at -O2 (SPARC)


Hi Jakub, Richard,

I need your help for this one.  GCC 3.3.3, 3.3.4pre, 3.4.0, 3.4.1pre ICE at 
-O2 on the following testcase extracted from the 2.6.7-rc1 kernel:

static __inline__ __attribute__ ((always_inline))
int page_mapping (unsigned flags)
{
  if (1u & (flags >> 16))
    return 1;
  return 0;
}
void install_page (unsigned flags)
{
  if (__builtin_expect (!page_mapping (flags), 0))
    __builtin_trap ();
}

pr15693.c: In function `install_page':
pr15693.c:12: error: unrecognizable insn:
(insn 53 16 54 0 0x401ad380 (set (reg:SI 112)
        (zero_extract:SI (reg:SI 110)
            (const_int 1 [0x1])
            (const_int 31 [0x1f]))) -1 (nil)
    (expr_list:REG_DEAD (reg:SI 110)
        (nil)))
pr15693.c:12: internal compiler error: in extract_insn, at recog.c:2175


What happens if that combine builds the following valid insn:

(insn 17 16 18 0 0x401ad3c0 (set (reg:CC 100 %icc)
        (compare:CC (zero_extract:SI (reg:SI 110)
                (const_int 1 [0x1])
                (const_int 31 [0x1f]))
            (const_int 0 [0x0]))) 149 {*cmp_zero_extract} (insn_list 15 
(nil))
    (expr_list:REG_DEAD (reg:SI 110)
        (nil)))

and ce2 splits it back into:

(insn 53 16 54 0 0x401ad380 (set (reg:SI 112)
        (zero_extract:SI (reg:SI 110)
            (const_int 1 [0x1])
            (const_int 31 [0x1f]))) -1 (nil)
    (expr_list:REG_DEAD (reg:SI 110)
        (nil)))

(insn 54 53 55 0 0x401ad380 (set (reg:CC 100 %icc)
        (compare:CC (reg:SI 112)
            (const_int 0 [0x0]))) -1 (nil)
    (expr_list:REG_DEAD (reg:SI 112)
        (nil)))

which is not valid anymore.


This is a regression from GCC 3.3.2 which was introduced/exposed by

2004-01-11  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/13392
	* builtins.c (expand_builtin_expect_jump): Handle conditional jumps
	to drop through label.  Don't fall back to SCC even when conditional
	jump has not been found.


Before the patch, a NOTE_INSN_EXPECTED_VALUE was emitted along with the 
unusual insn:

(insn 30 29 31 (nil) (parallel [
            (set (reg:SI 113)
                (eq:SI (reg:SI 114)
                    (const_int 0 [0x0])))
            (clobber (reg:CC 100 %icc))
        ]) -1 (nil)
    (nil))

(note 31 30 32 (eq (reg:SI 113)
        (const_int 0 [0x0])) NOTE_INSN_EXPECTED_VALUE)

After the patch, they are not emitted anymore.


In both cases (before and after the patch), the __builtin_expect jump is 
given the same prob in 03.jump:

(jump_insn 33 32 45 3 0x401ad380 (set (pc)
        (if_then_else (eq (reg:CC 100 %icc)
                (const_int 0 [0x0]))
            (label_ref 40)
            (pc))) 37 {*normal_branch} (nil)
    (expr_list:REG_BR_PRED (concat (const_int 6 [0x6])
            (const_int 9001 [0x2329]))
        (nil)))
;; End of basic block 3, registers live:
 (nil)

;; Start of basic block 4, registers live: (nil)
(note 45 33 35 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 35 45 36 4 0x401ad380 (trap_if (const_int 1 [0x1])
        (const_int 5 [0x5])) -1 (nil)
    (nil))
;; End of basic block 4, registers live:
 (nil)

However, after the patch (presumably because of the absence of the unusual 
insn), GCSE is able to thread the jumps and the __builtin_expect jump is 
eliminated altogether.  We eventually end up with

(jump_insn 18 17 40 0 0x401ad3c0 (set (pc)
        (if_then_else (ne (reg:CC 100 %icc)
                (const_int 0 [0x0]))
            (label_ref 37)
            (pc))) 37 {*normal_branch} (insn_list 17 (nil))
    (expr_list:REG_DEAD (reg:CC 100 %icc)
        (expr_list:REG_BR_PROB (const_int 3300 [0xce4])
            (nil))))
;; End of basic block 0, registers live:
 14 [%sp] 31 [%i7] 101 [%sfp]

;; Start of basic block 1, registers live: 14 [%sp] 101 [%sfp]
(note 40 18 32 1 [bb 1] NOTE_INSN_BASIC_BLOCK)

(insn 32 40 33 1 0x401ad380 (trap_if (const_int 1 [0x1])
        (const_int 5 [0x5])) -1 (nil)
    (nil))
;; End of basic block 1, registers live:
 14 [%sp] 101 [%sfp]

in 19.combine, that is the expected jump is wrongly predicted!


The compiler generates the invalid insn when it applies the TRAP-IF 
transformation to the RTL during ce2 right after combine.  This didn't 
happen before the patch because the TRAP-IF was applied during ce1, which 
runs before combine.


What should we fix?  If we fix the back-end, can we generate code as 
efficient as what was emitted by GCC 3.3.2?  With a peephole?

install_page:
        !#PROLOGUE# 0
        !#PROLOGUE# 1
        srl     %o0, 16, %o0
        andcc   %o0, 1, %g0
        te      5
        retl
        nop


Thanks in advance.

-- 
Eric Botcazou


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