[llvm] [InferAddressSpaces] apply InferAddressSpaces to inttoptr-zext-ptrtoint address expression. (PR #79108)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 20 23:50:35 PDT 2024
================
@@ -266,38 +266,67 @@ static Type *getPtrOrVecOfPtrsWithNewAS(Type *Ty, unsigned NewAddrSpace) {
return Ty->getWithNewType(NPT);
}
-// Check whether that's no-op pointer bicast using a pair of
-// `ptrtoint`/`inttoptr` due to the missing no-op pointer bitcast over
-// different address spaces.
-static bool isNoopPtrIntCastPair(const Operator *I2P, const DataLayout &DL,
- const TargetTransformInfo *TTI) {
+// Return valid PtrToInt Operator if it's a no-op pointer bitcast using a pair
+// of `ptrtoint`/`inttoptr` or a pointer bitcast using
+// `ptrtoint`-`zext`-`inttoptr` over different address spaces.
+static Operator *getNoopOrExtPtrIntCastPair(const Operator *I2P,
+ const DataLayout &DL,
+ const TargetTransformInfo *TTI) {
assert(I2P->getOpcode() == Instruction::IntToPtr);
- auto *P2I = dyn_cast<Operator>(I2P->getOperand(0));
- if (!P2I || P2I->getOpcode() != Instruction::PtrToInt)
- return false;
- // Check it's really safe to treat that pair of `ptrtoint`/`inttoptr` as a
- // no-op cast. Besides checking both of them are no-op casts, as the
- // reinterpreted pointer may be used in other pointer arithmetic, we also
- // need to double-check that through the target-specific hook. That ensures
- // the underlying target also agrees that's a no-op address space cast and
- // pointer bits are preserved.
- // The current IR spec doesn't have clear rules on address space casts,
- // especially a clear definition for pointer bits in non-default address
- // spaces. It would be undefined if that pointer is dereferenced after an
- // invalid reinterpret cast. Also, due to the unclearness for the meaning of
- // bits in non-default address spaces in the current spec, the pointer
- // arithmetic may also be undefined after invalid pointer reinterpret cast.
- // However, as we confirm through the target hooks that it's a no-op
- // addrspacecast, it doesn't matter since the bits should be the same.
- unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
+ auto *Op = dyn_cast<Operator>(I2P->getOperand(0));
+ if (!Op)
+ return nullptr;
+ bool validAddrSpaceCast = false;
+ Operator *P2I = nullptr;
unsigned I2PAS = I2P->getType()->getPointerAddressSpace();
- return CastInst::isNoopCast(Instruction::CastOps(I2P->getOpcode()),
- I2P->getOperand(0)->getType(), I2P->getType(),
- DL) &&
- CastInst::isNoopCast(Instruction::CastOps(P2I->getOpcode()),
- P2I->getOperand(0)->getType(), P2I->getType(),
- DL) &&
- (P2IOp0AS == I2PAS || TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
+ switch (Op->getOpcode()) {
+ case Instruction::PtrToInt: {
+ // Check it's really safe to treat that pair of `ptrtoint`/`inttoptr` as a
+ // no-op cast. We need to double-check that through the target-specific
+ // hook. That ensures the underlying target also agrees that's a no-op
+ // address space cast and pointer bits are preserved. The current IR spec
+ // doesn't have clear rules on address space casts, especially a clear
+ // definition for pointer bits in non-default address spaces. It would be
+ // undefined if that pointer is dereferenced after an invalid reinterpret
+ // cast. Also, due to the unclearness for the meaning of bits in non-default
+ // address spaces in the current spec, the pointer arithmetic may also be
+ // undefined after invalid pointer reinterpret cast. However, as we confirm
+ // through the target hooks that it's a no-op addrspacecast, it doesn't
+ // matter since the bits should be the same.
+ P2I = Op;
+ unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
+ validAddrSpaceCast =
+ (P2IOp0AS == I2PAS || TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
+ break;
+ }
+ case Instruction::ZExt: {
+ // check src address pointer and dst address pointer should be different
+ // address space and different size
+ P2I = dyn_cast<Operator>(Op->getOperand(0));
+ if (P2I && P2I->getOpcode() == Instruction::PtrToInt) {
+ unsigned P2IOp0AS =
+ P2I->getOperand(0)->getType()->getPointerAddressSpace();
+ unsigned P2IOp0SizeInBits =
+ DL.getPointerTypeSizeInBits(P2I->getOperand(0)->getType());
+ unsigned I2PSizeInBits = DL.getPointerTypeSizeInBits(I2P->getType());
+ validAddrSpaceCast =
+ (P2IOp0AS != I2PAS && P2IOp0SizeInBits < I2PSizeInBits);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ // We also need to check both `inttoptr` and `ptrtoint` are no-op casts, as
+ // the reinterpreted pointer may be used in other pointer arithmetic.
+ if (validAddrSpaceCast &&
+ CastInst::isNoopCast(Instruction::CastOps(I2P->getOpcode()),
+ I2P->getOperand(0)->getType(), I2P->getType(), DL) &&
+ CastInst::isNoopCast(Instruction::CastOps(P2I->getOpcode()),
+ P2I->getOperand(0)->getType(), P2I->getType(), DL)) {
+ return P2I;
----------------
arsenm wrote:
Make this a helper function called in the contexts above instead of falling through to post-process it?
https://github.com/llvm/llvm-project/pull/79108
More information about the llvm-commits
mailing list