> On Apr 18, 2016, at 9:12 AM, Tom Stellard via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > Here is the initial proposal with some formatting fixed: > > Currently, the LLVM IR uses a binary value (SingleThread/CrossThread) to > represent synchronization scope on atomic instructions. We would like to > enhance the representation of memory scopes in LLVM IR to allow more values > than just the current two. The intention of this email is to invite > comments on our proposal. There are some discussion before and it can be > found here: > https://groups.google.com/forum/#!searchin/llvm-dev/hsail/llvm-dev/46eEpS5h0E4/i3T9xw-DNVYJ > > Here is our new proposal: > > ================================================================> We still let the bitcode store memory scopes as "unsigned integers", since > that is the easiest way to maintain compatibility. The values 0 and 1 are > special. All other values are meaningful only within that bc file. In > addition, "a global metadata in the file" will provide a map from unsigned > integers to string symbols which should be used to interpret all the > non-standard integers. If the global metadata is empty or non-existent, > then all non-zero values will be mapped to "system", which is the current > behavior. > > The proposed syntax for synchronization scope is as follows: > * Synchronization scopes are of arbitrary width, but implemented as > unsigned in the bitcode, just like address spaces. > * Cross-thread is default. > * Keyword "singlethread" is unchanged > * New syntax "synchscope(n)" for other target-specific scopes. > * There is no keyword for cross-thread, but it can be specified as > "synchscope(0)".Why not going with a metadata attachment directly and kill the "singlethread" keyword? Something like: Something like: cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!42} cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!43} ... !42 = !{"singlethread"} !43 = !{"L2"} I also avoids manipulating/pruning the global map, and target won't depend on integer to keep bitcode compatibility. -- Mehdi> > The proposed new integer implementation expanded synchronization scopes are > as follows: > > *********************************************************************** > | Format | Single Thread | System (renamed) | Intermediate | > ----------------------------------------------------------------------| > | Bitcode | zero | one | unsigned n | > | Assembly | singlethread, | empty (default), | synchscope(n-1) | > | synchscope(~0U) synchscope(0) | > | In-memory | ~0U | zero | unsigned n-1 | > | SelectionDAG | ~0U | zero | unsigned n-1 | > *********************************************************************** > > The choice of “~0U” for singlethread makes it easy to maintain backward > compatibility in the bitcode. The values 0 and 1 remain unchanged in the > bitcode, and the reader simply decrements them by one to compute the > correct value in the in-memory data-structure. > > Name Mapping > > Now we comes to name mapping from integers to strings. If a CLANG front end > wants to map a language that has memory scopes (e.g. OpenCL) to LLVM IR, > how does it determine what syncscopes to use? Without any rules, each > target can define its own meaning for the scopes, can give them any name, > and can map them to the LLVM-IR unit values in any way. In this case, I > think each target have to provide a mapping function that maps a specific > language’s name for a scope into that targets name for a scope that has > conservatively the same semantics. Namely, the act of supporting a new > language that has memory scopes requires every target to support that > language to be updated accordingly. > > Therefore, in order to allow front end writers to share memory scope > definitions when they match to avoid the effort of updating all targets for > each language,it's better to define standard memory scope names. A target > is free to implement them or not, but if a target does implement them they > must have the defined relational semantics (e.g., hierarchical nesting). If > a target does implement them then it will be able to support any language > that uses them, including languages not yet invented. A new memory scope > name can be added if the existing ones are insufficient. > > With the first try, we can define the standard scopes with what a common > language that has memory scopes needs, e.g., OpenCL uses system, device, > workgroup, workitem. It uses the same approach as LLVM has done for debug > information. There are standard debug entities (that a common language (C) > needs), and each new language uses those standard entities where there is a > match, and subsequently defines only the delta. > > A bitcode example with the proposal > ***************************************************************** > define void <at> test(i32* %addr) { > ; forward compatibility > cmpxchg i32* %addr, i32 42, i32 0 singlethread monotonic monotonic > > ; new synchscope that will be defined by each backend > cmpxchg i32* %addr, i32 42, i32 0 synchscope(2) monotonic monotonic, 2 > cmpxchg i32* %addr, i32 42, i32 0 synchscope(3) monotonic monotonic, 3 > > ret void > } > > !synchscope = metadata !{{i32 0, !"SingleThread"}, {i32 2, !"WorkGroup"}, > ...} > ***************************************************************** > > ================================================================> _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
On 04/18/2016 09:45 AM, Mehdi Amini via llvm-dev wrote:>> On Apr 18, 2016, at 9:12 AM, Tom Stellard via llvm-dev <llvm-dev at lists.llvm.org> wrote: >> >> Here is the initial proposal with some formatting fixed: >> >> Currently, the LLVM IR uses a binary value (SingleThread/CrossThread) to >> represent synchronization scope on atomic instructions. We would like to >> enhance the representation of memory scopes in LLVM IR to allow more values >> than just the current two. The intention of this email is to invite >> comments on our proposal. There are some discussion before and it can be >> found here: >> https://groups.google.com/forum/#!searchin/llvm-dev/hsail/llvm-dev/46eEpS5h0E4/i3T9xw-DNVYJ >> >> Here is our new proposal: >> >> ================================================================>> We still let the bitcode store memory scopes as "unsigned integers", since >> that is the easiest way to maintain compatibility. The values 0 and 1 are >> special. All other values are meaningful only within that bc file. In >> addition, "a global metadata in the file" will provide a map from unsigned >> integers to string symbols which should be used to interpret all the >> non-standard integers. If the global metadata is empty or non-existent, >> then all non-zero values will be mapped to "system", which is the current >> behavior. >> >> The proposed syntax for synchronization scope is as follows: >> * Synchronization scopes are of arbitrary width, but implemented as >> unsigned in the bitcode, just like address spaces. >> * Cross-thread is default. >> * Keyword "singlethread" is unchanged >> * New syntax "synchscope(n)" for other target-specific scopes. >> * There is no keyword for cross-thread, but it can be specified as >> "synchscope(0)". > > Why not going with a metadata attachment directly and kill the "singlethread" keyword? Something like: > Something like: > > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!42} > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!43} > > ... > > !42 = !{"singlethread"} > !43 = !{"L2"} > > > I also avoids manipulating/pruning the global map, and target won't depend on integer to keep bitcode compatibility.+1. I like this idea. Haven't given it serious thought, but on the surface this sounds nice. We'd need to establish a naming scheme so that targets could add meta tags without preventing upstream from adding generic ones going forward. Philip
On Mon, Apr 18, 2016 at 09:45:55AM -0700, Mehdi Amini wrote:> > > On Apr 18, 2016, at 9:12 AM, Tom Stellard via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > > > Here is the initial proposal with some formatting fixed: > > > > Currently, the LLVM IR uses a binary value (SingleThread/CrossThread) to > > represent synchronization scope on atomic instructions. We would like to > > enhance the representation of memory scopes in LLVM IR to allow more values > > than just the current two. The intention of this email is to invite > > comments on our proposal. There are some discussion before and it can be > > found here: > > https://groups.google.com/forum/#!searchin/llvm-dev/hsail/llvm-dev/46eEpS5h0E4/i3T9xw-DNVYJ > > > > Here is our new proposal: > > > > ================================================================> > We still let the bitcode store memory scopes as "unsigned integers", since > > that is the easiest way to maintain compatibility. The values 0 and 1 are > > special. All other values are meaningful only within that bc file. In > > addition, "a global metadata in the file" will provide a map from unsigned > > integers to string symbols which should be used to interpret all the > > non-standard integers. If the global metadata is empty or non-existent, > > then all non-zero values will be mapped to "system", which is the current > > behavior. > > > > The proposed syntax for synchronization scope is as follows: > > * Synchronization scopes are of arbitrary width, but implemented as > > unsigned in the bitcode, just like address spaces. > > * Cross-thread is default. > > * Keyword "singlethread" is unchanged > > * New syntax "synchscope(n)" for other target-specific scopes. > > * There is no keyword for cross-thread, but it can be specified as > > "synchscope(0)". > > > Why not going with a metadata attachment directly and kill the "singlethread" keyword? Something like: > Something like: > > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!42} > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!43} > > ... > > !42 = !{"singlethread"} > !43 = !{"L2"} > > > I also avoids manipulating/pruning the global map, and target won't depend on integer to keep bitcode compatibility. > >This seems like it will work assuming that promoting something like "L2" to the most conservative memory scope is legal (this is what would have to happen if the metadata was dropped). Are there any targets where this type of' promotion would be illegal? -Tom> -- > Mehdi > > > > > > > > The proposed new integer implementation expanded synchronization scopes are > > as follows: > > > > *********************************************************************** > > | Format | Single Thread | System (renamed) | Intermediate | > > ----------------------------------------------------------------------| > > | Bitcode | zero | one | unsigned n | > > | Assembly | singlethread, | empty (default), | synchscope(n-1) | > > | synchscope(~0U) synchscope(0) | > > | In-memory | ~0U | zero | unsigned n-1 | > > | SelectionDAG | ~0U | zero | unsigned n-1 | > > *********************************************************************** > > > > The choice of “~0U” for singlethread makes it easy to maintain backward > > compatibility in the bitcode. The values 0 and 1 remain unchanged in the > > bitcode, and the reader simply decrements them by one to compute the > > correct value in the in-memory data-structure. > > > > Name Mapping > > > > Now we comes to name mapping from integers to strings. If a CLANG front end > > wants to map a language that has memory scopes (e.g. OpenCL) to LLVM IR, > > how does it determine what syncscopes to use? Without any rules, each > > target can define its own meaning for the scopes, can give them any name, > > and can map them to the LLVM-IR unit values in any way. In this case, I > > think each target have to provide a mapping function that maps a specific > > language’s name for a scope into that targets name for a scope that has > > conservatively the same semantics. Namely, the act of supporting a new > > language that has memory scopes requires every target to support that > > language to be updated accordingly. > > > > Therefore, in order to allow front end writers to share memory scope > > definitions when they match to avoid the effort of updating all targets for > > each language,it's better to define standard memory scope names. A target > > is free to implement them or not, but if a target does implement them they > > must have the defined relational semantics (e.g., hierarchical nesting). If > > a target does implement them then it will be able to support any language > > that uses them, including languages not yet invented. A new memory scope > > name can be added if the existing ones are insufficient. > > > > With the first try, we can define the standard scopes with what a common > > language that has memory scopes needs, e.g., OpenCL uses system, device, > > workgroup, workitem. It uses the same approach as LLVM has done for debug > > information. There are standard debug entities (that a common language (C) > > needs), and each new language uses those standard entities where there is a > > match, and subsequently defines only the delta. > > > > A bitcode example with the proposal > > ***************************************************************** > > define void <at> test(i32* %addr) { > > ; forward compatibility > > cmpxchg i32* %addr, i32 42, i32 0 singlethread monotonic monotonic > > > > ; new synchscope that will be defined by each backend > > cmpxchg i32* %addr, i32 42, i32 0 synchscope(2) monotonic monotonic, 2 > > cmpxchg i32* %addr, i32 42, i32 0 synchscope(3) monotonic monotonic, 3 > > > > ret void > > } > > > > !synchscope = metadata !{{i32 0, !"SingleThread"}, {i32 2, !"WorkGroup"}, > > ...} > > ***************************************************************** > > > > ================================================================> > _______________________________________________ > > LLVM Developers mailing list > > llvm-dev at lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >
Hi all, On 02.05.2016 17:46, Tom Stellard via llvm-dev wrote:>> Why not going with a metadata attachment directly and kill the "singlethread" keyword? Something like: >> >Something like: >> > >> > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!42} >> > cmpxchg i32* %addr, i32 42, i32 0 monotonic monotonic, 3, !memory.scope{!43} >> > >> >... >> > >> >!42 = !{"singlethread"} >> >!43 = !{"L2"} >> > >> > >> >I also avoids manipulating/pruning the global map, and target won't depend on integer to keep bitcode compatibility. >> > >> > > This seems like it will work assuming that promoting something like "L2" to the > most conservative memory scope is legal (this is what would have to happen > if the metadata was dropped). Are there any targets where this type of' > promotion would be illegal?+1 Sorry to enter this discussion so late, but in my opinion this is a very good non-intrusive starting point solution. Implementing it as a MD with the assumption of there being a safe conservative memory scope to fall back to (in case the MD gets stripped off for some reason) converts it to a mere optimization hint without the need to touch LLVM IR instruction semantics. Also, as it's only a MD, if we encounter a need to extend it later towards a more integrated solution (or a mechanism to support targets where this scheme is not feasible), we can more easily do so. BR, -- Pekka