[llvm] 798eb71 - [NFC][StackSafety] Dedup callees

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 01:15:07 PDT 2020


Author: Vitaly Buka
Date: 2020-08-14T01:14:52-07:00
New Revision: 798eb71c3a5a43f592b006e1b41620c54cacb721

URL: https://github.com/llvm/llvm-project/commit/798eb71c3a5a43f592b006e1b41620c54cacb721
DIFF: https://github.com/llvm/llvm-project/commit/798eb71c3a5a43f592b006e1b41620c54cacb721.diff

LOG: [NFC][StackSafety] Dedup callees

Added: 
    

Modified: 
    llvm/lib/Analysis/StackSafetyAnalysis.cpp
    llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
    llvm/test/Bitcode/thinlto-function-summary-paramaccess.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
index db3eb0bc49a5..0baf0c2d54b2 100644
--- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp
+++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
@@ -95,20 +95,16 @@ template <typename CalleeTy> struct CallInfo {
   const CalleeTy *Callee = nullptr;
   /// Index of argument which pass address.
   size_t ParamNo = 0;
-  // Offset range of address from base address (alloca or calling function
-  // argument).
-  // Range should never set to empty-set, that is an invalid access range
-  // that can cause empty-set to be propagated with ConstantRange::add
-  ConstantRange Offset;
-  CallInfo(const CalleeTy *Callee, size_t ParamNo, const ConstantRange &Offset)
-      : Callee(Callee), ParamNo(ParamNo), Offset(Offset) {}
-};
 
-template <typename CalleeTy>
-raw_ostream &operator<<(raw_ostream &OS, const CallInfo<CalleeTy> &P) {
-  return OS << "@" << P.Callee->getName() << "(arg" << P.ParamNo << ", "
-            << P.Offset << ")";
-}
+  CallInfo(const CalleeTy *Callee, size_t ParamNo)
+      : Callee(Callee), ParamNo(ParamNo) {}
+
+  struct Less {
+    bool operator()(const CallInfo &L, const CallInfo &R) const {
+      return std::tie(L.Callee, L.ParamNo) < std::tie(R.Callee, R.ParamNo);
+    }
+  };
+};
 
 /// Describe uses of address (alloca or parameter) inside of the function.
 template <typename CalleeTy> struct UseInfo {
@@ -117,7 +113,12 @@ template <typename CalleeTy> struct UseInfo {
   ConstantRange Range;
 
   // List of calls which pass address as an argument.
-  SmallVector<CallInfo<CalleeTy>, 4> Calls;
+  // Value is offset range of address from base address (alloca or calling
+  // function argument). Range should never set to empty-set, that is an invalid
+  // access range that can cause empty-set to be propagated with
+  // ConstantRange::add
+  std::map<CallInfo<CalleeTy>, ConstantRange, typename CallInfo<CalleeTy>::Less>
+      Calls;
 
   UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}
 
@@ -128,7 +129,9 @@ template <typename CalleeTy>
 raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) {
   OS << U.Range;
   for (auto &Call : U.Calls)
-    OS << ", " << Call;
+    OS << ", "
+       << "@" << Call.first.Callee->getName() << "(arg" << Call.first.ParamNo
+       << ", " << Call.second << ")";
   return OS;
 }
 
@@ -410,7 +413,11 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr,
         }
 
         assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee));
-        US.Calls.emplace_back(Callee, ArgNo, offsetFrom(UI, Ptr));
+        ConstantRange Offsets = offsetFrom(UI, Ptr);
+        auto Insert =
+            US.Calls.emplace(CallInfo<GlobalValue>(Callee, ArgNo), Offsets);
+        if (!Insert.second)
+          Insert.first->second = Insert.first->second.unionWith(Offsets);
         break;
       }
 
@@ -516,12 +523,12 @@ template <typename CalleeTy>
 bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
                                                          bool UpdateToFullSet) {
   bool Changed = false;
-  for (auto &CS : US.Calls) {
-    assert(!CS.Offset.isEmptySet() &&
+  for (auto &KV : US.Calls) {
+    assert(!KV.second.isEmptySet() &&
            "Param range can't be empty-set, invalid offset range");
 
     ConstantRange CalleeRange =
-        getArgumentAccessRange(CS.Callee, CS.ParamNo, CS.Offset);
+        getArgumentAccessRange(KV.first.Callee, KV.first.ParamNo, KV.second);
     if (!US.Range.contains(CalleeRange)) {
       Changed = true;
       if (UpdateToFullSet)
@@ -561,7 +568,7 @@ void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
     auto &FS = F.second;
     for (auto &KV : FS.Params)
       for (auto &CS : KV.second.Calls)
-        Callees.push_back(CS.Callee);
+        Callees.push_back(CS.first.Callee);
 
     llvm::sort(Callees);
     Callees.erase(std::unique(Callees.begin(), Callees.end()), Callees.end());
@@ -650,16 +657,18 @@ const ConstantRange *findParamAccess(const FunctionSummary &FS,
 void resolveAllCalls(UseInfo<GlobalValue> &Use,
                      const ModuleSummaryIndex *Index) {
   ConstantRange FullSet(Use.Range.getBitWidth(), true);
-  for (auto &C : Use.Calls) {
-    const Function *F = findCalleeInModule(C.Callee);
+  auto TmpCalls = std::move(Use.Calls);
+  for (const auto &C : TmpCalls) {
+    const Function *F = findCalleeInModule(C.first.Callee);
     if (F) {
-      C.Callee = F;
+      Use.Calls.emplace(CallInfo<GlobalValue>(F, C.first.ParamNo), C.second);
       continue;
     }
 
     if (!Index)
       return Use.updateRange(FullSet);
-    GlobalValueSummary *GVS = getGlobalValueSummary(Index, C.Callee->getGUID());
+    GlobalValueSummary *GVS =
+        getGlobalValueSummary(Index, C.first.Callee->getGUID());
 
     FunctionSummary *FS = resolveCallee(GVS);
     ++NumModuleCalleeLookupTotal;
@@ -667,18 +676,13 @@ void resolveAllCalls(UseInfo<GlobalValue> &Use,
       ++NumModuleCalleeLookupFailed;
       return Use.updateRange(FullSet);
     }
-    const ConstantRange *Found = findParamAccess(*FS, C.ParamNo);
+    const ConstantRange *Found = findParamAccess(*FS, C.first.ParamNo);
     if (!Found || Found->isFullSet())
       return Use.updateRange(FullSet);
     ConstantRange Access = Found->sextOrTrunc(Use.Range.getBitWidth());
     if (!Access.isEmptySet())
-      Use.updateRange(addOverflowNever(Access, C.Offset));
-    C.Callee = nullptr;
+      Use.updateRange(addOverflowNever(Access, C.second));
   }
-
-  Use.Calls.erase(std::remove_if(Use.Calls.begin(), Use.Calls.end(),
-                                 [](auto &T) { return !T.Callee; }),
-                  Use.Calls.end());
 }
 
 GVToSSI createGlobalStackSafetyInfo(
@@ -692,8 +696,11 @@ GVToSSI createGlobalStackSafetyInfo(
   auto Copy = Functions;
 
   for (auto &FnKV : Copy)
-    for (auto &KV : FnKV.second.Params)
+    for (auto &KV : FnKV.second.Params) {
       resolveAllCalls(KV.second, Index);
+      if (KV.second.Range.isFullSet())
+        KV.second.Calls.clear();
+    }
 
   uint32_t PointerSize = Copy.begin()
                              ->first->getParent()
@@ -708,8 +715,8 @@ GVToSSI createGlobalStackSafetyInfo(
       auto &A = KV.second;
       resolveAllCalls(A, Index);
       for (auto &C : A.Calls) {
-        A.updateRange(
-            SSDFA.getArgumentAccessRange(C.Callee, C.ParamNo, C.Offset));
+        A.updateRange(SSDFA.getArgumentAccessRange(C.first.Callee,
+                                                   C.first.ParamNo, C.second));
       }
       // FIXME: This is needed only to preserve calls in print() results.
       A.Calls = SrcF.Allocas.find(KV.first)->second.Calls;
@@ -799,11 +806,16 @@ StackSafetyInfo::getParamAccesses() const {
       // will make ParamAccess::Range as FullSet anyway. So we can drop the
       // entire parameter like we did above.
       // TODO(vitalybuka): Return already filtered parameters from getInfo().
-      if (C.Offset.isFullSet()) {
+      if (C.second.isFullSet()) {
         ParamAccesses.pop_back();
         break;
       }
-      Param.Calls.emplace_back(C.ParamNo, C.Callee->getGUID(), C.Offset);
+      Param.Calls.emplace_back(C.first.ParamNo, C.first.Callee->getGUID(),
+                               C.second);
+      llvm::sort(Param.Calls, [](const FunctionSummary::ParamAccess::Call &L,
+                                 const FunctionSummary::ParamAccess::Call &R) {
+        return std::tie(L.ParamNo, L.Callee) < std::tie(R.ParamNo, R.Callee);
+      });
     }
   }
   return ParamAccesses;
@@ -992,7 +1004,8 @@ void llvm::generateParamAccessSummary(ModuleSummaryIndex &Index) {
               US.Calls.clear();
               break;
             }
-            US.Calls.emplace_back(S, Call.ParamNo, Call.Offsets);
+            US.Calls.emplace(CallInfo<FunctionSummary>(S, Call.ParamNo),
+                             Call.Offsets);
           }
         }
         Functions.emplace(FS, std::move(FI));

diff  --git a/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll b/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
index 8cb875b8a9aa..6be426f6bbd3 100644
--- a/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
+++ b/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
@@ -354,8 +354,8 @@ define void @TwoArguments() #0 {
 ; CHECK-LABEL: @TwoArguments dso_preemptable{{$}}
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: allocas uses:
-; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}}
-; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}}
+; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
+; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
 ; CHECK-EMPTY:
 entry:
   %x = alloca i64, align 4
@@ -369,8 +369,8 @@ define void @TwoArgumentsOOBOne() #0 {
 ; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}}
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: allocas uses:
-; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}}
-; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}}
+; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
+; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
 ; CHECK-EMPTY:
 entry:
   %x = alloca i64, align 4
@@ -384,8 +384,8 @@ define void @TwoArgumentsOOBOther() #0 {
 ; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}}
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: allocas uses:
-; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}}
-; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}}
+; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
+; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
 ; CHECK-EMPTY:
 entry:
   %x = alloca i64, align 4
@@ -400,8 +400,8 @@ define void @TwoArgumentsOOBBoth() #0 {
 ; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}}
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: allocas uses:
-; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}}
-; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}}
+; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
+; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
 ; CHECK-EMPTY:
 entry:
   %x = alloca i64, align 4

diff  --git a/llvm/test/Bitcode/thinlto-function-summary-paramaccess.ll b/llvm/test/Bitcode/thinlto-function-summary-paramaccess.ll
index e52dda708161..1757173ec52b 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-paramaccess.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-paramaccess.ll
@@ -210,11 +210,11 @@ entry:
 }
 
 ; SSI-LABEL: for function 'CallMany'
-; SSI: p[]: empty-set, @Callee(arg0, [-715,-714)), @Callee(arg0, [-33,-32)), @Callee(arg0, [124,125))
-; BC-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=3 op4=0 op5=[[CALLEE]] op6=1431 op7=1429 op8=0 op9=[[CALLEE]] op10=67 op11=65 op12=0 op13=[[CALLEE]] op14=248 op15=250/>
+; SSI: p[]: empty-set, @Callee(arg0, [-715,125))
+; BC-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=1 op4=0 op5=[[CALLEE]] op6=1431 op7=250/>
 ; BC-NEXT: <PERMODULE
-; DIS-DAG: = gv: (name: "CallMany", summaries: {{.*}} calls: ((callee: ^{{.*}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{.*}}, param: 0, offset: [-715, -715]), (callee: ^{{.*}}, param: 0, offset: [-33, -33]), (callee: ^{{.*}}, param: 0, offset: [124, 124]))))))) ; guid = 17150418543861409076
-; DCO-DAG: = gv: (guid: 17150418543861409076, summaries: (function: (module: ^0, flags: ({{[^()]+}}), insts: 7, funcFlags: ({{[^()]+}}), calls: ((callee: ^[[CALLEE:.]])), params: ((param: 0, offset: [0, -1], calls: ((callee: ^[[CALLEE]], param: 0, offset: [-715, -715]), (callee: ^[[CALLEE]], param: 0, offset: [-33, -33]), (callee: ^[[CALLEE]], param: 0, offset: [124, 124]))))))){{$}}
+; DIS-DAG: = gv: (name: "CallMany", summaries: {{.*}} calls: ((callee: ^{{.*}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{.*}}, param: 0, offset: [-715, 124]))))))) ; guid = 17150418543861409076
+; DCO-DAG: = gv: (guid: 17150418543861409076, summaries: (function: (module: ^0, flags: ({{[^()]+}}), insts: 7, funcFlags: ({{[^()]+}}), calls: ((callee: ^[[CALLEE:.]])), params: ((param: 0, offset: [0, -1], calls: ((callee: ^[[CALLEE]], param: 0, offset: [-715, 124]))))))){{$}}
 define void @CallMany(i8* %p) #0 {
 entry:
   %p0 = getelementptr i8, i8* %p, i64 -715
@@ -230,11 +230,11 @@ entry:
 }
 
 ; SSI-LABEL: for function 'CallMany2'
-; SSI: p[]: empty-set, @Callee(arg0, [-715,-714)), @Callee2(arg1, [-33,-32)), @Callee(arg0, [124,125))
-; BC-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=3 op4=0 op5=[[CALLEE]] op6=1431 op7=1429 op8=1 op9=[[CALLEE2:-?[0-9]+]] op10=67 op11=65 op12=0 op13=[[CALLEE]] op14=248 op15=250/>
+; SSI: p[]: empty-set, @Callee(arg0, [-715,125))
+; BC-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=2 op4=0 op5=[[CALLEE]] op6=1431 op7=250 op8=1 op9=[[CALLEE2:-?[0-9]+]] op10=67 op11=65/>
 ; BC-NEXT: <PERMODULE
-; DIS-DAG: = gv: (name: "CallMany2", summaries: {{.*}} calls: ((callee: ^{{.*}}), (callee: ^{{.*}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{.*}}, param: 0, offset: [-715, -715]), (callee: ^{{.*}}, param: 1, offset: [-33, -33]), (callee: ^{{.*}}, param: 0, offset: [124, 124]))))))) ; guid = 16654048340802466690
-; DCO-DAG: = gv: (guid: 16654048340802466690, summaries: (function: (module: ^0, flags: ({{[^()]+}}), insts: 7, funcFlags: ({{[^()]+}}), calls: ((callee: ^{{[0-9]+}}), (callee: ^{{[0-9]+}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{[0-9]+}}, param: 0, offset: [-715, -715]), (callee: ^{{[0-9]+}}, param: 1, offset: [-33, -33]), (callee: ^{{[0-9]+}}, param: 0, offset: [124, 124]))))))){{$}}
+; DIS-DAG: = gv: (name: "CallMany2", summaries: {{.*}} calls: ((callee: ^{{.*}}), (callee: ^{{.*}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{.*}}, param: 0, offset: [-715, 124]), (callee: ^{{.*}}, param: 1, offset: [-33, -33]))))))) ; guid = 16654048340802466690
+; DCO-DAG: = gv: (guid: 16654048340802466690, summaries: (function: (module: ^0, flags: ({{[^()]+}}), insts: 7, funcFlags: ({{[^()]+}}), calls: ((callee: ^{{[0-9]+}}), (callee: ^{{[0-9]+}})), params: ((param: 0, offset: [0, -1], calls: ((callee: ^{{[0-9]+}}, param: 0, offset: [-715, 124]), (callee: ^{{[0-9]+}}, param: 1, offset: [-33, -33]))))))){{$}}
 define void @CallMany2(i8* %p) #0 {
 entry:
   %p0 = getelementptr i8, i8* %p, i64 -715
@@ -250,7 +250,7 @@ entry:
 }
 
 ; SSI-LABEL: for function 'CallManyUnsafe'
-; SSI: p[]: full-set, @Callee(arg0, [-715,-714)), @Callee(arg0, [-33,-32)), @Callee(arg0, [124,125))
+; SSI: p[]: full-set, @Callee(arg0, [-715,125))
 ; BC-NEXT: <PERMODULE
 ; DIS-DAG: = gv: (name: "CallManyUnsafe", summaries: {{.*}} calls: ((callee: ^{{.*}}))))) ; guid = 15696680128757863301
 ; DCO-DAG: = gv: (guid: 15696680128757863301, summaries: (function: (module: ^0, flags: ({{[^()]+}}), insts: 9, funcFlags: ({{[^()]+}}), calls: ((callee: ^[[CALLEE:.]]))))){{$}}
@@ -334,8 +334,8 @@ entry:
 ; COMBINED-NEXT: <COMBINED abbrevid=4 op0=16
 ; COMBINED-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=1 op4=0 op5=[[CALLEE2]] op6=1431 op7=1429/>
 ; COMBINED-NEXT: <COMBINED abbrevid=4 op0=17
-; COMBINED-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=3 op4=0 op5=[[CALLEE2]] op6=1431 op7=1429 op8=1 op9=[[CALLEE1]] op10=67 op11=65 op12=0 op13=[[CALLEE2]] op14=248 op15=250/>
+; COMBINED-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=2 op4=0 op5=[[CALLEE2]] op6=1431 op7=250 op8=1 op9=[[CALLEE1]] op10=67 op11=65/>
 ; COMBINED-NEXT: <COMBINED abbrevid=4 op0=18
-; COMBINED-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=3 op4=0 op5=[[CALLEE2]] op6=1431 op7=1429 op8=0 op9=[[CALLEE2]] op10=67 op11=65 op12=0 op13=[[CALLEE2]] op14=248 op15=250/>
+; COMBINED-NEXT: <PARAM_ACCESS op0=0 op1=0 op2=0 op3=1 op4=0 op5=[[CALLEE2]] op6=1431 op7=250/>
 ; COMBINED-NEXT: <COMBINED abbrevid=4 op0=19
 ; COMBINED-NEXT: <BLOCK_COUNT op0=19/>
\ No newline at end of file


        


More information about the llvm-commits mailing list