> From: DJ Delorie <[EMAIL PROTECTED]> > >> where then the target may declare class machine_mode >> target_int_mode ("HI", 16), > > This is where we disagree. The *target* shouldn't map types to modes. > The *MI* should map types to modes. The target just creates the modes > it supports and describes them. The MI looks them up by description > (NOT NAME). If the MI needs a 32 bit unsigned scalar, it does > lookup_mode(32, M_SCALAR, M_UNSIGNED) and uses whatever gets returned.
- ok, and how does it know that it needs a 32-bit unsigned scalar? Answer: because it wants to know what mode it needs to specify for for an operation on a particular type which has those characteristics as defined by the targets definition of an int for example. (so why in the world is it desirable to go go in a big circle to identify which mode corresponds to a type as defined by the target, rather than simply having the target define it directly?) > The fact that you're still trying to assign a "well known name" to a > given type/mode/whatever means you haven't gotten away from the (to > me) fundamental problem, that MI chooses modes according to what > they're *for* instead of according to what they *are*. - unless I misunderstand (which I admittedly may), the MI portion of the code is and should be based on manipulating data structures which correspond to user programs which are digested down to a canonical representation of "well known named" operators with operands of correspondingly "well known named" types (such as bool, char, int, float); who's sizes are defined by the target. So it would seem to stand to reason that the MI portion of GCC does and should restrict itself to well known "type" modes, which are defined to be mapped to physical modes as defined by the target? please see below) >> target_unit_mode // presumably the target's smallest addressable datum. > > BImode in most cases, not really useful that way. - maybe we are using different terminology, as there would seem to be no reason that a target couldn't define that a bool was a 16-bit wide datum while being able to address memory with a 4-bit wide granularity. (in essence, there needs to be a mechanism by which a target may define the it's address resolution, and alignment requirements, independently of it's specified type sizes, if not this way, then some other) >> target_word_mode // presumably the target's largest addressable datum. > > BLKmode in all cases. Also not useful. - I hope not, as block mode operands seem to be used for moving data with finer granularity than the target's word-width when initializing char array and/or struct members (which need not be aligned to the width of of the target's widest naturally addressable datum, but it's smallest?) >> as there seems no valid reason for the target neutral portion of the >> compiler to ever refer to XXmode under any circumstance? > > Ah, but in your case it *is* aware, it just calls it > "target_word_mode" instead of "SImode" with all the same problems with > assumptions. - no?, I presume that "target_word_mode" would merely describe (mentioned above), an aspect of the physical target's natural memory access granularity, without having any presumed relationship to any particular separately defined target "type" mode such as it's target_int_mode for example. >> where correspondingly the MI portions of GCC utilizes the appropriate >> pointer mode as a function of the type of access being performed, > > In my case, the target has to check the attributes of the > function/data to decide what kind of pointer to use. Again, "MI > assuming" that all function pointers are the same is WRONG. - understood, although it would seem much easier if the MI portion simply identified the type of pointer it required based upon the context of the access which it inherently knows (which the target may map to whatever mode it desires), rather than the target having to try to figure out based upon the more limited tree/rtx context visible to it?) thereby also exposing more potential opportunities for MI optimization to the middle end it would seem? >> - understood, although I honestly don't believe there are that many, and >> it eliminates any possible confusion, and a host of other #defines. > > My current port supports maybe 4-5 hard modes. There are 19 > machine_modes defined. That's about 4x as many as I really need to > define, and that doesn't even include synthetic vector modes and such. - understood, although hardly believe that it's a problem to require that a target define the logical->physical mapping required for for the 20 or so logically distinct type variations that the MI portion is and should be aware of (rather than subject the mapping to any mishandling) >> - as you've noted, all the information GCC MI portion needs to "do the >> right thing" already exists scattered in various target definitions, >> but it hasn't prevented mode assumptions from being made, and XXmodes >> being hard-coded into the MI sources on occasion; which is the only >> reason that I thought that by forcing target_TYPE_mode's to be the >> only thing available, GCC would indirectly be forced to always to the >> "right thing"? > > The less available the better, true. But target_*_modes don't need to > be available either. If you use a query/lookup API, MI can assume > there are a *lot* of machine modes (one for each variable, one for > each function, one for each C data type, etc), and let the target map > them to available modes. - I do believe were just using somewhat different terminology, as the MI portion of the compiler does and must deal with "well known named" typed operations and operands. > targetm.modes.set_mode_for_decl(decl); > > See? This allows for a custom mode just for the given decl (it might > be a 17 bit ternary value in a DSP), doesn't make assumptions about > available machine modes, and MI can provide a naive default hook for > targets that do "the usual thing". - sorry, I don't see; as the program code, and internal tree representation of that code (as you've noted below), identifies all nodes as having one of N canonical types (bool, char, short, int, *, [], etc.) not an arbitrary type, (where these canonical types need only be mapped to target supported/named/defined modes upon code generation, it would seem?) > if (!TYPE_MODE (TREE_TYPE (decl))) > TYPE_MODE (TREE_TYPE (decl)) = find_mode_for_type (TREE_TYPE (decl)); > DECL_MODE (decl) = TYPE_MODE (TREE_TYPE (decl)); - why bother if: TYPE_MODE :: *target_type_mode, i.e: typedef struct { char* name; char* mode: char size: enum attribute {is_signed, is_unsigned, is_floating, is_void}; } target_type_mode; where the target defines: enum type_mode { bool_mode = &(target_type_mode){"bool", "QI", 10, is_unsinged}, char_mode = &(target_type_mode){"char", "QI", 10, is_unsigned}, uint_mode = &(target_type_mode){"uint", "HI", 17, is_unsigned}, ...} thereby the MI portion need only do stuff like: if (TYPE_MODE(...) == char_mode) ... -or- if(TYPE_MODE(...)->size < word_mode->.size) ... where when required for target template mapping, mode names may be extracted via. TYPE_MODE(...)->mode, thereby the MI remains fully abstracted, and never needs to be aware or manipulate physical modes as named and utilized by the target it would seem? > or something like that. Caching is OK if you cache it the right way > (with a type, not in a global "this is a pointer" variable). (but recognize we're likely looking a things from different perspectives)