Non-call exceptions versus cse

Andrew Haley aph@redhat.com
Wed Nov 20 07:37:00 GMT 2002


Michael Matz writes:
 > Hi,
 > 
 > On Wed, 20 Nov 2002, Andrew Haley wrote:
 > 
 > > From what I remember, you said that flow would work correctly in this
 > > case iff the value read from memory were first copied to a temporary,
 > > and that's what I'm trying to do.
 > >
 > > This is the Java code that is not compiled correctly:
 > >
 > >     boolean ok = false;
 > >     int nn = 0;
 > >
 > > [ ... ]
 > >
 > >     ok = false;
 > >     try
 > >       {
 > > 	int[] x = (int[])null;
 > > 	nn = x[0];
 > >       }
 > >     catch (NullPointerException _)
 > >       {
 > > 	ok = true;
 > >       }
 > >
 > >     if (!ok || nn != 0)
 > >       throw new RuntimeException("test failed:3");
 > >
 > > The problem is that nn is assigned to a register for the period
 > > between the assignment in the try block and the test after the catch.
 > 
 > But it's not assigned the same register before the begin of the try{}?

That's how it appears to me.

 > This would indicate a problem in flow, because the use of nn is
 > reached by both defs (the =0 one through the exception edge, and
 > the =x[0] one through the fallthrough).  This means that either all
 > refs of nn have to be the same register, or all memory.  The
 > problem here of course is, that if the assignement is only one
 > insn, that we have a choice what should happen to the outputs of
 > the insn, if the exception happens _during_ that insn.  It seems
 > java wants to define the output's as untouched in that case

Yes, that's right.  That is why, after discussing this with rth, I
concluded that the right thing was to read into a temporary rather
than directly into the destination.  As long as the temporary isn't
deleted everything is OK.

 > , or?  This seems different to what Ada wants.  Maybe this should
 > be really differentiated in the backend depending on a
 > flag_exception_clobbers_outputs, which Ada would set.

That's one idea.

 > If it's set we can depend on the change of the outputs no matter if
 > the exceptions occurs or not.
 > 
 > Hmm, OTOH the above (java semantic) can be implemented without a flag
 > already in the frontends by using short temporaries.  I.e. transforming
 > any
 >   (output1, output2, ...) <== may_trap (i1, i2, ...)
 > into
 >   { type t1,t2, ...;
 >     (t1, t2, ...) <== may_trap (i1, i2, ...)
 >     /* Point 1 */
 >     (output1, output2, ...) <== (t1, t2, ...)
 >   }

That's similar to what I do in the Java front end.

More precisely, what I do transforms

    output1 = may_trap (i1);

 into

    output1 = ({ type t1; t1 = may_trap (i1); t1; });

However, cse removes t1, which is how this disussion started.  There's
a hole in my bucket...

 > Double hmm.  Then it must be ensured, that these two statements are not
 > combined again, indeed.  But that shouldn't happen anyway, because at
 > "Point 1" above a new basic block begins, and the first block can be left
 > (by throwing) _without_ setting (output1, ...).  Ergo combining both
 > should already be prevented, if you emit such code sequence in the
 > frontend.

Well, they aren't so prevented.  The two patches I submitted are cases
where the compiler does this combination.

BTW, this is the RTL in question before CSE:

   (note 27 22 28 0 ("Array_3.java") 64)
   
   (insn 28 27 30 0 0x40228554 (set (reg/v/f:SI 63)
           (const_int 0 [0x0])) -1 (nil)
       (nil))
   
   (note 30 28 33 0 ("Array_3.java") 66)
   
   (insn 33 30 233 0 0x402284a4 (set (reg/v:SI 65)
           (mem/s:SI (plus:SI (reg/v/f:SI 63)
                   (const_int 4 [0x4])) [15 <variable>.length+0 S4 A32])) -1 (nil)
       (expr_list:REG_EH_REGION (const_int 1 [0x1])
           (nil)))
   ;; End of basic block 0, registers live:
    (nil)
   
   ;; Start of basic block 1, registers live: (nil)
   (note 233 33 35 1 [bb 1] NOTE_INSN_BASIC_BLOCK)
   
   (insn 35 233 39 1 0x40228554 (set (reg/v:SI 61)
           (reg/v:SI 65)) -1 (nil)
       (nil))
   
And after CSE:

   (note 27 22 30 0 ("Array_3.java") 64)
   
   (note 30 27 33 0 ("Array_3.java") 66)
   
   (insn 33 30 233 0 0x402284a4 (set (reg/v:SI 61)
           (mem/s:SI (const_int 4 [0x4]) [15 <variable>.length+0 S4 A32])) 38 {*movsi_1} (nil)
       (expr_list:REG_EH_REGION (const_int 1 [0x1])
           (nil)))
   ;; End of basic block 0, registers live:
    (nil)
   
   ;; Start of basic block 1, registers live: (nil)
   
Andrew.



More information about the Gcc-patches mailing list