[M3devel] loophole/copysign

Jay K jay.krell at cornell.edu
Tue Jul 6 00:50:38 CEST 2010


The C trees are much higher level.

First, cm3/m3-libs/m3core/src/float/test_copysign.c which is analogous to CopySign, the C code:

typedef struct {
        unsigned rest : 31;
        unsigned sign : 1;
} float_t;

float copy_sign_f(float from, float to)
{
        float res = to;
        ((float_t*)&res)->sign = ((float_t*)&from)->sign;
        return res;
}

is what we should somehow strive for.

It yields a tree with almost everything preserved (typedefs fall out).
gcc-4.2 -fdump-tree-all -c test_copysign.c 

test_copysign.c.003t.original:

;; Function copy_sign_f (copy_sign_f)
;; enabled by -tree-original

{
  float res = to;

    float res = to;
  ((struct float_t *) &res)->sign = ((struct float_t *) &from)->sign;
  return res;
}

which is nothing like what we produce.
We don't have structs/member_refs ever, I believe.


To maybe answer your question..well..:

int reinterpret(float f)
{
  return *(int*)&f;
}

gcc-4.2 -ftree-dump-all -c 5.c well, the tree is high super high fidelity, nearly
indistinguishable from the input C:


;; Function reinterpret (reinterpret)
;; enabled by -tree-original
{
  return *(int *) &f;
}


I think we would produce about the same thing if we went down the non-bitfield path in load or store.
You know ... we don't even need to do loophole, but we need to do just one load or one store, with a conversion,
instead of storing one way and loading the other.


You could imagine parse.c might buffer up one load or store and then if the next instruction is not store or load, just flush it,
but if it is store or load, merge them. Well, it depends on what load or store is to of course.


 - Jay

----------------------------------------
> Subject: Re: [M3devel] loophole/copysign
> From: hosking at cs.purdue.edu
> Date: Mon, 5 Jul 2010 18:27:10 -0400
> CC: m3devel at elegosoft.com
> To: jay.krell at cornell.edu
>
> OK, so now I begin to understand. What you are saying is that gcc needs to have a union type capturing the fact that the variable is accessed using 2 different types. What happens in C code where you cast a memory location from one type to another? How does gcc cope with that? Presumably it gets some sort of type aliasing information?
>
> On 5 Jul 2010, at 17:42, Jay K wrote:
>
> >
> > CastExpr.m3 has precious few calls to CG.Loophole, including none for this case.
> > cm3cg -y output for m3core/LongReal.mc CopySign has no calls to loophole.
> > We store into a local as one type and read it back as another type.
> >
> > - Jay
> >
> > ----------------------------------------
> >> From: hosking at cs.purdue.edu
> >> Date: Mon, 5 Jul 2010 17:33:43 -0400
> >> To: jay.krell at cornell.edu
> >> CC: m3devel at elegosoft.com
> >> Subject: Re: [M3devel] loophole/copysign
> >>
> >> Surely we should instead give it the type conversion from what was stored to what is loaded. Can you point me at the problem code in CastExpr?
> >>
> >> On 5 Jul 2010, at 16:44, Jay K wrote:
> >>
> >>>
> >>> I don't think a barrier worked.
> >>> The thing is, I don't think a change in parse.c alone can work. It isn't being given enough information.
> >>> Or, well, it does have enough information, but, like, it is information it never uses.
> >>> It has some type information. It would have to notice that the most recent store to a variable was
> >>> of a different type than a load.
> >>>
> >>> - Jay
> >>>
> >>>
> >>>
> >>> ----------------------------------------
> >>>> Subject: Re: [M3devel] loophole/copysign
> >>>> From: hosking at cs.purdue.edu
> >>>> Date: Mon, 5 Jul 2010 14:24:01 -0400
> >>>> CC: m3devel at elegosoft.com
> >>>> To: jay.krell at cornell.edu
> >>>>
> >>>> We shouldn't need a barrier here. That is for memory operations, whereas these need not be. I would hate to make this change. Why can't we produce gcc trees that accomplish what we need?
> >>>>
> >>>> On 5 Jul 2010, at 05:24, Jay K wrote:
> >>>>
> >>>>>
> >>>>> Our codegen is remarkably low level. That is, lower level earlier than C.
> >>>>>
> >>>>>
> >>>>> gcc/m3cg -ftree-dump-all
> >>>>>
> >>>>>
> >>>>> As early as LongFloat.mc.003t.original, the first file dumped, we have:
> >>>>>
> >>>>> LongFloat__CopySign (M3_CtKayy_x, M3_CtKayy_y)
> >>>>> {
> >>>>> xreel M3_CtKayy__result;
> >>>>> xreel M3_CtKayy_res;
> >>>>>
> >>>>> xreel M3_CtKayy__result;
> >>>>> xreel M3_CtKayy_res;
> >>>>> M3_CtKayy_res = M3_CtKayy_x;
> >>>>> BIT_FIELD_REF = (word_8) ((int_64)
> >>>>> BIT_FIELD_REF & -129 | (word_64) BIT_FIELD_REF <(int_64) BIT_FIELD_REF , 1, 7> << 7 & 255);
> >>>>> = M3_CtKayy_res;
> >>>>> return ;
> >>>>> }
> >>>>>
> >>>>> compared to C where as test_copysign.c.t69.copyrename3, the last file dumped, we have:
> >>>>>
> >>>>> copy_sign_f (from, to)
> >>>>> {
> >>>>> float res;
> >>>>> float D.1918;
> >>>>> D.1917;
> >>>>> struct float_t * from.1;
> >>>>> struct float_t * res.0;
> >>>>>
> >>>>> :
> >>>>> res = to_1;
> >>>>> res.0_4 = (struct float_t *) &res;
> >>>>> from.1_5 = (struct float_t *) &from;
> >>>>> D.1917_6 = from.1_5->sign;
> >>>>> res.0_4->sign = D.1917_6;
> >>>>> D.1918_7 = res;
> >>>>> return D.1918_7;
> >>>>>
> >>>>> }
> >>>>>
> >>>>>
> >>>>> See, you know, from gcc's point of view, we don't have any records/structs/unions.
> >>>>> Just integers and offsets from them mostly.
> >>>>>
> >>>>>
> >>>>> The right fix is to build up types.
> >>>>> That way also debugging with gdb will have a chance.
> >>>>> Perhaps not a small amount of work. But maybe not too bad.
> >>>>>
> >>>>>
> >>>>> For now my inclination is in m3front to insert a barrier between the store and the load associated with loopholes.
> >>>>> At least if one type but not the other is floating point.
> >>>>> I don't know if that will work, but maybe.
> >>>>>
> >>>>> Or maybe have m3front actually call loophole for this case and again, either a barrier or make the load and/or
> >>>>> store volatile.
> >>>>>
> >>>>> - Jay
> >>>>>
> >>>>
> >>>
> >>
> >
>
 		 	   		  


More information about the M3devel mailing list