Remove checks covering multiple batch-hasbit-checks.

We used to generate the checks like
```
 if ((BatchCheckHasBit(has_bits[1], mask1) ||       // <- this one
      BatchCheckHasBit(has_bits[2], mask2))) {      // <- this one
  if (BatchCheckHasBit(has_bits[1], mask1)) { ... }
  if (BatchCheckHasBit(has_bits[2], mask2)) { ... }
}
```

I suppose they were added when the size of a batch was limited by 8. The current limit is 32. This CL eliminates these multi-batch checks without performance regression.

PiperOrigin-RevId: 1000933241
diff --git a/src/google/protobuf/compiler/cpp/field_chunk.cc b/src/google/protobuf/compiler/cpp/field_chunk.cc
index 8075e4f..d58c677 100644
--- a/src/google/protobuf/compiler/cpp/field_chunk.cc
+++ b/src/google/protobuf/compiler/cpp/field_chunk.cc
@@ -1,11 +1,9 @@
 #include "google/protobuf/compiler/cpp/field_chunk.h"
 
 #include <cstdint>
-#include <vector>
 
 #include "absl/log/absl_check.h"
 #include "absl/numeric/bits.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "google/protobuf/compiler/cpp/field_layout.h"
 #include "google/protobuf/descriptor.h"
@@ -20,38 +18,6 @@
 
 namespace {
 
-// Returns the (common) hasbit index offset. Callers must guarantee "fields" is
-// not empty. Debug-check fails if it sees different hasbit index offset in
-// "fields".
-int GetCommonHasbitIndexOffset(absl::Span<const FieldDescriptor*> fields,
-                               const FieldLayout& field_layout) {
-  ABSL_CHECK(!fields.empty());
-
-  int word_idx = field_layout.GetHasWordIndex(fields.front()).value();
-  for (auto* field : fields) {
-    ABSL_DCHECK_EQ(word_idx, field_layout.GetHasWordIndex(field).value());
-  }
-  return word_idx;
-}
-
-// Asserts that chunks in [it, end) share hasbit index offset and returns it.
-int GetSameHasbitIndexOffset(ChunkIterator it, ChunkIterator end,
-                             const FieldLayout& field_layout) {
-  ABSL_CHECK(it != end);
-  absl::optional<int> prev_offset;
-  for (; it != end; ++it) {
-    // Skip empty chunks (likely due to extraction).
-    if (it->fields.empty()) continue;
-
-    int offset =
-        GetCommonHasbitIndexOffset(absl::MakeSpan(it->fields), field_layout);
-    ABSL_CHECK(!prev_offset.has_value() || *prev_offset == offset);
-    prev_offset = offset;
-  }
-  ABSL_CHECK(prev_offset.has_value());
-  return *prev_offset;
-}
-
 uint32_t GenRawChunkMask(absl::Span<const FieldDescriptor* const> fields,
                          int first_index_offset,
                          const FieldLayout& field_layout) {
@@ -92,22 +58,6 @@
   return SimplifyChunkMask(chunk_mask, first_index_offset, field_layout);
 }
 
-// Returns a bit mask based on has_bit index of "fields" in chunks in [it, end).
-// Assumes that all chunks share the same hasbit word.
-uint32_t GenChunkMask(ChunkIterator it, ChunkIterator end,
-                      const FieldLayout& field_layout) {
-  ABSL_CHECK(it != end);
-
-  int first_index_offset = GetSameHasbitIndexOffset(it, end, field_layout);
-
-  uint32_t chunk_mask = 0;
-  for (; it != end; ++it) {
-    chunk_mask |= GenRawChunkMask(it->fields, first_index_offset, field_layout);
-  }
-
-  return SimplifyChunkMask(chunk_mask, first_index_offset, field_layout);
-}
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/field_chunk.h b/src/google/protobuf/compiler/cpp/field_chunk.h
index b8f5be2..2e3a034 100644
--- a/src/google/protobuf/compiler/cpp/field_chunk.h
+++ b/src/google/protobuf/compiler/cpp/field_chunk.h
@@ -19,27 +19,17 @@
 namespace cpp {
 
 struct FieldChunk {
-  FieldChunk(bool has_hasbit, bool is_rarely_present, bool should_split)
-      : has_hasbit(has_hasbit),
-        is_rarely_present(is_rarely_present),
-        should_split(should_split) {}
+  explicit FieldChunk(bool has_hasbit) : has_hasbit(has_hasbit) {}
 
   bool has_hasbit;
-  bool is_rarely_present;
-  bool should_split;
 
   std::vector<const FieldDescriptor*> fields;
 };
 
-using ChunkIterator = std::vector<FieldChunk>::iterator;
-
 PROTOC_EXPORT uint32_t
 GenChunkMask(absl::Span<const FieldDescriptor* const> fields,
              const FieldLayout& field_layout);
 
-PROTOC_EXPORT uint32_t GenChunkMask(ChunkIterator it, ChunkIterator end,
-                                    const FieldLayout& field_layout);
-
 struct AlwaysTruePred {
   template <typename T>
   bool operator()(const T&) const {
@@ -64,48 +54,12 @@
     }
     if (force_new_chunk || !equivalent(chunks.back().fields.back(), field)) {
       force_new_chunk = false;
-      chunks.emplace_back(HasHasbit(field, options),
-                          IsRarelyPresent(field, options),
-                          ShouldSplit(field, options));
+      chunks.emplace_back(HasHasbit(field, options));
     }
     chunks.back().fields.push_back(field);
   }
   return chunks;
 }
-
-template <typename Predicate>
-ChunkIterator FindNextUnequalChunk(ChunkIterator start, ChunkIterator end,
-                                   const Predicate& equal) {
-  auto it = start;
-  while (++it != end) {
-    if (!equal(*start, *it)) {
-      return it;
-    }
-  }
-  return end;
-}
-
-// Returns an array of field descriptors that meet "predicate" in [it, end). The
-// matched fields are removed from the original range.
-template <typename Predicate>
-std::vector<const FieldDescriptor*> ExtractFields(ChunkIterator it,
-                                                  ChunkIterator end,
-                                                  const Predicate& predicate) {
-  std::vector<const FieldDescriptor*> res;
-  for (; it != end; ++it) {
-    auto& source = it->fields;
-    if (source.empty()) continue;
-
-    for (const auto* f : source) {
-      if (predicate(f)) {
-        res.push_back(f);
-      }
-    }
-    source.erase(std::remove_if(source.begin(), source.end(), predicate),
-                 source.end());
-  }
-  return res;
-}
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/field_chunk_test.cc b/src/google/protobuf/compiler/cpp/field_chunk_test.cc
index b636709..573b756 100644
--- a/src/google/protobuf/compiler/cpp/field_chunk_test.cc
+++ b/src/google/protobuf/compiler/cpp/field_chunk_test.cc
@@ -21,7 +21,6 @@
 namespace {
 
 using proto2_unittest::TestAllTypes;
-using testing::IsEmpty;
 
 template <typename ProtoT>
 std::vector<const google::protobuf::FieldDescriptor*> CreateFieldArray(
@@ -86,68 +85,6 @@
   EXPECT_FALSE(chunks[1].fields.front()->is_repeated());
 }
 
-TEST(FindNextTest, AllEqual) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-  auto it = FindNextUnequalChunk(
-      chunks.begin(), chunks.end(),
-      [](const FieldChunk&, const FieldChunk&) { return true; });
-
-  EXPECT_EQ(it, chunks.end());
-}
-
-TEST(FindNextTest, AllUnequal) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-  auto it = FindNextUnequalChunk(
-      chunks.begin(), chunks.end(),
-      [](const FieldChunk&, const FieldChunk&) { return false; });
-
-  ASSERT_NE(it, chunks.end());
-  EXPECT_EQ(it->fields, chunks[1].fields);
-}
-
-TEST(ExtractTest, ExtractNone) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-
-  ASSERT_EQ(chunks.size(), 2);
-  auto extracted =
-      ExtractFields(chunks.begin(), chunks.end(),
-                    [](const FieldDescriptor* f) { return false; });
-
-  EXPECT_THAT(extracted, IsEmpty());
-}
-
-TEST(ExtractTest, ExtractAll) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-
-  ASSERT_EQ(chunks.size(), 2);
-
-  auto extracted = ExtractFields(chunks.begin(), chunks.end(),
-                                 [](const FieldDescriptor* f) { return true; });
-
-  ASSERT_EQ(chunks.size(), 2);
-  ASSERT_THAT(chunks[0].fields, IsEmpty());
-  ASSERT_THAT(chunks[1].fields, IsEmpty());
-
-  auto fields = CreateFieldArray<TestAllTypes>(field_names);
-  EXPECT_THAT(extracted, testing::ElementsAreArray(fields));
-}
-
 TEST(GenChunkMaskTest, ValidMaskFromFields) {
   const char* field_names[] = {"optional_int32", "optional_int64"};
 
@@ -164,28 +101,6 @@
   EXPECT_EQ(mask, (1 << kHasbitIdxAt0) | (1 << kHasbitIdxAt1));
 }
 
-TEST(GenChunkMaskTest, ValidMaskFromChunks) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-
-  ASSERT_EQ(chunks.size(), 2);
-  ASSERT_EQ(chunks[0].fields.size(), 1);
-  ASSERT_EQ(chunks[0].fields[0]->index(), 0);
-  ASSERT_EQ(chunks[1].fields.size(), 1);
-  ASSERT_EQ(chunks[1].fields[0]->index(), 1);
-
-  const uint32_t kHasbitIdxAt0 = 3;
-  const uint32_t kHasbitIdxAt1 = 5;
-  auto field_layout =
-      FieldLayout::BuildForTesting({chunks[0].fields[0], chunks[1].fields[0]},
-                                   {kHasbitIdxAt0, kHasbitIdxAt1});
-  uint32_t mask = GenChunkMask(chunks.begin(), chunks.end(), field_layout);
-  EXPECT_EQ(mask, (1 << kHasbitIdxAt0) | (1 << kHasbitIdxAt1));
-}
-
 TEST(GenChunkMaskTest, FullWordMaskFromFields) {
   const Descriptor* descriptor = TestAllTypes::GetDescriptor();
   std::vector<const FieldDescriptor*> fields;
@@ -221,24 +136,6 @@
             ~uint32_t{0});
 }
 
-TEST(GenChunkMaskTest, FullWordMaskFromChunks) {
-  const char* field_names[] = {"optional_int32", "optional_int64"};
-  auto chunks = CreateAndCollectFields<TestAllTypes>(
-      field_names, [](const FieldDescriptor* lhs, const FieldDescriptor* rhs) {
-        return false;
-      });
-  ASSERT_EQ(chunks.size(), 2);
-
-  auto field_layout = FieldLayout::BuildForTesting(
-      {chunks[0].fields[0], chunks[1].fields[0]}, {0, 1});
-  ASSERT_EQ(field_layout.CountFieldsSharingHasWord(0), 2);
-
-  EXPECT_EQ(GenChunkMask(chunks.begin(), chunks.end(), field_layout),
-            ~uint32_t{0});
-  EXPECT_EQ(GenChunkMask(chunks.begin(), chunks.begin() + 1, field_layout),
-            uint32_t{1});
-}
-
 }  // namespace
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc
index 5a9e56c..2adcaab 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -435,91 +435,6 @@
   return false;
 }
 
-// Returns true if two chunks may be grouped for hasword check to skip multiple
-// cold fields at once. They have to share the following traits:
-// - whether they have hasbits
-// - whether they are rarely present
-// - whether they are split
-bool MayGroupChunksForHaswordsCheck(const FieldChunk& a, const FieldChunk& b) {
-  return a.has_hasbit == b.has_hasbit &&
-         a.is_rarely_present == b.is_rarely_present &&
-         a.should_split == b.should_split;
-}
-
-// Returns true if it emits conditional check against hasbit words. This is
-// useful to skip multiple fields that are unlikely present based on profile
-// (go/pdproto). Assumes that each chunk is limited to one has "word".
-bool MaybeEmitHaswordsCheck(ChunkIterator it, ChunkIterator end,
-                            const Options& options,
-                            const FieldLayout& field_layout,
-                            int cached_has_word_index, const std::string& from,
-                            io::Printer* p) {
-  if (!it->has_hasbit || !IsProfileDriven(options) ||
-      std::distance(it, end) < 2 || !it->is_rarely_present) {
-    return false;
-  }
-
-  auto hasbit_word = [&field_layout](const FieldDescriptor* field) {
-    return field_layout.GetHasWordIndex(field).value();
-  };
-  auto is_same_hasword = [&](const FieldChunk& a, const FieldChunk& b) {
-    // Empty fields are assumed to have the same haswords.
-    if (a.fields.empty() || b.fields.empty()) return true;
-
-    return hasbit_word(a.fields.front()) == hasbit_word(b.fields.front());
-  };
-
-  struct HasWordMask {
-    int word;
-    uint32_t mask;
-  };
-
-  std::vector<HasWordMask> hasword_masks;
-  while (it != end) {
-    auto next = FindNextUnequalChunk(it, end, is_same_hasword);
-    for (; it != next; ++it) {
-      if (!it->fields.empty()) {
-        hasword_masks.push_back({hasbit_word(it->fields.front()),
-                                 GenChunkMask(it, next, field_layout)});
-        break;
-      }
-    }
-    // Jump to the next batch instead.
-    it = next;
-  }
-
-  if (hasword_masks.empty()) return false;
-
-  // Emit has_bit check for each has_bit_dword index.
-  p->Emit({{"cond",
-            [&] {
-              int first_word = hasword_masks.front().word;
-              for (const auto& m : hasword_masks) {
-                uint32_t mask = m.mask;
-                int this_word = m.word;
-                if (this_word != first_word) {
-                  p->Emit(R"cc(
-                    ||
-                  )cc");
-                }
-                auto v =
-                    p->WithVars({{"mask", absl::StrFormat("0x%08xU", mask)}});
-                if (this_word == cached_has_word_index) {
-                  p->Emit("BatchCheckHasBit(cached_has_bits, $mask$)");
-                } else {
-                  p->Emit({{"from", from}, {"word", this_word}},
-                          "BatchCheckHasBit($from$_impl_._has_bits_[$word$], "
-                          "$mask$)");
-                }
-              }
-            }}},
-          R"cc(
-            if (ABSL_PREDICT_FALSE($cond$)) {
-          )cc");
-  p->Indent();
-  return true;
-}
-
 // Calculates the expected number of branch checks executed for a chunk of
 // `size` fields, where `p_none` is the probability that none of the fields
 // are present.
@@ -547,7 +462,7 @@
 
 FieldChunk ChunkWithFields(const FieldChunk& chunk,
                            std::vector<const FieldDescriptor*> fields) {
-  FieldChunk res(chunk.has_hasbit, chunk.is_rarely_present, chunk.should_split);
+  FieldChunk res(chunk.has_hasbit);
   res.fields = std::move(fields);
   return res;
 }
@@ -3461,78 +3376,56 @@
   enclosing_if_chunks = PartitionToMinimizeExpectedBranches(
       std::move(enclosing_if_chunks), options_);
 
-  auto it = enclosing_if_chunks.begin();
-  auto end = enclosing_if_chunks.end();
   int cached_has_word_index = -1;
 
-  while (it != end) {
-    auto next = FindNextUnequalChunk(it, end, MayGroupChunksForHaswordsCheck);
-    bool has_haswords_check = MaybeEmitHaswordsCheck(
-        it, next, options_, field_layout_, cached_has_word_index, "this_.", p);
+  for (const FieldChunk& chunk : enclosing_if_chunks) {
+    const std::vector<const FieldDescriptor*>& fields = chunk.fields;
 
-    while (it != next) {
-      const std::vector<const FieldDescriptor*>& fields = it->fields;
-
-      const int has_word_index =
-          field_layout_.GetHasWordIndex(fields.front()).value();
-      if (cached_has_word_index != has_word_index) {
-        cached_has_word_index = has_word_index;
-        p->Emit({{"cached_has_word_index", cached_has_word_index}}, R"cc(
-          cached_has_bits = this_.$has_bits$[$cached_has_word_index$];
-        )cc");
-      }
-
-      const auto print_clear_field_chunk = [&] {
-        for (const auto& field : fields) {
-          p->Emit({{"cond",
-                    [&] {
-                      PrintPresenceCheckCondition(field, field_layout_, p,
-                                                  options_);
-                    }},
-                   {"clear_field", [&] { emit_clear_field(field); }}},
-                  R"cc(
-                    if ($cond$) {
-                      $clear_field$;
-                    }
-                  )cc");
-        }
-      };
-
-      // Whether we wrap this chunk in:
-      //   if (cached_has_bits & <chunk hasbits>) { /* chunk. */ }
-      if (fields.size() > 1) {
-        // Emit an if() that will let us skip the whole chunk if none are set.
-        uint32_t chunk_mask = GenChunkMask(fields, field_layout_);
-
-        ABSL_DCHECK_GE(absl::popcount(chunk_mask), 2);
-
-        const std::string cond = GenerateConditionMaybeWithProbabilityForGroup(
-            chunk_mask, fields, options_);
-        p->Emit(
-            {{"cond", cond}, {"clear_field_chunk", print_clear_field_chunk}},
-            R"cc(
-              if ($cond$) {
-                $clear_field_chunk$;
-              }
-            )cc");
-      } else {
-        print_clear_field_chunk();
-      }
-
-      // To next chunk.
-      ++it;
-    }
-
-    if (has_haswords_check) {
-      p->Outdent();
-      p->Emit(R"cc(
-        }
+    const int has_word_index =
+        field_layout_.GetHasWordIndex(fields.front()).value();
+    if (cached_has_word_index != has_word_index) {
+      cached_has_word_index = has_word_index;
+      p->Emit({{"cached_has_word_index", cached_has_word_index}}, R"cc(
+        cached_has_bits = this_.$has_bits$[$cached_has_word_index$];
       )cc");
-
-      // Reset here as it may have been updated in just closed if statement.
-      cached_has_word_index = -1;
     }
-  };
+
+    const auto print_clear_field_chunk = [&] {
+      for (const auto& field : fields) {
+        p->Emit({{"cond",
+                  [&] {
+                    PrintPresenceCheckCondition(field, field_layout_, p,
+                                                options_);
+                  }},
+                 {"clear_field", [&] { emit_clear_field(field); }}},
+                R"cc(
+                  if ($cond$) {
+                    $clear_field$;
+                  }
+                )cc");
+      }
+    };
+
+    // Whether we wrap this chunk in:
+    //   if (cached_has_bits & <chunk hasbits>) { /* chunk. */ }
+    if (fields.size() > 1) {
+      // Emit an if() that will let us skip the whole chunk if none are set.
+      uint32_t chunk_mask = GenChunkMask(fields, field_layout_);
+
+      ABSL_DCHECK_GE(absl::popcount(chunk_mask), 2);
+
+      const std::string cond = GenerateConditionMaybeWithProbabilityForGroup(
+          chunk_mask, fields, options_);
+      p->Emit({{"cond", cond}, {"clear_field_chunk", print_clear_field_chunk}},
+              R"cc(
+                if ($cond$) {
+                  $clear_field_chunk$;
+                }
+              )cc");
+    } else {
+      print_clear_field_chunk();
+    }
+  }
 }
 
 void MessageGenerator::GenerateClear(io::Printer* p) {
@@ -4057,24 +3950,10 @@
               generator.GenerateMergingCode(p);
             },
             /*with_enclosing_braces_always=*/true);
-      } else if (cached_has_word_index !=
-                 field_layout_.GetHasWordIndex(field).value()) {
-        // Check hasbit, not using cached bits.
-        auto v = p->WithVars(HasBitVars(field));
-        p->Emit(
-            {{"merge_field",
-              [&] {
-                prepare_split();
-                generator.GenerateMergingCode(p);
-              }}},
-            R"cc(
-              if (CheckHasBit(from.$has_bits$[$has_array_index$], $has_mask$)) {
-                $merge_field$;
-              }
-            )cc");
       } else {
         // Check hasbit, using cached bits.
-        ABSL_CHECK(HasHasbit(field, options_));
+        ABSL_CHECK_EQ(field_layout_.GetHasWordIndex(field),
+                      cached_has_word_index);
         int has_bit_index = field_layout_.GetHasBitIndex(field).value();
 
         p->Emit(
@@ -4123,28 +4002,8 @@
       [&](const auto* f) { return ShouldSplit(f, options_) == is_split; });
   chunks = PartitionToMinimizeExpectedBranches(std::move(chunks), options_);
 
-  auto it = chunks.begin();
-  auto end = chunks.end();
-  while (it != end) {
-    auto next = FindNextUnequalChunk(it, end, MayGroupChunksForHaswordsCheck);
-    bool has_haswords_check = MaybeEmitHaswordsCheck(
-        it, next, options_, field_layout_, cached_has_word_index, "from.", p);
-
-    while (it != next) {
-      emit_merge_chunk(it->fields);
-      ++it;
-    }
-
-    if (has_haswords_check) {
-      p->Outdent();
-      p->Emit(R"cc(
-        }
-      )cc");
-
-      // Reset here as it may have been updated in just closed if
-      // statement.
-      cached_has_word_index = -1;
-    }
+  for (const FieldChunk& chunk : chunks) {
+    emit_merge_chunk(chunk.fields);
   }
 
   return cached_has_word_index >= 0;
@@ -4977,8 +4836,6 @@
     chunks.insert(it, std::move(chunk));
   }
 
-  auto it = chunks.begin();
-  auto end = chunks.end();
   int cached_has_word_index = -1;
   const auto update_cached_has_bits = [&](auto& fields) {
     const int has_word_index =
@@ -4992,95 +4849,75 @@
             )cc");
   };
 
-  while (it != end) {
-    auto next = FindNextUnequalChunk(it, end, MayGroupChunksForHaswordsCheck);
-    bool has_haswords_check = MaybeEmitHaswordsCheck(
-        it, next, options_, field_layout_, cached_has_word_index, "this_.", p);
+  for (const FieldChunk& chunk : chunks) {
+    const auto& fields = chunk.fields;
 
-    while (it != next) {
-      const auto& fields = it->fields;
-
-      // If the chunk is a fixed size singular chunk, use a branchless
-      // approach for it.
-      if (absl::optional<int> fsize = FixedSize(fields[0])) {
-        update_cached_has_bits(fields);
-        // When a single field is the only field in its has_word, `GenChunkMask`
-        // returns ~0u, which would fail the `absl::has_single_bit(mask)` check
-        // below, emitting `::absl::popcount` instead of `static_cast<bool>`.
-        // Therefore we process the single-field case separately.
-        uint32_t mask =
-            fields.size() == 1
-                ? uint32_t{1}
-                      << (field_layout_.GetHasBitIndex(fields[0]).value() % 32)
-                : GenChunkMask(fields, field_layout_);
-        p->Emit({{"mask", absl::StrFormat("0x%08xU", mask)},
-                 {"popcount", absl::has_single_bit(mask) ? "static_cast<bool>"
-                                                         : "::absl::popcount"},
-                 {"fsize", *fsize}},
-                R"cc(
-                  //~
-                  total_size += $popcount$($mask$ & cached_has_bits) * $fsize$;
-                )cc");
-        ++it;
-        continue;
-      }
-
-      const bool check_has_word =
-          fields.size() > 1 &&
-          field_layout_.GetHasWordIndex(fields[0]).has_value();
-      p->Emit({{"update_byte_size_for_chunk",
-                [&] {
-                  // Go back and emit checks for each of the fields we
-                  // processed.
-                  for (const auto* field : fields) {
-                    EmitUpdateByteSizeForField(field, p, cached_has_word_index);
-                  }
-                }},
-               {"may_update_cached_has_word_index",
-                [&] {
-                  if (!check_has_word) return;
-                  update_cached_has_bits(fields);
-                }},
-               {"check_if_chunk_present",
-                [&] {
-                  if (!check_has_word) {
-                    return;
-                  }
-
-                  // Emit an if() that will let us skip the whole chunk
-                  // if none are set.
-                  uint32_t chunk_mask = GenChunkMask(fields, field_layout_);
-
-                  // Check has_bits at a time if we have more than one field in
-                  // this chunk.
-                  ABSL_DCHECK_GE(absl::popcount(chunk_mask), 2);
-
-                  p->Emit({{"condition",
-                            GenerateConditionMaybeWithProbabilityForGroup(
-                                chunk_mask, fields, options_)}},
-                          "if ($condition$)");
-                }}},
+    // If the chunk is a fixed size singular chunk, use a branchless
+    // approach for it.
+    if (absl::optional<int> fsize = FixedSize(fields[0])) {
+      update_cached_has_bits(fields);
+      // When a single field is the only field in its has_word, `GenChunkMask`
+      // returns ~0u, which would fail the `absl::has_single_bit(mask)` check
+      // below, emitting `::absl::popcount` instead of `static_cast<bool>`.
+      // Therefore we process the single-field case separately.
+      uint32_t mask =
+          fields.size() == 1
+              ? uint32_t{1}
+                    << (field_layout_.GetHasBitIndex(fields[0]).value() % 32)
+              : GenChunkMask(fields, field_layout_);
+      p->Emit({{"mask", absl::StrFormat("0x%08xU", mask)},
+               {"popcount", absl::has_single_bit(mask) ? "static_cast<bool>"
+                                                       : "::absl::popcount"},
+               {"fsize", *fsize}},
               R"cc(
-                $may_update_cached_has_word_index$;
-                $check_if_chunk_present$ {
-                  //~ Force newline.
-                  $update_byte_size_for_chunk$;
-                }
+                //~
+                total_size += $popcount$($mask$ & cached_has_bits) * $fsize$;
               )cc");
-
-      // To next chunk.
-      ++it;
+      continue;
     }
 
-    if (has_haswords_check) {
-      p->Emit(R"cc(
-        }
-      )cc");
+    const bool check_has_word =
+        fields.size() > 1 &&
+        field_layout_.GetHasWordIndex(fields[0]).has_value();
+    p->Emit({{"update_byte_size_for_chunk",
+              [&] {
+                // Go back and emit checks for each of the fields we
+                // processed.
+                for (const auto* field : fields) {
+                  EmitUpdateByteSizeForField(field, p, cached_has_word_index);
+                }
+              }},
+             {"may_update_cached_has_word_index",
+              [&] {
+                if (!check_has_word) return;
+                update_cached_has_bits(fields);
+              }},
+             {"check_if_chunk_present",
+              [&] {
+                if (!check_has_word) {
+                  return;
+                }
 
-      // Reset here as it may have been updated in just closed if
-      // statement.
-      cached_has_word_index = -1;
-    }
+                // Emit an if() that will let us skip the whole chunk
+                // if none are set.
+                uint32_t chunk_mask = GenChunkMask(fields, field_layout_);
+
+                // Check has_bits at a time if we have more than one field in
+                // this chunk.
+                ABSL_DCHECK_GE(absl::popcount(chunk_mask), 2);
+
+                p->Emit({{"condition",
+                          GenerateConditionMaybeWithProbabilityForGroup(
+                              chunk_mask, fields, options_)}},
+                        "if ($condition$)");
+              }}},
+            R"cc(
+              $may_update_cached_has_word_index$;
+              $check_if_chunk_present$ {
+                //~ Force newline.
+                $update_byte_size_for_chunk$;
+              }
+            )cc");
   }
 }