-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[ConstantFolding] Avoid use of isNonIntegralPointerType() #159959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ConstantFolding] Avoid use of isNonIntegralPointerType() #159959
Conversation
Created using spr 1.3.8-beta.1 [skip ci]
Created using spr 1.3.8-beta.1
|
@llvm/pr-subscribers-llvm-transforms Author: Alexander Richardson (arichardson) ChangesAvoiding any new inttoptr is unnecessarily restrictive for "plain" Full diff: https://github.com/llvm/llvm-project/pull/159959.diff 3 Files Affected:
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index a3b2e62a1b8ba..e4eac1892cfde 100755
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -951,21 +951,22 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
// If the base value for this address is a literal integer value, fold the
// getelementptr to the resulting integer value casted to the pointer type.
- APInt BasePtr(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
+ APInt BaseIntVal(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
if (auto *CE = dyn_cast<ConstantExpr>(Ptr)) {
if (CE->getOpcode() == Instruction::IntToPtr) {
if (auto *Base = dyn_cast<ConstantInt>(CE->getOperand(0)))
- BasePtr = Base->getValue().zextOrTrunc(BasePtr.getBitWidth());
+ BaseIntVal = Base->getValue().zextOrTrunc(BaseIntVal.getBitWidth());
}
}
auto *PTy = cast<PointerType>(Ptr->getType());
- if ((Ptr->isNullValue() || BasePtr != 0) &&
- !DL.isNonIntegralPointerType(PTy)) {
+ if ((Ptr->isNullValue() || BaseIntVal != 0) &&
+ !DL.shouldAvoidIntToPtr(Ptr->getType())) {
+
// If the index size is smaller than the pointer size, add to the low
// bits only.
- BasePtr.insertBits(BasePtr.trunc(BitWidth) + Offset, 0);
- Constant *C = ConstantInt::get(Ptr->getContext(), BasePtr);
+ BaseIntVal.insertBits(BaseIntVal.trunc(BitWidth) + Offset, 0);
+ Constant *C = ConstantInt::get(Ptr->getContext(), BaseIntVal);
return ConstantExpr::getIntToPtr(C, ResTy);
}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll
deleted file mode 100644
index 2049def9b59b7..0000000000000
--- a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
-
-target datalayout = "p:16:16:16:8"
-
-; The GEP should only modify the low 8 bits of the pointer.
-define ptr @test() {
-; CHECK-LABEL: define ptr @test() {
-; We need to use finer-grained DataLayout properties for non-integral pointers
-; FIXME: Should be: ret ptr inttoptr (i16 -256 to ptr)
-; CHECK-NEXT: ret ptr getelementptr (i8, ptr inttoptr (i16 -1 to ptr), i8 1)
-;
- %base = inttoptr i16 -1 to ptr
- %gep = getelementptr i8, ptr %base, i8 1
- ret ptr %gep
-}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll
new file mode 100644
index 0000000000000..16980b54f93ad
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll
@@ -0,0 +1,75 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
+;; Check that we do not create new inttoptr intstructions for unstable pointers
+;; or pointers with external state (even if the values are all constants).
+;; NOTE: for all but the zero address space, the GEP should only modify the low 8 bits of the pointer.
+target datalayout = "p:16:16:16:16-p1:16:16:16:8-pu2:16:16:16:8-pe3:16:16:16:8"
+
+define ptr @test_null_base_normal() {
+; CHECK-LABEL: define ptr @test_null_base_normal() {
+; CHECK-NEXT: ret ptr inttoptr (i16 -2 to ptr)
+;
+ %gep = getelementptr i8, ptr null, i8 -2
+ ret ptr %gep
+}
+define ptr @test_inttoptr_base_normal() {
+; CHECK-LABEL: define ptr @test_inttoptr_base_normal() {
+; CHECK-NEXT: ret ptr null
+;
+ %base = inttoptr i16 -1 to ptr
+ %gep = getelementptr i8, ptr %base, i8 1
+ ret ptr %gep
+}
+
+;; Transformation is fine for non-integral address space, but we can only change
+;; the index bits (i8 -2 == i16 254)
+define ptr addrspace(1) @test_null_base_nonintegral() {
+; CHECK-LABEL: define ptr addrspace(1) @test_null_base_nonintegral() {
+; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 254 to ptr addrspace(1))
+;
+ %gep = getelementptr i8, ptr addrspace(1) null, i8 -2
+ ret ptr addrspace(1) %gep
+}
+define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
+; CHECK-LABEL: define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
+; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 -256 to ptr addrspace(1))
+;
+ %base = inttoptr i16 -1 to ptr addrspace(1)
+ %gep = getelementptr i8, ptr addrspace(1) %base, i8 1
+ ret ptr addrspace(1) %gep
+}
+
+;; For unstable pointers we should avoid any introduction of inttoptr
+define ptr addrspace(2) @test_null_base_unstable() {
+; CHECK-LABEL: define ptr addrspace(2) @test_null_base_unstable() {
+; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) null, i8 -2)
+;
+ %gep = getelementptr i8, ptr addrspace(2) null, i8 -2
+ ret ptr addrspace(2) %gep
+}
+define ptr addrspace(2) @test_inttoptr_base_unstable() {
+; CHECK-LABEL: define ptr addrspace(2) @test_inttoptr_base_unstable() {
+; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), i8 1)
+;
+ %base = inttoptr i16 -1 to ptr addrspace(2)
+ %gep = getelementptr i8, ptr addrspace(2) %base, i8 1
+ ret ptr addrspace(2) %gep
+}
+
+;; The same is true for pointers with external state: no new inttoptr
+define ptr addrspace(3) @test_null_base_external() {
+; CHECK-LABEL: define ptr addrspace(3) @test_null_base_external() {
+; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) null, i8 -2)
+;
+ %gep = getelementptr i8, ptr addrspace(3) null, i8 -2
+ ret ptr addrspace(3) %gep
+}
+
+define ptr addrspace(3) @test_inttoptr_base_external() {
+; CHECK-LABEL: define ptr addrspace(3) @test_inttoptr_base_external() {
+; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), i8 1)
+;
+ %base = inttoptr i16 -1 to ptr addrspace(3)
+ %gep = getelementptr i8, ptr addrspace(3) %base, i8 1
+ ret ptr addrspace(3) %gep
+}
|
|
@llvm/pr-subscribers-llvm-analysis Author: Alexander Richardson (arichardson) ChangesAvoiding any new inttoptr is unnecessarily restrictive for "plain" Full diff: https://github.com/llvm/llvm-project/pull/159959.diff 3 Files Affected:
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index a3b2e62a1b8ba..e4eac1892cfde 100755
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -951,21 +951,22 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
// If the base value for this address is a literal integer value, fold the
// getelementptr to the resulting integer value casted to the pointer type.
- APInt BasePtr(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
+ APInt BaseIntVal(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
if (auto *CE = dyn_cast<ConstantExpr>(Ptr)) {
if (CE->getOpcode() == Instruction::IntToPtr) {
if (auto *Base = dyn_cast<ConstantInt>(CE->getOperand(0)))
- BasePtr = Base->getValue().zextOrTrunc(BasePtr.getBitWidth());
+ BaseIntVal = Base->getValue().zextOrTrunc(BaseIntVal.getBitWidth());
}
}
auto *PTy = cast<PointerType>(Ptr->getType());
- if ((Ptr->isNullValue() || BasePtr != 0) &&
- !DL.isNonIntegralPointerType(PTy)) {
+ if ((Ptr->isNullValue() || BaseIntVal != 0) &&
+ !DL.shouldAvoidIntToPtr(Ptr->getType())) {
+
// If the index size is smaller than the pointer size, add to the low
// bits only.
- BasePtr.insertBits(BasePtr.trunc(BitWidth) + Offset, 0);
- Constant *C = ConstantInt::get(Ptr->getContext(), BasePtr);
+ BaseIntVal.insertBits(BaseIntVal.trunc(BitWidth) + Offset, 0);
+ Constant *C = ConstantInt::get(Ptr->getContext(), BaseIntVal);
return ConstantExpr::getIntToPtr(C, ResTy);
}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll
deleted file mode 100644
index 2049def9b59b7..0000000000000
--- a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
-
-target datalayout = "p:16:16:16:8"
-
-; The GEP should only modify the low 8 bits of the pointer.
-define ptr @test() {
-; CHECK-LABEL: define ptr @test() {
-; We need to use finer-grained DataLayout properties for non-integral pointers
-; FIXME: Should be: ret ptr inttoptr (i16 -256 to ptr)
-; CHECK-NEXT: ret ptr getelementptr (i8, ptr inttoptr (i16 -1 to ptr), i8 1)
-;
- %base = inttoptr i16 -1 to ptr
- %gep = getelementptr i8, ptr %base, i8 1
- ret ptr %gep
-}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll
new file mode 100644
index 0000000000000..16980b54f93ad
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-nonintegral.ll
@@ -0,0 +1,75 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
+;; Check that we do not create new inttoptr intstructions for unstable pointers
+;; or pointers with external state (even if the values are all constants).
+;; NOTE: for all but the zero address space, the GEP should only modify the low 8 bits of the pointer.
+target datalayout = "p:16:16:16:16-p1:16:16:16:8-pu2:16:16:16:8-pe3:16:16:16:8"
+
+define ptr @test_null_base_normal() {
+; CHECK-LABEL: define ptr @test_null_base_normal() {
+; CHECK-NEXT: ret ptr inttoptr (i16 -2 to ptr)
+;
+ %gep = getelementptr i8, ptr null, i8 -2
+ ret ptr %gep
+}
+define ptr @test_inttoptr_base_normal() {
+; CHECK-LABEL: define ptr @test_inttoptr_base_normal() {
+; CHECK-NEXT: ret ptr null
+;
+ %base = inttoptr i16 -1 to ptr
+ %gep = getelementptr i8, ptr %base, i8 1
+ ret ptr %gep
+}
+
+;; Transformation is fine for non-integral address space, but we can only change
+;; the index bits (i8 -2 == i16 254)
+define ptr addrspace(1) @test_null_base_nonintegral() {
+; CHECK-LABEL: define ptr addrspace(1) @test_null_base_nonintegral() {
+; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 254 to ptr addrspace(1))
+;
+ %gep = getelementptr i8, ptr addrspace(1) null, i8 -2
+ ret ptr addrspace(1) %gep
+}
+define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
+; CHECK-LABEL: define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
+; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 -256 to ptr addrspace(1))
+;
+ %base = inttoptr i16 -1 to ptr addrspace(1)
+ %gep = getelementptr i8, ptr addrspace(1) %base, i8 1
+ ret ptr addrspace(1) %gep
+}
+
+;; For unstable pointers we should avoid any introduction of inttoptr
+define ptr addrspace(2) @test_null_base_unstable() {
+; CHECK-LABEL: define ptr addrspace(2) @test_null_base_unstable() {
+; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) null, i8 -2)
+;
+ %gep = getelementptr i8, ptr addrspace(2) null, i8 -2
+ ret ptr addrspace(2) %gep
+}
+define ptr addrspace(2) @test_inttoptr_base_unstable() {
+; CHECK-LABEL: define ptr addrspace(2) @test_inttoptr_base_unstable() {
+; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), i8 1)
+;
+ %base = inttoptr i16 -1 to ptr addrspace(2)
+ %gep = getelementptr i8, ptr addrspace(2) %base, i8 1
+ ret ptr addrspace(2) %gep
+}
+
+;; The same is true for pointers with external state: no new inttoptr
+define ptr addrspace(3) @test_null_base_external() {
+; CHECK-LABEL: define ptr addrspace(3) @test_null_base_external() {
+; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) null, i8 -2)
+;
+ %gep = getelementptr i8, ptr addrspace(3) null, i8 -2
+ ret ptr addrspace(3) %gep
+}
+
+define ptr addrspace(3) @test_inttoptr_base_external() {
+; CHECK-LABEL: define ptr addrspace(3) @test_inttoptr_base_external() {
+; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), i8 1)
+;
+ %base = inttoptr i16 -1 to ptr addrspace(3)
+ %gep = getelementptr i8, ptr addrspace(3) %base, i8 1
+ ret ptr addrspace(3) %gep
+}
|
|
|
||
| define ptr addrspace(3) @test_inttoptr_base_external() { | ||
| ; CHECK-LABEL: define ptr addrspace(3) @test_inttoptr_base_external() { | ||
| ; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), i8 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this really matters for CHERI, we could also emit the inttoptr (i16 -256 to ptr addrspace(1)) directly, but maybe it's cleaner to not attempt to perform any inttoptr based transforms?
nikic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Created using spr 1.3.8-beta.1 [skip ci]
Created using spr 1.3.8-beta.1
Created using spr 1.3.8-beta.1
|
The transform looks correct to me |
Created using spr 1.3.8-beta.1 [skip ci]
Created using spr 1.3.8-beta.1
Avoiding any new inttoptr is unnecessarily restrictive for "plain" non-integral pointers, but it is important for unstable pointers and pointers with external state. Fixes another test codegen regression from llvm/llvm-project#105735. Reviewed By: nikic Pull Request: llvm/llvm-project#159959
Avoiding any new inttoptr is unnecessarily restrictive for "plain"
non-integral pointers, but it is important for unstable pointers and
pointers with external state. Fixes another test codegen regression
from #105735.