Skip to content

Commit 55815b6

Browse files
authored
[Value] Look through inttoptr (add ..) in accumulateConstantOffsets (#124981)
Look through inttoptr (add (ptrtoint P), C) when accumulating offsets. Adds a missing fold after #123518 Alive2 for the tests with changes: https://alive2.llvm.org/ce/z/VvPrzv PR: #124981
1 parent 9b52dbe commit 55815b6

File tree

4 files changed

+62
-19
lines changed

4 files changed

+62
-19
lines changed

llvm/include/llvm/IR/Value.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,10 @@ class Value {
710710
/// For example, for a value \p ExternalAnalysis might try to calculate a
711711
/// lower bound. If \p ExternalAnalysis is successful, it should return true.
712712
///
713+
/// If \p LookThroughIntToPtr is true then this method also looks through
714+
/// IntToPtr and PtrToInt constant expressions. The returned pointer may not
715+
/// have the same provenance as this value.
716+
///
713717
/// If this is called on a non-pointer value, it returns 'this' and the
714718
/// \p Offset is not modified.
715719
///
@@ -722,17 +726,19 @@ class Value {
722726
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
723727
bool AllowInvariantGroup = false,
724728
function_ref<bool(Value &Value, APInt &Offset)> ExternalAnalysis =
725-
nullptr) const;
729+
nullptr,
730+
bool LookThroughIntToPtr = false) const;
726731

727732
Value *stripAndAccumulateConstantOffsets(
728733
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
729734
bool AllowInvariantGroup = false,
730735
function_ref<bool(Value &Value, APInt &Offset)> ExternalAnalysis =
731-
nullptr) {
736+
nullptr,
737+
bool LookThroughIntToPtr = false) {
732738
return const_cast<Value *>(
733739
static_cast<const Value *>(this)->stripAndAccumulateConstantOffsets(
734-
DL, Offset, AllowNonInbounds, AllowInvariantGroup,
735-
ExternalAnalysis));
740+
DL, Offset, AllowNonInbounds, AllowInvariantGroup, ExternalAnalysis,
741+
LookThroughIntToPtr));
736742
}
737743

738744
/// This is a wrapper around stripAndAccumulateConstantOffsets with the

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,11 +1258,16 @@ Constant *llvm::ConstantFoldCompareInstOperands(
12581258
if (Ops0->getType()->isPointerTy() && !ICmpInst::isSigned(Predicate)) {
12591259
unsigned IndexWidth = DL.getIndexTypeSizeInBits(Ops0->getType());
12601260
APInt Offset0(IndexWidth, 0);
1261-
Value *Stripped0 =
1262-
Ops0->stripAndAccumulateInBoundsConstantOffsets(DL, Offset0);
1261+
bool IsEqPred = ICmpInst::isEquality(Predicate);
1262+
Value *Stripped0 = Ops0->stripAndAccumulateConstantOffsets(
1263+
DL, Offset0, /*AllowNonInbounds=*/IsEqPred,
1264+
/*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
1265+
/*LookThroughIntToPtr=*/IsEqPred);
12631266
APInt Offset1(IndexWidth, 0);
1264-
Value *Stripped1 =
1265-
Ops1->stripAndAccumulateInBoundsConstantOffsets(DL, Offset1);
1267+
Value *Stripped1 = Ops1->stripAndAccumulateConstantOffsets(
1268+
DL, Offset1, /*AllowNonInbounds=*/IsEqPred,
1269+
/*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
1270+
/*LookThroughIntToPtr=*/IsEqPred);
12661271
if (Stripped0 == Stripped1)
12671272
return ConstantInt::getBool(
12681273
Ops0->getContext(),

llvm/lib/IR/Value.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,8 @@ const Value *Value::stripPointerCastsForAliasAnalysis() const {
714714
const Value *Value::stripAndAccumulateConstantOffsets(
715715
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
716716
bool AllowInvariantGroup,
717-
function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
717+
function_ref<bool(Value &, APInt &)> ExternalAnalysis,
718+
bool LookThroughIntToPtr) const {
718719
if (!getType()->isPtrOrPtrVectorTy())
719720
return this;
720721

@@ -775,6 +776,24 @@ const Value *Value::stripAndAccumulateConstantOffsets(
775776
V = RV;
776777
if (AllowInvariantGroup && Call->isLaunderOrStripInvariantGroup())
777778
V = Call->getArgOperand(0);
779+
} else if (auto *Int2Ptr = dyn_cast<Operator>(V)) {
780+
// Try to accumulate across (inttoptr (add (ptrtoint p), off)).
781+
if (!AllowNonInbounds || !LookThroughIntToPtr || !Int2Ptr ||
782+
Int2Ptr->getOpcode() != Instruction::IntToPtr ||
783+
Int2Ptr->getOperand(0)->getType()->getScalarSizeInBits() != BitWidth)
784+
return V;
785+
786+
auto *Add = dyn_cast<AddOperator>(Int2Ptr->getOperand(0));
787+
if (!Add)
788+
return V;
789+
790+
auto *Ptr2Int = dyn_cast<PtrToIntOperator>(Add->getOperand(0));
791+
auto *CI = dyn_cast<ConstantInt>(Add->getOperand(1));
792+
if (!Ptr2Int || !CI)
793+
return V;
794+
795+
Offset += CI->getValue();
796+
V = Ptr2Int->getOperand(0);
778797
}
779798
assert(V->getType()->isPtrOrPtrVectorTy() && "Unexpected operand type!");
780799
} while (Visited.insert(V).second);

llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2-
; RUN: opt -p instcombine -S %s | FileCheck %s
2+
; RUN: opt -p instsimplify -S %s | FileCheck %s
33

44
@glob = external global [314 x i64]
55

66
define i1 @known_constexpr_add_eq() {
77
; CHECK-LABEL: define i1 @known_constexpr_add_eq() {
8-
; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
9-
; CHECK-NEXT: ret i1 [[COND]]
8+
; CHECK-NEXT: ret i1 false
109
;
1110
%cond = icmp eq ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
1211
ret i1 %cond
1312
}
1413

1514
define i1 @known_constexpr_add_eq_ops_swapped() {
1615
; CHECK-LABEL: define i1 @known_constexpr_add_eq_ops_swapped() {
17-
; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
18-
; CHECK-NEXT: ret i1 [[COND]]
16+
; CHECK-NEXT: ret i1 false
1917
;
20-
%cond = icmp eq ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
18+
%cond = icmp eq ptr inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr), getelementptr inbounds nuw (i8, ptr @glob, i64 80)
2119
ret i1 %cond
2220
}
2321

2422
define i1 @known_constexpr_add_ne() {
2523
; CHECK-LABEL: define i1 @known_constexpr_add_ne() {
26-
; CHECK-NEXT: [[COND:%.*]] = icmp ne ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
27-
; CHECK-NEXT: ret i1 [[COND]]
24+
; CHECK-NEXT: ret i1 true
2825
;
2926
%cond = icmp ne ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80), inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr)
3027
ret i1 %cond
@@ -41,8 +38,7 @@ define i1 @wrap_positive_to_negate() {
4138
; 9223372036854775808 = 2^63
4239
define i1 @wrap_positive_to_zero() {
4340
; CHECK-LABEL: define i1 @wrap_positive_to_zero() {
44-
; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr @glob, inttoptr (i64 add (i64 ptrtoint (ptr getelementptr nuw (i8, ptr @glob, i64 -9223372036854775808) to i64), i64 -9223372036854775808) to ptr)
45-
; CHECK-NEXT: ret i1 [[COND]]
41+
; CHECK-NEXT: ret i1 true
4642
;
4743
%cond = icmp eq ptr @glob, inttoptr (i64 add (i64 ptrtoint (ptr getelementptr nuw (i8, ptr @glob, i64 9223372036854775808)to i64), i64 9223372036854775808) to ptr)
4844
ret i1 %cond
@@ -99,3 +95,20 @@ define ptr @return_inttoptr() {
9995
;
10096
ret ptr inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 8) to ptr)
10197
}
98+
99+
define i1 @known_constexpr_add_nested_1() {
100+
; CHECK-LABEL: define i1 @known_constexpr_add_nested_1() {
101+
; CHECK-NEXT: ret i1 true
102+
;
103+
%cond = icmp eq ptr @glob, inttoptr (i64 add (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr @glob, i64 80) to i64), i64 -80) to ptr)
104+
ret i1 %cond
105+
}
106+
107+
define i1 @known_constexpr_add_nested_2() {
108+
; CHECK-LABEL: define i1 @known_constexpr_add_nested_2() {
109+
; CHECK-NEXT: ret i1 true
110+
;
111+
;%cond = icmp eq ptr @glob, ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr), i64 80)
112+
%cond = icmp eq ptr @glob, getelementptr inbounds nuw (i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 -80) to ptr), i64 80)
113+
ret i1 %cond
114+
}

0 commit comments

Comments
 (0)