Add a write barrier elimination pass

We can eliminate redundant write barriers as we don't need several
for the same receiver. For example:

```
MyObject o;
o.inner_obj = io;
o.inner_obj2 = io2;
o.inner_obj3 = io3;
```

We can keep the write barrier for `inner_obj` and remove the other
two.

Note that we cannot perform this optimization across
invokes, suspend check, or instructions that can throw.

Local improvements (pixel 5, speed compile):
 * System server: -280KB (-0.56%)
 * SystemUIGoogle: -330KB (-1.16%)
 * AGSA: -3876KB (-1.19%)

Bug: 260843353
Fixes: 260843353
Change-Id: Ibf98efbe891ee00e46125853c3e97ae30aa3ff30
diff --git a/compiler/optimizing/write_barrier_elimination.h b/compiler/optimizing/write_barrier_elimination.h
new file mode 100644
index 0000000..a3769e7
--- /dev/null
+++ b/compiler/optimizing/write_barrier_elimination.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_WRITE_BARRIER_ELIMINATION_H_
+#define ART_COMPILER_OPTIMIZING_WRITE_BARRIER_ELIMINATION_H_
+
+#include "base/macros.h"
+#include "optimization.h"
+
+namespace art HIDDEN {
+
+// Eliminates unnecessary write barriers from InstanceFieldSet, StaticFieldSet, and ArraySet.
+//
+// We can eliminate redundant write barriers as we don't need several for the same receiver. For
+// example:
+//   MyObject o;
+//   o.inner_obj = io;
+//   o.inner_obj2 = io2;
+//   o.inner_obj3 = io3;
+// 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 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 {
+ public:
+  WriteBarrierElimination(HGraph* graph,
+                          OptimizingCompilerStats* stats,
+                          const char* name = kWBEPassName)
+      : HOptimization(graph, name, stats) {}
+
+  bool Run() override;
+
+  static constexpr const char* kWBEPassName = "write_barrier_elimination";
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WriteBarrierElimination);
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_OPTIMIZING_WRITE_BARRIER_ELIMINATION_H_