[llvm-commits] [PATCH] Define 'atomic load' and 'atomic store' as variants of load/store
Eli Friedman
eli.friedman at gmail.com
Fri Aug 5 13:29:53 PDT 2011
On Fri, Aug 5, 2011 at 1:05 PM, Jeffrey Yasskin <jyasskin at google.com> wrote:
> On Thu, Aug 4, 2011 at 7:01 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>> Patch attached.
>>
>> This should be mostly straightforward, but I'd like to check to see if
>> anyone has comments on how alignment is handled on atomic loads and
>> stores. Other comments also welcome, of course.
>>
>> (After this, I get the fun task of going through every call to
>> isVolatile() in LLVM.)
>
>
>>
>> Index: include/llvm/Instructions.h
>> ===================================================================
>> --- include/llvm/Instructions.h (revision 136929)
>> +++ include/llvm/Instructions.h (working copy)
>> @@ -171,11 +179,42 @@
>> /// getAlignment - Return the alignment of the access that is being performed
>> ///
>> unsigned getAlignment() const {
>> - return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1;
>> + return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1;
>
> I'd recommend extracting these bit-shifting accessors into helper
> functions eventually.
OK; I guess the combo of Align+Volatile+Ordering+SynchScope is
relevant to almost all of these.
>> }
>>
>> void setAlignment(unsigned Align);
>>
>> + /// Returns the ordering effect of this fence.
>
> This is a load, not a fence, right?
>
>> + AtomicOrdering getOrdering() const {
>> + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
>> + }
>> +
>> + /// Set the ordering constraint on this fence. May only be Acquire, Release,
>> + /// AcquireRelease, or SequentiallyConsistent.
>
> May only be NotAtomic, Unordered, Monotonic, Acquire, or
> SequentiallyConsistent, right?
>
>> + void setOrdering(AtomicOrdering Ordering) {
>> + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
>> + (Ordering << 7));
>> + }
>
>> @@ -247,11 +294,42 @@
>
>> + /// Returns the ordering effect of this fence.
>
> Similarly, not a fence.
>
>> + AtomicOrdering getOrdering() const {
>> + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
>> + }
>> +
>> + /// Set the ordering constraint on this fence. May only be Acquire, Release,
>> + /// AcquireRelease, or SequentiallyConsistent.
>
> Stores may be any ordering except Acquire and AcquireRelease.
>
>> + void setOrdering(AtomicOrdering Ordering) {
>> + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
>> + (Ordering << 7));
>> + }
>> +
>> + SynchronizationScope getSynchScope() const {
>> + return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
>> + }
>> +
>> + /// Specify whether this fence orders other operations with respect to all
>
> s/fence/store/ here too.
>
>> + /// concurrently executing threads, or only with respect to signal handlers
>> + /// executing in the same thread.
>> + void setSynchScope(SynchronizationScope xthread) {
>> + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
>> + (xthread << 6));
>> + }
Ugh... too much copy-paste; will fix.
>> Index: docs/LangRef.html
>> ===================================================================
>> --- docs/LangRef.html (revision 136929)
>> +++ docs/LangRef.html (working copy)
>> @@ -4588,6 +4586,19 @@
>> number or order of execution of this <tt>load</tt> with other <a
>> href="#volatile">volatile operations</a>.</p>
>>
>> +<p>If the <code>load</code> is marked as <code>atomic</code>, it takes an extra
>> + <a href="#ordering">ordering</a> and optional <code>singlethread</code>
>> + argument. The <code>release</code> and <code>acq_rel</code> orderings are
>> + not valid on <code>load</code> instructions. Atomic loads produce <a
>> + href="#memorymodel">defined</a> results when they may see multiple atomic
>> + stores. The type of the pointee must be an integer type whose bit width
>> + is a power of two greater than or equal to eight and less than or equal
>> + to a target-specific size limit. <code>align</code> must be explicitly
>> + specified on atomic loads, and the load has undefined behavior if the
>> + alignment is not set to a value which is at least the size in bytes of
>> + the pointee. <code>!nontemporal</code> does not have any defined semantics
>> + for atomic loads.</p>
>
> Given that "A value of 0 or an omitted align argument means that the
> operation has the preferential alignment for the target", I'm not sure
> you need to require an explicit alignment for atomic loads and stores.
> It'd make sense to me to just say that an alignment less than the
> width of the type has undefined behavior.
>
> But I don't have strong opinions about this.
>
>> <p>The optional constant <tt>align</tt> argument specifies the alignment of the
>> operation (that is, the alignment of the memory address). A value of 0 or an
>> omitted <tt>align</tt> argument means that the operation has the preferential
>> @@ -4648,6 +4659,19 @@
>> order of execution of this <tt>store</tt> with other <a
>> href="#volatile">volatile operations</a>.</p>
>>
>> +<p>If the <code>store</code> is marked as <code>atomic</code>, it takes an extra
>> + <a href="#ordering">ordering</a> and optional <code>singlethread</code>
>> + argument. The <code>acquire</code> and <code>acq_rel</code> orderings aren't
>> + valid on <code>store</code> instructions. Atomic loads produce <a
>> + href="#memorymodel">defined</a> results when they may see multiple atomic
>> + stores. The type of the pointee must be an integer type whose bit width
>> + is a power of two greater than or equal to eight and less than or equal
>> + to a target-specific size limit. <code>align</code> must be explicitly
>> + specified on atomic loads, and the load has undefined behavior if the
>
> s/load/store/
And again. :)
>> + alignment is not set to a value which is at least the size in bytes of
>> + the pointee. <code>!nontemporal</code> does not have any defined semantics
>> + for atomic stores.</p>
>> +
>> <p>The optional constant "align" argument specifies the alignment of the
>> operation (that is, the alignment of the memory address). A value of 0 or an
>> omitted "align" argument means that the operation has the preferential
>> Index: lib/VMCore/AsmWriter.cpp
>> ===================================================================
>> --- lib/VMCore/AsmWriter.cpp (revision 136929)
>> +++ lib/VMCore/AsmWriter.cpp (working copy)
>> @@ -1660,13 +1660,16 @@
>> }
>>
>> // If this is a volatile load or store, print out the volatile marker.
>
> Copy this for the atomic marker.
K.
>> + if ((isa<LoadInst>(I) && cast<LoadInst>(I).isAtomic()) ||
>> + (isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic()))
>> + Out << "atomic ";
>> +
>> if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
>> - (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())) {
>> - Out << "volatile ";
>> - } else if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall()) {
>> - // If this is a call, check if it's a tail call.
>> + (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()))
>> + Out << "volatile ";
>> +
>
> Otherwise, looks good to me.
Thanks for looking this over.
-Eli
More information about the llvm-commits
mailing list