[llvm] 7f59264 - [IPSCCP] Intersect attribute info for interprocedural args (#106397)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 29 00:35:00 PDT 2024


Author: Nikita Popov
Date: 2024-08-29T09:34:56+02:00
New Revision: 7f59264d469d690fcd1cead0a2dfc02739d17db4

URL: https://github.com/llvm/llvm-project/commit/7f59264d469d690fcd1cead0a2dfc02739d17db4
DIFF: https://github.com/llvm/llvm-project/commit/7f59264d469d690fcd1cead0a2dfc02739d17db4.diff

LOG: [IPSCCP] Intersect attribute info for interprocedural args (#106397)

IPSCCP can currently return worse results than SCCP for arguments that
are tracked interprocedurally, because information from attributes is
not used for them.

Fix this by intersecting in the attribute information when propagating
lattice values from calls.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SCCPSolver.cpp
    llvm/test/Transforms/SCCP/pointer-nonnull.ll
    llvm/test/Transforms/SCCP/range-attribute.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 982b1041c7c514..59775d2199ca61 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -820,19 +820,21 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
       markOverdefined(ValueState[V], V);
   }
 
-  void trackValueOfArgument(Argument *A) {
+  ValueLatticeElement getArgAttributeVL(Argument *A) {
     if (A->getType()->isIntOrIntVectorTy()) {
-      if (std::optional<ConstantRange> Range = A->getRange()) {
-        markConstantRange(ValueState[A], A, *Range);
-        return;
-      }
-    }
-    if (A->hasNonNullAttr()) {
-      markNotNull(ValueState[A], A);
-      return;
+      if (std::optional<ConstantRange> Range = A->getRange())
+        return ValueLatticeElement::getRange(*Range);
     }
+    if (A->hasNonNullAttr())
+      return ValueLatticeElement::getNot(Constant::getNullValue(A->getType()));
     // Assume nothing about the incoming arguments without attributes.
-    markOverdefined(A);
+    return ValueLatticeElement::getOverdefined();
+  }
+
+  void trackValueOfArgument(Argument *A) {
+    if (A->getType()->isStructTy())
+      return (void)markOverdefined(A);
+    mergeInValue(A, getArgAttributeVL(A));
   }
 
   bool isStructLatticeConstant(Function *F, StructType *STy);
@@ -1800,7 +1802,9 @@ void SCCPInstVisitor::handleCallArguments(CallBase &CB) {
                        getMaxWidenStepsOpts());
         }
       } else
-        mergeInValue(&*AI, getValueState(*CAI), getMaxWidenStepsOpts());
+        mergeInValue(&*AI,
+                     getValueState(*CAI).intersect(getArgAttributeVL(&*AI)),
+                     getMaxWidenStepsOpts());
     }
   }
 }

diff  --git a/llvm/test/Transforms/SCCP/pointer-nonnull.ll b/llvm/test/Transforms/SCCP/pointer-nonnull.ll
index d035df399b77be..54eb12317680e4 100644
--- a/llvm/test/Transforms/SCCP/pointer-nonnull.ll
+++ b/llvm/test/Transforms/SCCP/pointer-nonnull.ll
@@ -210,18 +210,22 @@ define internal i1 @ip_test_nonnull_callee(ptr nonnull %p) {
 ;
 ; IPSCCP-LABEL: define internal i1 @ip_test_nonnull_callee(
 ; IPSCCP-SAME: ptr nonnull [[P:%.*]]) {
-; IPSCCP-NEXT:    [[CMP:%.*]] = icmp ne ptr [[P]], null
-; IPSCCP-NEXT:    ret i1 [[CMP]]
+; IPSCCP-NEXT:    ret i1 poison
 ;
   %cmp = icmp ne ptr %p, null
   ret i1 %cmp
 }
 
 define i1 @ip_test_nonnull_caller(ptr %p) {
-; CHECK-LABEL: define i1 @ip_test_nonnull_caller(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
-; CHECK-NEXT:    ret i1 [[RES]]
+; SCCP-LABEL: define i1 @ip_test_nonnull_caller(
+; SCCP-SAME: ptr [[P:%.*]]) {
+; SCCP-NEXT:    [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
+; SCCP-NEXT:    ret i1 [[RES]]
+;
+; IPSCCP-LABEL: define i1 @ip_test_nonnull_caller(
+; IPSCCP-SAME: ptr [[P:%.*]]) {
+; IPSCCP-NEXT:    [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]])
+; IPSCCP-NEXT:    ret i1 true
 ;
   %res = call i1 @ip_test_nonnull_callee(ptr %p)
   ret i1 %res

diff  --git a/llvm/test/Transforms/SCCP/range-attribute.ll b/llvm/test/Transforms/SCCP/range-attribute.ll
index c55eb03a5c8158..207732bf2bac4d 100644
--- a/llvm/test/Transforms/SCCP/range-attribute.ll
+++ b/llvm/test/Transforms/SCCP/range-attribute.ll
@@ -193,8 +193,7 @@ define i1 @ip_range_attribute_constant() {
 
 define internal i1 @ip_cmp_attribute_overdefined_callee(i32 range(i32 0, 10) %x) {
 ; IPSCCP-LABEL: @ip_cmp_attribute_overdefined_callee(
-; IPSCCP-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 10
-; IPSCCP-NEXT:    ret i1 [[CMP]]
+; IPSCCP-NEXT:    ret i1 poison
 ;
 ; SCCP-LABEL: @ip_cmp_attribute_overdefined_callee(
 ; SCCP-NEXT:    ret i1 true
@@ -204,9 +203,13 @@ define internal i1 @ip_cmp_attribute_overdefined_callee(i32 range(i32 0, 10) %x)
 }
 
 define i1 @ip_cmp_attribute_overdefined_caller(i32 %x) {
-; CHECK-LABEL: @ip_cmp_attribute_overdefined_caller(
-; CHECK-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
-; CHECK-NEXT:    ret i1 [[RES]]
+; IPSCCP-LABEL: @ip_cmp_attribute_overdefined_caller(
+; IPSCCP-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
+; IPSCCP-NEXT:    ret i1 true
+;
+; SCCP-LABEL: @ip_cmp_attribute_overdefined_caller(
+; SCCP-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_overdefined_callee(i32 [[X:%.*]])
+; SCCP-NEXT:    ret i1 [[RES]]
 ;
   %res = call i1 @ip_cmp_attribute_overdefined_callee(i32 %x)
   ret i1 %res
@@ -214,9 +217,7 @@ define i1 @ip_cmp_attribute_overdefined_caller(i32 %x) {
 
 define internal i1 @ip_cmp_attribute_intersect_callee(i32 range(i32 0, 10) %x) {
 ; IPSCCP-LABEL: @ip_cmp_attribute_intersect_callee(
-; IPSCCP-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
-; IPSCCP-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], true
-; IPSCCP-NEXT:    ret i1 [[AND]]
+; IPSCCP-NEXT:    ret i1 poison
 ;
 ; SCCP-LABEL: @ip_cmp_attribute_intersect_callee(
 ; SCCP-NEXT:    [[CMP2:%.*]] = icmp uge i32 [[X:%.*]], 5
@@ -230,9 +231,13 @@ define internal i1 @ip_cmp_attribute_intersect_callee(i32 range(i32 0, 10) %x) {
 }
 
 define i1 @ip_cmp_attribute_intersect_caller(i32 range(i32 5, 15) %x) {
-; CHECK-LABEL: @ip_cmp_attribute_intersect_caller(
-; CHECK-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
-; CHECK-NEXT:    ret i1 [[RES]]
+; IPSCCP-LABEL: @ip_cmp_attribute_intersect_caller(
+; IPSCCP-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
+; IPSCCP-NEXT:    ret i1 true
+;
+; SCCP-LABEL: @ip_cmp_attribute_intersect_caller(
+; SCCP-NEXT:    [[RES:%.*]] = call i1 @ip_cmp_attribute_intersect_callee(i32 [[X:%.*]])
+; SCCP-NEXT:    ret i1 [[RES]]
 ;
   %res = call i1 @ip_cmp_attribute_intersect_callee(i32 %x)
   ret i1 %res


        


More information about the llvm-commits mailing list