[llvm] 4a3e000 - [IR] Handle trunc for ptrtoaddr(inttoptr) cast pair (#162842)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 13 02:10:45 PDT 2025
Author: Nikita Popov
Date: 2025-10-13T09:10:41Z
New Revision: 4a3e0001e367a930cb7dec2dcd072cc512825aff
URL: https://github.com/llvm/llvm-project/commit/4a3e0001e367a930cb7dec2dcd072cc512825aff
DIFF: https://github.com/llvm/llvm-project/commit/4a3e0001e367a930cb7dec2dcd072cc512825aff.diff
LOG: [IR] Handle trunc for ptrtoaddr(inttoptr) cast pair (#162842)
For ptrtoint(inttoptr) and ptrtoaddr(inttoptr), handle the case where
the source and destination size do not match and convert to either zext
or trunc. We can't do this if the middle size is smaller than both
src/dest, because we'd have to perform an additional masking operation
in that case.
Most of these cases are handled by dint of ptrtoint/inttoptr size
canonicalization (so I added some unit tests instead). However, the
ptrtoaddr(inttoptr) case where the pointer size and address size differ
is relevant, as in that case the mismatch in integer sizes is canonical.
Added:
Modified:
llvm/lib/IR/Instructions.cpp
llvm/test/Transforms/InstCombine/ptrtoaddr.ll
llvm/unittests/IR/InstructionsTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 88e7c44a8b885..9060a89bb15ff 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -2965,8 +2965,7 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
// zext, sext -> zext, because sext can't sign extend after zext
return Instruction::ZExt;
case 11: {
- // inttoptr, ptrtoint/ptrtoaddr -> bitcast if SrcSize<=PtrSize/AddrSize
- // and SrcSize==DstSize
+ // inttoptr, ptrtoint/ptrtoaddr -> integer cast
if (!DL)
return 0;
unsigned MidSize = secondOp == Instruction::PtrToAddr
@@ -2974,10 +2973,15 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
: DL->getPointerTypeSizeInBits(MidTy);
unsigned SrcSize = SrcTy->getScalarSizeInBits();
unsigned DstSize = DstTy->getScalarSizeInBits();
- // TODO: Could also produce zext or trunc here.
- if (SrcSize <= MidSize && SrcSize == DstSize)
- return Instruction::BitCast;
- return 0;
+ // If the middle size is smaller than both source and destination,
+ // an additional masking operation would be required.
+ if (MidSize < SrcSize && MidSize < DstSize)
+ return 0;
+ if (DstSize < SrcSize)
+ return Instruction::Trunc;
+ if (DstSize > SrcSize)
+ return Instruction::ZExt;
+ return Instruction::BitCast;
}
case 12:
// addrspacecast, addrspacecast -> bitcast, if SrcAS == DstAS
diff --git a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
index 7b0b152990216..ffaa8b110e32c 100644
--- a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
+++ b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll
@@ -23,10 +23,7 @@ define i64 @ptrtoaddr_inttoptr_arg(i64 %a) {
define i32 @ptrtoaddr_inttoptr_arg_addrsize(i32 %a) {
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_arg_addrsize(
; CHECK-SAME: i32 [[A:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[A]] to i64
-; CHECK-NEXT: [[TOPTR:%.*]] = inttoptr i64 [[TMP1]] to ptr addrspace(1)
-; CHECK-NEXT: [[TOADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[TOPTR]] to i32
-; CHECK-NEXT: ret i32 [[TOADDR]]
+; CHECK-NEXT: ret i32 [[A]]
;
%toptr = inttoptr i32 %a to ptr addrspace(1)
%toaddr = ptrtoaddr ptr addrspace(1) %toptr to i32
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index fe9e7e8228490..f4693bfb1a4d1 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -606,12 +606,14 @@ TEST(InstructionTest, ConstrainedTrans) {
TEST(InstructionsTest, isEliminableCastPair) {
LLVMContext C;
- DataLayout DL1("p1:32:32");
+ DataLayout DL1("p1:32:32-p2:64:64:64:32");
Type *Int16Ty = Type::getInt16Ty(C);
+ Type *Int32Ty = Type::getInt32Ty(C);
Type *Int64Ty = Type::getInt64Ty(C);
Type *PtrTy64 = PointerType::get(C, 0);
Type *PtrTy32 = PointerType::get(C, 1);
+ Type *PtrTy64_32 = PointerType::get(C, 2);
// Source and destination pointers have same size -> bitcast.
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
@@ -637,6 +639,42 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int64Ty, &DL1),
0U);
+ // Destination larger than source. Pointer type same as destination.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int16Ty, PtrTy64,
+ Int64Ty, &DL1),
+ CastInst::ZExt);
+
+ // Destination larger than source. Pointer type
diff erent from destination.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int16Ty, PtrTy32,
+ Int64Ty, &DL1),
+ CastInst::ZExt);
+
+ // Destination smaller than source. Pointer type same as source.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int64Ty, PtrTy64,
+ Int16Ty, &DL1),
+ CastInst::Trunc);
+
+ // Destination smaller than source. Pointer type
diff erent from source.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt, Int64Ty, PtrTy32,
+ Int16Ty, &DL1),
+ CastInst::Trunc);
+
+ // ptrtoaddr with address size != pointer size. Truncating case.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToAddr, Int64Ty,
+ PtrTy64_32, Int32Ty, &DL1),
+ CastInst::Trunc);
+
+ // ptrtoaddr with address size != pointer size. Non-truncating case.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToAddr, Int32Ty,
+ PtrTy64_32, Int32Ty, &DL1),
+ CastInst::BitCast);
+
// Test that we don't eliminate bitcasts between
diff erent address spaces,
// or if we don't have available pointer size information.
DataLayout DL2("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
More information about the llvm-commits
mailing list