On 04/27/2012 04:37 AM, Richard Guenther wrote:
Since integral atomics are always of an unsigned type , I could switch over
and use 'unsigned size' instead of 'tree fntype' for them (I will rename
it), but then things may be more complicated when dealing with generic
atomics... those can be structure or array types and I was planning to
allow leaving the type in case I discover something useful I can do with it.
It may ultimately turn out that the real type isn't going to matter, in
which case I will remove it and replace it with an unsigned int for size.
So it eventually will support variable-size types?
we support arbitrary sized objects now for exchange, compare_exchange,
load, and store. I just havent added the support to gimple_atomic yet.
Thats next on my list.
And the reason memmodel is a tree is because, as ridiculous as it seems, it
can ultimately be a runtime value. Even barring that, it shows up as a
variable after inlining before various propagation engines run, especially
in the C++ templates. So it must be a tree.
Ick. That sounds gross. So, if it ends up a variable at the time we generate
assembly we use a "conservative" constant value for it?
Indeed, ICK, and yes, I make it SEQ_CST at compile time if a variable
value gets all the way through to codegen.
Hmm, ok. So you are changing GENERIC in fact. I suppose _Atomic is
restricted to global variables. Can I attach _Atomic to allocated
storage via pointer casts? Consider writing up semantics of _Atomic
into generic.texi please.
Yes, I have a start on implementing _Atomic which adds the bit to the
type. And no, it isn't restricted to globals... it just indicates said
hunk of memory must be accessed in an atomic manner. You can use it on
automatics if you want...
I believe _Atomic can also be used in casts as well. so an atomic call
may have to be injected into a dereference expression as well to load or
update memory.
I'll update .texi along with the patch when I get to it.
Well, they are calls with a very well-defined set of side-effects.
Otherwise not representing them as calls would be a waste of time.
Thus, no - they do not need to be considered "calls" everywhere (well,
treating them the same as calls should be conservative) but treating
them as "atomics" even if they were expanded as calls needs to be
correct.
Yeah, I was starting with them as calls just to be conservative and get
the same behaviour, then refine them by examining each GIMPLE_ATOMIC use
in detail.
Looks like a hieararchy "no target or anything else" -> "target" ->
"expr" -> "memorder" would work, with only "lhs" being optional and
present everywhere.
Of course the hierarchy only makes sense for things that are not trees
(I was thinking of memorder originally - but that thought fell apart).
So in the
end apart from abstracting a base for FENCE the flat hieararchy makes sense
(all but FENCE have a type / size).
Is it really worth it to have 2 different types of gimple_atomic nodes
in order to avoid having an unused type field in atomic_fence?
Atomic_fence has an order field, so it requires the use of op[0] in
order for gimple_atomic_order() to work properly, we can't have all the
other gimple nodes inherit from that, so we'd need a base which
basically has just the KIND in it, and target/no-target nodes inherit
from that. So we'd have:
/ gimple_atomic_fence
atomic_base
\ gimple_atomic_all_others
then all the checks for is_gimple_atomic() have to look for both
gimple_atomic_all_others and gimple_atomic_fence.
Perhaps a better option is to shift all the operands by one since the
type is a tree... ie, if there is a a target, there is also a type entry, so
op[0] remains ORDER,
op[1] is the newly inserted TYPE
op[2] then becomes the TARGET,
op[3...] ,when present, are all shifted over by one.
the type can be removed from the structure and now there would be no
wastage. Is that reasonable?
Andrew