Introduce and use `SetCtrlInLargeTable`, when we know that table is at least one group. Similarly to `SetCtrlInSingleGroupTable`, we can save some operations.

https://gcc.godbolt.org/z/PjrzxbMz7

We are saving ~3 microops that is not big, but still positive.

Currently the function is not used in the hot loop, but the plan is to use the function in the new implementation of `GrowToNextCapacityAndPrepareInsert`. So introducing and battle test the function in advance to simplify review iterations.

Additionally adding "PrepareInsert" to "DropDeletesWithoutResize". That is done for consistency with `GrowToNextCapacityAndPrepareInsert` and to move more code to the colder function.

Microbenchmarks:
```
name                                                                                       old INSTRUCTIONS/op  new INSTRUCTIONS/op  delta
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:16                             179 ± 0%             179 ± 0%  -0.29%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:32                             197 ± 0%             196 ± 0%  -0.66%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:64                             206 ± 0%             204 ± 0%  -0.68%        (p=0.000 n=27+26)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:128                            210 ± 0%             208 ± 0%  -0.66%        (p=0.000 n=25+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:256                            212 ± 0%             210 ± 0%  -0.67%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:512                            213 ± 0%             211 ± 0%  -0.74%        (p=0.000 n=27+26)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:1024                           213 ± 0%             211 ± 0%  -0.69%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:2048                           213 ± 0%             212 ± 0%  -0.72%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:4096                           213 ± 0%             212 ± 0%  -0.69%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:8192                           213 ± 0%             212 ± 0%  -0.68%        (p=0.000 n=27+26)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:16384                          213 ± 0%             212 ± 0%  -0.70%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:32768                          213 ± 0%             212 ± 0%  -0.70%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:65536                          219 ± 1%             218 ± 0%  -0.77%        (p=0.000 n=27+26)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:131072                         210 ± 0%             209 ± 0%  -0.56%        (p=0.000 n=27+25)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:262144                         203 ± 0%             203 ± 0%  -0.32%        (p=0.000 n=27+27)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:524288                         203 ± 0%             202 ± 0%  -0.29%        (p=0.000 n=25+26)
BM_SWISSMAP_EraseInsert_Hot<::absl::flat_hash_set, 4>/set_size:1048576                        202 ± 0%             201 ± 0%  -0.20%        (p=0.000 n=27+27)
```
PiperOrigin-RevId: 728988087
Change-Id: Ic63f45eed3b922c4255dc36077fcf9a3d9b8b5ec
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 948ff86..b13cf5e 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -259,8 +259,9 @@
   ABSL_UNREACHABLE();
 }
 
-void DropDeletesWithoutResize(CommonFields& common,
-                              const PolicyFunctions& policy) {
+size_t DropDeletesWithoutResizeAndPrepareInsert(CommonFields& common,
+                                                size_t new_hash,
+                                                const PolicyFunctions& policy) {
   void* set = &common;
   void* slot_array = common.slot_array();
   const size_t capacity = common.capacity();
@@ -320,7 +321,7 @@
 
     // Element doesn't move.
     if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
-      SetCtrl(common, i, H2(hash), slot_size);
+      SetCtrlInLargeTable(common, i, H2(hash), slot_size);
       continue;
     }
 
@@ -329,14 +330,14 @@
       // Transfer element to the empty spot.
       // SetCtrl poisons/unpoisons the slots so we have to call it at the
       // right time.
-      SetCtrl(common, new_i, H2(hash), slot_size);
+      SetCtrlInLargeTable(common, new_i, H2(hash), slot_size);
       (*transfer)(set, new_slot_ptr, slot_ptr, 1);
-      SetCtrl(common, i, ctrl_t::kEmpty, slot_size);
+      SetCtrlInLargeTable(common, i, ctrl_t::kEmpty, slot_size);
       // Initialize or change empty space id.
       tmp_space_id = i;
     } else {
       assert(IsDeleted(ctrl[new_i]));
-      SetCtrl(common, new_i, H2(hash), slot_size);
+      SetCtrlInLargeTable(common, new_i, H2(hash), slot_size);
       // Until we are done rehashing, DELETED marks previously FULL slots.
 
       if (tmp_space_id == kUnknownId) {
@@ -357,8 +358,14 @@
       slot_ptr = PrevSlot(slot_ptr, slot_size);
     }
   }
+  // Prepare insert for the new element.
+  PrepareInsertCommon(common);
   ResetGrowthLeft(common);
+  FindInfo find_info = find_first_non_full(common, new_hash);
+  SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), policy.slot_size);
+  common.infoz().RecordInsert(new_hash, find_info.probe_length);
   common.infoz().RecordRehash(total_probe_length);
+  return find_info.offset;
 }
 
 static bool WasNeverFull(CommonFields& c, size_t index) {
@@ -416,7 +423,7 @@
   }
 
   c.growth_info().OverwriteFullAsDeleted();
-  SetCtrl(c, index, ctrl_t::kDeleted, slot_size);
+  SetCtrlInLargeTable(c, index, ctrl_t::kDeleted, slot_size);
 }
 
 void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
@@ -802,7 +809,7 @@
       total_probe_length = policy.find_new_positions_and_transfer_slots(
           common, old_ctrl, old_slots, old_capacity);
       find_info = find_first_non_full(common, new_hash);
-      SetCtrl(common, find_info.offset, new_h2, policy.slot_size);
+      SetCtrlInLargeTable(common, find_info.offset, new_h2, policy.slot_size);
     }
     assert(old_capacity > policy.soo_capacity);
     (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
@@ -825,7 +832,7 @@
 // tombstones via rehash or growth to next capacity.
 ABSL_ATTRIBUTE_NOINLINE
 size_t RehashOrGrowToNextCapacityAndPrepareInsert(
-    CommonFields& common, size_t hash, const PolicyFunctions& policy) {
+    CommonFields& common, size_t new_hash, const PolicyFunctions& policy) {
   const size_t cap = common.capacity();
   ABSL_ASSUME(cap > 0);
   if (cap > Group::kWidth &&
@@ -872,16 +879,10 @@
     //  762 | 149836       0.37        13 | 148559       0.74       190
     //  807 | 149736       0.39        14 | 151107       0.39        14
     //  852 | 150204       0.42        15 | 151019       0.42        15
-    DropDeletesWithoutResize(common, policy);
-    FindInfo find_info = find_first_non_full(common, hash);
-    PrepareInsertCommon(common);
-    common.growth_info().OverwriteEmptyAsFull();
-    SetCtrl(common, find_info.offset, H2(hash), policy.slot_size);
-    common.infoz().RecordInsert(hash, find_info.probe_length);
-    return find_info.offset;
+    return DropDeletesWithoutResizeAndPrepareInsert(common, new_hash, policy);
   } else {
     // Otherwise grow the container.
-    return GrowToNextCapacityAndPrepareInsert(common, hash, policy);
+    return GrowToNextCapacityAndPrepareInsert(common, new_hash, policy);
   }
 }
 
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 28f5cf0..0715bbf 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1905,6 +1905,22 @@
   SetCtrlInSingleGroupTable(c, i, static_cast<ctrl_t>(h), slot_size);
 }
 
+// Like SetCtrl, but in a table with capacity >= Group::kWidth - 1,
+// we can save some operations when setting the cloned control byte.
+inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, ctrl_t h,
+                                size_t slot_size) {
+  ABSL_SWISSTABLE_ASSERT(c.capacity() >= Group::kWidth - 1);
+  DoSanitizeOnSetCtrl(c, i, h, slot_size);
+  ctrl_t* ctrl = c.control();
+  ctrl[i] = h;
+  ctrl[((i - NumClonedBytes()) & c.capacity()) + NumClonedBytes()] = h;
+}
+// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
+inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, h2_t h,
+                                size_t slot_size) {
+  SetCtrlInLargeTable(c, i, static_cast<ctrl_t>(h), slot_size);
+}
+
 // growth_info (which is a size_t) is stored with the backing array.
 constexpr size_t BackingArrayAlignment(size_t align_of_slot) {
   return (std::max)(align_of_slot, alignof(GrowthInfo));