> 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)