[llvm] [SelectionDAGBuilder] Fix non-determanism in `shouldKeepJumpConditionsTogether` (PR #83687)

via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 2 21:13:57 PST 2024


https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/83687

>From afc5fbe74695cc3dae474855379bccaafafecae9 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sat, 2 Mar 2024 12:05:05 -0600
Subject: [PATCH] [SelectionDAGBuilder] Fix non-determanism in
 `shouldKeepJumpConditionsTogether`

The issue was we where iteration on `SmallPtrSet` order which is based
on runtime address and thus can vary with the same input. Fix by just
using `SmallMapVector` with dummy value.
---
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 27 ++++++++++---------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 4f6263cc492fe3..fb057f95ca5be8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2450,11 +2450,10 @@ SelectionDAGBuilder::EmitBranchForMergedCondition(const Value *Cond,
 
 // Collect dependencies on V recursively. This is used for the cost analysis in
 // `shouldKeepJumpConditionsTogether`.
-static bool
-collectInstructionDeps(SmallPtrSet<const Instruction *, 8> *Deps,
-                       const Value *V,
-                       SmallPtrSet<const Instruction *, 8> *Necessary = nullptr,
-                       unsigned Depth = 0) {
+static bool collectInstructionDeps(
+    SmallMapVector<const Instruction *, bool, 8> *Deps, const Value *V,
+    SmallMapVector<const Instruction *, bool, 8> *Necessary = nullptr,
+    unsigned Depth = 0) {
   // Return false if we have an incomplete count.
   if (Depth >= SelectionDAG::MaxRecursionDepth)
     return false;
@@ -2471,7 +2470,7 @@ collectInstructionDeps(SmallPtrSet<const Instruction *, 8> *Deps,
   }
 
   // Already added this dep.
-  if (!Deps->insert(I).second)
+  if (!Deps->try_emplace(I, false).second)
     return true;
 
   for (unsigned OpIdx = 0, E = I->getNumOperands(); OpIdx < E; ++OpIdx)
@@ -2526,7 +2525,9 @@ bool SelectionDAGBuilder::shouldKeepJumpConditionsTogether(
     return false;
 
   // Collect "all" instructions that lhs condition is dependent on.
-  SmallPtrSet<const Instruction *, 8> LhsDeps, RhsDeps;
+  // Use map for stable iteration (to avoid non-determanism of iteration of
+  // SmallPtrSet). The `bool` value is just a dummy.
+  SmallMapVector<const Instruction *, bool, 8> LhsDeps, RhsDeps;
   collectInstructionDeps(&LhsDeps, Lhs);
   // Collect "all" instructions that rhs condition is dependent on AND are
   // dependencies of lhs. This gives us an estimate on which instructions we
@@ -2536,7 +2537,7 @@ bool SelectionDAGBuilder::shouldKeepJumpConditionsTogether(
   // Add the compare instruction itself unless its a dependency on the LHS.
   if (const auto *RhsI = dyn_cast<Instruction>(Rhs))
     if (!LhsDeps.contains(RhsI))
-      RhsDeps.insert(RhsI);
+      RhsDeps.try_emplace(RhsI, false);
 
   const auto &TLI = DAG.getTargetLoweringInfo();
   const auto &TTI =
@@ -2564,9 +2565,9 @@ bool SelectionDAGBuilder::shouldKeepJumpConditionsTogether(
   // instructions.
   for (unsigned PruneIters = 0; PruneIters < MaxPruneIters; ++PruneIters) {
     const Instruction *ToDrop = nullptr;
-    for (const auto *Ins : RhsDeps) {
-      if (!ShouldCountInsn(Ins)) {
-        ToDrop = Ins;
+    for (const auto &InsPair : RhsDeps) {
+      if (!ShouldCountInsn(InsPair.first)) {
+        ToDrop = InsPair.first;
         break;
       }
     }
@@ -2575,13 +2576,13 @@ bool SelectionDAGBuilder::shouldKeepJumpConditionsTogether(
     RhsDeps.erase(ToDrop);
   }
 
-  for (const auto *Ins : RhsDeps) {
+  for (const auto &InsPair : RhsDeps) {
     // Finally accumulate latency that we can only attribute to computing the
     // RHS condition. Use latency because we are essentially trying to calculate
     // the cost of the dependency chain.
     // Possible TODO: We could try to estimate ILP and make this more precise.
     CostOfIncluding +=
-        TTI.getInstructionCost(Ins, TargetTransformInfo::TCK_Latency);
+        TTI.getInstructionCost(InsPair.first, TargetTransformInfo::TCK_Latency);
 
     if (CostOfIncluding > CostThresh)
       return false;



More information about the llvm-commits mailing list