[llvm] 55815b6 - [Value] Look through inttoptr (add ..) in accumulateConstantOffsets (#124981)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 30 12:58:42 PST 2025
Author: Florian Hahn
Date: 2025-01-30T20:58:38Z
New Revision: 55815b621b3a8f56a36c93229de1356e325a136f
URL: https://github.com/llvm/llvm-project/commit/55815b621b3a8f56a36c93229de1356e325a136f
DIFF: https://github.com/llvm/llvm-project/commit/55815b621b3a8f56a36c93229de1356e325a136f.diff
LOG: [Value] Look through inttoptr (add ..) in accumulateConstantOffsets (#124981)
Look through inttoptr (add (ptrtoint P), C) when accumulating offsets.
Adds a missing fold after
https://github.com/llvm/llvm-project/pull/123518
Alive2 for the tests with changes: https://alive2.llvm.org/ce/z/VvPrzv
PR: https://github.com/llvm/llvm-project/pull/124981
Added:
Modified:
llvm/include/llvm/IR/Value.h
llvm/lib/Analysis/ConstantFolding.cpp
llvm/lib/IR/Value.cpp
llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h
index 011aedece94ab7..cfed12e2f5f8d2 100644
--- a/llvm/include/llvm/IR/Value.h
+++ b/llvm/include/llvm/IR/Value.h
@@ -710,6 +710,10 @@ class Value {
/// For example, for a value \p ExternalAnalysis might try to calculate a
/// lower bound. If \p ExternalAnalysis is successful, it should return true.
///
+ /// If \p LookThroughIntToPtr is true then this method also looks through
+ /// IntToPtr and PtrToInt constant expressions. The returned pointer may not
+ /// have the same provenance as this value.
+ ///
/// If this is called on a non-pointer value, it returns 'this' and the
/// \p Offset is not modified.
///
@@ -722,17 +726,19 @@ class Value {
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
bool AllowInvariantGroup = false,
function_ref<bool(Value &Value, APInt &Offset)> ExternalAnalysis =
- nullptr) const;
+ nullptr,
+ bool LookThroughIntToPtr = false) const;
Value *stripAndAccumulateConstantOffsets(
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
bool AllowInvariantGroup = false,
function_ref<bool(Value &Value, APInt &Offset)> ExternalAnalysis =
- nullptr) {
+ nullptr,
+ bool LookThroughIntToPtr = false) {
return const_cast<Value *>(
static_cast<const Value *>(this)->stripAndAccumulateConstantOffsets(
- DL, Offset, AllowNonInbounds, AllowInvariantGroup,
- ExternalAnalysis));
+ DL, Offset, AllowNonInbounds, AllowInvariantGroup, ExternalAnalysis,
+ LookThroughIntToPtr));
}
/// This is a wrapper around stripAndAccumulateConstantOffsets with the
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 80c1277e631653..d645bf8f7b6212 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1258,11 +1258,16 @@ Constant *llvm::ConstantFoldCompareInstOperands(
if (Ops0->getType()->isPointerTy() && !ICmpInst::isSigned(Predicate)) {
unsigned IndexWidth = DL.getIndexTypeSizeInBits(Ops0->getType());
APInt Offset0(IndexWidth, 0);
- Value *Stripped0 =
- Ops0->stripAndAccumulateInBoundsConstantOffsets(DL, Offset0);
+ bool IsEqPred = ICmpInst::isEquality(Predicate);
+ Value *Stripped0 = Ops0->stripAndAccumulateConstantOffsets(
+ DL, Offset0, /*AllowNonInbounds=*/IsEqPred,
+ /*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
+ /*LookThroughIntToPtr=*/IsEqPred);
APInt Offset1(IndexWidth, 0);
- Value *Stripped1 =
- Ops1->stripAndAccumulateInBoundsConstantOffsets(DL, Offset1);
+ Value *Stripped1 = Ops1->stripAndAccumulateConstantOffsets(
+ DL, Offset1, /*AllowNonInbounds=*/IsEqPred,
+ /*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
+ /*LookThroughIntToPtr=*/IsEqPred);
if (Stripped0 == Stripped1)
return ConstantInt::getBool(
Ops0->getContext(),
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index eddb67282fca46..b5a69b9ecdde45 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -714,7 +714,8 @@ const Value *Value::stripPointerCastsForAliasAnalysis() const {
const Value *Value::stripAndAccumulateConstantOffsets(
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
bool AllowInvariantGroup,
- function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
+ function_ref<bool(Value &, APInt &)> ExternalAnalysis,
+ bool LookThroughIntToPtr) const {
if (!getType()->isPtrOrPtrVectorTy())
return this;
@@ -775,6 +776,24 @@ const Value *Value::stripAndAccumulateConstantOffsets(
V = RV;
if (AllowInvariantGroup && Call->isLaunderOrStripInvariantGroup())
V = Call->getArgOperand(0);
+ } else if (auto *Int2Ptr = dyn_cast<Operator>(V)) {
+ // Try to accumulate across (inttoptr (add (ptrtoint p), off)).
+ if (!AllowNonInbounds || !LookThroughIntToPtr || !Int2Ptr ||
+ Int2Ptr->getOpcode() != Instruction::IntToPtr ||
+ Int2Ptr->getOperand(0)->getType()->getScalarSizeInBits() != BitWidth)
+ return V;
+
+ auto *Add = dyn_cast<AddOperator>(Int2Ptr->getOperand(0));
+ if (!Add)
+ return V;
+
+ auto *Ptr2Int = dyn_cast<PtrToIntOperator>(Add->getOperand(0));
+ auto *CI = dyn_cast<ConstantInt>(Add->getOperand(1));
+ if (!Ptr2Int || !CI)
+ return V;
+
+ Offset += CI->getValue();
+ V = Ptr2Int->getOperand(0);
}
assert(V->getType()->isPtrOrPtrVectorTy() && "Unexpected operand type!");
} while (Visited.insert(V).second);
diff --git a/llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll b/llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll
index 59b41574102464..34dee39463d9b6 100644
--- a/llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll
+++ b/llvm/test/Transforms/InstSimplify/constant-fold-inttoptr-add.ll
@@ -1,12 +1,11 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -p instcombine -S %s | FileCheck %s
+; RUN: opt -p instsimplify -S %s | FileCheck %s
@glob = external global [314 x i64]
define i1 @known_constexpr_add_eq() {
; CHECK-LABEL: define i1 @known_constexpr_add_eq() {
-; 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)
-; CHECK-NEXT: ret i1 [[COND]]
+; CHECK-NEXT: ret i1 false
;
%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)
ret i1 %cond
@@ -14,17 +13,15 @@ define i1 @known_constexpr_add_eq() {
define i1 @known_constexpr_add_eq_ops_swapped() {
; CHECK-LABEL: define i1 @known_constexpr_add_eq_ops_swapped() {
-; 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)
-; CHECK-NEXT: ret i1 [[COND]]
+; CHECK-NEXT: ret i1 false
;
- %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)
+ %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)
ret i1 %cond
}
define i1 @known_constexpr_add_ne() {
; CHECK-LABEL: define i1 @known_constexpr_add_ne() {
-; 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)
-; CHECK-NEXT: ret i1 [[COND]]
+; CHECK-NEXT: ret i1 true
;
%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)
ret i1 %cond
@@ -41,8 +38,7 @@ define i1 @wrap_positive_to_negate() {
; 9223372036854775808 = 2^63
define i1 @wrap_positive_to_zero() {
; CHECK-LABEL: define i1 @wrap_positive_to_zero() {
-; 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)
-; CHECK-NEXT: ret i1 [[COND]]
+; CHECK-NEXT: ret i1 true
;
%cond = icmp eq ptr @glob, inttoptr (i64 add (i64 ptrtoint (ptr getelementptr nuw (i8, ptr @glob, i64 9223372036854775808)to i64), i64 9223372036854775808) to ptr)
ret i1 %cond
@@ -99,3 +95,20 @@ define ptr @return_inttoptr() {
;
ret ptr inttoptr (i64 add (i64 ptrtoint (ptr @glob to i64), i64 8) to ptr)
}
+
+define i1 @known_constexpr_add_nested_1() {
+; CHECK-LABEL: define i1 @known_constexpr_add_nested_1() {
+; CHECK-NEXT: ret i1 true
+;
+ %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)
+ ret i1 %cond
+}
+
+define i1 @known_constexpr_add_nested_2() {
+; CHECK-LABEL: define i1 @known_constexpr_add_nested_2() {
+; CHECK-NEXT: ret i1 true
+;
+ ;%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)
+ %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)
+ ret i1 %cond
+}
More information about the llvm-commits
mailing list