Skip to content

Commit 3e64db5

Browse files
authored
[ConstantFolding] Support ptrtoaddr in cast folds (#162480)
We can support the same folds for as for ptrtoint. For the cast pair fold we just need to use the address type instead. The gep based folds were already operating on the address (aka index) width anyway.
1 parent a5d37d5 commit 3e64db5

File tree

2 files changed

+54
-16
lines changed

2 files changed

+54
-16
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,30 +1495,31 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14951495
default:
14961496
llvm_unreachable("Missing case");
14971497
case Instruction::PtrToAddr:
1498-
// TODO: Add some of the ptrtoint folds here as well.
1499-
break;
15001498
case Instruction::PtrToInt:
15011499
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
15021500
Constant *FoldedValue = nullptr;
1503-
// If the input is a inttoptr, eliminate the pair. This requires knowing
1501+
// If the input is an inttoptr, eliminate the pair. This requires knowing
15041502
// the width of a pointer, so it can't be done in ConstantExpr::getCast.
15051503
if (CE->getOpcode() == Instruction::IntToPtr) {
1506-
// zext/trunc the inttoptr to pointer size.
1507-
FoldedValue = ConstantFoldIntegerCast(CE->getOperand(0),
1508-
DL.getIntPtrType(CE->getType()),
1504+
// zext/trunc the inttoptr to pointer/address size.
1505+
Type *MidTy = Opcode == Instruction::PtrToInt
1506+
? DL.getAddressType(CE->getType())
1507+
: DL.getIntPtrType(CE->getType());
1508+
FoldedValue = ConstantFoldIntegerCast(CE->getOperand(0), MidTy,
15091509
/*IsSigned=*/false, DL);
15101510
} else if (auto *GEP = dyn_cast<GEPOperator>(CE)) {
15111511
// If we have GEP, we can perform the following folds:
1512-
// (ptrtoint (gep null, x)) -> x
1513-
// (ptrtoint (gep (gep null, x), y) -> x + y, etc.
1512+
// (ptrtoint/ptrtoaddr (gep null, x)) -> x
1513+
// (ptrtoint/ptrtoaddr (gep (gep null, x), y) -> x + y, etc.
15141514
unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
15151515
APInt BaseOffset(BitWidth, 0);
15161516
auto *Base = cast<Constant>(GEP->stripAndAccumulateConstantOffsets(
15171517
DL, BaseOffset, /*AllowNonInbounds=*/true));
15181518
if (Base->isNullValue()) {
15191519
FoldedValue = ConstantInt::get(CE->getContext(), BaseOffset);
15201520
} else {
1521-
// ptrtoint (gep i8, Ptr, (sub 0, V)) -> sub (ptrtoint Ptr), V
1521+
// ptrtoint/ptrtoaddr (gep i8, Ptr, (sub 0, V))
1522+
// -> sub (ptrtoint/ptrtoaddr Ptr), V
15221523
if (GEP->getNumIndices() == 1 &&
15231524
GEP->getSourceElementType()->isIntegerTy(8)) {
15241525
auto *Ptr = cast<Constant>(GEP->getPointerOperand());
@@ -1528,12 +1529,13 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
15281529
Sub->getOpcode() == Instruction::Sub &&
15291530
Sub->getOperand(0)->isNullValue())
15301531
FoldedValue = ConstantExpr::getSub(
1531-
ConstantExpr::getPtrToInt(Ptr, IntIdxTy), Sub->getOperand(1));
1532+
ConstantExpr::getCast(Opcode, Ptr, IntIdxTy),
1533+
Sub->getOperand(1));
15321534
}
15331535
}
15341536
}
15351537
if (FoldedValue) {
1536-
// Do a zext or trunc to get to the ptrtoint dest size.
1538+
// Do a zext or trunc to get to the ptrtoint/ptrtoaddr dest size.
15371539
return ConstantFoldIntegerCast(FoldedValue, DestTy, /*IsSigned=*/false,
15381540
DL);
15391541
}

llvm/test/Transforms/InstCombine/ptrtoaddr.ll

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3-
target datalayout = "p1:64:64:64:32"
3+
4+
; The ptrtoaddr folds are also valid for pointers that have external state.
5+
target datalayout = "pe1:64:64:64:32"
6+
7+
@g = external global i8
8+
@g2 = external global i8
9+
10+
@g.as1 = external addrspace(1) global i8
11+
@g2.as1 = external addrspace(1) global i8
412

513
define i32 @ptrtoaddr_inttoptr_arg(i32 %a) {
614
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_arg(
@@ -24,14 +32,14 @@ define i32 @ptrtoaddr_inttoptr() {
2432

2533
define i32 @ptrtoaddr_inttoptr_diff_size1() {
2634
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_diff_size1() {
27-
; CHECK-NEXT: ret i32 ptrtoaddr (ptr addrspace(1) inttoptr (i64 -1 to ptr addrspace(1)) to i32)
35+
; CHECK-NEXT: ret i32 -1
2836
;
2937
ret i32 ptrtoaddr (ptr addrspace(1) inttoptr (i64 -1 to ptr addrspace(1)) to i32)
3038
}
3139

3240
define i32 @ptrtoaddr_inttoptr_diff_size2() {
3341
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_diff_size2() {
34-
; CHECK-NEXT: ret i32 ptrtoaddr (ptr addrspace(1) inttoptr (i16 -1 to ptr addrspace(1)) to i32)
42+
; CHECK-NEXT: ret i32 65535
3543
;
3644
ret i32 ptrtoaddr (ptr addrspace(1) inttoptr (i16 -1 to ptr addrspace(1)) to i32)
3745
}
@@ -52,14 +60,42 @@ define i64 @ptr2addr2_inttoptr_noas2() {
5260

5361
define i64 @ptrtoaddr_inttoptr_noas_diff_size1() {
5462
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_noas_diff_size1() {
55-
; CHECK-NEXT: ret i64 ptrtoaddr (ptr inttoptr (i32 -1 to ptr) to i64)
63+
; CHECK-NEXT: ret i64 4294967295
5664
;
5765
ret i64 ptrtoaddr (ptr inttoptr (i32 -1 to ptr) to i64)
5866
}
5967

6068
define i64 @ptrtoaddr_inttoptr_noas_diff_size2() {
6169
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_noas_diff_size2() {
62-
; CHECK-NEXT: ret i64 ptrtoaddr (ptr inttoptr (i128 -1 to ptr) to i64)
70+
; CHECK-NEXT: ret i64 -1
6371
;
6472
ret i64 ptrtoaddr (ptr inttoptr (i128 -1 to ptr) to i64)
6573
}
74+
75+
define i64 @ptrtoaddr_gep_null() {
76+
; CHECK-LABEL: define i64 @ptrtoaddr_gep_null() {
77+
; CHECK-NEXT: ret i64 42
78+
;
79+
ret i64 ptrtoaddr (ptr getelementptr (i8, ptr null, i64 42) to i64)
80+
}
81+
82+
define i32 @ptrtoaddr_gep_null_addrsize() {
83+
; CHECK-LABEL: define i32 @ptrtoaddr_gep_null_addrsize() {
84+
; CHECK-NEXT: ret i32 42
85+
;
86+
ret i32 ptrtoaddr (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i32 42) to i32)
87+
}
88+
89+
define i64 @ptrtoaddr_gep_sub() {
90+
; CHECK-LABEL: define i64 @ptrtoaddr_gep_sub() {
91+
; CHECK-NEXT: ret i64 sub (i64 ptrtoaddr (ptr @g to i64), i64 ptrtoaddr (ptr @g2 to i64))
92+
;
93+
ret i64 ptrtoaddr (ptr getelementptr (i8, ptr @g, i64 sub (i64 0, i64 ptrtoaddr (ptr @g2 to i64))) to i64)
94+
}
95+
96+
define i32 @ptrtoaddr_gep_sub_addrsize() {
97+
; CHECK-LABEL: define i32 @ptrtoaddr_gep_sub_addrsize() {
98+
; CHECK-NEXT: ret i32 sub (i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), i32 ptrtoaddr (ptr addrspace(1) @g2.as1 to i32))
99+
;
100+
ret i32 ptrtoaddr (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @g.as1, i32 sub (i32 0, i32 ptrtoaddr (ptr addrspace(1) @g2.as1 to i32))) to i32)
101+
}

0 commit comments

Comments
 (0)