[llvm] r276174 - [SCCP] Zap multiple return values.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 13:17:13 PDT 2016


Author: davide
Date: Wed Jul 20 15:17:13 2016
New Revision: 276174

URL: http://llvm.org/viewvc/llvm-project?rev=276174&view=rev
Log:
[SCCP] Zap multiple return values.

We can replace the return values with undef if we replaced all
the call uses with a constant/undef.

Differential Revision:  https://reviews.llvm.org/D22336

Added:
    llvm/trunk/test/Transforms/SCCP/dont-zap-return.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
    llvm/trunk/test/Transforms/SCCP/ipsccp-basic.ll

Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=276174&r1=276173&r2=276174&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Wed Jul 20 15:17:13 2016
@@ -300,6 +300,12 @@ public:
     return TrackedGlobals;
   }
 
+  /// getMRVFunctionsTracked - Get the set of functions which return multiple
+  /// values tracked by the pass.
+  const SmallPtrSet<Function *, 16> getMRVFunctionsTracked() {
+    return MRVFunctionsTracked;
+  }
+
   void markOverdefined(Value *V) {
     assert(!V->getType()->isStructTy() &&
            "structs should use markAnythingOverdefined");
@@ -316,6 +322,20 @@ public:
       markOverdefined(V);
   }
 
+  // isStructLatticeConstant - Return true if all the lattice values
+  // corresponding to elements of the structure are not overdefined,
+  // false otherwise.
+  bool isStructLatticeConstant(Function *F, StructType *STy) {
+    for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+      const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i));
+      assert(It != TrackedMultipleRetVals.end());
+      LatticeVal LV = It->second;
+      if (LV.isOverdefined())
+        return false;
+    }
+    return true;
+  }
+
 private:
   // pushToWorkList - Helper for markConstant/markForcedConstant
   void pushToWorkList(LatticeVal &IV, Value *V) {
@@ -1690,6 +1710,19 @@ static bool AddressIsTaken(const GlobalV
   return false;
 }
 
+static void findReturnsToZap(Function &F,
+                             SmallPtrSet<Function *, 32> &AddressTakenFunctions,
+                             SmallVector<ReturnInst *, 8> &ReturnsToZap) {
+  // We can only do this if we know that nothing else can call the function.
+  if (!F.hasLocalLinkage() || AddressTakenFunctions.count(&F))
+    return;
+
+  for (BasicBlock &BB : F)
+    if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
+      if (!isa<UndefValue>(RI->getOperand(0)))
+        ReturnsToZap.push_back(RI);
+}
+
 static bool runIPSCCP(Module &M, const DataLayout &DL,
                       const TargetLibraryInfo *TLI) {
   SCCPSolver Solver(DL, TLI);
@@ -1866,21 +1899,20 @@ static bool runIPSCCP(Module &M, const D
   // whether other functions are optimizable.
   SmallVector<ReturnInst*, 8> ReturnsToZap;
 
-  // TODO: Process multiple value ret instructions also.
   const DenseMap<Function*, LatticeVal> &RV = Solver.getTrackedRetVals();
   for (const auto &I : RV) {
     Function *F = I.first;
     if (I.second.isOverdefined() || F->getReturnType()->isVoidTy())
       continue;
+    findReturnsToZap(*F, AddressTakenFunctions, ReturnsToZap);
+  }
 
-    // We can only do this if we know that nothing else can call the function.
-    if (!F->hasLocalLinkage() || AddressTakenFunctions.count(F))
-      continue;
-
-    for (BasicBlock &BB : *F)
-      if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
-        if (!isa<UndefValue>(RI->getOperand(0)))
-          ReturnsToZap.push_back(RI);
+  for (const auto &F : Solver.getMRVFunctionsTracked()) {
+    assert(F->getReturnType()->isStructTy() &&
+           "The return type should be a struct");
+    StructType *STy = cast<StructType>(F->getReturnType());
+    if (Solver.isStructLatticeConstant(F, STy))
+      findReturnsToZap(*F, AddressTakenFunctions, ReturnsToZap);
   }
 
   // Zap all returns which we've identified as zap to change.

Added: llvm/trunk/test/Transforms/SCCP/dont-zap-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SCCP/dont-zap-return.ll?rev=276174&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SCCP/dont-zap-return.ll (added)
+++ llvm/trunk/test/Transforms/SCCP/dont-zap-return.ll Wed Jul 20 15:17:13 2016
@@ -0,0 +1,24 @@
+; RUN: opt -ipsccp < %s -S | FileCheck %s
+
+define internal {i32, i32} @identity(i32 %patatino) {
+  %foo = insertvalue {i32, i32} {i32 1, i32 undef}, i32 %patatino, 1
+  ret {i32, i32} %foo
+}
+
+; Check that the return value is not transformed to undef
+; CHECK: define internal { i32, i32 } @identity(i32 %patatino) {
+; CHECK-NEXT:  %foo = insertvalue { i32, i32 } { i32 1, i32 undef }, i32 %patatino, 1
+; CHECK-NEXT:  ret { i32, i32 } %foo
+; CHECK-NEXT: }
+
+
+define {i32, i32} @caller(i32 %pat) {
+  %S1 = call {i32, i32} @identity(i32 %pat)
+  ret {i32, i32} %S1
+}
+
+; Check that we don't invent values and propagate them.
+; CHECK: define { i32, i32 } @caller(i32 %pat) {
+; CHECK-NEXT:  %S1 = call { i32, i32 } @identity(i32 %pat)
+; CHECK-NEXT:  ret { i32, i32 } %S1
+; CHECK-NEXT: }

Modified: llvm/trunk/test/Transforms/SCCP/ipsccp-basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SCCP/ipsccp-basic.ll?rev=276174&r1=276173&r2=276174&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SCCP/ipsccp-basic.ll (original)
+++ llvm/trunk/test/Transforms/SCCP/ipsccp-basic.ll Wed Jul 20 15:17:13 2016
@@ -83,7 +83,7 @@ define internal {i64,i64} @test4a() {
 }
 
 ; CHECK-LABEL: define internal { i64, i64 } @test4a(
-; CHECK-NEXT:   ret { i64, i64 } { i64 5, i64 4 }
+; CHECK-NEXT:   ret { i64, i64 } undef
 ; CHECK-NEXT: }
 
 define i64 @test4b() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
@@ -167,7 +167,7 @@ define internal %T @test7a(i32 %A) {
   %mrv1 = insertvalue %T %mrv0, i32 %A, 1
   ret %T %mrv1
 ; CHECK-LABEL: @test7a(
-; CHECK-NEXT: ret %T { i32 18, i32 17 }
+; CHECK-NEXT: ret %T undef
 }
 
 define i32 @test7b() {




More information about the llvm-commits mailing list