The r8c/m16c family cannot shift by more than 16 bits at a time ever,
or 8 bits at a time with constant shifts.  So, to do a variable number
of shift on a 32 bit value, it needs to emit a conditional, turning
the attached example into this:

i = 0xfffff;
if (j >= 16)
  {
    i >>= 8;
    i >>= 8;
    j -= 16;
  }
...

Combine (rightfully) knows that i becomes the constant 0xf and
replaces the two constant shifts with it.  However, it doesn't update
the life information.  So, we have a basic block (#3 below) which has
register 28 live, but being assigned (i.e. it's really dead).  GCC
notices this later, and dies.

Ideas?


--------------------
int foo(int j)
{
  long i = 0xfffff;
  return i >> j;
}

--------------------
$ ./cc1 -quiet -Os dj.c
Register 28 died unexpectedly.
;; basic block 3, loop depth 0, count 0
;; prev block 2, next block 4
;; pred:       2 [50.0%]  (fallthru)
;; succ:       4 [100.0%]  (fallthru)
;; Registers live at start:  7 [fb] 8 [sp] 11 [argp] 28 30
(note 34 13 14 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
(note 14 34 15 3 NOTE_INSN_DELETED)
(insn 15 14 16 3 (set (reg:SI 28)
        (const_int 15 [0xf])) 173 {movsi_splittable} (nil)
    (nil))
(insn 16 15 17 3 (set (reg:QI 30)
        (plus:QI (reg:QI 30)
            (const_int 16 [0x10]))) 2 {addqi3} (nil)
    (nil))
;; Registers live at end:  7 [fb] 8 [sp] 11 [argp] 28 30
dj.c: In function 'foo':
dj.c:5: internal compiler error: internal consistency failure


--------------------
#0  internal_error (gmsgid=0x868f18 "internal consistency failure")
    at ../../gcc/gcc/diagnostic.c:582
#1  0x00000000005e6da9 in verify_local_live_at_start 
(new_live_at_start=0xbce5f8, bb=0x2a95599480)
    at ../../gcc/gcc/flow.c:544
#2  0x00000000005e71a2 in update_life_info (blocks=0x0, 
extent=UPDATE_LIFE_LOCAL, prop_flags=5)
    at ../../gcc/gcc/flow.c:698
#3  0x00000000005ede09 in recompute_reg_usage () at ../../gcc/gcc/flow.c:4476
#4  0x00000000006ef93e in execute_one_pass (pass=0xb1bda0) at 
../../gcc/gcc/passes.c:872
#5  0x00000000006efaac in execute_pass_list (pass=0xb1bda0) at 
../../gcc/gcc/passes.c:919
#6  0x00000000006efabe in execute_pass_list (pass=0xb1cc20) at 
../../gcc/gcc/passes.c:920


--------------------
;; Function foo (foo)

insn_cost 6: 4
insn_cost 11: 4
insn_cost 12: 4
insn_cost 13: 0
insn_cost 14: 8
insn_cost 15: 8
insn_cost 16: 8
insn_cost 18: 8
insn_cost 26: 4
insn_cost 32: 0
(note 2 0 8 NOTE_INSN_DELETED)

;; Start of basic block 2, registers live: 2 [r1] 7 [fb] 8 [sp] 11 [argp]
(note 8 2 6 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 6 8 7 2 (set (reg/v:HI 26 [ j ])
        (reg:HI 2 r1 [ j ])) 171 {movhi_op} (nil)
    (expr_list:REG_DEAD (reg:HI 2 r1 [ j ])
        (nil)))

(note 7 6 11 2 NOTE_INSN_FUNCTION_BEG)

(insn 11 7 12 2 (set (reg:QI 30)
        (neg:QI (subreg:QI (reg/v:HI 26 [ j ]) 0))) 12 {negqi2} 
(insn_list:REG_DEP_TRUE 6 (nil))
    (expr_list:REG_DEAD (reg/v:HI 26 [ j ])
        (nil)))

(insn 12 11 13 2 (set (reg:SI 28)
        (const_int 1048575 [0xfffff])) 173 {movsi_splittable} (nil)
    (expr_list:REG_EQUAL (const_int 1048575 [0xfffff])
        (nil)))

(jump_insn 13 12 34 2 (set (pc)
        (if_then_else (ge (reg:QI 30)
                (const_int -16 [0xfffffffffffffff0]))
            (label_ref 17)
            (pc))) 47 {cbranchqi4} (insn_list:REG_DEP_TRUE 11 (nil))
    (expr_list:REG_BR_PROB (const_int 5000 [0x1388])
        (nil)))
;; End of basic block 2, registers live:
 7 [fb] 8 [sp] 11 [argp] 28 30

;; Start of basic block 3, registers live: 7 [fb] 8 [sp] 11 [argp] 28 30
(note 34 13 14 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(note 14 34 15 3 NOTE_INSN_DELETED)

(insn 15 14 16 3 (set (reg:SI 28)
        (const_int 15 [0xf])) 173 {movsi_splittable} (nil)
    (nil))

(insn 16 15 17 3 (set (reg:QI 30)
        (plus:QI (reg:QI 30)
            (const_int 16 [0x10]))) 2 {addqi3} (nil)
    (nil))
;; End of basic block 3, registers live:
 7 [fb] 8 [sp] 11 [argp] 28 30

;; Start of basic block 4, registers live: 7 [fb] 8 [sp] 11 [argp] 28 30
(code_label 17 16 35 4 2 "" [1 uses])

(note 35 17 18 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 18 35 23 4 (parallel [
            (set (reg:SI 28)
                (ashiftrt:SI (reg:SI 28)
                    (neg:QI (reg:QI 30))))
            (clobber (scratch:HI))
        ]) 225 {ashrsi3_16} (nil)
    (expr_list:REG_DEAD (reg:QI 30)
        (expr_list:REG_UNUSED (scratch:HI)
            (expr_list:REG_EQUAL (ashiftrt:SI (const_int 1048575 [0xfffff])
                    (subreg:QI (reg/v:HI 26 [ j ]) 0))
                (nil)))))

(note 23 18 26 4 NOTE_INSN_FUNCTION_END)

(insn 26 23 32 4 (set (reg/i:HI 0 r0 [ <result> ])
        (subreg:HI (reg:SI 28) 0)) 171 {movhi_op} (insn_list:REG_DEP_TRUE 18 
(nil))
    (expr_list:REG_DEAD (reg:SI 28)
        (nil)))

(insn 32 26 0 4 (use (reg/i:HI 0 r0 [ <result> ])) -1 (insn_list:REG_DEP_TRUE 
26 (nil))
    (nil))
;; End of basic block 4, registers live:
 0 [r0] 7 [fb] 8 [sp] 11 [argp]

Reply via email to