hfinkel added inline comments. ================ Comment at: lib/CodeGen/CGExpr.cpp:1286 @@ -1283,1 +1285,3 @@ + Value = Builder.CreateNoAlias(Value, NAI->second); + if (Ty->isAtomicType() || ---------------- hfinkel wrote: > hfinkel wrote: > > rjmccall wrote: > > > hfinkel wrote: > > > > rjmccall wrote: > > > > > This is very strange. Why do the aliasing properties of an address > > > > > cause metadata to be attached to the value stored into it? Shouldn't > > > > > the metadata be on the address (in which case, perhaps it should have > > > > > been attached to the load from the restrict pointer?) or the store? > > > > > > > > > > Also, please find some way to avoid doing a DenseMap lookup on every > > > > > single store. I would guess that the address only has an entry in > > > > > that table if it was restrict-qualified; you can probably find a way > > > > > to pass that information down. > > > > > This is very strange. Why do the aliasing properties of an address > > > > > cause metadata to be attached to the value stored into it? Shouldn't > > > > > the metadata be on the address (in which case, perhaps it should have > > > > > been attached to the load from the restrict pointer?) or the store? > > > > > > > > > > > > To be clear, this is not the metadata, this is the intrinsic; the > > > > metadata needs to be attached to all access in the scope. The intrinsic > > > > wraps the 'noalias' address. And this is "wrapping" the > > > > restrict-qualified address with the llvm.noalias intrinsic before it is > > > > stored into the stack space allocated for the local variable. > > > > > > > > > Also, please find some way to avoid doing a DenseMap lookup on every > > > > > single store. I would guess that the address only has an entry in > > > > > that table if it was restrict-qualified; you can probably find a way > > > > > to pass that information down. > > > > > > > > You are right: some (indirect) caller of this function should see a > > > > restrict-qualified variable. Maybe this information should end up in > > > > the LValue structure? > > > > > > > > Maybe it is worth now thinking about that should be the follow-on > > > > patch, because that also might influence the design. This patch handles > > > > direct restrict-qualified local variables, but does not handle the case > > > > where the variables are inside a structure. Specifically, I mean this: > > > > > > > > struct V { > > > > double * restrict x; > > > > double * restrict y; > > > > double * restrict z; > > > > }; > > > > > > > > void foo() { > > > > V v = { getX(), getY(), getZ() }; > > > > // The stores that compose this initializer need to be wrapped in > > > > @llvm.noalias also. > > > > } > > > > > > > > So I'd like to end up with a design for this patch that is easy to > > > > extend to handle the restrict-qualified-local-structure-member case as > > > > well. > > > "Value" is the value being stored to the address. > > > > > > If I've got code like this: > > > double * restrict addr = get_addr(); > > > double value = get_value(); > > > *addr = value; > > > > > > you are producing IR like > > > %addr = call double* @get_addr() > > > %value = call double get_value() > > > %value2 = call @llvm.noalias(double %value) > > > store %value2, %addr > > > > > > This is what I'm saying does not make any sense, because there's nothing > > > special about %value; the restrictions are on %addr. I think you > > > probably just have a bug in your patch and meant to use Addr. > > > > > > > You are right: some (indirect) caller of this function should see a > > > > restrict-qualified variable. Maybe this information should end up in > > > > the LValue structure? > > > > > > Yes, we already store when l-values are volatile, so storing that they're > > > restrict should be easy. > > No, this is not correct. If I have code like this: > > > > double * restrict addr = get_addr(); > > double value = get_value(); > > *addr = value; > > > > then we don't get code like this: > > > > %addr = call double* @get_addr() > > %value = call double get_value() > > %value2 = call @llvm.noalias(double %value) > > store %value2, %addr > > > > The code that Clang generates does not look like that: it does not generate > > an SSA variable for %addr, it generates a local stack location for it, and > > then loads/stores from that location when accessed. The only address that > > appear in NoAliasAddrMap are the address of the local allocas for the > > restrict-qualified variables themselves. It is only the pointer values > > being stored into the local restrict-qualified variables themselves that > > get wrapped. > > > > If you look at the regression test, I think it is clear that the code does > > the right thing. (If that's not clear, I should improve the test.) > > Yes, we already store when l-values are volatile, so storing that they're > > restrict should be easy. > > FWIW, LValue already keeps track of whether or not the value is restrict > qualified (along with whether or not it is volatile). I'll see if I can > predicate the map lookup on that, which may be the best solution (does not > increase the size of LValue for an uncommon case, but also does not perform a > map lookup for every store). > Before I forget ;) -- Here's the actual IR for this case you've provided above...
$ cat /tmp/ta.c double *get_addr(void); double get_value(void); void foo() { double * restrict addr = get_addr(); double value = get_value(); *addr = value; } The optimized IR is: $ clang -O3 -S -emit-llvm -o - /tmp/ta.c ; ModuleID = '/tmp/ta.c' target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" ; Function Attrs: nounwind define void @foo() #0 { entry: %call = tail call double* @get_addr() #2, !noalias !1 %0 = tail call double* @llvm.noalias.p0f64(double* %call, metadata !1) #2 %call1 = tail call double @get_value() #2, !noalias !1 store double %call1, double* %0, align 8, !tbaa !4, !noalias !1 ret void } and the original IR is: $ clang -O3 -S -emit-llvm -o - /tmp/ta.c -mllvm -disable-llvm-optzns ; ModuleID = '/tmp/ta.c' target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" ; Function Attrs: nounwind define void @foo() #0 { entry: %addr = alloca double*, align 8 %value = alloca double, align 8 %0 = bitcast double** %addr to i8* call void @llvm.lifetime.start(i64 8, i8* %0) #1, !noalias !1 %call = call double* @get_addr(), !noalias !1 %1 = call double* @llvm.noalias.p0f64(double* %call, metadata !1) #1 store double* %1, double** %addr, align 8, !tbaa !4, !noalias !1 %2 = bitcast double* %value to i8* call void @llvm.lifetime.start(i64 8, i8* %2) #1, !noalias !1 %call1 = call double @get_value(), !noalias !1 store double %call1, double* %value, align 8, !tbaa !8, !noalias !1 %3 = load double, double* %value, align 8, !tbaa !8, !noalias !1 %4 = load double*, double** %addr, align 8, !tbaa !4, !noalias !1 store double %3, double* %4, align 8, !tbaa !8, !noalias !1 %5 = bitcast double* %value to i8* call void @llvm.lifetime.end(i64 8, i8* %5) #1 %6 = bitcast double** %addr to i8* call void @llvm.lifetime.end(i64 8, i8* %6) #1 ret void } Thanks again! http://reviews.llvm.org/D9403 _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits