| /* | 
 |  * Copyright (C) 2014 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. | 
 |  */ | 
 |  | 
 | #include "base/arena_allocator.h" | 
 | #include "builder.h" | 
 | #include "code_generator.h" | 
 | #include "dex/dex_file.h" | 
 | #include "dex/dex_instruction.h" | 
 | #include "driver/compiler_options.h" | 
 | #include "nodes.h" | 
 | #include "optimizing_unit_test.h" | 
 | #include "prepare_for_register_allocation.h" | 
 | #include "ssa_liveness_analysis.h" | 
 |  | 
 | namespace art { | 
 |  | 
 | class LivenessTest : public OptimizingUnitTest { | 
 |  protected: | 
 |   void TestCode(const std::vector<uint16_t>& data, const char* expected); | 
 | }; | 
 |  | 
 | static void DumpBitVector(BitVector* vector, | 
 |                           std::ostream& buffer, | 
 |                           size_t count, | 
 |                           const char* prefix) { | 
 |   buffer << prefix; | 
 |   buffer << '('; | 
 |   for (size_t i = 0; i < count; ++i) { | 
 |     buffer << vector->IsBitSet(i); | 
 |   } | 
 |   buffer << ")\n"; | 
 | } | 
 |  | 
 | void LivenessTest::TestCode(const std::vector<uint16_t>& data, const char* expected) { | 
 |   HGraph* graph = CreateCFG(data); | 
 |   // `Inline` conditions into ifs. | 
 |   std::unique_ptr<CompilerOptions> compiler_options = | 
 |       CommonCompilerTest::CreateCompilerOptions(kRuntimeISA, "default"); | 
 |   PrepareForRegisterAllocation(graph, *compiler_options).Run(); | 
 |   std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options); | 
 |   SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator()); | 
 |   liveness.Analyze(); | 
 |  | 
 |   std::ostringstream buffer; | 
 |   for (HBasicBlock* block : graph->GetBlocks()) { | 
 |     buffer << "Block " << block->GetBlockId() << std::endl; | 
 |     size_t ssa_values = liveness.GetNumberOfSsaValues(); | 
 |     BitVector* live_in = liveness.GetLiveInSet(*block); | 
 |     DumpBitVector(live_in, buffer, ssa_values, "  live in: "); | 
 |     BitVector* live_out = liveness.GetLiveOutSet(*block); | 
 |     DumpBitVector(live_out, buffer, ssa_values, "  live out: "); | 
 |     BitVector* kill = liveness.GetKillSet(*block); | 
 |     DumpBitVector(kill, buffer, ssa_values, "  kill: "); | 
 |   } | 
 |   ASSERT_STREQ(expected, buffer.str().c_str()); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, CFG1) { | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (0)\n" | 
 |     "  live out: (0)\n" | 
 |     "  kill: (1)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (0)\n" | 
 |     "  live out: (0)\n" | 
 |     "  kill: (0)\n" | 
 |     "Block 2\n" | 
 |     "  live in: (0)\n" | 
 |     "  live out: (0)\n" | 
 |     "  kill: (0)\n"; | 
 |  | 
 |   // Constant is not used. | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, CFG2) { | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (0)\n" | 
 |     "  live out: (1)\n" | 
 |     "  kill: (1)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (1)\n" | 
 |     "  live out: (0)\n" | 
 |     "  kill: (0)\n" | 
 |     "Block 2\n" | 
 |     "  live in: (0)\n" | 
 |     "  live out: (0)\n" | 
 |     "  kill: (0)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::RETURN); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, CFG3) { | 
 |   const char* expected = | 
 |     "Block 0\n"  // entry block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (110)\n" | 
 |     "Block 1\n"  // block with add | 
 |     "  live in: (110)\n" | 
 |     "  live out: (001)\n" | 
 |     "  kill: (001)\n" | 
 |     "Block 2\n"  // block with return | 
 |     "  live in: (001)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 3\n"  // exit block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM( | 
 |     Instruction::CONST_4 | 3 << 12 | 0, | 
 |     Instruction::CONST_4 | 4 << 12 | 1 << 8, | 
 |     Instruction::ADD_INT_2ADDR | 1 << 12, | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::RETURN); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, CFG4) { | 
 |   // var a; | 
 |   // if (0 == 0) { | 
 |   //   a = 5; | 
 |   // } else { | 
 |   //   a = 4; | 
 |   // } | 
 |   // return a; | 
 |   // | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant5, constant4, phi) | 
 |   const char* expected = | 
 |     "Block 0\n"  // entry block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (1110)\n" | 
 |     "  kill: (1110)\n" | 
 |     "Block 1\n"  // block with if | 
 |     "  live in: (1110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 2\n"  // else block | 
 |     "  live in: (0010)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 3\n"  // then block | 
 |     "  live in: (0100)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 4\n"  // return block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0001)\n" | 
 |     "Block 5\n"  // exit block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::GOTO | 0x200, | 
 |     Instruction::CONST_4 | 5 << 12 | 0, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, CFG5) { | 
 |   // var a = 0; | 
 |   // if (0 == 0) { | 
 |   // } else { | 
 |   //   a = 4; | 
 |   // } | 
 |   // return a; | 
 |   // | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant4, phi) | 
 |   const char* expected = | 
 |     "Block 0\n"  // entry block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (110)\n" | 
 |     "Block 1\n"  // block with if | 
 |     "  live in: (110)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 2\n"  // else block | 
 |     "  live in: (010)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 3\n"  // return block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (001)\n" | 
 |     "Block 4\n"  // exit block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 5\n"  // block to avoid critical edge. Predecessor is 1, successor is 3. | 
 |     "  live in: (100)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 3, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, Loop1) { | 
 |   // Simple loop with one preheader and one back edge. | 
 |   // var a = 0; | 
 |   // while (a == a) { | 
 |   //   a = 4; | 
 |   // } | 
 |   // return; | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant4, phi) | 
 |   const char* expected = | 
 |     "Block 0\n"  // entry block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (110)\n" | 
 |     "Block 1\n"  // pre header | 
 |     "  live in: (110)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (010)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (001)\n" | 
 |     "Block 3\n"  // back edge | 
 |     "  live in: (010)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 4\n"  // return block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 5\n"  // exit block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n"; | 
 |  | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::GOTO | 0xFD00, | 
 |     Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, Loop3) { | 
 |   // Test that the returned value stays live in a preceding loop. | 
 |   // var a = 0; | 
 |   // while (a == a) { | 
 |   //   a = 4; | 
 |   // } | 
 |   // return 5; | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant5, constant4, phi) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (1110)\n" | 
 |     "  kill: (1110)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (1110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0001)\n" | 
 |     "Block 3\n"  // back edge | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 4\n"  // return block | 
 |     "  live in: (0100)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 5\n"  // exit block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::GOTO | 0xFD00, | 
 |     Instruction::CONST_4 | 5 << 12 | 1 << 8, | 
 |     Instruction::RETURN | 1 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 |  | 
 | TEST_F(LivenessTest, Loop4) { | 
 |   // Make sure we support a preheader of a loop not being the first predecessor | 
 |   // in the predecessor list of the header. | 
 |   // var a = 0; | 
 |   // while (a == a) { | 
 |   //   a = 4; | 
 |   // } | 
 |   // return a; | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant4, phi) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (000)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (110)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (110)\n" | 
 |     "  live out: (110)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (010)\n" | 
 |     "  live out: (011)\n" | 
 |     "  kill: (001)\n" | 
 |     "Block 3\n"  // back edge | 
 |     "  live in: (010)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 4\n"  // pre loop header | 
 |     "  live in: (110)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 5\n"  // return block | 
 |     "  live in: (001)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 6\n"  // exit block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::GOTO | 0x500, | 
 |     Instruction::IF_EQ, 5, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::GOTO | 0xFD00, | 
 |     Instruction::GOTO | 0xFC00, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, Loop5) { | 
 |   // Make sure we create a preheader of a loop when a header originally has two | 
 |   // incoming blocks and one back edge. | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant5, constant4, phi in block 8) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (1110)\n" | 
 |     "  kill: (1110)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (1110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 2\n" | 
 |     "  live in: (0010)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 3\n" | 
 |     "  live in: (0100)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 4\n"  // loop header | 
 |     "  live in: (0001)\n" | 
 |     "  live out: (0001)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 5\n"  // back edge | 
 |     "  live in: (0001)\n" | 
 |     "  live out: (0001)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 6\n"  // return block | 
 |     "  live in: (0001)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 7\n"  // exit block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 8\n"  // synthesized pre header | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0001)\n" | 
 |     "  kill: (0001)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::GOTO | 0x200, | 
 |     Instruction::CONST_4 | 5 << 12 | 0, | 
 |     Instruction::IF_EQ, 3, | 
 |     Instruction::GOTO | 0xFE00, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, Loop6) { | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant4, constant5, phi in block 2) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (1110)\n" | 
 |     "  kill: (1110)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (1110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0111)\n" | 
 |     "  kill: (0001)\n" | 
 |     "Block 3\n" | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 4\n"  // back edge | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 5\n"  // back edge | 
 |     "  live in: (0110)\n" | 
 |     "  live out: (0110)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 6\n"  // return block | 
 |     "  live in: (0001)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n" | 
 |     "Block 7\n"  // exit block | 
 |     "  live in: (0000)\n" | 
 |     "  live out: (0000)\n" | 
 |     "  kill: (0000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 8, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 5 << 12 | 0, | 
 |     Instruction::GOTO | 0xFA00, | 
 |     Instruction::GOTO | 0xF900, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 |  | 
 | TEST_F(LivenessTest, Loop7) { | 
 |   // Bitsets are made of: | 
 |   // (constant0, constant4, constant5, phi in block 2, phi in block 6) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (00000)\n" | 
 |     "  live out: (11100)\n" | 
 |     "  kill: (11100)\n" | 
 |     "Block 1\n" | 
 |     "  live in: (11100)\n" | 
 |     "  live out: (01100)\n" | 
 |     "  kill: (00000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (01100)\n" | 
 |     "  live out: (01110)\n" | 
 |     "  kill: (00010)\n" | 
 |     "Block 3\n" | 
 |     "  live in: (01100)\n" | 
 |     "  live out: (01100)\n" | 
 |     "  kill: (00000)\n" | 
 |     "Block 4\n"  // loop exit | 
 |     "  live in: (00100)\n" | 
 |     "  live out: (00000)\n" | 
 |     "  kill: (00000)\n" | 
 |     "Block 5\n"  // back edge | 
 |     "  live in: (01100)\n" | 
 |     "  live out: (01100)\n" | 
 |     "  kill: (00000)\n" | 
 |     "Block 6\n"  // return block | 
 |     "  live in: (00000)\n" | 
 |     "  live out: (00000)\n" | 
 |     "  kill: (00001)\n" | 
 |     "Block 7\n"  // exit block | 
 |     "  live in: (00000)\n" | 
 |     "  live out: (00000)\n" | 
 |     "  kill: (00000)\n" | 
 |     "Block 8\n"  // synthesized block to avoid critical edge. | 
 |     "  live in: (00010)\n" | 
 |     "  live out: (00000)\n" | 
 |     "  kill: (00000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 8, | 
 |     Instruction::CONST_4 | 4 << 12 | 0, | 
 |     Instruction::IF_EQ, 4, | 
 |     Instruction::CONST_4 | 5 << 12 | 0, | 
 |     Instruction::GOTO | 0x0200, | 
 |     Instruction::GOTO | 0xF900, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST_F(LivenessTest, Loop8) { | 
 |   // var a = 0; | 
 |   // while (a == a) { | 
 |   //   a = a + a; | 
 |   // } | 
 |   // return a; | 
 |   // | 
 |   // We want to test that the ins of the loop exit | 
 |   // does contain the phi. | 
 |   // Bitsets are made of: | 
 |   // (constant0, phi, add) | 
 |   const char* expected = | 
 |     "Block 0\n" | 
 |     "  live in: (000)\n" | 
 |     "  live out: (100)\n" | 
 |     "  kill: (100)\n" | 
 |     "Block 1\n"  // pre loop header | 
 |     "  live in: (100)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 2\n"  // loop header | 
 |     "  live in: (000)\n" | 
 |     "  live out: (010)\n" | 
 |     "  kill: (010)\n" | 
 |     "Block 3\n"  // back edge | 
 |     "  live in: (010)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (001)\n" | 
 |     "Block 4\n"  // return block | 
 |     "  live in: (010)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n" | 
 |     "Block 5\n"  // exit block | 
 |     "  live in: (000)\n" | 
 |     "  live out: (000)\n" | 
 |     "  kill: (000)\n"; | 
 |  | 
 |   const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 6, | 
 |     Instruction::ADD_INT, 0, 0, | 
 |     Instruction::GOTO | 0xFB00, | 
 |     Instruction::RETURN | 0 << 8); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | }  // namespace art |