This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fix incongruous GEP type addrspace
ClosedPublic

Authored by EwanCrawford on Sep 20 2018, 3:03 AM.

Details

Summary

Currently running the @insertelem_after_gep function below through the InstCombine pass with opt produces invalid IR.

Input:

define void @insertelem_after_gep(<16 x i32>* %t0) {
   %t1 = bitcast <16 x i32>* %t0 to [16 x i32]*
   %t2 = addrspacecast [16 x i32]* %t1 to [16 x i32] addrspace(3)*
   %t3 = getelementptr inbounds [16 x i32], [16 x i32] addrspace(3)* %t2, i64 0, i64 0
   %t4 = insertelement <16 x i32 addrspace(3)*> undef, i32 addrspace(3)* %t3, i32 0
   call void @extern_vec_pointers_func(<16 x i32 addrspace(3)*> %t4)
   ret void
}

Output:

define void @insertelem_after_gep(<16 x i32>* %t0) {
  %t3 = getelementptr inbounds <16 x i32>, <16 x i32>* %t0, i64 0, i64 0
  %t4 = insertelement <16 x i32 addrspace(3)*> undef, i32 addrspace(3)* %t3, i32 0
  call void @my_extern_func(<16 x i32 addrspace(3)*> %t4)
  ret void
}

Which although causes no complaints when produced, isn't valid IR as the insertelement use of the %t3 GEP expects an address space.

opt: /tmp/bad.ll:52:73: error: '%t3' defined with type 'i32*' but expected 'i32 addrspace(3)*'
  %t4 = insertelement <16 x i32 addrspace(3)*> undef, i32 addrspace(3)* %t3, i32 0

I've fixed this by adding an addrspacecast after the GEP in the InstCombine pass, and including a check for this type mismatch to the verifier.

Diff Detail

Repository
rL LLVM

Event Timeline

EwanCrawford created this revision.Sep 20 2018, 3:03 AM
lebedev.ri added inline comments.Sep 21 2018, 12:59 AM
lib/Transforms/InstCombine/InstructionCombining.cpp
2033–2035 ↗(On Diff #166249)

I do not understand, why do we need to create a new GEP here, as compared to the old code?
Why can't we just only create AddrSpaceCastInst if needed?

EwanCrawford added inline comments.Sep 21 2018, 2:31 AM
lib/Transforms/InstCombine/InstructionCombining.cpp
2033–2035 ↗(On Diff #166249)

Thanks for taking a look @lebedev.ri!

Doing setOperand then setSourceElementType in the old code doesn't actually change the type of the GEP Value for this test case. I get i32 addrspace(3)* for GEP.getType() both before and after these operation, despite the fact that the GEP now points to a i32* afterwards.

Therefore if we call new addrSpaceCastInst(GEP, GEPType) we hit an assert since the types of GEP and GEPType are identical. However if we create a new GEP, then it is correctly instantiated with the i32* type and the addrSpaceCastInst can be created successfully.

That was my thinking anyway.

Looking at the existing code in this file, this seems like the way to handle it. Reviewing D44833 (where I added this transform), can we minimize the test to something like:

define i32 addrspace(3)* @bitcast_vec_to_array_gep(<7 x i32>* %x, i64 %y, i64 %z) {
  %arr_ptr = bitcast <7 x i32>* %x to [7 x i32]*
  %asc = addrspacecast [7 x i32]* %arr_ptr to [7 x i32] addrspace(3)*
  %gep = getelementptr [7 x i32], [7 x i32] addrspace(3)* %asc, i64 %y, i64 %z
  ret i32 addrspace(3)* %gep
}

There should be an 'inbounds' test too to cover the other code path. Given that this doesn't trigger the IR verifier (should we fix that too?), you could add the tests showing the bogus IR as a preliminary commit.

Thanks for the feedback @spatel.
I've modified the test according to your suggestions and added a check to the verifier which fires without the instcombine change.

spatel added a comment.Oct 4 2018, 2:11 PM

LGTM, but let's see if @lebedev.ri has any other feedback before marking as approved.

lib/Transforms/InstCombine/InstructionCombining.cpp
2059 ↗(On Diff #168254)

Nit: since we know there are only 3 operands here, it would be less ambiguous to use something like { Op[1], Op[2] } here?

LGTM, but let's see if @lebedev.ri has any other feedback before marking as approved.

No, no real feedback, that is why i'm not commenting.

lib/IR/Verifier.cpp
3142 ↗(On Diff #168254)

if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) {

lib/Transforms/InstCombine/InstructionCombining.cpp
2055 ↗(On Diff #168254)

nit: Maybe add a comment explaining why we are creating a new GEP + AddrSpaceCast?

EwanCrawford edited the summary of this revision. (Show Details)

done, thanks again

spatel accepted this revision.Oct 5 2018, 6:13 AM

LGTM - thanks!

This revision is now accepted and ready to land.Oct 5 2018, 6:13 AM
This revision was automatically updated to reflect the committed changes.