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]

Re: Question about CASE_DROPS_THROUGH


Roger Sayle <roger@eyesopen.com> writes:
[...]
> Alas, the VAX backends's unique requirement to keep the "offset table"
> in the RTL stream has been the source of continual headaches for GCC.
>
> Perhaps rather than drop support for the VAX completely, a compromise
> would be to simply discontinue support of its' CASE_ op-code?  This
> simplifies much CFG manipulation, with only a small performance/space
> cost to the VAX.

While I certainly have no objection to dropping VAX, it seems to me
that there have been problems with the 'offset table' in the RTL
stream on other architectures.  More accurately, there are problems
with the "tablejump insn" -- here's the RTL generated for a simple
switch for the x86 (range check not shown):

(insn 13 83 14 2 (set (reg/f:SI 61)
        (label_ref:SI 17)) -1 (nil)
    (insn_list:REG_LABEL 17 (nil)))

(insn 14 13 15 2 (set (reg:SI 62)
        (mem/u/c:SI (plus:SI (mult:SI (reg/v:SI 60 [ x ])
                    (const_int 4 [0x4]))
                (reg/f:SI 61)) [0 S4 A8])) -1 (nil)
    (nil))

(jump_insn 15 14 16 2 (parallel [
            (set (pc)
                (reg:SI 62))
            (use (label_ref 17))
        ]) -1 (nil)
    (nil))

(barrier 16 15 17)

(code_label 17 16 18 11 "" [2 uses])

(jump_insn 18 17 19 (addr_vec:SI [
            (label_ref:SI 25)
            (label_ref:SI 31)
            (label_ref:SI 37)
            (label_ref:SI 43)
            (label_ref:SI 49)
            (label_ref:SI 55)
            (label_ref:SI 61)
            (label_ref:SI 67)
        ]) -1 (nil)
    (nil))

(barrier 19 18 20)

Getting rid of the VAX casesi isn't going to cure the fact that we
have a bizarre jump_insn that has to be special cased in recog; that
the barrier at insn 16 is special cased not to constitute a basic
block boundary; that insns 17 and 18 are unreachable, although
code_label 17 does have its address taken.  The only additional twist
that the VAX adds is, control *can* reach the label vector (sort of):
RTL for VAX looks like this:

(jump_insn 11 4 12 0 (set (pc)
        (if_then_else (leu (minus:SI (reg/v:SI 23 [ x ])
                    (const_int 0 [0x0]))
                (const_int 7 [0x7]))
            (plus:SI (sign_extend:SI (mem:HI (plus:SI (mult:SI
        (minus:SI (reg/v:SI 23 [ x ])
                                    (const_int 0 [0x0]))
                                (const_int 2 [0x2]))
                            (pc)) [0 S2 A8]))
                (label_ref:SI 12))
            (pc))) -1 (nil)
    (nil))

(code_label 12 11 79 2 11 "" [1 uses])

(note 79 12 13 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(jump_insn 13 79 17 2 (addr_diff_vec:HI (label_ref:SI 12)
         [
            (label_ref:SI 21)
            (label_ref:SI 27)
            (label_ref:SI 33)
            (label_ref:SI 39)
            (label_ref:SI 45)
            (label_ref:SI 51)
            (label_ref:SI 57)
            (label_ref:SI 63)
        ]
        (const_int 0 [0x0])
        (const_int 0 [0x0])) -1 (nil)
    (nil))

(note 17 13 18 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

----

So how would I do it?  I'd embed the addr_vec/addr_diff_vec inside the
insn that refers to it.  For x86,

(insn 13 83 14 2 (set (reg/f:SI 61)  ; this loads the address of the
      (addr_vec:SI [                 ; addr_vec, which is off in .rodata
            (label_ref:SI 25)
            (label_ref:SI 31)
            (label_ref:SI 37)
            (label_ref:SI 43)
            (label_ref:SI 49)
            (label_ref:SI 55)
            (label_ref:SI 61)
            (label_ref:SI 67)
        ]) -1 (nil)
    (nil)))

(insn 14 13 15 2 (set (reg:SI 62)
        (mem/u/c:SI (plus:SI (mult:SI (reg/v:SI 60 [ x ])
                    (const_int 4 [0x4]))
                (reg/f:SI 61)) [0 S4 A8])) -1 (nil)
    (nil))

(jump_insn 15 14 16 2 (set (pc)
       (reg:SI 62)) -1 (nil)
    (nil))

(barrier 16 15 25)

(code_label 25 16 ...)  ; code for each case begins here

and for VAX, 

(jump_insn 11 4 79 0 (set (pc)
        (if_then_else (leu (minus:SI (reg/v:SI 23 [ x ])
                    (const_int 0 [0x0]))
                (const_int 7 [0x7]))
            (plus:SI (sign_extend:SI (mem:HI (plus:SI (mult:SI
        (minus:SI (reg/v:SI 23 [ x ])
                                    (const_int 0 [0x0]))
                                (const_int 2 [0x2]))
                            (pc)) [0 S2 A8]))
                  (addr_diff_vec:HI (pc)
         [
            (label_ref:SI 21)
            (label_ref:SI 27)
            (label_ref:SI 33)
            (label_ref:SI 39)
            (label_ref:SI 45)
            (label_ref:SI 51)
            (label_ref:SI 57)
            (label_ref:SI 63)
        ]
        (const_int 0 [0x0])
        (const_int 0 [0x0])))
            (pc))) -1 (nil)
    (nil))

(note 79 11 ... NOTE_INSN_BASIC_BLOCK)

The output routine for the insn that contains the addr_vec or
addr_diff_vec is then responsible for emitting assembly that does the
right thing.  I would also remove direct support for casesi from the
tree-to-RTL expander.  Let it generate a canonical sequence that
includes the range check as separate insns, and if the combiner can't
crunch it all back together, the VAX port can deal with it in
peepholes.  That puts the burden of generating optimal code for this
not-very-popular port on the port maintainers, where it belongs.

(It should be noted that there are a lot of ports that use the
"casesi" expander, but in all cases other than VAX there appears to be
no good reason for this - they're just duplicating what stmt.c would
do if it had only "tablejump" to work with.  I was particularly
curious to see if the s390 had a similar instruction to the VAX, but
if it does we aren't using it.)

zw


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