[SDAG] Recovering pointer types

I am wondering if there is a good/easy way to recover the original type of a pointer parameter in the SDAG. Here’s the problem that I am dealing with:

define <4 x i32> @test(i32* nocapture readonly %a) local_unnamed_addr #0 {
entry:
%0 = bitcast i32* %a to <4 x i32>*
%1 = load <4 x i32>, <4 x i32>* %0, align 16, !tbaa !2
ret <4 x i32> %1
}

The problem is that the alignment requirements on my target for a load of an i32* are different from those on a <4 x i32>*. I don’t see a way to specify that with the DataLayout and when the SelectionDAG is built, the bitcast goes away because both the source and destination types are the same (i64 according to the DataLayout).

So I end up with this as the initial SDAG:
Initial selection DAG: BB#0 ‘test:entry’
SelectionDAG has 9 nodes:
t0: ch = EntryToken
t3: i64 = Constant<0>
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t5: v4i32,ch = load<LD16%0> t0, t2, undef:i64
t7: ch,glue = CopyToReg t0, Register:v4i32 %V2, t5
t8: ch = PPCISD::RET_FLAG t7, Register:v4i32 %V2, t7:1

What I would like to do is emit efficient code for cases where the parameter pointer has the same alignment requirements as the load and emit the conservative but less efficient code in other cases.

Nemanja

Do you actually need to know the original type for this? Isn’t it enough to know the alignment? The getAlignment() / getOriginalAlignment() methods on the LoadSDNode should give you this.

David

David, thank you for the prompt response.

I originally implemented this with a check of getAlignment(). However, both getAlignment() and getOriginalAlignment() on the <4 x i32> load return the stronger alignment (16) rather than the alignment that the i32* parameter would have (4).

So I am a bit stuck in terms of how to verify the original alignment.

It sounds as if the problem here is actually in the front end. For your target, the alignment of <4 x i32> is 4, and so the load should have alignment 4. For some reason, it’s being promoted to 16. If this is clang, then it has probably decided that all 4-way vectors for your target must be naturally aligned. You can change that in the TargetInfo object (I can’t remember if it’s the Basic or CodeGen one that you want for this) for your target.

David

Thank you once again David and thanks for your patience.

I am certainly shifting gears to look at the front end in this case, but here’s a bit more clarification of the situation I’m facing.

The natural alignment for vectors on my target (PPC64) is 16. So if the parameter is a pointer to a vector, the alignment on the parameter as well as the load will be 16 and everything is fine. However, what I’d like to have happen is that if the vector load is from a pointer to a scalar cast to a pointer to a vector, that the alignment on the scalar pointer be propagated to the vector load.

Namely,

vector char foo(vector int *a) {

return *(vector char *)a; // The alignment on the load should be 16 (same as that on the parameter)
}

whereas

vector char foo(int *a) {

return *(vector char *)a; // The alignment on the load should be weaker (same as that on the parameter)
}

I will continue to look at what needs to be changed in the FE and will consider posting the question on cfe-dev if I can’t get anywhere.