diff --git a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp index 03efc156df1e8..ff070c1e0de5e 100644 --- a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp +++ b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp @@ -521,12 +521,27 @@ void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack( DenseSet &Visited) const { assert(V->getType()->isPtrOrPtrVectorTy()); + auto EmplaceBack = [&](Value *Val) { + // The inttoptr can't get the pointer operand of ptrtoint from its user + // operand. When the address space of ptrtoint changes, it won't insert + // inttoptr into WorkList during updating address space. We push its pointer + // operand ahead of inttoptr to make sure the pointer operand's address + // space can be updated first. + Operator *AddrExpr = dyn_cast(Val); + if (AddrExpr && AddrExpr->getOpcode() == Instruction::IntToPtr) { + for (Value *PtrOperand : getPointerOperands(*AddrExpr, *DL, TTI)) { + appendsFlatAddressExpressionToPostorderStack(PtrOperand, PostorderStack, + Visited); + } + } + PostorderStack.emplace_back(Val, false); + }; // Generic addressing expressions may be hidden in nested constant // expressions. if (ConstantExpr *CE = dyn_cast(V)) { // TODO: Look in non-address parts, like icmp operands. if (isAddressExpression(*CE, *DL, TTI) && Visited.insert(CE).second) - PostorderStack.emplace_back(CE, false); + EmplaceBack(CE); return; } @@ -534,13 +549,13 @@ void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack( if (V->getType()->getPointerAddressSpace() == FlatAddrSpace && isAddressExpression(*V, *DL, TTI)) { if (Visited.insert(V).second) { - PostorderStack.emplace_back(V, false); + EmplaceBack(V); if (auto *Op = dyn_cast(V)) for (auto &O : Op->operands()) if (ConstantExpr *CE = dyn_cast(O)) if (isAddressExpression(*CE, *DL, TTI) && Visited.insert(CE).second) - PostorderStack.emplace_back(CE, false); + EmplaceBack(CE); } } } @@ -607,6 +622,7 @@ InferAddressSpacesImpl::collectFlatAddressExpressions(Function &F) const { if (PostorderStack.back().getInt()) { if (TopVal->getType()->getPointerAddressSpace() == FlatAddrSpace) Postorder.push_back(TopVal); + PostorderStack.pop_back(); continue; } @@ -883,8 +899,9 @@ static Value *cloneConstantExprWithNewAddressSpace( if (CE->getOpcode() == Instruction::IntToPtr) { assert(isNoopPtrIntCastPair(cast(CE), *DL, TTI)); Constant *Src = cast(CE->getOperand(0))->getOperand(0); - assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace); - return Src; + if (Src->getType() == TargetType) + return Src; + return ConstantExpr::getAddrSpaceCast(Src, TargetType); } // Computes the operands of the new constant expression. diff --git a/llvm/test/Transforms/InferAddressSpaces/NVPTX/inttoptr_constexpr.ll b/llvm/test/Transforms/InferAddressSpaces/NVPTX/inttoptr_constexpr.ll new file mode 100644 index 0000000000000..5275b777a550c --- /dev/null +++ b/llvm/test/Transforms/InferAddressSpaces/NVPTX/inttoptr_constexpr.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -S -mtriple=nvptx64-nvidia-cuda -passes=infer-address-spaces %s | FileCheck %s + +@g = addrspace(1) global i32 0, align 4 + +define void @test() { +; CHECK-LABEL: define void @test() { +; CHECK-NEXT: store i32 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr addrspacecast (ptr addrspace(1) @g to ptr) to i64), i64 7) to ptr), align 4 +; CHECK-NEXT: ret void +; + store i32 0, ptr inttoptr (i64 + xor (i64 + ptrtoint (ptr + addrspacecast (ptr addrspace(1) @g to ptr) + to i64), + i64 7) + to ptr) + + ret void +} + +define void @test1() { +; CHECK-LABEL: define void @test1() { +; CHECK-NEXT: store i32 0, ptr addrspace(1) @g, align 4 +; CHECK-NEXT: ret void +; + store i32 0, ptr inttoptr (i64 + ptrtoint (ptr + addrspacecast (ptr addrspace(1) @g to ptr) + to i64) + to ptr) + + ret void +}