LGTM https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... File lib/Transforms/Instrumentation/ThreadSanitizer.cpp (right): https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... lib/Transforms/Instrumentation/ThreadSanitizer.cpp:177: NamePart = "_fetch_and"; _fetch_and appears twice
https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... File lib/Transforms/Instrumentation/ThreadSanitizer.cpp (right): https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... lib/Transforms/Instrumentation/ThreadSanitizer.cpp:177: NamePart = "_fetch_and"; On 2012/10/04 10:25:47, kcc1 wrote: > _fetch_and appears twice Where is the second one?
FTR, here is the test generator: package main import ( "fmt" "os" "text/template" ) func main() { fmt.Print(header) for size := uint32(0); size < 5; size++ { for _, order := range []string{"unordered", "monotonic" /*"consume",*/, "acquire", "seq_cst"} { output(loadTempl, size, order, nil) } for _, order := range []string{"unordered", "monotonic", "release", "seq_cst"} { output(storeTempl, size, order, nil) } for _, order := range []string{"monotonic" /*"consume",*/, "acquire", "release", "acq_rel", "seq_cst"} { for _, rmw := range []string{"xchg", "add", "sub", "and", "or", "xor"} { output(rmwTempl, size, order, map[string]string{"RMW": rmw, "TsanRMW": tsanRMWs[rmw]}) } } for _, order := range []string{"monotonic" /*"consume",*/, "acquire", "release", "acq_rel", "seq_cst"} { output(casTempl, size, order, nil) } } for _, order := range []string{ /*"consume",*/ "acquire", "release", "acq_rel", "seq_cst"} { for _, ftype := range []string{"signal", "thread"} { output(fenceTempl, 0, order, map[string]string{"FenceType": ftype, "Scope": tsanScopes[ftype]}) } } } func output(templ *template.Template, size uint32, order string, params map[string]string) { data := map[string]string{ "Size": fmt.Sprint(8 * (1 << size)), "ByteSize": fmt.Sprint(1 << size), "Order": order, "TsanOrder": tsanOrders[order], } for k, v := range params { data[k] = v } templ.Execute(os.Stdout, data) } var tsanOrders = map[string]string{ "unordered": "100501", "monotonic": "100501", "consume": "100502", "acquire": "100504", "release": "100508", "acq_rel": "100516", "seq_cst": "100532", } var tsanRMWs = map[string]string{ "xchg": "exchange", "add": "fetch_add", "sub": "fetch_sub", "and": "fetch_and", "or": "fetch_or", "xor": "fetch_xor", } var tsanScopes = map[string]string{ "signal": "singlethread", "thread": "", } var loadTempl = template.Must(template.New("foo").Parse(` define i{{.Size}} @atomic{{.Size}}_load_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: %0 = load atomic i{{.Size}}* %a {{.Order}}, align {{.ByteSize}} ret i{{.Size}} %0 } ; CHECK: atomic{{.Size}}_load_{{.Order}} ; CHECK: call i{{.Size}} @__tsan_atomic{{.Size}}_load(i{{.Size}}* %a, i32 {{.TsanOrder}}) `)) var storeTempl = template.Must(template.New("foo").Parse(` define void @atomic{{.Size}}_store_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: store atomic i{{.Size}} 0, i{{.Size}}* %a {{.Order}}, align {{.ByteSize}} ret void } ; CHECK: atomic{{.Size}}_store_{{.Order}} ; CHECK: call void @__tsan_atomic{{.Size}}_store(i{{.Size}}* %a, i{{.Size}} 0, i32 {{.TsanOrder}}) `)) var rmwTempl = template.Must(template.New("foo").Parse(` define void @atomic{{.Size}}_{{.RMW}}_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: atomicrmw {{.RMW}} i{{.Size}}* %a, i{{.Size}} 0 {{.Order}} ret void } ; CHECK: atomic{{.Size}}_{{.RMW}}_{{.Order}} ; CHECK: call i{{.Size}} @__tsan_atomic{{.Size}}_{{.TsanRMW}}(i{{.Size}}* %a, i{{.Size}} 0, i32 {{.TsanOrder}}) `)) var casTempl = template.Must(template.New("foo").Parse(` define void @atomic{{.Size}}_cas_{{.Order}}(i{{.Size}}* %a) nounwind uwtable { entry: cmpxchg i{{.Size}}* %a, i{{.Size}} 0, i{{.Size}} 1 {{.Order}} ret void } ; CHECK: atomic{{.Size}}_cas_{{.Order}} ; CHECK: call i{{.Size}} @__tsan_atomic{{.Size}}_compare_exchange_val(i{{.Size}}* %a, i{{.Size}} 0, i{{.Size}} 1, i32 {{.TsanOrder}}) `)) var fenceTempl = template.Must(template.New("foo").Parse(` define void @atomic_{{.FenceType}}_fence_{{.Order}}() nounwind uwtable { entry: fence {{.Scope}} {{.Order}} ret void } ; CHECK: atomic_{{.FenceType}}_fence_{{.Order}} ; CHECK: call void @__tsan_atomic_{{.FenceType}}_fence(i32 {{.TsanOrder}}) `)) var header = `; RUN: opt < %s -tsan -S | FileCheck %s ; Check that atomic memory operations are converted to calls into ThreadSanitizer runtime. target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ` On Thu, Oct 4, 2012 at 2:25 PM, <kcc@google.com> wrote: > LGTM > > > https://codereview.appspot.**com/6587082/diff/1/lib/** > Transforms/Instrumentation/**ThreadSanitizer.cpp<https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/ThreadSanitizer.cpp> > File lib/Transforms/**Instrumentation/**ThreadSanitizer.cpp (right): > > https://codereview.appspot.**com/6587082/diff/1/lib/** > Transforms/Instrumentation/**ThreadSanitizer.cpp#newcode177<https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/ThreadSanitizer.cpp#newcode177> > lib/Transforms/**Instrumentation/**ThreadSanitizer.cpp:177: NamePart = > "_fetch_and"; > _fetch_and appears twice > > https://codereview.appspot.**com/6587082/<https://codereview.appspot.com/6587... >
https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... File lib/Transforms/Instrumentation/ThreadSanitizer.cpp (right): https://codereview.appspot.com/6587082/diff/1/lib/Transforms/Instrumentation/... lib/Transforms/Instrumentation/ThreadSanitizer.cpp:177: NamePart = "_fetch_and"; my bad. ignore this