<div dir="ltr">Why should SelectionDAGBuilder generate an explicit bitcast for a no-op bitcast? By definition, no bits are changed; so if the EVTs match, there is nothing to do. The fundamental problem is how address spaces are handled, and specifically how they are converted, in LLVM IR. Address space casts are currently implemented with bitcasts (in general). While this works out for the LLVM IR type system, it does not match the semantics of an address space cast for some targets. For PTX, and address space cast may involve changing bits in the address. Therefore, a bitcast is not a valid way to perform an address space cast. We introduced target intrinsics to perform address space casts for this purpose. But I feel that this problem is likely not specific to PTX. A target that uses different pointer sizes for different address spaces would be hit by this issue even more, since a bitcast would not even be valid IR.</div>
<div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Aug 8, 2013 at 8:03 AM, Michele Scandale <span dir="ltr"><<a href="mailto:michele.scandale@gmail.com" target="_blank">michele.scandale@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On 08/08/2013 11:04 AM, David Chisnall wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
What happens when I link together two IR modules from different front ends that have different language-specific address spaces?<br>
</blockquote>
<br></div>
I agree with Micah: if during the linking two IR modules there are incoherences (e.g. in module1 2 -> 1 and in module2 2 -> 3) then the modules are incompatible and the link process should fail.<div><div class="h5">
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I would be very hesitant about using address spaces until we've fixed their semantics to disallow bitcasts between different address spaces and require an explicit address space cast. To illustrate the problem, consider the following trivial example:<br>
<br>
typedef __attribute__((address_space(<u></u>256))) int* gsptr;<br>
<br>
int *toglobal(gsptr foo)<br>
{<br>
return (int*)foo;<br>
}<br>
<br>
int load(int *foo)<br>
{<br>
return *foo;<br>
}<br>
<br>
int loadgs(gsptr foo)<br>
{<br>
return *foo;<br>
}<br>
<br>
int loadgs2(gsptr foo)<br>
{<br>
return *toglobal(foo);<br>
}<br>
<br>
When we compile this to LLVM IR with clang (disabling asynchronous unwind tables for clarity), at -O2 we get this:<br>
<br>
define i32* @toglobal(i32 addrspace(256)* %foo) nounwind readnone ssp {<br>
%1 = bitcast i32 addrspace(256)* %foo to i32*<br>
ret i32* %1<br>
}<br>
<br>
define i32 @load(i32* nocapture %foo) nounwind readonly ssp {<br>
%1 = load i32* %foo, align 4, !tbaa !0<br>
ret i32 %1<br>
}<br>
<br>
define i32 @loadgs(i32 addrspace(256)* nocapture %foo) nounwind readonly ssp {<br>
%1 = load i32 addrspace(256)* %foo, align 4, !tbaa !0<br>
ret i32 %1<br>
}<br>
<br>
define i32 @loadgs2(i32 addrspace(256)* nocapture %foo) nounwind readonly ssp {<br>
%1 = bitcast i32 addrspace(256)* %foo to i32*<br>
%2 = load i32* %1, align 4, !tbaa !0<br>
ret i32 %2<br>
}<br>
<br>
Note that in loadgs2, the call to toglobal has been inlined and so the back end will just see a bitcast, which SelectionDAG treats as a no-op. The assembly we get from this is:<br>
<br>
_toglobal: ## @toglobal<br>
## BB#0:<br>
pushq %rbp<br>
movq %rsp, %rbp<br>
movq %rdi, %rax<br>
popq %rbp<br>
ret<br>
load: ## @load<br>
## BB#0:<br>
pushq %rbp<br>
movq %rsp, %rbp<br>
movl (%rdi), %eax<br>
popq %rbp<br>
ret<br>
<br>
.globl _loadgs<br>
.align 4, 0x90<br>
loadgs: ## @loadgs<br>
## BB#0:<br>
pushq %rbp<br>
movq %rsp, %rbp<br>
movl %gs:(%rdi), %eax<br>
popq %rbp<br>
ret<br>
<br>
.globl _loadgs2<br>
.align 4, 0x90<br>
loadgs2: ## @loadgs2<br>
## BB#0:<br>
pushq %rbp<br>
movq %rsp, %rbp<br>
movl (%rdi), %eax<br>
popq %rbp<br>
ret<br>
<br>
loadgs() has been compiled correctly. It uses the parameter as a gs-relative address and performs the load. The assembly for load() and loadgs2(), however, are identical: both are treating the parameter as a linear (not gs-relative) address. The cast has been lost. This is even simpler when you look at toglobal(), which has just become a noop. The correct code for this should be (I believe):<br>
<br>
_toglobal: ## @toglobal<br>
## BB#0:<br>
pushq %rbp<br>
movq %rsp, %rbp<br>
lea %gs:(%rdi), %rax<br>
popq %rbp<br>
ret<br>
<br>
In the inlined version, the lea and movl should be combined into a single gs-relativel movl.<br>
<br>
Until we can generate correct code from IR containing address spaces, discussion of how to optimise this IR seems premature.<br>
</blockquote>
<br></div></div>
I've done a quick test: the problem is that the BITCAST node is not generated during the SelectionDAG building. If you look in SelectionDAGBuilder::<u></u>visitBitCast, you will see that the node is generated only if the operand value of the bitcast operation and the result value have different EVTs: the address space information is not handled in EVT and so pointers in different address spaces are mapped to the same EVT that imply a missing BITCAST node.<br>
<br>
Maybe rethinking the way address spaces are handled at the interface between middle-end and backend would allow to fix also these kind of problems. BTW, I think this specific problem can be used for a bug report :-).<br>
<br>
Thanks.<span class="HOEnZb"><font color="#888888"><br>
<br>
-Michele</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
______________________________<u></u>_________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvmdev</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><br><div>Thanks,</div><div><br></div><div>Justin Holewinski</div>
</div>