-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
[FunctionAttrs] Fix incorrect nonnull inference for non-inbounds GEP #91180
Conversation
For inbounds GEPs, if the source pointer is non-null, the result must also be non-null. However, this does not hold for non-inbounds GEPs. Fixes llvm#91177.
@llvm/pr-subscribers-llvm-transforms Author: Nikita Popov (nikic) ChangesFor inbounds GEPs, if the source pointer is non-null, the result must also be non-null. However, this does not hold for non-inbounds GEPs. Fixes #91177. Full diff: https://github.com/llvm/llvm-project/pull/91180.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 8e11cbf1cee469..26a4508aa1513a 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -1186,10 +1186,15 @@ static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
switch (RVI->getOpcode()) {
// Extend the analysis by looking upwards.
case Instruction::BitCast:
- case Instruction::GetElementPtr:
case Instruction::AddrSpaceCast:
FlowsToReturn.insert(RVI->getOperand(0));
continue;
+ case Instruction::GetElementPtr:
+ if (cast<GEPOperator>(RVI)->isInBounds()) {
+ FlowsToReturn.insert(RVI->getOperand(0));
+ continue;
+ }
+ return false;
case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(RVI);
FlowsToReturn.insert(SI->getTrueValue());
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index 3d483f671b1af7..8d6f6a7c73f809 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -197,7 +197,7 @@ declare i32 @__gxx_personality_v0(...)
define ptr @lookup_bit(ptr %q, i32 %bitno) readnone nounwind {
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
-; FNATTRS-LABEL: define nonnull ptr @lookup_bit
+; FNATTRS-LABEL: define ptr @lookup_bit
; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] {
; FNATTRS-NEXT: [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
; FNATTRS-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]]
diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
index d9bdb6298ed0fd..ec5545b969e550 100644
--- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll
@@ -905,26 +905,26 @@ define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{
; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr nocapture readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR7]] personality ptr @esfp {
; FNATTRS-NEXT: entry:
; FNATTRS-NEXT: invoke void @use2nonnull(ptr [[A]], ptr [[B]])
-; FNATTRS-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
+; FNATTRS-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
; FNATTRS: cont:
; FNATTRS-NEXT: [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null
; FNATTRS-NEXT: ret i1 [[NULL_CHECK]]
; FNATTRS: exc:
; FNATTRS-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
-; FNATTRS-NEXT: filter [0 x ptr] zeroinitializer
+; FNATTRS-NEXT: filter [0 x ptr] zeroinitializer
; FNATTRS-NEXT: unreachable
;
; ATTRIBUTOR-LABEL: define i1 @parent8(
; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nocapture nofree readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR8]] personality ptr @esfp {
; ATTRIBUTOR-NEXT: entry:
; ATTRIBUTOR-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])
-; ATTRIBUTOR-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
+; ATTRIBUTOR-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
; ATTRIBUTOR: cont:
; ATTRIBUTOR-NEXT: [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null
; ATTRIBUTOR-NEXT: ret i1 [[NULL_CHECK]]
; ATTRIBUTOR: exc:
; ATTRIBUTOR-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
-; ATTRIBUTOR-NEXT: filter [0 x ptr] zeroinitializer
+; ATTRIBUTOR-NEXT: filter [0 x ptr] zeroinitializer
; ATTRIBUTOR-NEXT: unreachable
;
@@ -1415,5 +1415,20 @@ define void @PR43833_simple(ptr %0, i32 %1) {
br i1 %11, label %7, label %8
}
+define ptr @pr91177_non_inbounds_gep(ptr nonnull %arg) {
+; FNATTRS-LABEL: define ptr @pr91177_non_inbounds_gep(
+; FNATTRS-SAME: ptr nonnull readnone [[ARG:%.*]]) #[[ATTR0]] {
+; FNATTRS-NEXT: [[RES:%.*]] = getelementptr i8, ptr [[ARG]], i64 -8
+; FNATTRS-NEXT: ret ptr [[RES]]
+;
+; ATTRIBUTOR-LABEL: define ptr @pr91177_non_inbounds_gep(
+; ATTRIBUTOR-SAME: ptr nofree nonnull readnone [[ARG:%.*]]) #[[ATTR0]] {
+; ATTRIBUTOR-NEXT: [[RES:%.*]] = getelementptr i8, ptr [[ARG]], i64 -8
+; ATTRIBUTOR-NEXT: ret ptr [[RES]]
+;
+ %res = getelementptr i8, ptr %arg, i64 -8
+ ret ptr %res
+}
+
attributes #0 = { null_pointer_is_valid }
attributes #1 = { nounwind willreturn}
|
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. Nice catch!
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, thanks!
…lvm#91180) For inbounds GEPs, if the source pointer is non-null, the result must also be non-null. However, this does not hold for non-inbounds GEPs. Fixes llvm#91177. (cherry picked from commit f34d30c)
…lvm#91180) For inbounds GEPs, if the source pointer is non-null, the result must also be non-null. However, this does not hold for non-inbounds GEPs. Fixes llvm#91177. (cherry picked from commit f34d30c)
For inbounds GEPs, if the source pointer is non-null, the result must also be non-null. However, this does not hold for non-inbounds GEPs.
Fixes #91177.