[SLP] Optimize stacksave dependence handling [NFC]
authorPhilip Reames <listmail@philipreames.com>
Fri, 25 Mar 2022 17:01:39 +0000 (10:01 -0700)
committerPhilip Reames <listmail@philipreames.com>
Fri, 25 Mar 2022 17:04:10 +0000 (10:04 -0700)
After writing the commit message for 4b1bace28, realized that the mentioned optimization was rather straight forward.  We already have the code for scanning a block during region initialization, we can simply keep track if we've seen a stacksave or stackrestore.  If we haven't, none of these dependencies are relevant and we can avoid the relatively expensive scans entirely.

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

index 7296dba..7999f46 100644 (file)
@@ -2764,6 +2764,7 @@ private:
       ScheduleEnd = nullptr;
       FirstLoadStoreInRegion = nullptr;
       LastLoadStoreInRegion = nullptr;
+      RegionHasStackSave = false;
 
       // Reduce the maximum schedule region size by the size of the
       // previous scheduling run.
@@ -3032,6 +3033,11 @@ private:
     /// (can be null).
     ScheduleData *LastLoadStoreInRegion = nullptr;
 
+    /// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
+    /// region?  Used to optimize the dependence calculation for the
+    /// common case where there isn't.
+    bool RegionHasStackSave = false;
+
     /// The current size of the scheduling region.
     int ScheduleRegionSize = 0;
 
@@ -8016,6 +8022,10 @@ void BoUpSLP::BlockScheduling::initScheduleData(Instruction *FromI,
       }
       CurrentLoadStore = SD;
     }
+
+    if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
+        match(I, m_Intrinsic<Intrinsic::stackrestore>()))
+      RegionHasStackSave = true;
   }
   if (NextLoadStore) {
     if (CurrentLoadStore)
@@ -8099,40 +8109,42 @@ void BoUpSLP::BlockScheduling::calculateDependencies(ScheduleData *SD,
         }
       }
 
-      // If we have an inalloc alloca instruction, it needs to be scheduled
-      // after any preceeding stacksave.  We also need to prevent any alloca
-      // from reordering above a preceeding stackrestore.
-      if (match(BundleMember->Inst, m_Intrinsic<Intrinsic::stacksave>()) ||
-          match(BundleMember->Inst, m_Intrinsic<Intrinsic::stackrestore>())) {
-        for (Instruction *I = BundleMember->Inst->getNextNode();
-             I != ScheduleEnd; I = I->getNextNode()) {
-          if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
-              match(I, m_Intrinsic<Intrinsic::stackrestore>()))
-            // Any allocas past here must be control dependent on I, and I
-            // must be memory dependend on BundleMember->Inst.
-            break;
+      if (RegionHasStackSave) {
+        // If we have an inalloc alloca instruction, it needs to be scheduled
+        // after any preceeding stacksave.  We also need to prevent any alloca
+        // from reordering above a preceeding stackrestore.
+        if (match(BundleMember->Inst, m_Intrinsic<Intrinsic::stacksave>()) ||
+            match(BundleMember->Inst, m_Intrinsic<Intrinsic::stackrestore>())) {
+          for (Instruction *I = BundleMember->Inst->getNextNode();
+               I != ScheduleEnd; I = I->getNextNode()) {
+            if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
+                match(I, m_Intrinsic<Intrinsic::stackrestore>()))
+              // Any allocas past here must be control dependent on I, and I
+              // must be memory dependend on BundleMember->Inst.
+              break;
 
-          if (!isa<AllocaInst>(I))
-            continue;
+            if (!isa<AllocaInst>(I))
+              continue;
 
-          // Add the dependency
-          makeControlDependent(I);
+            // Add the dependency
+            makeControlDependent(I);
+          }
         }
-      }
 
-      // In addition to the cases handle just above, we need to prevent
-      // allocas from moving below a stacksave.  The stackrestore case
-      // is currently thought to be conservatism.
-      if (isa<AllocaInst>(BundleMember->Inst)) {
-        for (Instruction *I = BundleMember->Inst->getNextNode();
-             I != ScheduleEnd; I = I->getNextNode()) {
-          if (!match(I, m_Intrinsic<Intrinsic::stacksave>()) &&
-              !match(I, m_Intrinsic<Intrinsic::stackrestore>()))
-            continue;
+        // In addition to the cases handle just above, we need to prevent
+        // allocas from moving below a stacksave.  The stackrestore case
+        // is currently thought to be conservatism.
+        if (isa<AllocaInst>(BundleMember->Inst)) {
+          for (Instruction *I = BundleMember->Inst->getNextNode();
+               I != ScheduleEnd; I = I->getNextNode()) {
+            if (!match(I, m_Intrinsic<Intrinsic::stacksave>()) &&
+                !match(I, m_Intrinsic<Intrinsic::stackrestore>()))
+              continue;
 
-          // Add the dependency
-          makeControlDependent(I);
-          break;
+            // Add the dependency
+            makeControlDependent(I);
+            break;
+          }
         }
       }