[M3devel] max_align

Tony Hosking hosking at cs.purdue.edu
Sun Feb 28 00:08:07 CET 2010


On 27 Feb 2010, at 17:12, Jay K wrote:

> ok..I'll maybe reply more later.
>  
>  
> But what does it mean to
>  
>  
> load_int(type1, value1)

Take value, cast to type1 (may involve sign extend from low bits/truncation of high bits), push on stack.

> load_int(type2, value2)

Take value, cast to type2 (may involve sign extend from low bits/truncation of high bits), push on stack.

> add(type3)

Add values on stack, interpreted as type3 (perhaps sign extended/truncated), with result of type3.

> It seems like both the values and the operations have types.

The types say how the bits of the operands are to be interpreted.

> I do try to consider all types, with "ELSE <* ASSERT FALSE *>", be it an if ladder or a switch.
> Perhaps that is too little thought?
> I admit, ZType, IType, AType, etc., I can't keep them straight.
> I "know" that floats are handled specially by m3back and so I can ignore them in most code
> and that the backend traffics only rarely in 8 or 16 bit types, so the four most interesting
> types are Int32, Int64, Word32, Word64.

Correct.

> As well, since my agenda is currently 64bit longint, I just need to add word64/int64 to
> the existing paths.

Right.

>  (m3back is so geared against int8/word8/int16/word16 that it takes special pain
> to widen all function results, lest they be generated by a C compiler, and the
> historical command indict the C compiler's behavior, I edited out the subjectivity;
> and the 8 bits produced by setccop are always
> immediately widened; I have to revisit that soon, I think the code can be much better.
> That is part of the evidence to what it traffics in.)

Yes, the front-end never usually generates stack values of 8/16 bits.  All integer operations are in the 32/64-bit types.

>  
>  
>  - Jay
> 
> 
> Subject: Re: [M3devel] max_align
> From: hosking at cs.purdue.edu
> Date: Sat, 27 Feb 2010 16:24:41 -0500
> CC: m3devel at elegosoft.com
> To: jay.krell at cornell.edu
> 
> 
> On 27 Feb 2010, at 15:50, Jay K wrote:
> 
>  > Target.Int values would always be interpreted based on their associated type
> 
>  
>   They kind of mostly are?
>   Except..I mean..you know..I bury a size in them, which is a step.
> 
> No, my point was that the front-end generates properly typed operations.  The specs for m3middle state that all Target.Int values are to be used for only their low bits as defined by the associated type of the operation.  Consider what would happen if we had a C-generating backend.  All the integer values would be expressed as emitted by TInt.ToBytes  (i.e., just the significant bytes of the value).  Then, the operations are defined as implicitly casting those values using the given type.  Thus, for:
> 
> add Int.32
> 
> the semantics are:
> 
> take the two operands from the stack, sign-extend their low 32 bits, and perform the addition, with the result interpreted as Int.32.
> 
> e.g.,  in C, (int)a + (int)b
> 
> So, for your backend code, you don't need the TIntN/TWordN length encoded in the value.  The operations define how a Target.Int is to be interpreted.  Target.Int is just a bunch of bits that are interpreted according to the type on the operation!  You need to choose the proper operation from TInt/TWord to get signed/unsigned, and in some cases (Rotate) to define the bits to be rotated.  Then, to get the appropriate result from the Target.Int operations you need to mask/extend the bits of the result correctly to match the sign.
> 
> I hope this is starting to make more sense to you, and help to motivate why I've been so pedantic about the TInt/TWord support!
> 
>   But the signnedness is not buried in them and I might get that wrong sometimes.
>   It is often, you know, the operation and not the type.
>   "Shift is always unsigned."
>   But Add isn't.
>   But with "half range cardinals", I'm not sure it matters.
>   16_40000000 * 2 overflows the same for INTEGER and CARDINAL
>   LAST(INTEGER) + 1 ditto.
>  
> 
>   Some operations do vary and they are handled correctly I think: abs, mul, div.
>   Actually this is somewhat wrong: signed and unsigned multiplication I don't think
>   needs to vary the way it does. They are the same in the lower bits.
>   The compiler doesn't need to be so picky I believe. In particular, in the following C:
>    int F1(int a, int b) { return a * b; }
>    unsigned F2(unsigned a, unsigned b) { return a * b; }
>    __int64 F3(int a, int b) { return a * (__int64)b; }
>    unsigned __int64 F3(unsigned a, unsigned b) { return a * (unsigned __int64)b; }
>  
> 
>  only one of them does unsigned multiplication, the last.
>  (and notice that it does it inline with one instruction; something
>   our compiler will be harder pressed to do given the lack of mixed operations!
>   but you could leave it to a smart optimizer)
>  
> 
>  > Is64, IsWord, IsInt, Target.FloatType
>  
> 
> In familiar territory (C and C++),
> I like switches because they "evaluate simultaneously", at least however the compiler can figure it.
> 
>  
> That is:
>  
> 
>   if foo == 1  
>   else if foo == 2  
>   else if foo == 3  
>   else if foo == 4  
>   else if foo == 5  
> 
> unless the compiler is very smart is always go to penalize 5 comparisons for "5",
> plus the compiler might assume I'm meaning to optimize the earlier cases
> as being more common, but then I have to worry about the ordering
> to get the common cases earlier whereas
> if I write
> switch (foo)
>  case 1: ...
>  case 2: ...
>  case 3: ...
>  case 4: ...
>  case 5: ...
>  
> 
> I'll let the compiler chose between table lookup, linear search, binary search.
> "table lookup" being "simultaneous evaluation", binary search being nice
>  
> 
> I also don't like "if ladders" because if I'm stepping through unoptimized
> code line by line, it is tedious.
> [mostly omitted aside: I go out of my way when writing command line
> parsers in C to have a switch statement instead of an if/elseif/elseif ladder]
>  
> 
> However
>  In Modula-3, I've gotten warnings when I miss cases, so there is overhead
>   of always writing "else".
>   Partly this because I don't know Modula-3 well.
> 
> You should try to avoid else so that you are forced to handle every case.  This is exactly my point.  The m3back code has a lot of places that must handle a range of types (e.g., IType, AType, etc.) and using cases forces you to think about all in the range.
> 
>   The use of FloatType[type] was already there, and it is good
>   to have equivalence classes to reduce the number of cases listed
>   and allow for more to be added later, "silently".
> 
> Again, with CASE you can still select for those, without having a cascade of IF.
> 
> 
> I also don't like "data based interfaces", I prefer function calls,
> that's why Is64 instead of is foo IN Types64.
>  (but FloatType[type] was already there)
>  Granted, I lament the lack of inlining in m3back.
> 
> Function call is overkill.  Use the types!
> 
> I'm worried about nomenclature if/when this is extended to 64bit architectures.
> I wonder if "Is64" should be "IsLong" or RegisterCount > 1 or something.
> 
> No, because the front-end generates explicit types of the form Int64, Int32, Word64, Word32 for all of the code generated through m3middle.  You can rely on those types as being correct.
> 
> I think I just drifted away from using TInt.Min/Max{8,16,32,64}.
> 
> The whole point here was for you to be explicit about types and ranges.  If you know you are performing Int32 addition then you can check that the result is in range for TInt.Min32..TInt.Max32.  That's exactly how you should be using TInt and getting away from the TIntN/TWordN kludge.
> 
> I'll see if any uses remain.
> Eh maybe just:
> C:\dev2\cm3.2\m3-sys\m3back\src\M3x86.m3(3846):    TWordN.And(imm, TWordN.Max32, immA[0]);
> 
>  
> Some places were in extract/insert, and looked wrong.
> 
>  
> Yes definitely more eyes on m3back appreciated.
>   Heck more eyes on cm3 appreciated! We have way too few. :(
> There were many style changes along with making things not work.
> I didn't want to sift through it all so I put it all back.
> Now to ponder sifting through it more slowly from a working baseline.
>  
> 
> Also I often favor mvar.mvar_type over mvar.type, so I can plain text
> search for mvar_type, and not just "type".
> 
> I do find that to be overly verbose.  WIth a decent IDE it can resolve those definitions (Eclipse M3 plugin anyone?).
> 
>  I realize that you can't throw out all contexta all the time, but,
>   there is something to be said for flatter namespaces.
> Nothing scales like plain text search.
> No language aware search work adequately.
>   Let alone the matter of existance of languages x tools.
>  
>  
> I don't think that's a mismash in the first 3, but yes FloatType makes it inconsistent.
> I would certainly be ok with TypeIsFloat to make it more consistently function call based,
> thoug I know I put in some cases too -- for the "simultaneous evaluation" property.
>  
>  
>  - Jay
> 
> 
> 
> 
> 
> 
>  
> From: hosking at cs.purdue.edu
> Date: Sat, 27 Feb 2010 14:54:40 -0500
> To: jay.krell at cornell.edu
> CC: m3devel at elegosoft.com
> Subject: Re: [M3devel] max_align
> 
> P.S. Sorry for all the push-back from me in m3middle/m3back.  I'm feeling like the module police lately. I really do need to take some time to look over your m3back code and see how it can be tidied.  Ideally, the Target.Int values would always be interpreted based on their associated type (which from the looks of things gets passed around just about all the places it is needed).  That means checking bounds whenever performing operations using TInt (that's why I added TInt.Min/Max{8,16,32,64} and TWord.Max{8,16,32,64}).  I did adopt your version of the signed TInt.Extend (which was much the same as my old Chop) and added the equivalent unsigned TWord.Truncate.  One quick observation on some of the m3back code: There were a lot of places where I thought you should use CASE on the type instead of conditionals (currently involving a mishmash of Is64, IsWord, IsInt, Target.FloatType, etc.  Using CASE has the advantage of warning when you don't handle every case value, and moreover makes the code more readable (uniformly handling each of the type combinations).
> 
> Antony Hosking | Associate Professor | Computer Science | Purdue University
> 305 N. University Street | West Lafayette | IN 47907 | USA
> Office +1 765 494 6001 | Mobile +1 765 427 5484
> 
> 
> 
> 
> On 27 Feb 2010, at 14:11, Jay K wrote:
> 
> The issue on NT386 I was thinking of is the alignment of temporaries. That probably doesn't matter.
>  We probably don't generate atomic operations against them.
>   I already changed it to 64 for the front/middle ends
>  
> But right, max_align is wrong for a few targets.
>  
> I believe max_align ends up being basically target-independent. It is always 64.
>  Types are always aligned on their size.
> The only exceptions are 68K platforms where max_align is possibly 2 bytes.
>   68K targets aren't likely to rematerialize ever, though it is on my hypothetical long list.
>  
>  
> PPC_something prefers a 128 bit aligned jmpbuf, but lower is ok, and max_align isn't applied to the jmpbufs
> that the compiler generates, and 128 bit alignment can't be specified in Csetjmp.i3 -- seems
> like a language hole to me.
>  
>  
> I'd like to "just" do this, but I haven't fired up the relevant targets in a while: FreeBSD/NetBSD/x86.
>  
>  
>  - Jay
> 
>  
> > From: hosking at cs.purdue.edu
> > Date: Sat, 27 Feb 2010 11:10:32 -0500
> > To: jay.krell at cornell.edu
> > CC: m3devel at elegosoft.com
> > Subject: Re: [M3devel] TInt/TWord/N
> > 
> > Yes, we do need to fix max_align for 64-bit atomics. I don't know what issues it will shake out though.
> > On 27 Feb 2010, at 02:34, Jay K wrote:
> > 
> > > 
> > >> As I understand it your stuff in m3back is mostly working.
> > >> I took a look at the code there and I see a number of issues
> > > 
> > > 
> > > Tony, I don't know of anything that isn't working.
> > > Please let me know.
> > > All 64bit operations should work. atomic32 should work.
> > > Not yet atomic8/16/64, soon.
> > > Oh there is an alignment issue once atomic64 is there.
> > > It's present on other platforms too, for different reasons (incorrect max_align).
> > > 
> > > 
> > > Thanks,
> > > - Jay
> > > 
> > > 
> > > ----------------------------------------
> > >> From: hosking at cs.purdue.edu
> > >> Date: Sat, 27 Feb 2010 01:16:32 -0500
> > >> To: jay.krell at cornell.edu
> > >> CC: m3devel at elegosoft.com
> > >> Subject: Re: [M3devel] TInt/TWord/N
> > >> 
> > >> The solution is not to push upstream into m3middle.
> > >> I'll try to find some time to push through what is needed in m3back. I can't promise anything soon. Let's leave things lie for a while. As I understand it your stuff in m3back is mostly working. I took a look at the code there and I see a number of issues. Hopefully I can get a look sometime.
> > >> 
> > >> -- T
> > >> 
> > >> On 26 Feb 2010, at 23:48, Jay K wrote:
> > >> 
> > >>> 
> > >>> Tony, I just don't understand what is wrong with TIntN, TWordN.
> > >>> They are what TInt/TWord did for a long time after all. ?
> > >>> Sometimes we have 4 byte integers, sometimes 8. When 4, we want overflow checking in 4, for every single operation, not just a chop when they end up in a register or such. Right? It seems natural to bundle that up conveniently. And putting them in m3middle didn't seem so contaminating to me, since they layer thinly over Target.Int. Nor do I know what the fix is, short of inlining the repitious conversions and checks.
> > >>> 
> > >>> 
> > >>> - Jay
> > >>> 
> > >>> 
> > >>> ----------------------------------------
> > >>>> From: hosking at cs.purdue.edu
> > >>>> Date: Fri, 26 Feb 2010 19:51:15 -0500
> > >>>> To: jkrell at elego.de
> > >>>> CC: m3commit at elegosoft.com
> > >>>> Subject: Re: [M3commit] CVS Update: cm3
> > >>>> 
> > >>>> I've just spent most of the day decontaminating m3middle and putting TIntN and TWordN back into m3back as deprecated modules. m3back needs to be fixed to get rid of these. I don't have time to mess with this stuff and I am peeved that I wasted a whole day on this.
> > >>>> 
> > >>>> On 26 Feb 2010, at 13:48, Jay Krell wrote:
> > >>>> 
> > >>>>> CVSROOT: /usr/cvs
> > >>>>> Changes by: jkrell at birch. 10/02/26 13:48:34
> > >>>>> 
> > >>>>> Modified files:
> > >>>>> cm3/m3-sys/m3back/src/: Codex86.i3 Codex86.m3 M3x86.m3
> > >>>>> M3x86Rep.i3 Stackx86.i3 Stackx86.m3
> > >>>>> Wrx86.i3 Wrx86.m3 m3makefile
> > >>>>> cm3/m3-sys/m3middle/src/: TInt.i3 TInt.m3 TIntN.i3 TIntN.m3
> > >>>>> TWordN.i3 TWordN.m3 Target.i3
> > >>>>> Target.m3 m3makefile
> > >>>>> Removed files:
> > >>>>> cm3/m3-sys/m3back/src/: M3BackInt.i3 M3BackInt.m3 M3BackWord.i3
> > >>>>> M3BackWord.m3
> > >>>>> 
> > >>>>> Log message:
> > >>>>> introduce type Target.IntN which is Int plus a precision
> > >>>>> just like the old Target.Int
> > >>>>> (previously M3BackInt.Int)
> > >>>>> 
> > >>>>> make TIntN and TWordN support it
> > >>>>> they are just thin wrappers over TInt, TWord
> > >>>>> previously named M3BackInt, M3BackWord
> > >>>>> 
> > >>>>> add small amount of support to TInt:
> > >>>>> SignExtend, SignedTruncate, ZeroExtend, UnsignedTruncate
> > >>>>> These could, if desired, go into their only users: TIntN, TWordN.
> > >>>>> (with the understanding that that Target.Int is "revealed" to them.)
> > >>>>> 
> > >>>>> add maxN, minN fields to Target.Int_type, that are equal to max and min but have a precision
> > >>>>> 
> > >>>>> NOTE: Don't worry Tony, the vast majority of m3middle, m3front, TInt, Tword are unchanged
> > >>>>> This is "just" additions.
> > >>>>> (Moving maintenance cost from m3back to m3middle, if that isn't a no-op.)
> > >>>>> (Coming up with alternate names for M3BackInt, M3BackWord => TIntN, TWordN)
> > >>>>> (A little unsatisfactory that N is bytes instead of bits.)
> > >>>>> (What a fun little exercise that might be, changing Int to be array [0..63] of [0..1] :) )
> > >>>>> 
> > >>>>> While at it, in TIntN, rename things slightly:
> > >>>>> FromInt => FromHostInteger
> > >>>>> ToInt => ToHostInteger
> > >>>>> 
> > >>>>> "Int" is "Target.Int"
> > >>>>> "HostInteger" is "INTEGER"
> > >>>>> 
> > >>>>> again, TInt/TWord/m3front/m3middle not much affected.
> > >>>>> 
> > >>>>> One fishy/uncertain thing in all of this, something to test out, is cross builds
> > >>>>> that target NT386 from 64bit host. Is TIntN.ToHostInteger correct? Or do we
> > >>>>> really need INTEGER to be 4 bytes throughout m3back?
> > >>>>> (I know that mklib has little endian dependency.)
> > >>>> 
> > >> 
> > 
> 
> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20100227/8c86c70c/attachment-0002.html>


More information about the M3devel mailing list