vlad via llvm-dev
2015-Nov-13 11:17 UTC
[llvm-dev] llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
Hello, list I am not quite sure if what I'm experiencing is a bug or intentional behavior. In the code below the result of a function call is a deopt arg to llvm.experimental.gc.statepoint (http://llvm.org/docs/Statepoints.html#llvm-experimental-gc-statepoint-intrinsic). Therefore a Stack Map containing location of this variable is created upon code generation. Here's the complete example: define i64 addrspace(1)* @func() { %p = inttoptr i64 42 to i64 addrspace(1)* ret i64 addrspace(1)* %p } define i8 @main() #0 gc "statepoint-example" { %result = call i64 addrspace(1)* @func() %token = call i32 (i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f ( i64 111, i32 0, i64 addrspace(1)* ()* @func, i32 0, i32 0, i32 0, i32 1, i64 addrspace(1)* %result) ; the only deopt arg %b = ptrtoint i64 addrspace(1)* %result to i64 %c = trunc i64 %b to i8 ret i8 %c } declare i32 @llvm.experimental.gc.statepoint.p0f_p1i64f(i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) declare i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32) attributes #0 = { "no-frame-pointer-elim"="true" } I compile with `llc -O3 -x86-asm-syntax=intel`. Here is the meat of the emitted asm: call func mov rbx, rax mov qword ptr [rbp - 16], rbx call func Here is the corresponding Stack Map Location: .byte 2 .byte 8 .short 7 .long 0 Which means, according to http://llvm.org/docs/StackMaps.html#stack-map-format, that it's a Direct location rsp + 0 (rsp has DWARF register number 7). Which I find is not exactly true, as it should rather be an Indirect location [rsp + 0], or better yet, considering I specified "no-frame-pointer-elim"="true", [rbp - 16]. The only explanation about direct locations in the doc is "If an alloca value is passed directly to a stack map intrinsic, then LLVM may fold the frame index into the stack map as an optimization to avoid allocating a register or stack slot. These frame indices will be encoded as Direct locations in the form BP + Offset." And as far as I can see it's not the case here. I have a new version of LLVM which I built yesterday. Please help me understand what's happening here. Thanks in advance
Philip Reames via llvm-dev
2015-Nov-15 01:21 UTC
[llvm-dev] llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
Viad, My initial impression is that you've stumbled across a bug. I suspect that we - the only active users of the deopt info in the statepoint I know of - have been inverting the meaning of Direct and Indirect throughout our code. (i.e. we're consistent, but swapped on the documented meaning) I've asked Sanjoy to confirm that, and if he believes that is actually the case, we will fix upstream to use Indirect in this case. I'll try to have more information for you early next week. Can I ask what you're using the deopt information for? Do you have a language runtime which supports deoptimization? Or are you using it for something different? If so, what? I'm curious to know how others are using the infrastructure. Philip On 11/13/2015 03:17 AM, vlad via llvm-dev wrote:> Hello, list > > I am not quite sure if what I'm experiencing is a bug or intentional > behavior. > > In the code below the result of a function call is a deopt arg to > llvm.experimental.gc.statepoint > (http://llvm.org/docs/Statepoints.html#llvm-experimental-gc-statepoint-intrinsic). > > Therefore a Stack Map containing location of this variable is created > upon code generation. > > Here's the complete example: > > define i64 addrspace(1)* @func() { > %p = inttoptr i64 42 to i64 addrspace(1)* > ret i64 addrspace(1)* %p > } > > define i8 @main() #0 gc "statepoint-example" { > %result = call i64 addrspace(1)* @func() > > %token = call i32 (i64, i32, i64 addrspace(1)* ()*, i32, i32, > ...) @llvm.experimental.gc.statepoint.p0f_p1i64f ( > i64 111, i32 0, > i64 addrspace(1)* ()* @func, > i32 0, i32 0, i32 0, > i32 1, > i64 addrspace(1)* %result) ; the only deopt arg > > > %b = ptrtoint i64 addrspace(1)* %result to i64 > %c = trunc i64 %b to i8 > ret i8 %c > } > > > declare i32 @llvm.experimental.gc.statepoint.p0f_p1i64f(i64, i32, > i64 addrspace(1)* ()*, i32, i32, ...) > declare i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32) > > attributes #0 = { "no-frame-pointer-elim"="true" } > > I compile with `llc -O3 -x86-asm-syntax=intel`. > > Here is the meat of the emitted asm: > call func > mov rbx, rax > mov qword ptr [rbp - 16], rbx > call func > > Here is the corresponding Stack Map Location: > .byte 2 > .byte 8 > .short 7 > .long 0 > Which means, according to > http://llvm.org/docs/StackMaps.html#stack-map-format, that it's a > Direct location rsp + 0 (rsp has DWARF register number 7). > Which I find is not exactly true, as it should rather be an Indirect > location [rsp + 0], or better yet, considering I specified > "no-frame-pointer-elim"="true", [rbp - 16]. > > The only explanation about direct locations in the doc is "If an > alloca value is passed directly to a stack map intrinsic, then LLVM > may fold the frame index into the stack map as an optimization to > avoid allocating a register or stack slot. These frame indices will be > encoded as Direct locations in the form BP + Offset." And as far as I > can see it's not the case here. > > I have a new version of LLVM which I built yesterday. > > Please help me understand what's happening here. Thanks in advance > > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
vlad via llvm-dev
2015-Nov-16 10:46 UTC
[llvm-dev] llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
> Vlad, > > My initial impression is that you've stumbled across a bug. I suspect > that we - the only active users of the deopt info in the statepoint I > know of - have been inverting the meaning of Direct and Indirect > throughout our code. (i.e. we're consistent, but swapped on the > documented meaning) I've asked Sanjoy to confirm that, and if he > believes that is actually the case, we will fix upstream to use > Indirect in this case. > > I'll try to have more information for you early next week.Hi, Philip! Thank you for taking time to look into it! May be it's a separate question, but I hope it's OK to ask in this thread. Would it be hard to make the statepoint intrinsic produce frame pointer based offset (instead of sp-based) if "no-frame-pointer-elim"="true" attribute is specified?> Can I ask what you're using the deopt information for? Do you have a > language runtime which supports deoptimization? Or are you using it > for something different? If so, what? I'm curious to know how others > are using the infrastructure.Sure. I am working on LLV8, which is an attempt to use LLVM MCJIT as a backend for Google V8. So yes, we have a language runtime which supports deoptimization. Deoptimization support wasn't hard. We use the stackmap intrinsic for that. (And we've encountered each type of Location except Direct so far). Now I am implementing the safepoint functionality which is why I use the gc.statepoint intrinsic. The two utility passes have been extremely helpful. The use-cases they support are much more general than my needs though. So I use a modified version of RewriteStatepointsForGC, which only appends the pointer values live across the statepoint to <deopt args>.> Philip > > On 11/13/2015 03:17 AM, vlad via llvm-dev wrote: >> Hello, list >> >> I am not quite sure if what I'm experiencing is a bug or intentional >> behavior. >> >> In the code below the result of a function call is a deopt arg to >> llvm.experimental.gc.statepoint >> (http://llvm.org/docs/Statepoints.html#llvm-experimental-gc-statepoint-intrinsic). >> Therefore a Stack Map containing location of this variable is created >> upon code generation. >> >> Here's the complete example: >> >> define i64 addrspace(1)* @func() { >> %p = inttoptr i64 42 to i64 addrspace(1)* >> ret i64 addrspace(1)* %p >> } >> >> define i8 @main() #0 gc "statepoint-example" { >> %result = call i64 addrspace(1)* @func() >> >> %token = call i32 (i64, i32, i64 addrspace(1)* ()*, i32, i32, >> ...) @llvm.experimental.gc.statepoint.p0f_p1i64f ( >> i64 111, i32 0, >> i64 addrspace(1)* ()* @func, >> i32 0, i32 0, i32 0, >> i32 1, >> i64 addrspace(1)* %result) ; the only deopt arg >> >> >> %b = ptrtoint i64 addrspace(1)* %result to i64 >> %c = trunc i64 %b to i8 >> ret i8 %c >> } >> >> >> declare i32 @llvm.experimental.gc.statepoint.p0f_p1i64f(i64, i32, >> i64 addrspace(1)* ()*, i32, i32, ...) >> declare i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32) >> >> attributes #0 = { "no-frame-pointer-elim"="true" } >> >> I compile with `llc -O3 -x86-asm-syntax=intel`. >> >> Here is the meat of the emitted asm: >> call func >> mov rbx, rax >> mov qword ptr [rbp - 16], rbx >> call func >> >> Here is the corresponding Stack Map Location: >> .byte 2 >> .byte 8 >> .short 7 >> .long 0 >> Which means, according to >> http://llvm.org/docs/StackMaps.html#stack-map-format, that it's a >> Direct location rsp + 0 (rsp has DWARF register number 7). >> Which I find is not exactly true, as it should rather be an Indirect >> location [rsp + 0], or better yet, considering I specified >> "no-frame-pointer-elim"="true", [rbp - 16]. >> >> The only explanation about direct locations in the doc is "If an >> alloca value is passed directly to a stack map intrinsic, then LLVM >> may fold the frame index into the stack map as an optimization to >> avoid allocating a register or stack slot. These frame indices will be >> encoded as Direct locations in the form BP + Offset." And as far as I >> can see it's not the case here. >> >> I have a new version of LLVM which I built yesterday. >> >> Please help me understand what's happening here. Thanks in advance >> >> >> >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reasonably Related Threads
- llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
- llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
- Operand bundles and gc transition arguments
- Status of Garbage Collection with Statepoints in LLVM
- PlaceSafepoints, operand bundles, and RewriteStatepointsForGC