Generate selects for nested ternary operators

After an R8 update, the generated dex instructions are different
which means that the structure of the graph is different and we
weren't recognizing a possibility of select generation.

We now recognize it and can update the graph on the fly,
generating the corresponding selects.

Bug: 239385201
Fixes: 239385201
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I07644f0a69369e809994b4dd39bdd95c2cc7dc6c
diff --git a/compiler/optimizing/select_generator.h b/compiler/optimizing/select_generator.h
index 30ac8a8..4f13917 100644
--- a/compiler/optimizing/select_generator.h
+++ b/compiler/optimizing/select_generator.h
@@ -57,7 +57,9 @@
 #ifndef ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_
 #define ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_
 
+#include "base/scoped_arena_containers.h"
 #include "optimization.h"
+#include "optimizing/nodes.h"
 
 namespace art {
 
@@ -72,6 +74,43 @@
   static constexpr const char* kSelectGeneratorPassName = "select_generator";
 
  private:
+  bool TryGenerateSelectSimpleDiamondPattern(HBasicBlock* block,
+                                             ScopedArenaSafeMap<HInstruction*, HSelect*>* cache);
+
+  // When generating code for nested ternary operators (e.g. `return (x > 100) ? 100 : ((x < -100) ?
+  // -100 : x);`), a dexer can generate a double diamond pattern but it is not a clear cut one due
+  // to the merging of the blocks. `TryFixupDoubleDiamondPattern` recognizes that pattern and fixes
+  // up the graph to have a clean double diamond that `TryGenerateSelectSimpleDiamondPattern` can
+  // use to generate selects.
+  //
+  // In ASCII, it turns:
+  //
+  //      1 (outer if)
+  //     / \
+  //    2   3 (inner if)
+  //    |  / \
+  //    | 4  5
+  //     \/  |
+  //      6  |
+  //       \ |
+  //         7
+  //         |
+  //         8
+  // into:
+  //      1 (outer if)
+  //     / \
+  //    2   3 (inner if)
+  //    |  / \
+  //    | 4  5
+  //     \/ /
+  //      6
+  //      |
+  //      8
+  //
+  // In short, block 7 disappears and we merge 6 and 7. Now we have a diamond with {3,4,5,6}, and
+  // when that gets resolved we get another one with the outer if.
+  HBasicBlock* TryFixupDoubleDiamondPattern(HBasicBlock* block);
+
   DISALLOW_COPY_AND_ASSIGN(HSelectGenerator);
 };