Venkataramanan Kumar via llvm-dev
2019-Jul-08 18:31 UTC
[llvm-dev] Question on Aliasing and invariant load hoisting
Hi, I have the below test case. --snip-- struct st { int a; int b; }; int * ptr; int x,y; void bar(int *x); void foo() { struct st obj; bar(&obj.b); if(x) obj.a =x; else obj.a =y; for (int i=0; i<obj.a;i++) ptr[i]=i; } --snip-- LLVM IR produced at -O3 is shown below. ref: https://godbolt.org/z/WPlmfr --Snip-- %8 = getelementptr inbounds %struct.st, %struct.st* %1, i64 0, i32 0, !dbg ! 39 store i32 %7, i32* %8, align 4, !dbg !40 call void @llvm.dbg.value(metadata i32 0, metadata !26, metadata ! DIExpression()), !dbg !41 %9 = icmp sgt i32 %7, 0, !dbg !42 br i1 %9, label %10, label %12, !dbg !44 %11 = load i32*, i32** @ptr, align 8, !tbaa !45 br label %13, !dbg !44 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %2) #4, !dbg !47 ret void, !dbg !47 %14 = phi i64 [ 0, %10 ], [ %17, %13 ] call void @llvm.dbg.value(metadata i64 %14, metadata !26, metadata ! DIExpression()), !dbg !41 %15 = getelementptr inbounds i32, i32* %11, i64 %14, !dbg !48 %16 = trunc i64 %14 to i32, !dbg !49 store i32 %16, i32* %15, align 4, !dbg !49, !tbaa !33 %17 = add nuw nsw i64 %14, 1, !dbg !50 call void @llvm.dbg.value(metadata i32 undef, metadata !26, metadata ! DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !41 %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 %19 = sext i32 %18 to i64, !dbg !42 %20 = icmp slt i64 %17, %19, !dbg !42 br i1 %20, label %13, label %12, !dbg !44, !llvm.loop !54 } --Snip--- Question is why the load IR and sext IR (obj.a) is not getting hoisted out of the loop? --Snip-- %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 %19 = sext i32 %18 to i64, !dbg !42 --Snip is it because the "obj.a" can alias with "ptr" ? We are passing only "&obj.b" to bar. But still variable "ptr" is considered to be aliasing with "obj.a" ? regards, Venkat. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190709/3cea36d4/attachment.html>
Tim Northover via llvm-dev
2019-Jul-08 19:28 UTC
[llvm-dev] Question on Aliasing and invariant load hoisting
Hi Venkataramanan, On Mon, 8 Jul 2019 at 19:31, Venkataramanan Kumar via llvm-dev <llvm-dev at lists.llvm.org> wrote:> is it because the "obj.a" can alias with "ptr" ?Yes. At the IR level there's nothing to stop @bar from getelementptring backwards and accessing other parts of %1. I believe it would be somewhere between invalid and implementation-defined[*] at the C or C++ levels, but modelling that would be quite tricky. I thnk you'd need some kind of finer-grained escape analysis, supported by metadata (because there are constructs with otherwise very similar IR that *are* valid, for example if obj was an int[2]). Cheers. Tim. [*] Casts to/from ints are implementation-defined, so a compiler could allow it via "(int *)((uintptr_t)x - 4)" regardless of what the standard otherwise says. I don't recall seeing any discussion on whether Clang does or wants to do that.
Doerfert, Johannes via llvm-dev
2019-Jul-08 19:31 UTC
[llvm-dev] Question on Aliasing and invariant load hoisting
The whole object "escapes" into bar as it can be defined similar to the code below: void bar(int *x) { struct st *ST = ((char*)x) - offsetof(struct st, b)); ptr = &ST->a; *ptr = 999; // Initial upper bound, overwritten by ptr[0] = 0; } --------------------------------------- Johannes Doerfert Researcher Argonne National Laboratory Lemont, IL 60439, USA jdoerfert at anl.gov ________________________________________ From: llvm-dev <llvm-dev-bounces at lists.llvm.org> on behalf of Venkataramanan Kumar via llvm-dev <llvm-dev at lists.llvm.org> Sent: Monday, July 8, 2019 13:31 To: llvm-dev Subject: [llvm-dev] Question on Aliasing and invariant load hoisting Hi, I have the below test case. --snip-- struct st { int a; int b; }; int * ptr; int x,y; void bar(int *x); void foo() { struct st obj; bar(&obj.b); if(x) obj.a =x; else obj.a =y; for (int i=0; i<obj.a;i++) ptr[i]=i; } --snip-- LLVM IR produced at -O3 is shown below. ref: https://godbolt.org/z/WPlmfr --Snip-- %8 = getelementptr inbounds %struct.st<http://struct.st>, %struct.st<http://struct.st>* %1, i64 0, i32 0, !dbg !39 store i32 %7, i32* %8, align 4, !dbg !40 call void @llvm.dbg.value(metadata i32 0, metadata !26, metadata !DIExpression()), !dbg !41 %9 = icmp sgt i32 %7, 0, !dbg !42 br i1 %9, label %10, label %12, !dbg !44 %11 = load i32*, i32** @ptr, align 8, !tbaa !45 br label %13, !dbg !44 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %2) #4, !dbg !47 ret void, !dbg !47 %14 = phi i64 [ 0, %10 ], [ %17, %13 ] call void @llvm.dbg.value(metadata i64 %14, metadata !26, metadata !DIExpression()), !dbg !41 %15 = getelementptr inbounds i32, i32* %11, i64 %14, !dbg !48 %16 = trunc i64 %14 to i32, !dbg !49 store i32 %16, i32* %15, align 4, !dbg !49, !tbaa !33 %17 = add nuw nsw i64 %14, 1, !dbg !50 call void @llvm.dbg.value(metadata i32 undef, metadata !26, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !41 %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 %19 = sext i32 %18 to i64, !dbg !42 %20 = icmp slt i64 %17, %19, !dbg !42 br i1 %20, label %13, label %12, !dbg !44, !llvm.loop !54 } --Snip--- Question is why the load IR and sext IR (obj.a) is not getting hoisted out of the loop? --Snip-- %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 %19 = sext i32 %18 to i64, !dbg !42 --Snip is it because the "obj.a" can alias with "ptr" ? We are passing only "&obj.b" to bar. But still variable "ptr" is considered to be aliasing with "obj.a" ? regards, Venkat.
Venkataramanan Kumar via llvm-dev
2019-Jul-09 06:10 UTC
[llvm-dev] Question on Aliasing and invariant load hoisting
Hi Tim, Thank you for the clarifying this. On Tue, 9 Jul 2019 at 00:58, Tim Northover <t.p.northover at gmail.com> wrote:> Hi Venkataramanan, > > On Mon, 8 Jul 2019 at 19:31, Venkataramanan Kumar via llvm-dev > <llvm-dev at lists.llvm.org> wrote: > > is it because the "obj.a" can alias with "ptr" ? > > Yes. At the IR level there's nothing to stop @bar from > getelementptring backwards and accessing other parts of %1. > > I believe it would be somewhere between invalid and > implementation-defined[*] at the C or C++ levels, but modelling that > would be quite tricky. I thnk you'd need some kind of finer-grained > escape analysis, supported by metadata (because there are constructs > with otherwise very similar IR that *are* valid, for example if obj > was an int[2]). > > Cheers. > > Tim. > >So we can still do some inter procedural analysis, and check if only the passed bytes is accessed in all those escaping places?> [*] Casts to/from ints are implementation-defined, so a compiler could > allow it via "(int *)((uintptr_t)x - 4)" regardless of what the > standard otherwise says. I don't recall seeing any discussion on > whether Clang does or wants to do that. >regards, Venkat. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190709/1565026b/attachment-0001.html>
Venkataramanan Kumar via llvm-dev
2019-Jul-09 06:13 UTC
[llvm-dev] Question on Aliasing and invariant load hoisting
Hi Johannes, On Tue, 9 Jul 2019 at 01:01, Doerfert, Johannes <jdoerfert at anl.gov> wrote:> The whole object "escapes" into bar as it can be defined similar to the > code below: > > void bar(int *x) { > struct st *ST = ((char*)x) - offsetof(struct st, b)); > ptr = &ST->a; > *ptr = 999; // Initial upper bound, overwritten by ptr[0] = 0; > } > >Yes I was trying to do this. Thank you.> > --------------------------------------- > Johannes Doerfert > Researcher > > Argonne National Laboratory > Lemont, IL 60439, USA > > jdoerfert at anl.gov > > regards,Venkat.> ________________________________________ > From: llvm-dev <llvm-dev-bounces at lists.llvm.org> on behalf of > Venkataramanan Kumar via llvm-dev <llvm-dev at lists.llvm.org> > Sent: Monday, July 8, 2019 13:31 > To: llvm-dev > Subject: [llvm-dev] Question on Aliasing and invariant load hoisting > > Hi, > > I have the below test case. > --snip-- > struct st { > int a; > int b; > }; > > int * ptr; > int x,y; > > void bar(int *x); > > void foo() { > struct st obj; > bar(&obj.b); > if(x) > obj.a =x; > else > obj.a =y; > > for (int i=0; i<obj.a;i++) > ptr[i]=i; > } > --snip-- > > LLVM IR produced at -O3 is shown below. > ref: https://godbolt.org/z/WPlmfr > > --Snip-- > %8 = getelementptr inbounds %struct.st<http://struct.st>, %struct.st< > http://struct.st>* %1, i64 0, i32 0, !dbg !39 > store i32 %7, i32* %8, align 4, !dbg !40 > call void @llvm.dbg.value(metadata i32 0, metadata !26, metadata > !DIExpression()), !dbg !41 > %9 = icmp sgt i32 %7, 0, !dbg !42 > br i1 %9, label %10, label %12, !dbg !44 > > %11 = load i32*, i32** @ptr, align 8, !tbaa !45 > br label %13, !dbg !44 > > call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %2) #4, !dbg !47 > ret void, !dbg !47 > > %14 = phi i64 [ 0, %10 ], [ %17, %13 ] > call void @llvm.dbg.value(metadata i64 %14, metadata !26, metadata > !DIExpression()), !dbg !41 > %15 = getelementptr inbounds i32, i32* %11, i64 %14, !dbg !48 > %16 = trunc i64 %14 to i32, !dbg !49 > store i32 %16, i32* %15, align 4, !dbg !49, !tbaa !33 > %17 = add nuw nsw i64 %14, 1, !dbg !50 > call void @llvm.dbg.value(metadata i32 undef, metadata !26, metadata > !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !41 > %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 > %19 = sext i32 %18 to i64, !dbg !42 > %20 = icmp slt i64 %17, %19, !dbg !42 > br i1 %20, label %13, label %12, !dbg !44, !llvm.loop !54 > } > --Snip--- > > Question is why the load IR and sext IR (obj.a) is not getting hoisted > out of the loop? > --Snip-- > %18 = load i32, i32* %8, align 4, !dbg !51, !tbaa !52 > %19 = sext i32 %18 to i64, !dbg !42 > --Snip > > is it because the "obj.a" can alias with "ptr" ? > We are passing only "&obj.b" to bar. But still variable "ptr" is > considered to be aliasing with "obj.a" ? > > regards, > Venkat. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190709/471e6f77/attachment.html>
Apparently Analagous Threads
- [Debuginfo] Changing llvm.dbg.value and DBG_VALUE to support multiple location operands
- Help on finding Base GEP
- [Debuginfo] Changing llvm.dbg.value and DBG_VALUE to support multiple location operands
- [Debuginfo] Changing llvm.dbg.value and DBG_VALUE to support multiple location operands
- Help on finding Base GEP