Revert^6 "Disable write-barrier elimination pass"

This reverts commit 1be176f5a78750e2f0e32470f8c83e3d1643954d.

Reason for revert: Potential cause of build breakage for cf_riscv64_wear-trunk_staging-userdebug build 11353124

Change-Id: I5db1c9fba1edd4ab1eef30e2b547bb9649af5c10
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 441a93c..b00e7e1 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -158,25 +158,6 @@
   return EmitReadBarrier() ? kWithReadBarrier : kWithoutReadBarrier;
 }
 
-bool CodeGenerator::ShouldCheckGCCard(DataType::Type type,
-                                      HInstruction* value,
-                                      WriteBarrierKind write_barrier_kind) const {
-  const CompilerOptions& options = GetCompilerOptions();
-  const bool result =
-      // Check the GC card in debug mode,
-      options.EmitRunTimeChecksInDebugMode() &&
-      // only for CC GC,
-      options.EmitReadBarrier() &&
-      // and if we eliminated the write barrier in WBE.
-      !StoreNeedsWriteBarrier(type, value, write_barrier_kind) &&
-      CodeGenerator::StoreNeedsWriteBarrier(type, value);
-
-  DCHECK_IMPLIES(result, write_barrier_kind == WriteBarrierKind::kDontEmit);
-  DCHECK_IMPLIES(result, !GetGraph()->IsCompilingBaseline());
-
-  return result;
-}
-
 ScopedArenaAllocator* CodeGenerator::GetScopedAllocator() {
   DCHECK(code_generation_data_ != nullptr);
   return code_generation_data_->GetScopedAllocator();
@@ -1627,17 +1608,6 @@
   GetMoveResolver()->EmitNativeCode(&parallel_move);
 }
 
-bool CodeGenerator::StoreNeedsWriteBarrier(DataType::Type type,
-                                           HInstruction* value,
-                                           WriteBarrierKind write_barrier_kind) const {
-  // Check that null value is not represented as an integer constant.
-  DCHECK_IMPLIES(type == DataType::Type::kReference, !value->IsIntConstant());
-  // Branch profiling currently doesn't support running optimizations.
-  return GetGraph()->IsCompilingBaseline()
-            ? CodeGenerator::StoreNeedsWriteBarrier(type, value)
-            : write_barrier_kind != WriteBarrierKind::kDontEmit;
-}
-
 void CodeGenerator::ValidateInvokeRuntime(QuickEntrypointEnum entrypoint,
                                           HInstruction* instruction,
                                           SlowPathCode* slow_path) {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index fbb4f9e..88e5a20 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -380,11 +380,6 @@
   bool EmitNonBakerReadBarrier() const;
   ReadBarrierOption GetCompilerReadBarrierOption() const;
 
-  // Returns true if we should check the GC card for consistency purposes.
-  bool ShouldCheckGCCard(DataType::Type type,
-                         HInstruction* value,
-                         WriteBarrierKind write_barrier_kind) const;
-
   // Get the ScopedArenaAllocator used for codegen memory allocation.
   ScopedArenaAllocator* GetScopedAllocator();
 
@@ -508,11 +503,6 @@
     return type == DataType::Type::kReference && !value->IsNullConstant();
   }
 
-  // If we are compiling a graph with the WBE pass enabled, we want to honor the WriteBarrierKind
-  // set during the WBE pass.
-  bool StoreNeedsWriteBarrier(DataType::Type type,
-                              HInstruction* value,
-                              WriteBarrierKind write_barrier_kind) const;
 
   // Performs checks pertaining to an InvokeRuntime call.
   void ValidateInvokeRuntime(QuickEntrypointEnum entrypoint,
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 0332d9b..9027976 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1499,24 +1499,18 @@
   }
 }
 
-void CodeGeneratorARM64::MaybeMarkGCCard(Register object, Register value, bool emit_null_check) {
+void CodeGeneratorARM64::MarkGCCard(Register object, Register value, bool emit_null_check) {
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register card = temps.AcquireX();
+  Register temp = temps.AcquireW();   // Index within the CardTable - 32bit.
   vixl::aarch64::Label done;
   if (emit_null_check) {
     __ Cbz(value, &done);
   }
-  MarkGCCard(object);
-  if (emit_null_check) {
-    __ Bind(&done);
-  }
-}
-
-void CodeGeneratorARM64::MarkGCCard(Register object) {
-  UseScratchRegisterScope temps(GetVIXLAssembler());
-  Register card = temps.AcquireX();
-  Register temp = temps.AcquireW();  // Index within the CardTable - 32bit.
   // Load the address of the card table into `card`.
   __ Ldr(card, MemOperand(tr, Thread::CardTableOffset<kArm64PointerSize>().Int32Value()));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
+  // Calculate the offset (in the card table) of the card corresponding to
+  // `object`.
   __ Lsr(temp, object, gc::accounting::CardTable::kCardShift);
   // Write the `art::gc::accounting::CardTable::kCardDirty` value into the
   // `object`'s card.
@@ -1532,24 +1526,9 @@
   // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ Strb(card, MemOperand(card, temp.X()));
-}
-
-void CodeGeneratorARM64::CheckGCCardIsValid(Register object) {
-  UseScratchRegisterScope temps(GetVIXLAssembler());
-  Register card = temps.AcquireX();
-  Register temp = temps.AcquireW();  // Index within the CardTable - 32bit.
-  vixl::aarch64::Label done;
-  // Load the address of the card table into `card`.
-  __ Ldr(card, MemOperand(tr, Thread::CardTableOffset<kArm64PointerSize>().Int32Value()));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
-  __ Lsr(temp, object, gc::accounting::CardTable::kCardShift);
-  // assert (!clean || !self->is_gc_marking)
-  __ Ldrb(temp, MemOperand(card, temp.X()));
-  static_assert(gc::accounting::CardTable::kCardClean == 0);
-  __ Cbnz(temp, &done);
-  __ Cbz(mr, &done);
-  __ Unreachable();
-  __ Bind(&done);
+  if (emit_null_check) {
+    __ Bind(&done);
+  }
 }
 
 void CodeGeneratorARM64::SetupBlockedRegisters() const {
@@ -2339,16 +2318,12 @@
     }
   }
 
-  const bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
-
-  if (needs_write_barrier) {
-    codegen_->MaybeMarkGCCard(
+  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)) &&
+      write_barrier_kind != WriteBarrierKind::kDontEmit) {
+    codegen_->MarkGCCard(
         obj,
         Register(value),
-        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
-  } else if (codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind)) {
-    codegen_->CheckGCCardIsValid(obj);
+        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitWithNullCheck);
   }
 }
 
@@ -2902,9 +2877,8 @@
   DataType::Type value_type = instruction->GetComponentType();
   LocationSummary* locations = instruction->GetLocations();
   bool needs_type_check = instruction->NeedsTypeCheck();
-  const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
 
   Register array = InputRegisterAt(instruction, 0);
   CPURegister value = InputCPURegisterOrZeroRegAt(instruction, 2);
@@ -2915,17 +2889,13 @@
   MacroAssembler* masm = GetVIXLAssembler();
 
   if (!needs_write_barrier) {
-    if (codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind)) {
-      codegen_->CheckGCCardIsValid(array);
-    }
-
     DCHECK(!needs_type_check);
-    UseScratchRegisterScope temps(masm);
     if (index.IsConstant()) {
       offset += Int64FromLocation(index) << DataType::SizeShift(value_type);
       destination = HeapOperand(array, offset);
     } else {
-      Register temp_dest = temps.AcquireSameSizeAs(array);
+      UseScratchRegisterScope temps(masm);
+      Register temp = temps.AcquireSameSizeAs(array);
       if (instruction->GetArray()->IsIntermediateAddress()) {
         // We do not need to compute the intermediate address from the array: the
         // input instruction has done it already. See the comment in
@@ -2934,116 +2904,101 @@
           HIntermediateAddress* interm_addr = instruction->GetArray()->AsIntermediateAddress();
           DCHECK(interm_addr->GetOffset()->AsIntConstant()->GetValueAsUint64() == offset);
         }
-        temp_dest = array;
+        temp = array;
       } else {
-        __ Add(temp_dest, array, offset);
+        __ Add(temp, array, offset);
       }
-      destination = HeapOperand(temp_dest,
+      destination = HeapOperand(temp,
                                 XRegisterFrom(index),
                                 LSL,
                                 DataType::SizeShift(value_type));
     }
-
-    if (kPoisonHeapReferences && value_type == DataType::Type::kReference) {
-      DCHECK(value.IsW());
-      Register temp_src = temps.AcquireW();
-      __ Mov(temp_src, value.W());
-      GetAssembler()->PoisonHeapReference(temp_src.W());
-      source = temp_src;
-    }
-
     {
       // Ensure that between store and MaybeRecordImplicitNullCheck there are no pools emitted.
       EmissionCheckScope guard(GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
-      codegen_->Store(value_type, source, destination);
+      codegen_->Store(value_type, value, destination);
       codegen_->MaybeRecordImplicitNullCheck(instruction);
     }
   } else {
     DCHECK(!instruction->GetArray()->IsIntermediateAddress());
-    bool can_value_be_null = true;
+
+    bool can_value_be_null = instruction->GetValueCanBeNull();
+    vixl::aarch64::Label do_store;
+    if (can_value_be_null) {
+      __ Cbz(Register(value), &do_store);
+    }
+
     SlowPathCodeARM64* slow_path = nullptr;
-    if (!Register(value).IsZero()) {
-      can_value_be_null = instruction->GetValueCanBeNull();
-      vixl::aarch64::Label do_store;
-      if (can_value_be_null) {
-        __ Cbz(Register(value), &do_store);
+    if (needs_type_check) {
+      slow_path = new (codegen_->GetScopedAllocator()) ArraySetSlowPathARM64(instruction);
+      codegen_->AddSlowPath(slow_path);
+
+      const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+      const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
+      const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
+
+      UseScratchRegisterScope temps(masm);
+      Register temp = temps.AcquireSameSizeAs(array);
+      Register temp2 = temps.AcquireSameSizeAs(array);
+
+      // Note that when Baker read barriers are enabled, the type
+      // checks are performed without read barriers.  This is fine,
+      // even in the case where a class object is in the from-space
+      // after the flip, as a comparison involving such a type would
+      // not produce a false positive; it may of course produce a
+      // false negative, in which case we would take the ArraySet
+      // slow path.
+
+      // /* HeapReference<Class> */ temp = array->klass_
+      {
+        // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted.
+        EmissionCheckScope guard(GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
+        __ Ldr(temp, HeapOperand(array, class_offset));
+        codegen_->MaybeRecordImplicitNullCheck(instruction);
       }
+      GetAssembler()->MaybeUnpoisonHeapReference(temp);
 
-      if (needs_type_check) {
-        slow_path = new (codegen_->GetScopedAllocator()) ArraySetSlowPathARM64(instruction);
-        codegen_->AddSlowPath(slow_path);
+      // /* HeapReference<Class> */ temp = temp->component_type_
+      __ Ldr(temp, HeapOperand(temp, component_offset));
+      // /* HeapReference<Class> */ temp2 = value->klass_
+      __ Ldr(temp2, HeapOperand(Register(value), class_offset));
+      // If heap poisoning is enabled, no need to unpoison `temp`
+      // nor `temp2`, as we are comparing two poisoned references.
+      __ Cmp(temp, temp2);
 
-        const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
-        const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
-        const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
-
-        UseScratchRegisterScope temps(masm);
-        Register temp = temps.AcquireSameSizeAs(array);
-        Register temp2 = temps.AcquireSameSizeAs(array);
-
-        // Note that when Baker read barriers are enabled, the type
-        // checks are performed without read barriers.  This is fine,
-        // even in the case where a class object is in the from-space
-        // after the flip, as a comparison involving such a type would
-        // not produce a false positive; it may of course produce a
-        // false negative, in which case we would take the ArraySet
-        // slow path.
-
-        // /* HeapReference<Class> */ temp = array->klass_
-        {
-          // Ensure that between load and MaybeRecordImplicitNullCheck there are no pools emitted.
-          EmissionCheckScope guard(GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
-          __ Ldr(temp, HeapOperand(array, class_offset));
-          codegen_->MaybeRecordImplicitNullCheck(instruction);
-        }
+      if (instruction->StaticTypeOfArrayIsObjectArray()) {
+        vixl::aarch64::Label do_put;
+        __ B(eq, &do_put);
+        // If heap poisoning is enabled, the `temp` reference has
+        // not been unpoisoned yet; unpoison it now.
         GetAssembler()->MaybeUnpoisonHeapReference(temp);
 
-        // /* HeapReference<Class> */ temp = temp->component_type_
-        __ Ldr(temp, HeapOperand(temp, component_offset));
-        // /* HeapReference<Class> */ temp2 = value->klass_
-        __ Ldr(temp2, HeapOperand(Register(value), class_offset));
-        // If heap poisoning is enabled, no need to unpoison `temp`
-        // nor `temp2`, as we are comparing two poisoned references.
-        __ Cmp(temp, temp2);
-
-        if (instruction->StaticTypeOfArrayIsObjectArray()) {
-          vixl::aarch64::Label do_put;
-          __ B(eq, &do_put);
-          // If heap poisoning is enabled, the `temp` reference has
-          // not been unpoisoned yet; unpoison it now.
-          GetAssembler()->MaybeUnpoisonHeapReference(temp);
-
-          // /* HeapReference<Class> */ temp = temp->super_class_
-          __ Ldr(temp, HeapOperand(temp, super_offset));
-          // If heap poisoning is enabled, no need to unpoison
-          // `temp`, as we are comparing against null below.
-          __ Cbnz(temp, slow_path->GetEntryLabel());
-          __ Bind(&do_put);
-        } else {
-          __ B(ne, slow_path->GetEntryLabel());
-        }
-      }
-
-      if (can_value_be_null) {
-        DCHECK(do_store.IsLinked());
-        __ Bind(&do_store);
+        // /* HeapReference<Class> */ temp = temp->super_class_
+        __ Ldr(temp, HeapOperand(temp, super_offset));
+        // If heap poisoning is enabled, no need to unpoison
+        // `temp`, as we are comparing against null below.
+        __ Cbnz(temp, slow_path->GetEntryLabel());
+        __ Bind(&do_put);
+      } else {
+        __ B(ne, slow_path->GetEntryLabel());
       }
     }
 
-    DCHECK_NE(write_barrier_kind, WriteBarrierKind::kDontEmit);
-    // TODO(solanes): The WriteBarrierKind::kEmitNotBeingReliedOn case should be able to skip this
-    // write barrier when its value is null (without an extra cbz since we already checked if the
-    // value is null for the type check). This will be done as a follow-up since it is a runtime
-    // optimization that needs extra care.
-    // TODO(solanes): We can also skip it for known zero values which are not relied on i.e. when
-    // we have the Zero register as the value. If we do `HuntForOriginalReference` on the value
-    // we'll resolve this.
-    codegen_->MarkGCCard(array);
+    if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+      DCHECK_EQ(instruction->GetWriteBarrierKind(), WriteBarrierKind::kEmitNoNullCheck)
+          << " Already null checked so we shouldn't do it again.";
+      codegen_->MarkGCCard(array, value.W(), /* emit_null_check= */ false);
+    }
+
+    if (can_value_be_null) {
+      DCHECK(do_store.IsLinked());
+      __ Bind(&do_store);
+    }
 
     UseScratchRegisterScope temps(masm);
     if (kPoisonHeapReferences) {
-      DCHECK(value.IsW());
-      Register temp_source = temps.AcquireW();
+      Register temp_source = temps.AcquireSameSizeAs(array);
+        DCHECK(value.IsW());
       __ Mov(temp_source, value.W());
       GetAssembler()->PoisonHeapReference(temp_source);
       source = temp_source;
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index c78137b..7ff08f5 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -658,20 +658,10 @@
   const Arm64Assembler& GetAssembler() const override { return assembler_; }
   vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
 
-  // Emit a write barrier if:
-  // A) emit_null_check is false
-  // B) emit_null_check is true, and value is not null.
-  void MaybeMarkGCCard(vixl::aarch64::Register object,
-                       vixl::aarch64::Register value,
-                       bool emit_null_check);
-
-  // Emit a write barrier unconditionally.
-  void MarkGCCard(vixl::aarch64::Register object);
-
-  // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
-  // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
-  // GC is marking for eliminated write barriers.
-  void CheckGCCardIsValid(vixl::aarch64::Register object);
+  // Emit a write barrier.
+  void MarkGCCard(vixl::aarch64::Register object,
+                  vixl::aarch64::Register value,
+                  bool emit_null_check);
 
   void GenerateMemoryBarrier(MemBarrierKind kind);
 
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 544d35c..00c14b0 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -22,7 +22,6 @@
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
 #include "base/bit_utils_iterator.h"
-#include "base/globals.h"
 #include "class_root-inl.h"
 #include "class_table.h"
 #include "code_generator_utils.h"
@@ -5931,15 +5930,16 @@
       && is_wide
       && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
-  bool check_gc_card =
-      codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind);
-
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
   // Temporary registers for the write barrier.
   // TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark.
-  if (needs_write_barrier || check_gc_card) {
-    locations->AddTemp(Location::RequiresRegister());
-    locations->AddTemp(Location::RequiresRegister());
+  if (needs_write_barrier) {
+    if (write_barrier_kind != WriteBarrierKind::kDontEmit) {
+      locations->AddTemp(Location::RequiresRegister());
+      locations->AddTemp(Location::RequiresRegister());
+    } else if (kPoisonHeapReferences) {
+      locations->AddTemp(Location::RequiresRegister());
+    }
   } else if (generate_volatile) {
     // ARM encoding have some additional constraints for ldrexd/strexd:
     // - registers need to be consecutive
@@ -5955,8 +5955,6 @@
       locations->AddTemp(LocationFrom(r2));
       locations->AddTemp(LocationFrom(r3));
     }
-  } else if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
-    locations->AddTemp(Location::RequiresRegister());
   }
 }
 
@@ -5975,7 +5973,7 @@
   DataType::Type field_type = field_info.GetFieldType();
   uint32_t offset = field_info.GetFieldOffset().Uint32Value();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
 
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
@@ -5998,7 +5996,10 @@
 
     case DataType::Type::kReference: {
       vixl32::Register value_reg = RegisterFrom(value);
-      if (kPoisonHeapReferences) {
+      if (kPoisonHeapReferences && needs_write_barrier) {
+        // Note that in the case where `value` is a null reference,
+        // we do not enter this block, as a null reference does not
+        // need poisoning.
         DCHECK_EQ(field_type, DataType::Type::kReference);
         value_reg = RegisterFrom(locations->GetTemp(0));
         __ Mov(value_reg, RegisterFrom(value));
@@ -6068,19 +6069,16 @@
       UNREACHABLE();
   }
 
-  if (needs_write_barrier) {
+  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)) &&
+      write_barrier_kind != WriteBarrierKind::kDontEmit) {
     vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
     vixl32::Register card = RegisterFrom(locations->GetTemp(1));
-    codegen_->MaybeMarkGCCard(
+    codegen_->MarkGCCard(
         temp,
         card,
         base,
         RegisterFrom(value),
-        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
-  } else if (codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind)) {
-    vixl32::Register temp = RegisterFrom(locations->GetTemp(0));
-    vixl32::Register card = RegisterFrom(locations->GetTemp(1));
-    codegen_->CheckGCCardIsValid(temp, card, base);
+        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitWithNullCheck);
   }
 
   if (is_volatile) {
@@ -6833,12 +6831,8 @@
 void LocationsBuilderARMVIXL::VisitArraySet(HArraySet* instruction) {
   DataType::Type value_type = instruction->GetComponentType();
 
-  const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
-  bool check_gc_card =
-      codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind);
-
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
   bool needs_type_check = instruction->NeedsTypeCheck();
 
   LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
@@ -6852,13 +6846,12 @@
   } else {
     locations->SetInAt(2, Location::RequiresRegister());
   }
-  if (needs_write_barrier || check_gc_card || instruction->NeedsTypeCheck()) {
-    // Temporary registers for type checking, write barrier, checking the dirty bit, or register
-    // poisoning.
+  if (needs_write_barrier) {
+    // Temporary registers for the write barrier or register poisoning.
+    // TODO(solanes): We could reduce the temp usage but it requires some non-trivial refactoring of
+    // InstructionCodeGeneratorARMVIXL::VisitArraySet.
     locations->AddTemp(Location::RequiresRegister());
     locations->AddTemp(Location::RequiresRegister());
-  } else if (kPoisonHeapReferences && value_type == DataType::Type::kReference) {
-    locations->AddTemp(Location::RequiresRegister());
   }
 }
 
@@ -6868,9 +6861,8 @@
   Location index = locations->InAt(1);
   DataType::Type value_type = instruction->GetComponentType();
   bool needs_type_check = instruction->NeedsTypeCheck();
-  const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
   uint32_t data_offset =
       mirror::Array::DataOffset(DataType::Size(value_type)).Uint32Value();
   Location value_loc = locations->InAt(2);
@@ -6939,18 +6931,17 @@
           codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index));
         }
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        if (write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn) {
-          // We need to set a write barrier here even though we are writing null, since this write
-          // barrier is being relied on.
-          DCHECK(needs_write_barrier);
-          vixl32::Register temp1 = RegisterFrom(locations->GetTemp(0));
-          vixl32::Register temp2 = RegisterFrom(locations->GetTemp(1));
-          codegen_->MarkGCCard(temp1, temp2, array);
-        }
+        DCHECK(!needs_write_barrier);
         DCHECK(!needs_type_check);
         break;
       }
 
+      DCHECK(needs_write_barrier);
+      Location temp1_loc = locations->GetTemp(0);
+      vixl32::Register temp1 = RegisterFrom(temp1_loc);
+      Location temp2_loc = locations->GetTemp(1);
+      vixl32::Register temp2 = RegisterFrom(temp2_loc);
+
       bool can_value_be_null = instruction->GetValueCanBeNull();
       vixl32::Label do_store;
       if (can_value_be_null) {
@@ -6974,9 +6965,6 @@
         // negative, in which case we would take the ArraySet slow
         // path.
 
-        vixl32::Register temp1 = RegisterFrom(locations->GetTemp(0));
-        vixl32::Register temp2 = RegisterFrom(locations->GetTemp(1));
-
         {
           // Ensure we record the pc position immediately after the `ldr` instruction.
           ExactAssemblyScope aas(GetVIXLAssembler(),
@@ -7014,29 +7002,22 @@
         }
       }
 
+      if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+        DCHECK_EQ(instruction->GetWriteBarrierKind(), WriteBarrierKind::kEmitNoNullCheck)
+            << " Already null checked so we shouldn't do it again.";
+        codegen_->MarkGCCard(temp1, temp2, array, value, /* emit_null_check= */ false);
+      }
+
       if (can_value_be_null) {
         DCHECK(do_store.IsReferenced());
         __ Bind(&do_store);
       }
 
-      if (needs_write_barrier) {
-        // TODO(solanes): The WriteBarrierKind::kEmitNotBeingReliedOn case should be able to skip
-        // this write barrier when its value is null (without an extra CompareAndBranchIfZero since
-        // we already checked if the value is null for the type check). This will be done as a
-        // follow-up since it is a runtime optimization that needs extra care.
-        vixl32::Register temp1 = RegisterFrom(locations->GetTemp(0));
-        vixl32::Register temp2 = RegisterFrom(locations->GetTemp(1));
-        codegen_->MarkGCCard(temp1, temp2, array);
-      } else if (codegen_->ShouldCheckGCCard(
-                     value_type, instruction->GetValue(), write_barrier_kind)) {
-        vixl32::Register temp1 = RegisterFrom(locations->GetTemp(0));
-        vixl32::Register temp2 = RegisterFrom(locations->GetTemp(1));
-        codegen_->CheckGCCardIsValid(temp1, temp2, array);
-      }
-
       vixl32::Register source = value;
       if (kPoisonHeapReferences) {
-        vixl32::Register temp1 = RegisterFrom(locations->GetTemp(0));
+        // Note that in the case where `value` is a null reference,
+        // we do not enter this block, as a null reference does not
+        // need poisoning.
         DCHECK_EQ(value_type, DataType::Type::kReference);
         __ Mov(temp1, value);
         GetAssembler()->PoisonHeapReference(temp1);
@@ -7252,28 +7233,20 @@
   }
 }
 
-void CodeGeneratorARMVIXL::MaybeMarkGCCard(vixl32::Register temp,
-                                           vixl32::Register card,
-                                           vixl32::Register object,
-                                           vixl32::Register value,
-                                           bool emit_null_check) {
+void CodeGeneratorARMVIXL::MarkGCCard(vixl32::Register temp,
+                                      vixl32::Register card,
+                                      vixl32::Register object,
+                                      vixl32::Register value,
+                                      bool emit_null_check) {
   vixl32::Label is_null;
   if (emit_null_check) {
     __ CompareAndBranchIfZero(value, &is_null, /* is_far_target=*/ false);
   }
-  MarkGCCard(temp, card, object);
-  if (emit_null_check) {
-    __ Bind(&is_null);
-  }
-}
-
-void CodeGeneratorARMVIXL::MarkGCCard(vixl32::Register temp,
-                                      vixl32::Register card,
-                                      vixl32::Register object) {
   // Load the address of the card table into `card`.
   GetAssembler()->LoadFromOffset(
       kLoadWord, card, tr, Thread::CardTableOffset<kArmPointerSize>().Int32Value());
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
+  // Calculate the offset (in the card table) of the card corresponding to
+  // `object`.
   __ Lsr(temp, object, Operand::From(gc::accounting::CardTable::kCardShift));
   // Write the `art::gc::accounting::CardTable::kCardDirty` value into the
   // `object`'s card.
@@ -7289,24 +7262,9 @@
   // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ Strb(card, MemOperand(card, temp));
-}
-
-void CodeGeneratorARMVIXL::CheckGCCardIsValid(vixl32::Register temp,
-                                              vixl32::Register card,
-                                              vixl32::Register object) {
-  vixl32::Label done;
-  // Load the address of the card table into `card`.
-  GetAssembler()->LoadFromOffset(
-      kLoadWord, card, tr, Thread::CardTableOffset<kArmPointerSize>().Int32Value());
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
-  __ Lsr(temp, object, Operand::From(gc::accounting::CardTable::kCardShift));
-  // assert (!clean || !self->is_gc_marking)
-  __ Ldrb(temp, MemOperand(card, temp));
-  static_assert(gc::accounting::CardTable::kCardClean == 0);
-  __ CompareAndBranchIfNonZero(temp, &done, /*is_far_target=*/false);
-  __ CompareAndBranchIfZero(mr, &done, /*is_far_target=*/false);
-  __ Bkpt(0);
-  __ Bind(&done);
+  if (emit_null_check) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderARMVIXL::VisitParallelMove([[maybe_unused]] HParallelMove* instruction) {
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index c5b2447..00e0bfa 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -615,26 +615,12 @@
                                            HInstruction* instruction,
                                            SlowPathCode* slow_path);
 
-  // Emit a write barrier if:
-  // A) emit_null_check is false
-  // B) emit_null_check is true, and value is not null.
-  void MaybeMarkGCCard(vixl::aarch32::Register temp,
-                       vixl::aarch32::Register card,
-                       vixl::aarch32::Register object,
-                       vixl::aarch32::Register value,
-                       bool emit_null_check);
-
-  // Emit a write barrier unconditionally.
+  // Emit a write barrier.
   void MarkGCCard(vixl::aarch32::Register temp,
                   vixl::aarch32::Register card,
-                  vixl::aarch32::Register object);
-
-  // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
-  // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
-  // GC is marking for eliminated write barriers.
-  void CheckGCCardIsValid(vixl::aarch32::Register temp,
-                          vixl::aarch32::Register card,
-                          vixl::aarch32::Register object);
+                  vixl::aarch32::Register object,
+                  vixl::aarch32::Register value,
+                  bool emit_null_check);
 
   void GenerateMemoryBarrier(MemBarrierKind kind);
 
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 92eef9f..0c0b8a9 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -2422,21 +2422,16 @@
   }
 }
 
-void CodeGeneratorRISCV64::MaybeMarkGCCard(XRegister object,
-                                           XRegister value,
-                                           bool value_can_be_null) {
+void CodeGeneratorRISCV64::MarkGCCard(XRegister object,
+                                     XRegister value,
+                                     bool value_can_be_null) {
   Riscv64Label done;
-  if (value_can_be_null) {
-    __ Beqz(value, &done);
-  }
-  MarkGCCard(object);
-  __ Bind(&done);
-}
-
-void CodeGeneratorRISCV64::MarkGCCard(XRegister object) {
   ScratchRegisterScope srs(GetAssembler());
   XRegister card = srs.AllocateXRegister();
   XRegister temp = srs.AllocateXRegister();
+  if (value_can_be_null) {
+    __ Beqz(value, &done);
+  }
   // Load the address of the card table into `card`.
   __ Loadd(card, TR, Thread::CardTableOffset<kRiscv64PointerSize>().Int32Value());
 
@@ -2457,27 +2452,9 @@
   // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ Sb(card, temp, 0);  // No scratch register left for `Storeb()`.
-}
-
-void CodeGeneratorRISCV64::CheckGCCardIsValid(XRegister object) {
-  Riscv64Label done;
-  ScratchRegisterScope srs(GetAssembler());
-  XRegister card = srs.AllocateXRegister();
-  XRegister temp = srs.AllocateXRegister();
-  // Load the address of the card table into `card`.
-  __ Loadd(card, TR, Thread::CardTableOffset<kRiscv64PointerSize>().Int32Value());
-
-  // Calculate the address of the card corresponding to `object`.
-  __ Srli(temp, object, gc::accounting::CardTable::kCardShift);
-  __ Add(temp, card, temp);
-  // assert (!clean || !self->is_gc_marking)
-  __ Lb(temp, temp, 0);
-  static_assert(gc::accounting::CardTable::kCardClean == 0);
-  __ Bnez(temp, &done);
-  __ Loadw(temp, TR, Thread::IsGcMarkingOffset<kRiscv64PointerSize>().Int32Value());
-  __ Beqz(temp, &done);
-  __ Unimp();
-  __ Bind(&done);
+  if (value_can_be_null) {
+    __ Bind(&done);
+  }
 }
 
 void LocationsBuilderRISCV64::HandleFieldSet(HInstruction* instruction) {
@@ -2506,15 +2483,12 @@
     codegen_->MaybeRecordImplicitNullCheck(instruction);
   }
 
-  bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(type, instruction->InputAt(1), write_barrier_kind);
-  if (needs_write_barrier) {
-    codegen_->MaybeMarkGCCard(
+  if (CodeGenerator::StoreNeedsWriteBarrier(type, instruction->InputAt(1)) &&
+      write_barrier_kind != WriteBarrierKind::kDontEmit) {
+    codegen_->MarkGCCard(
         obj,
         value.AsRegister<XRegister>(),
-        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
-  } else if (codegen_->ShouldCheckGCCard(type, instruction->InputAt(1), write_barrier_kind)) {
-    codegen_->CheckGCCardIsValid(obj);
+        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitWithNullCheck);
   }
 }
 
@@ -2925,9 +2899,8 @@
   Location value = locations->InAt(2);
   DataType::Type value_type = instruction->GetComponentType();
   bool needs_type_check = instruction->NeedsTypeCheck();
-  const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
   size_t data_offset = mirror::Array::DataOffset(DataType::Size(value_type)).Uint32Value();
   SlowPathCodeRISCV64* slow_path = nullptr;
 
@@ -2988,18 +2961,15 @@
       }
     }
 
+    if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+      DCHECK_EQ(instruction->GetWriteBarrierKind(), WriteBarrierKind::kEmitNoNullCheck)
+          << " Already null checked so we shouldn't do it again.";
+      codegen_->MarkGCCard(array, value.AsRegister<XRegister>(), /* value_can_be_null= */ false);
+    }
+
     if (can_value_be_null) {
       __ Bind(&do_store);
     }
-
-    DCHECK_NE(instruction->GetWriteBarrierKind(), WriteBarrierKind::kDontEmit);
-    // TODO(solanes): The WriteBarrierKind::kEmitNotBeingReliedOn case should be able to skip
-    // this write barrier when its value is null (without an extra Beqz since we already checked
-    // if the value is null for the type check). This will be done as a follow-up since it is a
-    // runtime optimization that needs extra care.
-    codegen_->MarkGCCard(array);
-  } else if (codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind)) {
-    codegen_->CheckGCCardIsValid(array);
   }
 
   if (index.IsConstant()) {
diff --git a/compiler/optimizing/code_generator_riscv64.h b/compiler/optimizing/code_generator_riscv64.h
index ba43090..321403f 100644
--- a/compiler/optimizing/code_generator_riscv64.h
+++ b/compiler/optimizing/code_generator_riscv64.h
@@ -750,18 +750,7 @@
   // artReadBarrierForRootSlow.
   void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
 
-  // Emit a write barrier if:
-  // A) emit_null_check is false
-  // B) emit_null_check is true, and value is not null.
-  void MaybeMarkGCCard(XRegister object, XRegister value, bool emit_null_check);
-
-  // Emit a write barrier unconditionally.
-  void MarkGCCard(XRegister object);
-
-  // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
-  // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
-  // GC is marking for eliminated write barriers.
-  void CheckGCCardIsValid(XRegister object);
+  void MarkGCCard(XRegister object, XRegister value, bool value_can_be_null);
 
   //
   // Heap poisoning.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 058ecf7..71db5c9 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -44,7 +44,6 @@
 #include "utils/assembler.h"
 #include "utils/stack_checks.h"
 #include "utils/x86/assembler_x86.h"
-#include "utils/x86/constants_x86.h"
 #include "utils/x86/managed_register_x86.h"
 
 namespace art HIDDEN {
@@ -5873,23 +5872,17 @@
   DCHECK_EQ(size, linker_patches->size());
 }
 
-void CodeGeneratorX86::MaybeMarkGCCard(
+void CodeGeneratorX86::MarkGCCard(
     Register temp, Register card, Register object, Register value, bool emit_null_check) {
   NearLabel is_null;
   if (emit_null_check) {
     __ testl(value, value);
     __ j(kEqual, &is_null);
   }
-  MarkGCCard(temp, card, object);
-  if (emit_null_check) {
-    __ Bind(&is_null);
-  }
-}
-
-void CodeGeneratorX86::MarkGCCard(Register temp, Register card, Register object) {
   // Load the address of the card table into `card`.
   __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86PointerSize>().Int32Value()));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
+  // Calculate the offset (in the card table) of the card corresponding to
+  // `object`.
   __ movl(temp, object);
   __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
   // Write the `art::gc::accounting::CardTable::kCardDirty` value into the
@@ -5907,23 +5900,9 @@
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ movb(Address(temp, card, TIMES_1, 0),
           X86ManagedRegister::FromCpuRegister(card).AsByteRegister());
-}
-
-void CodeGeneratorX86::CheckGCCardIsValid(Register temp, Register card, Register object) {
-  NearLabel done;
-  __ j(kEqual, &done);
-  // Load the address of the card table into `card`.
-  __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86PointerSize>().Int32Value()));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
-  __ movl(temp, object);
-  __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
-  // assert (!clean || !self->is_gc_marking)
-  __ cmpb(Address(temp, card, TIMES_1, 0), Immediate(gc::accounting::CardTable::kCardClean));
-  __ j(kNotEqual, &done);
-  __ fs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86PointerSize>()), Immediate(0));
-  __ j(kEqual, &done);
-  __ int3();
-  __ Bind(&done);
+  if (emit_null_check) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) {
@@ -6049,17 +6028,14 @@
   } else {
     locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
 
-    bool needs_write_barrier =
-        codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
-    bool check_gc_card =
-        codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind);
-
-    if (needs_write_barrier || check_gc_card) {
-      locations->AddTemp(Location::RequiresRegister());
-      // Ensure the card is in a byte register.
-      locations->AddTemp(Location::RegisterLocation(ECX));
-    } else if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
-      locations->AddTemp(Location::RequiresRegister());
+    if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
+      if (write_barrier_kind != WriteBarrierKind::kDontEmit) {
+        locations->AddTemp(Location::RequiresRegister());
+        // Ensure the card is in a byte register.
+        locations->AddTemp(Location::RegisterLocation(ECX));
+      } else if (kPoisonHeapReferences) {
+        locations->AddTemp(Location::RequiresRegister());
+      }
     }
   }
 }
@@ -6075,7 +6051,7 @@
   LocationSummary* locations = instruction->GetLocations();
   Location value = locations->InAt(value_index);
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(value_index));
 
   if (is_volatile) {
     codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
@@ -6107,19 +6083,15 @@
 
     case DataType::Type::kInt32:
     case DataType::Type::kReference: {
-      if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
-        if (value.IsConstant()) {
-          DCHECK(value.GetConstant()->IsNullConstant())
-              << "constant value " << CodeGenerator::GetInt32ValueOf(value.GetConstant())
-              << " is not null. Instruction " << *instruction;
-          // No need to poison null, just do a movl.
-          __ movl(field_addr, Immediate(0));
-        } else {
-          Register temp = locations->GetTemp(0).AsRegister<Register>();
-          __ movl(temp, value.AsRegister<Register>());
-          __ PoisonHeapReference(temp);
-          __ movl(field_addr, temp);
-        }
+      if (kPoisonHeapReferences && needs_write_barrier) {
+        // Note that in the case where `value` is a null reference,
+        // we do not enter this block, as the reference does not
+        // need poisoning.
+        DCHECK_EQ(field_type, DataType::Type::kReference);
+        Register temp = locations->GetTemp(0).AsRegister<Register>();
+        __ movl(temp, value.AsRegister<Register>());
+        __ PoisonHeapReference(temp);
+        __ movl(field_addr, temp);
       } else if (value.IsConstant()) {
         int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
         __ movl(field_addr, Immediate(v));
@@ -6188,38 +6160,15 @@
     codegen_->MaybeRecordImplicitNullCheck(instruction);
   }
 
-  if (needs_write_barrier) {
+  if (needs_write_barrier && write_barrier_kind != WriteBarrierKind::kDontEmit) {
     Register temp = locations->GetTemp(0).AsRegister<Register>();
     Register card = locations->GetTemp(1).AsRegister<Register>();
-    if (value.IsConstant()) {
-      DCHECK(value.GetConstant()->IsNullConstant())
-          << "constant value " << CodeGenerator::GetInt32ValueOf(value.GetConstant())
-          << " is not null. Instruction: " << *instruction;
-      if (write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn) {
-        codegen_->MarkGCCard(temp, card, base);
-      }
-    } else {
-      codegen_->MaybeMarkGCCard(
-          temp,
-          card,
-          base,
-          value.AsRegister<Register>(),
-          value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
-    }
-  } else if (codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind)) {
-    if (value.IsConstant()) {
-      // If we are storing a constant for a reference, we are in the case where we are storing
-      // null but we cannot skip it as this write barrier is being relied on by coalesced write
-      // barriers.
-      DCHECK(value.GetConstant()->IsNullConstant())
-          << "constant value " << CodeGenerator::GetInt32ValueOf(value.GetConstant())
-          << " is not null. Instruction: " << *instruction;
-      // No need to check the dirty bit as this value is null.
-    } else {
-      Register temp = locations->GetTemp(0).AsRegister<Register>();
-      Register card = locations->GetTemp(1).AsRegister<Register>();
-      codegen_->CheckGCCardIsValid(temp, card, base);
-    }
+    codegen_->MarkGCCard(
+        temp,
+        card,
+        base,
+        value.AsRegister<Register>(),
+        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitWithNullCheck);
   }
 
   if (is_volatile) {
@@ -6500,11 +6449,8 @@
 void LocationsBuilderX86::VisitArraySet(HArraySet* instruction) {
   DataType::Type value_type = instruction->GetComponentType();
 
-  WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
-  bool check_gc_card =
-      codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
   bool needs_type_check = instruction->NeedsTypeCheck();
 
   LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
@@ -6525,14 +6471,13 @@
   } else {
     locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2)));
   }
-  if (needs_write_barrier || check_gc_card) {
-    // Used by reference poisoning, type checking, emitting, or checking a write barrier.
+  if (needs_write_barrier) {
+    // Used by reference poisoning or emitting write barrier.
     locations->AddTemp(Location::RequiresRegister());
-    // Only used when emitting or checking a write barrier. Ensure the card is in a byte register.
-    locations->AddTemp(Location::RegisterLocation(ECX));
-  } else if ((kPoisonHeapReferences && value_type == DataType::Type::kReference) ||
-             instruction->NeedsTypeCheck()) {
-    locations->AddTemp(Location::RequiresRegister());
+    if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+      // Only used when emitting a write barrier. Ensure the card is in a byte register.
+      locations->AddTemp(Location::RegisterLocation(ECX));
+    }
   }
 }
 
@@ -6544,9 +6489,8 @@
   Location value = locations->InAt(2);
   DataType::Type value_type = instruction->GetComponentType();
   bool needs_type_check = instruction->NeedsTypeCheck();
-  WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
 
   switch (value_type) {
     case DataType::Type::kBool:
@@ -6586,19 +6530,16 @@
         DCHECK(value.IsConstant()) << value;
         __ movl(address, Immediate(0));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        if (write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn) {
-          // We need to set a write barrier here even though we are writing null, since this write
-          // barrier is being relied on.
-          DCHECK(needs_write_barrier);
-          Register temp = locations->GetTemp(0).AsRegister<Register>();
-          Register card = locations->GetTemp(1).AsRegister<Register>();
-          codegen_->MarkGCCard(temp, card, array);
-        }
+        DCHECK(!needs_write_barrier);
         DCHECK(!needs_type_check);
         break;
       }
 
+      DCHECK(needs_write_barrier);
       Register register_value = value.AsRegister<Register>();
+      Location temp_loc = locations->GetTemp(0);
+      Register temp = temp_loc.AsRegister<Register>();
+
       bool can_value_be_null = instruction->GetValueCanBeNull();
       NearLabel do_store;
       if (can_value_be_null) {
@@ -6623,7 +6564,6 @@
         // false negative, in which case we would take the ArraySet
         // slow path.
 
-        Register temp = locations->GetTemp(0).AsRegister<Register>();
         // /* HeapReference<Class> */ temp = array->klass_
         __ movl(temp, Address(array, class_offset));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
@@ -6654,29 +6594,24 @@
         }
       }
 
+      if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+        DCHECK_EQ(instruction->GetWriteBarrierKind(), WriteBarrierKind::kEmitNoNullCheck)
+            << " Already null checked so we shouldn't do it again.";
+        Register card = locations->GetTemp(1).AsRegister<Register>();
+        codegen_->MarkGCCard(temp,
+                             card,
+                             array,
+                             value.AsRegister<Register>(),
+                             /* emit_null_check= */ false);
+      }
+
       if (can_value_be_null) {
         DCHECK(do_store.IsLinked());
         __ Bind(&do_store);
       }
 
-      if (needs_write_barrier) {
-        // TODO(solanes): The WriteBarrierKind::kEmitNotBeingReliedOn case should be able to skip
-        // this write barrier when its value is null (without an extra testl since we already
-        // checked if the value is null for the type check). This will be done as a follow-up since
-        // it is a runtime optimization that needs extra care.
-        Register temp = locations->GetTemp(0).AsRegister<Register>();
-        Register card = locations->GetTemp(1).AsRegister<Register>();
-        codegen_->MarkGCCard(temp, card, array);
-      } else if (codegen_->ShouldCheckGCCard(
-                     value_type, instruction->GetValue(), write_barrier_kind)) {
-        Register temp = locations->GetTemp(0).AsRegister<Register>();
-        Register card = locations->GetTemp(1).AsRegister<Register>();
-        codegen_->CheckGCCardIsValid(temp, card, array);
-      }
-
       Register source = register_value;
       if (kPoisonHeapReferences) {
-        Register temp = locations->GetTemp(0).AsRegister<Register>();
         __ movl(temp, register_value);
         __ PoisonHeapReference(temp);
         source = temp;
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 8a47181..5b59bfc 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -567,20 +567,10 @@
                        uint64_t index_in_table) const;
   void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) override;
 
-  // Emit a write barrier if:
-  // A) emit_null_check is false
-  // B) emit_null_check is true, and value is not null.
-  void MaybeMarkGCCard(
+  // Emit a write barrier.
+  void MarkGCCard(
       Register temp, Register card, Register object, Register value, bool emit_null_check);
 
-  // Emit a write barrier unconditionally.
-  void MarkGCCard(Register temp, Register card, Register object);
-
-  // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
-  // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
-  // GC is marking for eliminated write barriers.
-  void CheckGCCardIsValid(Register temp, Register card, Register object);
-
   void GenerateMemoryBarrier(MemBarrierKind kind);
 
   Label* GetLabelOf(HBasicBlock* block) const {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 705c14c..9d01019 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -5307,8 +5307,7 @@
 }
 
 void LocationsBuilderX86_64::HandleFieldSet(HInstruction* instruction,
-                                            const FieldInfo& field_info,
-                                            WriteBarrierKind write_barrier_kind) {
+                                            const FieldInfo& field_info) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
 
   LocationSummary* locations =
@@ -5316,9 +5315,7 @@
   DataType::Type field_type = field_info.GetFieldType();
   bool is_volatile = field_info.IsVolatile();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
-  bool check_gc_card =
-      codegen_->ShouldCheckGCCard(field_type, instruction->InputAt(1), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
 
   locations->SetInAt(0, Location::RequiresRegister());
   if (DataType::IsFloatingPointType(instruction->InputAt(1)->GetType())) {
@@ -5338,13 +5335,14 @@
   }
 
   // TODO(solanes): We could reduce the temp usage but it requires some non-trivial refactoring of
-  // InstructionCodeGeneratorX86_64::HandleFieldSet, GenerateVarHandleSet due to `extra_temp_index`.
-  if (needs_write_barrier ||
-      check_gc_card ||
-      (kPoisonHeapReferences && field_type == DataType::Type::kReference)) {
+  // InstructionCodeGeneratorX86_64::HandleFieldSet.
+  if (needs_write_barrier) {
     // Temporary registers for the write barrier.
     locations->AddTemp(Location::RequiresRegister());
     locations->AddTemp(Location::RequiresRegister());  // Possibly used for reference poisoning too.
+  } else if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
+    // Temporary register for the reference poisoning.
+    locations->AddTemp(Location::RequiresRegister());
   }
 }
 
@@ -5518,35 +5516,16 @@
     codegen_->MaybeRecordImplicitNullCheck(instruction);
   }
 
-  bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(field_type, instruction->InputAt(1), write_barrier_kind);
-  if (needs_write_barrier) {
-    if (value.IsConstant()) {
-      DCHECK(value.GetConstant()->IsNullConstant());
-      if (write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn) {
-        DCHECK_NE(extra_temp_index, 0u);
-        CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-        CpuRegister card = locations->GetTemp(extra_temp_index).AsRegister<CpuRegister>();
-        codegen_->MarkGCCard(temp, card, base);
-      }
-    } else {
-      DCHECK_NE(extra_temp_index, 0u);
-      CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-      CpuRegister card = locations->GetTemp(extra_temp_index).AsRegister<CpuRegister>();
-      codegen_->MaybeMarkGCCard(
-          temp,
-          card,
-          base,
-          value.AsRegister<CpuRegister>(),
-          value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
-    }
-  } else if (codegen_->ShouldCheckGCCard(
-                 field_type, instruction->InputAt(value_index), write_barrier_kind)) {
-    DCHECK_NE(extra_temp_index, 0u);
-    DCHECK(value.IsRegister());
+  if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(value_index)) &&
+      write_barrier_kind != WriteBarrierKind::kDontEmit) {
     CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
     CpuRegister card = locations->GetTemp(extra_temp_index).AsRegister<CpuRegister>();
-    codegen_->CheckGCCardIsValid(temp, card, base);
+    codegen_->MarkGCCard(
+        temp,
+        card,
+        base,
+        value.AsRegister<CpuRegister>(),
+        value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitWithNullCheck);
   }
 
   if (is_volatile) {
@@ -5580,7 +5559,7 @@
 }
 
 void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetWriteBarrierKind());
+  HandleFieldSet(instruction, instruction->GetFieldInfo());
 }
 
 void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
@@ -5607,7 +5586,7 @@
 }
 
 void LocationsBuilderX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetWriteBarrierKind());
+  HandleFieldSet(instruction, instruction->GetFieldInfo());
 }
 
 void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
@@ -5828,11 +5807,8 @@
 void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) {
   DataType::Type value_type = instruction->GetComponentType();
 
-  WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
-  bool check_gc_card =
-      codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
   bool needs_type_check = instruction->NeedsTypeCheck();
 
   LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
@@ -5847,16 +5823,13 @@
     locations->SetInAt(2, Location::RegisterOrConstant(instruction->InputAt(2)));
   }
 
-  if (needs_write_barrier || check_gc_card) {
-    // Used by reference poisoning, type checking, emitting write barrier, or checking write
-    // barrier.
+  if (needs_write_barrier) {
+    // Used by reference poisoning or emitting write barrier.
     locations->AddTemp(Location::RequiresRegister());
-    // Only used when emitting a write barrier, or when checking for the card table.
-    locations->AddTemp(Location::RequiresRegister());
-  } else if ((kPoisonHeapReferences && value_type == DataType::Type::kReference) ||
-             instruction->NeedsTypeCheck()) {
-    // Used for poisoning or type checking.
-    locations->AddTemp(Location::RequiresRegister());
+    if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+      // Only used when emitting a write barrier.
+      locations->AddTemp(Location::RequiresRegister());
+    }
   }
 }
 
@@ -5868,9 +5841,8 @@
   Location value = locations->InAt(2);
   DataType::Type value_type = instruction->GetComponentType();
   bool needs_type_check = instruction->NeedsTypeCheck();
-  const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
   bool needs_write_barrier =
-      codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
+      CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
 
   switch (value_type) {
     case DataType::Type::kBool:
@@ -5911,19 +5883,16 @@
         DCHECK(value.IsConstant()) << value;
         __ movl(address, Immediate(0));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
-        if (write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn) {
-          // We need to set a write barrier here even though we are writing null, since this write
-          // barrier is being relied on.
-          DCHECK(needs_write_barrier);
-          CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-          CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
-          codegen_->MarkGCCard(temp, card, array);
-        }
+        DCHECK(!needs_write_barrier);
         DCHECK(!needs_type_check);
         break;
       }
 
+      DCHECK(needs_write_barrier);
       CpuRegister register_value = value.AsRegister<CpuRegister>();
+      Location temp_loc = locations->GetTemp(0);
+      CpuRegister temp = temp_loc.AsRegister<CpuRegister>();
+
       bool can_value_be_null = instruction->GetValueCanBeNull();
       NearLabel do_store;
       if (can_value_be_null) {
@@ -5948,7 +5917,6 @@
         // false negative, in which case we would take the ArraySet
         // slow path.
 
-        CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
         // /* HeapReference<Class> */ temp = array->klass_
         __ movl(temp, Address(array, class_offset));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
@@ -5979,30 +5947,24 @@
         }
       }
 
+      if (instruction->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit) {
+        DCHECK_EQ(instruction->GetWriteBarrierKind(), WriteBarrierKind::kEmitNoNullCheck)
+            << " Already null checked so we shouldn't do it again.";
+        CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
+        codegen_->MarkGCCard(temp,
+                             card,
+                             array,
+                             value.AsRegister<CpuRegister>(),
+                             /* emit_null_check= */ false);
+      }
+
       if (can_value_be_null) {
         DCHECK(do_store.IsLinked());
         __ Bind(&do_store);
       }
 
-      if (needs_write_barrier) {
-        // TODO(solanes): The WriteBarrierKind::kEmitNotBeingReliedOn case should be able to skip
-        // this write barrier when its value is null (without an extra testl since we already
-        // checked if the value is null for the type check). This will be done as a follow-up since
-        // it is a runtime optimization that needs extra care.
-        CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-        CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
-        codegen_->MarkGCCard(temp, card, array);
-      } else if (codegen_->ShouldCheckGCCard(
-                     value_type, instruction->GetValue(), write_barrier_kind)) {
-        CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
-        CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
-        codegen_->CheckGCCardIsValid(temp, card, array);
-      }
-
       Location source = value;
       if (kPoisonHeapReferences) {
-        Location temp_loc = locations->GetTemp(0);
-        CpuRegister temp = temp_loc.AsRegister<CpuRegister>();
         __ movl(temp, register_value);
         __ PoisonHeapReference(temp);
         source = temp_loc;
@@ -6188,28 +6150,21 @@
   }
 }
 
-void CodeGeneratorX86_64::MaybeMarkGCCard(CpuRegister temp,
-                                          CpuRegister card,
-                                          CpuRegister object,
-                                          CpuRegister value,
-                                          bool emit_null_check) {
+void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp,
+                                     CpuRegister card,
+                                     CpuRegister object,
+                                     CpuRegister value,
+                                     bool emit_null_check) {
   NearLabel is_null;
   if (emit_null_check) {
     __ testl(value, value);
     __ j(kEqual, &is_null);
   }
-  MarkGCCard(temp, card, object);
-  if (emit_null_check) {
-    __ Bind(&is_null);
-  }
-}
-
-void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object) {
   // Load the address of the card table into `card`.
-  __ gs()->movq(card,
-                Address::Absolute(Thread::CardTableOffset<kX86_64PointerSize>().Int32Value(),
-                                  /* no_rip= */ true));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
+  __ gs()->movq(card, Address::Absolute(Thread::CardTableOffset<kX86_64PointerSize>().Int32Value(),
+                                        /* no_rip= */ true));
+  // Calculate the offset (in the card table) of the card corresponding to
+  // `object`.
   __ movq(temp, object);
   __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
   // Write the `art::gc::accounting::CardTable::kCardDirty` value into the
@@ -6226,27 +6181,9 @@
   // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
   // (no need to explicitly load `kCardDirty` as an immediate value).
   __ movb(Address(temp, card, TIMES_1, 0), card);
-}
-
-void CodeGeneratorX86_64::CheckGCCardIsValid(CpuRegister temp,
-                                             CpuRegister card,
-                                             CpuRegister object) {
-  NearLabel done;
-  // Load the address of the card table into `card`.
-  __ gs()->movq(card,
-                Address::Absolute(Thread::CardTableOffset<kX86_64PointerSize>().Int32Value(),
-                                  /* no_rip= */ true));
-  // Calculate the offset (in the card table) of the card corresponding to `object`.
-  __ movq(temp, object);
-  __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
-  // assert (!clean || !self->is_gc_marking)
-  __ cmpb(Address(temp, card, TIMES_1, 0), Immediate(gc::accounting::CardTable::kCardClean));
-  __ j(kNotEqual, &done);
-  __ gs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86_64PointerSize>(), true),
-                Immediate(0));
-  __ j(kEqual, &done);
-  __ int3();
-  __ Bind(&done);
+  if (emit_null_check) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderX86_64::VisitParallelMove([[maybe_unused]] HParallelMove* instruction) {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index b9467f9..e4d3eac 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -237,9 +237,7 @@
   void HandleBitwiseOperation(HBinaryOperation* operation);
   void HandleCondition(HCondition* condition);
   void HandleShift(HBinaryOperation* operation);
-  void HandleFieldSet(HInstruction* instruction,
-                      const FieldInfo& field_info,
-                      WriteBarrierKind write_barrier_kind);
+  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
   void HandleFieldGet(HInstruction* instruction);
   bool CpuHasAvxFeatureFlag();
   bool CpuHasAvx2FeatureFlag();
@@ -471,22 +469,12 @@
 
   const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const;
 
-  // Emit a write barrier if:
-  // A) emit_null_check is false
-  // B) emit_null_check is true, and value is not null.
-  void MaybeMarkGCCard(CpuRegister temp,
-                       CpuRegister card,
-                       CpuRegister object,
-                       CpuRegister value,
-                       bool emit_null_check);
-
-  // Emit a write barrier unconditionally.
-  void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object);
-
-  // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
-  // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
-  // GC is marking for eliminated write barriers.
-  void CheckGCCardIsValid(CpuRegister temp, CpuRegister card, CpuRegister object);
+  // Emit a write barrier.
+  void MarkGCCard(CpuRegister temp,
+                  CpuRegister card,
+                  CpuRegister object,
+                  CpuRegister value,
+                  bool emit_null_check);
 
   void GenerateMemoryBarrier(MemBarrierKind kind);
 
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index d60ec06..d4b0bf2 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -31,7 +31,6 @@
 #include "mirror/class.h"
 #include "nodes.h"
 #include "obj_ptr-inl.h"
-#include "optimizing/data_type.h"
 #include "scoped_thread_state_change-inl.h"
 #include "subtype_check.h"
 
@@ -1274,26 +1273,6 @@
   }
 }
 
-HInstruction* HuntForOriginalReference(HInstruction* ref) {
-  // An original reference can be transformed by instructions like:
-  //   i0 NewArray
-  //   i1 HInstruction(i0)  <-- NullCheck, BoundType, IntermediateAddress.
-  //   i2 ArraySet(i1, index, value)
-  DCHECK(ref != nullptr);
-  while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
-    ref = ref->InputAt(0);
-  }
-  return ref;
-}
-
-bool IsRemovedWriteBarrier(DataType::Type type,
-                           WriteBarrierKind write_barrier_kind,
-                           HInstruction* value) {
-  return write_barrier_kind == WriteBarrierKind::kDontEmit &&
-         type == DataType::Type::kReference &&
-         !value->IsNullConstant();
-}
-
 void GraphChecker::VisitArraySet(HArraySet* instruction) {
   VisitInstruction(instruction);
 
@@ -1307,80 +1286,6 @@
                      StrBool(instruction->NeedsTypeCheck()),
                      StrBool(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()))));
   }
-
-  if (IsRemovedWriteBarrier(instruction->GetComponentType(),
-                            instruction->GetWriteBarrierKind(),
-                            instruction->GetValue())) {
-    CheckWriteBarrier(instruction, [](HInstruction* it_instr) {
-      return it_instr->AsArraySet()->GetWriteBarrierKind();
-    });
-  }
-}
-
-void GraphChecker::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  VisitInstruction(instruction);
-  if (IsRemovedWriteBarrier(instruction->GetFieldType(),
-                            instruction->GetWriteBarrierKind(),
-                            instruction->GetValue())) {
-    CheckWriteBarrier(instruction, [](HInstruction* it_instr) {
-      return it_instr->AsInstanceFieldSet()->GetWriteBarrierKind();
-    });
-  }
-}
-
-void GraphChecker::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  VisitInstruction(instruction);
-  if (IsRemovedWriteBarrier(instruction->GetFieldType(),
-                            instruction->GetWriteBarrierKind(),
-                            instruction->GetValue())) {
-    CheckWriteBarrier(instruction, [](HInstruction* it_instr) {
-      return it_instr->AsStaticFieldSet()->GetWriteBarrierKind();
-    });
-  }
-}
-
-template <typename GetWriteBarrierKind>
-void GraphChecker::CheckWriteBarrier(HInstruction* instruction,
-                                     GetWriteBarrierKind&& get_write_barrier_kind) {
-  DCHECK(instruction->IsStaticFieldSet() ||
-         instruction->IsInstanceFieldSet() ||
-         instruction->IsArraySet());
-
-  // For removed write barriers, we expect that the write barrier they are relying on is:
-  // A) In the same block, and
-  // B) There's no instruction between them that can trigger a GC.
-  HInstruction* object = HuntForOriginalReference(instruction->InputAt(0));
-  bool found = false;
-  for (HBackwardInstructionIterator it(instruction); !it.Done(); it.Advance()) {
-    if (instruction->GetKind() == it.Current()->GetKind() &&
-        object == HuntForOriginalReference(it.Current()->InputAt(0)) &&
-        get_write_barrier_kind(it.Current()) == WriteBarrierKind::kEmitBeingReliedOn) {
-      // Found the write barrier we are relying on.
-      found = true;
-      break;
-    }
-
-    // We check the `SideEffects::CanTriggerGC` after failing to find the write barrier since having
-    // a write barrier that's relying on an ArraySet that can trigger GC is fine because the card
-    // table is marked after the GC happens.
-    if (it.Current()->GetSideEffects().Includes(SideEffects::CanTriggerGC())) {
-      AddError(
-          StringPrintf("%s %d from block %d was expecting a write barrier and it didn't find "
-                       "any. %s %d can trigger GC",
-                       instruction->DebugName(),
-                       instruction->GetId(),
-                       instruction->GetBlock()->GetBlockId(),
-                       it.Current()->DebugName(),
-                       it.Current()->GetId()));
-    }
-  }
-
-  if (!found) {
-    AddError(StringPrintf("%s %d in block %d didn't find a write barrier to latch onto",
-                          instruction->DebugName(),
-                          instruction->GetId(),
-                          instruction->GetBlock()->GetBlockId()));
-  }
 }
 
 void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) {
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 5704bce..38e2d7c 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -59,8 +59,6 @@
   void VisitPhi(HPhi* phi) override;
 
   void VisitArraySet(HArraySet* instruction) override;
-  void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override;
-  void VisitStaticFieldSet(HStaticFieldSet* instruction) override;
   void VisitBinaryOperation(HBinaryOperation* op) override;
   void VisitBooleanNot(HBooleanNot* instruction) override;
   void VisitBoundType(HBoundType* instruction) override;
@@ -95,9 +93,6 @@
   void HandleLoop(HBasicBlock* loop_header);
   void HandleBooleanInput(HInstruction* instruction, size_t input_index);
 
-  template <typename GetWriteBarrierKind>
-  void CheckWriteBarrier(HInstruction* instruction, GetWriteBarrierKind&& get_write_barrier_kind);
-
   // Was the last visit of the graph valid?
   bool IsValid() const {
     return errors_.empty();
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 2ae44cd..98e5261 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -986,7 +986,7 @@
 
   if (type == DataType::Type::kReference) {
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(base, value, value_can_be_null);
+    codegen->MarkGCCard(base, value, value_can_be_null);
   }
 }
 
@@ -1457,7 +1457,7 @@
   if (type == DataType::Type::kReference) {
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(base, new_value, new_value_can_be_null);
+    codegen->MarkGCCard(base, new_value, new_value_can_be_null);
   }
 
   UseScratchRegisterScope temps(masm);
@@ -1733,7 +1733,7 @@
     DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
     // Mark card for object as a new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(base, /*value=*/arg, new_value_can_be_null);
+    codegen->MarkGCCard(base, /*value=*/ arg, new_value_can_be_null);
   }
 
   __ Add(tmp_ptr, base.X(), Operand(offset));
@@ -3394,7 +3394,7 @@
     }
 
     // We only need one card marking on the destination array.
-    codegen_->MarkGCCard(dest.W());
+    codegen_->MarkGCCard(dest.W(), Register(), /* emit_null_check= */ false);
 
     __ Bind(&skip_copy_and_write_barrier);
   }
@@ -4977,7 +4977,7 @@
   }
 
   if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(value_index))) {
-    codegen->MaybeMarkGCCard(target.object, Register(value), /* emit_null_check= */ true);
+    codegen->MarkGCCard(target.object, Register(value), /* emit_null_check= */ true);
   }
 
   if (slow_path != nullptr) {
@@ -5141,7 +5141,7 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(new_value_index))) {
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(target.object, new_value.W(), new_value_can_be_null);
+    codegen->MarkGCCard(target.object, new_value.W(), new_value_can_be_null);
   }
 
   // Reuse the `offset` temporary for the pointer to the target location,
@@ -5445,7 +5445,7 @@
     DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
     // Mark card for object, the new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(target.object, arg.W(), new_value_can_be_null);
+    codegen->MarkGCCard(target.object, arg.W(), new_value_can_be_null);
   }
 
   // Reuse the `target.offset` temporary for the pointer to the target location,
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index c763721..0e2d1fd 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -1592,7 +1592,7 @@
     }
 
     // We only need one card marking on the destination array.
-    codegen_->MarkGCCard(temp1, temp2, dest);
+    codegen_->MarkGCCard(temp1, temp2, dest, NoReg, /* emit_null_check= */ false);
 
     __ Bind(&skip_copy_and_write_barrier);
   }
@@ -3020,7 +3020,7 @@
     UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
     vixl32::Register card = temps.Acquire();
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(temp, card, base, RegisterFrom(value), value_can_be_null);
+    codegen->MarkGCCard(temp, card, base, RegisterFrom(value), value_can_be_null);
   }
 }
 
@@ -3612,7 +3612,7 @@
     // Mark card for object assuming new value is stored. Worst case we will mark an unchanged
     // object and scan the receiver at the next GC for nothing.
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(tmp_ptr, tmp, base, new_value, value_can_be_null);
+    codegen->MarkGCCard(tmp_ptr, tmp, base, new_value, value_can_be_null);
   }
 
   vixl32::Label exit_loop_label;
@@ -3923,7 +3923,7 @@
     // Mark card for object as a new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
     vixl32::Register card = tmp_ptr;  // Use the `tmp_ptr` also as the `card` temporary.
-    codegen->MaybeMarkGCCard(temp, card, base, /*value=*/ RegisterFrom(arg), new_value_can_be_null);
+    codegen->MarkGCCard(temp, card, base, /*value=*/ RegisterFrom(arg), new_value_can_be_null);
   }
 
   // Note: UnsafeGetAndUpdate operations are sequentially consistent, requiring
@@ -4779,7 +4779,7 @@
     vixl32::Register temp = target.offset;
     vixl32::Register card = temps.Acquire();
     vixl32::Register value_reg = RegisterFrom(value);
-    codegen->MaybeMarkGCCard(temp, card, target.object, value_reg, /* emit_null_check= */ true);
+    codegen->MarkGCCard(temp, card, target.object, value_reg, /* emit_null_check= */ true);
   }
 
   if (slow_path != nullptr) {
@@ -5079,8 +5079,7 @@
     vixl32::Register card = tmp_ptr;
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(
-        temp, card, target.object, RegisterFrom(new_value), new_value_can_be_null);
+    codegen->MarkGCCard(temp, card, target.object, RegisterFrom(new_value), new_value_can_be_null);
   }
 
   if (slow_path != nullptr) {
@@ -5398,7 +5397,7 @@
     vixl32::Register card = tmp_ptr;
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(temp, card, target.object, RegisterFrom(arg), new_value_can_be_null);
+    codegen->MarkGCCard(temp, card, target.object, RegisterFrom(arg), new_value_can_be_null);
   }
 
   if (slow_path != nullptr) {
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc
index 698c7e5..a43ab2f 100644
--- a/compiler/optimizing/intrinsics_riscv64.cc
+++ b/compiler/optimizing/intrinsics_riscv64.cc
@@ -1771,7 +1771,7 @@
     }
 
     // We only need one card marking on the destination array.
-    codegen_->MarkGCCard(dest);
+    codegen_->MarkGCCard(dest, XRegister(kNoXRegister), /* emit_null_check= */ false);
 
     __ Bind(&skip_copy_and_write_barrier);
   }
@@ -2127,7 +2127,7 @@
 
   if (type == DataType::Type::kReference) {
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(base, value.AsRegister<XRegister>(), value_can_be_null);
+    codegen->MarkGCCard(base, value.AsRegister<XRegister>(), value_can_be_null);
   }
 }
 
@@ -2348,7 +2348,7 @@
   if (type == DataType::Type::kReference) {
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(object, new_value, new_value_can_be_null);
+    codegen->MarkGCCard(object, new_value, new_value_can_be_null);
   }
 
   ScratchRegisterScope srs(assembler);
@@ -2547,7 +2547,7 @@
     DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
     // Mark card for object as a new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(base, /*value=*/arg, new_value_can_be_null);
+    codegen->MarkGCCard(base, /*value=*/ arg, new_value_can_be_null);
   }
 
   ScratchRegisterScope srs(assembler);
@@ -3332,8 +3332,7 @@
   }
 
   if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(value_index))) {
-    codegen->MaybeMarkGCCard(
-        target.object, value.AsRegister<XRegister>(), /* emit_null_check= */ true);
+    codegen->MarkGCCard(target.object, value.AsRegister<XRegister>(), /* emit_null_check= */ true);
   }
 
   if (slow_path != nullptr) {
@@ -3555,8 +3554,7 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(value_type, invoke->InputAt(new_value_index))) {
     // Mark card for object assuming new value is stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(
-        target.object, new_value.AsRegister<XRegister>(), new_value_can_be_null);
+    codegen->MarkGCCard(target.object, new_value.AsRegister<XRegister>(), new_value_can_be_null);
   }
 
   // Scratch registers may be needed for `new_value` and `expected`.
@@ -3921,7 +3919,7 @@
     DCHECK(get_and_update_op == GetAndUpdateOp::kSet);
     // Mark card for object, the new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(target.object, arg.AsRegister<XRegister>(), new_value_can_be_null);
+    codegen->MarkGCCard(target.object, arg.AsRegister<XRegister>(), new_value_can_be_null);
   }
 
   size_t data_size = DataType::Size(value_type);
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index b21f36c..5986a2f 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -2023,11 +2023,11 @@
 
   if (type == DataType::Type::kReference) {
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(locations->GetTemp(0).AsRegister<Register>(),
-                             locations->GetTemp(1).AsRegister<Register>(),
-                             base,
-                             value_loc.AsRegister<Register>(),
-                             value_can_be_null);
+    codegen->MarkGCCard(locations->GetTemp(0).AsRegister<Register>(),
+                        locations->GetTemp(1).AsRegister<Register>(),
+                        base,
+                        value_loc.AsRegister<Register>(),
+                        value_can_be_null);
   }
 }
 
@@ -2363,7 +2363,7 @@
   bool value_can_be_null = true;  // TODO: Worth finding out this information?
   NearLabel skip_mark_gc_card;
   __ j(kNotZero, &skip_mark_gc_card);
-  codegen->MaybeMarkGCCard(temp, temp2, base, value, value_can_be_null);
+  codegen->MarkGCCard(temp, temp2, base, value, value_can_be_null);
   __ Bind(&skip_mark_gc_card);
 
   // If heap poisoning is enabled, we need to unpoison the values
@@ -2629,7 +2629,7 @@
     // Mark card for object as a new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
     DCHECK_EQ(temp2, ECX);  // Byte register for `MarkGCCard()`.
-    codegen->MaybeMarkGCCard(temp1, temp2, base, /*value=*/out_reg, new_value_can_be_null);
+    codegen->MarkGCCard(temp1, temp2, base, /*value=*/ out_reg, new_value_can_be_null);
 
     if (kPoisonHeapReferences) {
       // Use a temp to avoid poisoning base of the field address, which might happen if `out`
@@ -3357,7 +3357,7 @@
     }
 
     // We only need one card marking on the destination array.
-    codegen_->MarkGCCard(temp1, temp3, dest);
+    codegen_->MarkGCCard(temp1, temp3, dest, Register(kNoRegister), /* emit_null_check= */ false);
 
     __ Bind(&skip_copy_and_write_barrier);
   }
@@ -4176,8 +4176,7 @@
       is_volatile,
       /* value_can_be_null */ true,
       // Value can be null, and this write barrier is not being relied on for other sets.
-      value_type == DataType::Type::kReference ? WriteBarrierKind::kEmitNotBeingReliedOn :
-                                                 WriteBarrierKind::kDontEmit);
+      WriteBarrierKind::kEmitWithNullCheck);
 
   __ Bind(slow_path->GetExitLabel());
 }
@@ -4337,7 +4336,8 @@
             /* always_update_field= */ true,
             &temp2);
       }
-      codegen->MarkGCCard(temp, temp2, reference);
+      codegen->MarkGCCard(
+          temp, temp2, reference, value.AsRegister<Register>(), /* emit_null_check= */ false);
       if (kPoisonHeapReferences) {
         __ movl(temp, value.AsRegister<Register>());
         __ PoisonHeapReference(temp);
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 1876a70..5177ac4 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1153,7 +1153,8 @@
     }
 
     // We only need one card marking on the destination array.
-    codegen_->MarkGCCard(temp1, temp2, dest);
+    codegen_->MarkGCCard(
+        temp1, temp2, dest, CpuRegister(kNoRegister), /* emit_null_check= */ false);
 
     __ Bind(&skip_copy_and_write_barrier);
   }
@@ -2090,11 +2091,11 @@
 
   if (type == DataType::Type::kReference) {
     bool value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(locations->GetTemp(0).AsRegister<CpuRegister>(),
-                             locations->GetTemp(1).AsRegister<CpuRegister>(),
-                             base,
-                             value,
-                             value_can_be_null);
+    codegen->MarkGCCard(locations->GetTemp(0).AsRegister<CpuRegister>(),
+                        locations->GetTemp(1).AsRegister<CpuRegister>(),
+                        base,
+                        value,
+                        value_can_be_null);
   }
 }
 
@@ -2389,7 +2390,7 @@
 
   // Mark card for object assuming new value is stored.
   bool value_can_be_null = true;  // TODO: Worth finding out this information?
-  codegen->MaybeMarkGCCard(temp1, temp2, base, value, value_can_be_null);
+  codegen->MarkGCCard(temp1, temp2, base, value, value_can_be_null);
 
   Address field_addr(base, offset, TIMES_1, 0);
   if (codegen->EmitBakerReadBarrier()) {
@@ -2700,7 +2701,7 @@
 
     // Mark card for object as a new value shall be stored.
     bool new_value_can_be_null = true;  // TODO: Worth finding out this information?
-    codegen->MaybeMarkGCCard(temp1, temp2, base, /*value=*/out, new_value_can_be_null);
+    codegen->MarkGCCard(temp1, temp2, base, /*value=*/ out, new_value_can_be_null);
 
     if (kPoisonHeapReferences) {
       // Use a temp to avoid poisoning base of the field address, which might happen if `out`
@@ -4158,8 +4159,7 @@
       /*value_can_be_null=*/true,
       byte_swap,
       // Value can be null, and this write barrier is not being relied on for other sets.
-      value_type == DataType::Type::kReference ? WriteBarrierKind::kEmitNotBeingReliedOn :
-                                                 WriteBarrierKind::kDontEmit);
+      WriteBarrierKind::kEmitWithNullCheck);
 
   // setVolatile needs kAnyAny barrier, but HandleFieldSet takes care of that.
 
@@ -4444,7 +4444,7 @@
           &temp1,
           &temp2);
     }
-    codegen->MarkGCCard(temp1, temp2, ref);
+    codegen->MarkGCCard(temp1, temp2, ref, valreg, /* emit_null_check= */ false);
 
     DCHECK_EQ(valreg, out.AsRegister<CpuRegister>());
     if (kPoisonHeapReferences) {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 8dd89fa..0efe8f4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2903,10 +2903,6 @@
     next_ = Done() ? nullptr : instruction_->GetPrevious();
   }
 
-  explicit HBackwardInstructionIterator(HInstruction* instruction) : instruction_(instruction) {
-    next_ = Done() ? nullptr : instruction_->GetPrevious();
-  }
-
   bool Done() const { return instruction_ == nullptr; }
   HInstruction* Current() const { return instruction_; }
   void Advance() {
@@ -6373,13 +6369,19 @@
 };
 
 enum class WriteBarrierKind {
-  // Emit the write barrier. This write barrier is not being relied on so e.g. codegen can decide to
-  // skip it if the value stored is null. This is the default behavior.
-  kEmitNotBeingReliedOn,
-  // Emit the write barrier. This write barrier is being relied on and must be emitted.
-  kEmitBeingReliedOn,
+  // Emit the write barrier, with a runtime optimization which checks if the value that it is being
+  // set is null.
+  kEmitWithNullCheck,
+  // Emit the write barrier, without the runtime null check optimization. This could be set because:
+  //  A) It is a write barrier for an ArraySet (which does the optimization with the type check, so
+  //  it never does the optimization at the write barrier stage)
+  //  B) We know that the input can't be null
+  //  C) This write barrier is actually several write barriers coalesced into one. Potentially we
+  //  could ask if every value is null for a runtime optimization at the cost of compile time / code
+  //  size. At the time of writing it was deemed not worth the effort.
+  kEmitNoNullCheck,
   // Skip emitting the write barrier. This could be set because:
-  //  A) The write barrier is not needed (i.e. it is not a reference, or the value is the null
+  //  A) The write barrier is not needed (e.g. it is not a reference, or the value is the null
   //  constant)
   //  B) This write barrier was coalesced into another one so there's no need to emit it.
   kDontEmit,
@@ -6410,7 +6412,7 @@
                     declaring_class_def_index,
                     dex_file) {
     SetPackedFlag<kFlagValueCanBeNull>(true);
-    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
+    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitWithNullCheck);
     SetRawInputAt(0, object);
     SetRawInputAt(1, value);
   }
@@ -6431,11 +6433,8 @@
   void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
   void SetWriteBarrierKind(WriteBarrierKind kind) {
-    DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
+    DCHECK(kind != WriteBarrierKind::kEmitWithNullCheck)
         << "We shouldn't go back to the original value.";
-    DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
-                   GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
-        << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
     SetPackedField<WriteBarrierKindField>(kind);
   }
 
@@ -6577,7 +6576,8 @@
     SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference);
     SetPackedFlag<kFlagValueCanBeNull>(true);
     SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(false);
-    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
+    // ArraySets never do the null check optimization at the write barrier stage.
+    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNoNullCheck);
     SetRawInputAt(0, array);
     SetRawInputAt(1, index);
     SetRawInputAt(2, value);
@@ -6653,11 +6653,10 @@
   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
 
   void SetWriteBarrierKind(WriteBarrierKind kind) {
-    DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
+    DCHECK(kind != WriteBarrierKind::kEmitNoNullCheck)
         << "We shouldn't go back to the original value.";
-    DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
-                   GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
-        << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
+    DCHECK(kind != WriteBarrierKind::kEmitWithNullCheck)
+        << "We never do the null check optimization for ArraySets.";
     SetPackedField<WriteBarrierKindField>(kind);
   }
 
@@ -7517,7 +7516,7 @@
                     declaring_class_def_index,
                     dex_file) {
     SetPackedFlag<kFlagValueCanBeNull>(true);
-    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
+    SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitWithNullCheck);
     SetRawInputAt(0, cls);
     SetRawInputAt(1, value);
   }
@@ -7535,11 +7534,8 @@
 
   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
   void SetWriteBarrierKind(WriteBarrierKind kind) {
-    DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
+    DCHECK(kind != WriteBarrierKind::kEmitWithNullCheck)
         << "We shouldn't go back to the original value.";
-    DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
-                   GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
-        << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
     SetPackedField<WriteBarrierKindField>(kind);
   }
 
diff --git a/compiler/optimizing/scheduler_arm.cc b/compiler/optimizing/scheduler_arm.cc
index 510a0f5..cafb0f5 100644
--- a/compiler/optimizing/scheduler_arm.cc
+++ b/compiler/optimizing/scheduler_arm.cc
@@ -977,6 +977,8 @@
   DCHECK(codegen_ != nullptr);
   bool is_volatile = field_info.IsVolatile();
   DataType::Type field_type = field_info.GetFieldType();
+  bool needs_write_barrier =
+      CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
   bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
 
   switch (field_type) {
@@ -995,7 +997,7 @@
 
     case DataType::Type::kInt32:
     case DataType::Type::kReference:
-      if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
+      if (kPoisonHeapReferences && needs_write_barrier) {
         last_visited_internal_latency_ += kArmIntegerOpLatency * 2;
       }
       last_visited_latency_ = kArmMemoryStoreLatency;
diff --git a/compiler/optimizing/write_barrier_elimination.cc b/compiler/optimizing/write_barrier_elimination.cc
index 27348cd..6182125 100644
--- a/compiler/optimizing/write_barrier_elimination.cc
+++ b/compiler/optimizing/write_barrier_elimination.cc
@@ -21,8 +21,8 @@
 #include "base/scoped_arena_containers.h"
 #include "optimizing/nodes.h"
 
-// TODO(b/310755375, solanes): Enable WBE with the fixes.
-constexpr bool kWBEEnabled = true;
+// TODO(b/310755375, solanes): Disable WBE while we investigate crashes.
+constexpr bool kWBEEnabled = false;
 
 namespace art HIDDEN {
 
@@ -58,7 +58,7 @@
       DCHECK(it->second->AsInstanceFieldSet()->GetWriteBarrierKind() !=
              WriteBarrierKind::kDontEmit);
       DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
-      it->second->AsInstanceFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitBeingReliedOn);
+      it->second->AsInstanceFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitNoNullCheck);
       instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
       MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
     } else {
@@ -84,7 +84,7 @@
       DCHECK(it->second->IsStaticFieldSet());
       DCHECK(it->second->AsStaticFieldSet()->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
       DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
-      it->second->AsStaticFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitBeingReliedOn);
+      it->second->AsStaticFieldSet()->SetWriteBarrierKind(WriteBarrierKind::kEmitNoNullCheck);
       instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
       MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
     } else {
@@ -112,7 +112,8 @@
       DCHECK(it->second->IsArraySet());
       DCHECK(it->second->AsArraySet()->GetWriteBarrierKind() != WriteBarrierKind::kDontEmit);
       DCHECK_EQ(it->second->GetBlock(), instruction->GetBlock());
-      it->second->AsArraySet()->SetWriteBarrierKind(WriteBarrierKind::kEmitBeingReliedOn);
+      // We never skip the null check in ArraySets so that value is already set.
+      DCHECK(it->second->AsArraySet()->GetWriteBarrierKind() == WriteBarrierKind::kEmitNoNullCheck);
       instruction->SetWriteBarrierKind(WriteBarrierKind::kDontEmit);
       MaybeRecordStat(stats_, MethodCompilationStat::kRemovedWriteBarrier);
     } else {
diff --git a/compiler/optimizing/write_barrier_elimination.h b/compiler/optimizing/write_barrier_elimination.h
index 1e9ab7b..a3769e7 100644
--- a/compiler/optimizing/write_barrier_elimination.h
+++ b/compiler/optimizing/write_barrier_elimination.h
@@ -33,7 +33,7 @@
 // We can keep the write barrier for `inner_obj` and remove the other two.
 //
 // In order to do this, we set the WriteBarrierKind of the instruction. The instruction's kind are
-// set to kEmitBeingReliedOn (if this write barrier coalesced other write barriers, we don't want to
+// set to kEmitNoNullCheck (if this write barrier coalesced other write barriers, we don't want to
 // perform the null check optimization), or to kDontEmit (if the write barrier as a whole is not
 // needed).
 class WriteBarrierElimination : public HOptimization {
diff --git a/test/2247-checker-write-barrier-elimination/src/Main.java b/test/2247-checker-write-barrier-elimination/src/Main.java
index edf5bc2..c03ada3 100644
--- a/test/2247-checker-write-barrier-elimination/src/Main.java
+++ b/test/2247-checker-write-barrier-elimination/src/Main.java
@@ -55,10 +55,13 @@
     }
 
     /// CHECK-START: Main Main.$noinline$testInstanceFieldSets(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: InstanceFieldSet field_name:Main.inner field_type:Reference write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: InstanceFieldSet field_name:Main.inner field_type:Reference write_barrier_kind:EmitNoNullCheck
     /// CHECK: InstanceFieldSet field_name:Main.inner2 field_type:Reference write_barrier_kind:DontEmit
     /// CHECK: InstanceFieldSet field_name:Main.inner3 field_type:Reference write_barrier_kind:DontEmit
+
+    /// CHECK-START: Main Main.$noinline$testInstanceFieldSets(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static Main $noinline$testInstanceFieldSets(Main m, Object o, Object o2, Object o3) {
         m.inner = o;
         m.inner2 = o2;
@@ -67,10 +70,13 @@
     }
 
     /// CHECK-START: void Main.$noinline$testStaticFieldSets(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitNoNullCheck
     /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:DontEmit
     /// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:DontEmit
+
+    /// CHECK-START: void Main.$noinline$testStaticFieldSets(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static void $noinline$testStaticFieldSets(Object o, Object o2, Object o3) {
         inner_static = o;
         inner_static2 = o2;
@@ -78,12 +84,15 @@
     }
 
     /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySets(java.lang.Object[], java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNotBeingReliedOn
+    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNoNullCheck
+    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNoNullCheck
+    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNoNullCheck
+
+    /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySets(java.lang.Object[], java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
     /// CHECK: ; card_table
-    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNotBeingReliedOn
     /// CHECK: ; card_table
-    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNotBeingReliedOn
     /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static java.lang.Object[] $noinline$testArraySets(
             Object[] arr, Object o, Object o2, Object o3) {
         arr[0] = o;
@@ -93,10 +102,13 @@
     }
 
     /// CHECK-START: java.lang.Object[] Main.$noinline$testSwapArray(java.lang.Object[]) disassembly (after)
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+
+    /// CHECK-START: java.lang.Object[] Main.$noinline$testSwapArray(java.lang.Object[]) disassembly (after)
     /// CHECK: ; card_table
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+    /// CHECK-NOT: ; card_table
     private static java.lang.Object[] $noinline$testSwapArray(Object[] arr) {
         arr[0] = arr[1];
         arr[1] = arr[2];
@@ -105,10 +117,13 @@
     }
 
     /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTI() disassembly (after)
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+
+    /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTI() disassembly (after)
     /// CHECK: ; card_table
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+    /// CHECK-NOT: ; card_table
     private static java.lang.Object[] $noinline$testArraySetsSameRTI() {
         Object[] arr = new Object[3];
         arr[0] = inner_static;
@@ -119,9 +134,12 @@
 
     /// CHECK-START: Main Main.$noinline$testNullInstanceFieldSets(Main, java.lang.Object) disassembly (after)
     /// CHECK: InstanceFieldSet field_name:Main.inner field_type:Reference write_barrier_kind:DontEmit
-    /// CHECK: InstanceFieldSet field_name:Main.inner2 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: InstanceFieldSet field_name:Main.inner2 field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: InstanceFieldSet field_name:Main.inner3 field_type:Reference write_barrier_kind:DontEmit
+
+    /// CHECK-START: Main Main.$noinline$testNullInstanceFieldSets(Main, java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static Main $noinline$testNullInstanceFieldSets(Main m, Object o) {
         m.inner = null;
         m.inner2 = o;
@@ -131,9 +149,12 @@
 
     /// CHECK-START: void Main.$noinline$testNullStaticFieldSets(java.lang.Object) disassembly (after)
     /// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:DontEmit
-    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:DontEmit
+
+    /// CHECK-START: void Main.$noinline$testNullStaticFieldSets(java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static void $noinline$testNullStaticFieldSets(Object o) {
         inner_static = null;
         inner_static2 = o;
@@ -142,9 +163,12 @@
 
     /// CHECK-START: java.lang.Object[] Main.$noinline$testNullArraySets(java.lang.Object[], java.lang.Object) disassembly (after)
     /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: ArraySet needs_type_check:true can_trigger_gc:true write_barrier_kind:EmitNoNullCheck
     /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+
+    /// CHECK-START: java.lang.Object[] Main.$noinline$testNullArraySets(java.lang.Object[], java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static Object[] $noinline$testNullArraySets(Object[] arr, Object o) {
         arr[0] = null;
         arr[1] = o;
@@ -153,11 +177,18 @@
     }
 
     /// CHECK-START: Main Main.$noinline$testInstanceFieldSetsMultipleReceivers(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: InstanceFieldSet field_name:MultipleObject.inner field_type:Reference write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
-    /// CHECK: InstanceFieldSet field_name:MultipleObject.inner field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    // There are two extra card_tables for the initialization of the MultipleObject.
+    /// CHECK: InstanceFieldSet field_name:MultipleObject.inner field_type:Reference write_barrier_kind:EmitNoNullCheck
+    /// CHECK: InstanceFieldSet field_name:MultipleObject.inner field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: InstanceFieldSet field_name:MultipleObject.inner2 field_type:Reference write_barrier_kind:DontEmit
+
+    // Each one of the two NewInstance instructions have their own `card_table` reference.
+    /// CHECK-START: Main Main.$noinline$testInstanceFieldSetsMultipleReceivers(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static Main $noinline$testInstanceFieldSetsMultipleReceivers(
             Main m, Object o, Object o2, Object o3) throws Error {
         m.mo = new MultipleObject();
@@ -173,11 +204,14 @@
     }
 
     /// CHECK-START: void Main.$noinline$testStaticFieldSetsMultipleReceivers(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: StaticFieldSet field_name:MultipleObject.inner_static field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
-    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: StaticFieldSet field_name:MultipleObject.inner_static field_type:Reference write_barrier_kind:EmitWithNullCheck
+    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitNoNullCheck
     /// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:DontEmit
+
+    /// CHECK-START: void Main.$noinline$testStaticFieldSetsMultipleReceivers(java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static void $noinline$testStaticFieldSetsMultipleReceivers(
             Object o, Object o2, Object o3) {
         MultipleObject.inner_static = o;
@@ -187,15 +221,20 @@
 
     /// CHECK-START: java.lang.Object[][] Main.$noinline$testArraySetsMultipleReceiversSameRTI() disassembly (after)
     // Initializing the values
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
     /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
     // Setting the `array_of_arrays`.
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
     /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
+
+    /// CHECK-START: java.lang.Object[][] Main.$noinline$testArraySetsMultipleReceiversSameRTI() disassembly (after)
+    // Two array sets can't eliminate the write barrier
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    // One write barrier for the array of arrays' sets
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static java.lang.Object[][] $noinline$testArraySetsMultipleReceiversSameRTI() {
         Object[] arr = new Object[3];
         Object[] other_arr = new Object[3];
@@ -212,14 +251,17 @@
     private static void $noinline$emptyMethod() {}
 
     /// CHECK-START: Main Main.$noinline$testInstanceFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: InstanceFieldSet field_name:Main.inner field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: InstanceFieldSet field_name:Main.inner field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
-    /// CHECK: InstanceFieldSet field_name:Main.inner2 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: InstanceFieldSet field_name:Main.inner2 field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: MonitorOperation kind:enter
-    /// CHECK: InstanceFieldSet field_name:Main.inner3 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
+    /// CHECK: InstanceFieldSet field_name:Main.inner3 field_type:Reference write_barrier_kind:EmitWithNullCheck
+
+    /// CHECK-START: Main Main.$noinline$testInstanceFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
     /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static Main $noinline$testInstanceFieldSetsBlocked(
             Main m, Object o, Object o2, Object o3) {
         m.inner = o;
@@ -232,14 +274,17 @@
     }
 
     /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
-    /// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: StaticFieldSet field_name:Main.inner_static field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
-    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: StaticFieldSet field_name:Main.inner_static2 field_type:Reference write_barrier_kind:EmitWithNullCheck
     /// CHECK: MonitorOperation kind:enter
-    /// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:EmitNotBeingReliedOn
+    /// CHECK: StaticFieldSet field_name:Main.inner_static3 field_type:Reference write_barrier_kind:EmitWithNullCheck
+
+    /// CHECK-START: void Main.$noinline$testStaticFieldSetsBlocked(Main, java.lang.Object, java.lang.Object, java.lang.Object) disassembly (after)
     /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static void $noinline$testStaticFieldSetsBlocked(
             Main m, Object o, Object o2, Object o3) {
         inner_static = o;
@@ -251,14 +296,17 @@
     }
 
     /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
     /// CHECK: InvokeStaticOrDirect method_name:Main.$noinline$emptyMethod
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
-    /// CHECK: ; card_table
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
     /// CHECK: MonitorOperation kind:enter
-    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNotBeingReliedOn
+    /// CHECK: ArraySet needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitNoNullCheck
+
+    /// CHECK-START: java.lang.Object[] Main.$noinline$testArraySetsSameRTIBlocked(Main) disassembly (after)
     /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK: ; card_table
+    /// CHECK-NOT: ; card_table
     private static java.lang.Object[] $noinline$testArraySetsSameRTIBlocked(Main m) {
         Object[] arr = new Object[3];
         arr[0] = inner_static;
diff --git a/test/2272-checker-codegen-honor-write-barrier-kind/expected-stderr.txt b/test/2272-checker-codegen-honor-write-barrier-kind/expected-stderr.txt
deleted file mode 100644
index e69de29..0000000
--- a/test/2272-checker-codegen-honor-write-barrier-kind/expected-stderr.txt
+++ /dev/null
diff --git a/test/2272-checker-codegen-honor-write-barrier-kind/expected-stdout.txt b/test/2272-checker-codegen-honor-write-barrier-kind/expected-stdout.txt
deleted file mode 100644
index e69de29..0000000
--- a/test/2272-checker-codegen-honor-write-barrier-kind/expected-stdout.txt
+++ /dev/null
diff --git a/test/2272-checker-codegen-honor-write-barrier-kind/info.txt b/test/2272-checker-codegen-honor-write-barrier-kind/info.txt
deleted file mode 100644
index 455bb77..0000000
--- a/test/2272-checker-codegen-honor-write-barrier-kind/info.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Two regression tests:
-1) Regression test to honor the write barrier kind and set the dirty bit.
-2) Regression test for skipping a needed write barrier at runtime.
diff --git a/test/2272-checker-codegen-honor-write-barrier-kind/run.py b/test/2272-checker-codegen-honor-write-barrier-kind/run.py
deleted file mode 100644
index ebdb9b5..0000000
--- a/test/2272-checker-codegen-honor-write-barrier-kind/run.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#! /bin/bash
-#
-# Copyright (C) 2023 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-def run(ctx, args):
-  # Limit the managed heap to 16 MiB to force more garbage collections.
-  ctx.default_run(args, runtime_option=["-Xmx16m"])
diff --git a/test/2272-checker-codegen-honor-write-barrier-kind/src/Main.java b/test/2272-checker-codegen-honor-write-barrier-kind/src/Main.java
deleted file mode 100644
index f07286b..0000000
--- a/test/2272-checker-codegen-honor-write-barrier-kind/src/Main.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-public class Main {
-    public static void main(String[] args) {
-        $noinline$testHonorWriteBarrier();
-        $noinline$testDontSkipWriteBarrier();
-    }
-
-    public static void $noinline$testHonorWriteBarrier() {
-        String[] arr = {"Hello", "World"};
-        // We first run the gc to make sure the card is clean.
-        Runtime.getRuntime().gc();
-        // Continually call $noinline$testArraySetsHonorWriteBarrier while allocating over 64 MiB of
-        // memory (with heap size limited to 16 MiB), in order to increase memory pressure and
-        // eventually trigger a concurrent garbage collection, which will start by putting the GC in
-        // marking mode to trigger the bug.
-        for (int i = 0; i != 64 * 1024; ++i) {
-            $noinline$allocateAtLeast1KiB();
-            $noinline$testArraySetsHonorWriteBarrier(arr, "Universe");
-        }
-    }
-
-    // When the bug was present, $noinline$testArraySetsHonorWriteBarrier would never set the card
-    // as dirty (which is incorrect). arr[1]'s' write barrier depends on arr[0]'s write barrier. The
-    // disappeared BoundType in prepare_for_register_allocation shouldn't skip marking the card
-    // dirty.
-
-    /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (before)
-    /// CHECK: <<Null:l\d+>>   NullConstant
-    /// CHECK: <<BT:l\d+>>     BoundType [<<Null>>]
-    /// CHECK: ArraySet [<<arr:l\d+>>,<<index:i\d+>>,<<BT>>] value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-
-    /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (after)
-    /// CHECK: <<Null:l\d+>>   NullConstant
-    /// CHECK: ArraySet [<<arr:l\d+>>,<<index:i\d+>>,<<Null>>] value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-
-    /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) prepare_for_register_allocation (after)
-    /// CHECK-NOT: BoundType
-
-    /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsHonorWriteBarrier(java.lang.String[], java.lang.String) disassembly (after)
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    // / CHECK: ; card_table
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-    private static java.lang.String[] $noinline$testArraySetsHonorWriteBarrier(
-            String[] arr, String o2) {
-        Object o = null;
-        arr[0] = (String) o;
-        arr[1] = o2;
-        return arr;
-    }
-
-    public static void $noinline$testDontSkipWriteBarrier() {
-        String[] arr = {"Hello", "World"};
-        // We first run the gc to make sure the card is clean.
-        Runtime.getRuntime().gc();
-        // Continually call $noinline$testArraySets while allocating over 64 MiB of memory (with
-        // heap size limited to 16 MiB), in order to increase memory pressure and eventually trigger
-        // a concurrent garbage collection, which will start by putting the GC in marking mode to
-        // trigger the bug.
-        for (int i = 0; i != 64 * 1024; ++i) {
-            $noinline$allocateAtLeast1KiB();
-            $noinline$testArraySetsDontSkipWriteBarrier(arr, null, "Universe");
-        }
-    }
-
-    // When the bug was present, $noinline$testArraySetsDontSkipWriteBarrier would never set the
-    // card as dirty (which is incorrect). arr[1]'s write barrier depends on arr[0]'s write barrier.
-    // The code path should mark the card dirty without a null check on `o` in `arr[0] = o`.
-
-    /// CHECK-START: java.lang.String[] Main.$noinline$testArraySetsDontSkipWriteBarrier(java.lang.String[], java.lang.String, java.lang.String) disassembly (after)
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:EmitBeingReliedOn
-    /// CHECK: ArraySet value_can_be_null:true needs_type_check:false can_trigger_gc:false write_barrier_kind:DontEmit
-    private static java.lang.String[] $noinline$testArraySetsDontSkipWriteBarrier(
-            String[] arr, String o, String o2) {
-        arr[0] = o;
-        arr[1] = o2;
-        return arr;
-    }
-
-    // Allocate at least 1 KiB of memory on the managed heap.
-    // Retain some allocated memory and release old allocations so that the
-    // garbage collector has something to do.
-    public static void $noinline$allocateAtLeast1KiB() {
-        memory[allocationIndex] = new Object[1024 / 4];
-        ++allocationIndex;
-        if (allocationIndex == memory.length) {
-            allocationIndex = 0;
-        }
-    }
-
-    public static Object[] memory = new Object[1024];
-    public static int allocationIndex = 0;
-}
diff --git a/test/knownfailures.json b/test/knownfailures.json
index a0b7dcd..269b68d 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1,5 +1,10 @@
 [
     {
+        "tests": "2247-checker-write-barrier-elimination",
+        "description": ["Disable 2247- until we fix the WBE issue."],
+        "bug": "http://b/310755375"
+    },
+    {
         "tests": "153-reference-stress",
         "description": ["Disable 153-reference-stress temporarily until a fix",
                         "arrives."],