constant_folding_test.cc revision 93445689c714e53cabf347da4321ecf3023e926c
1556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/* 2556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Copyright (C) 2014 The Android Open Source Project 3556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 4556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Licensed under the Apache License, Version 2.0 (the "License"); 5556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * you may not use this file except in compliance with the License. 6556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * You may obtain a copy of the License at 7556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 8556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * http://www.apache.org/licenses/LICENSE-2.0 9556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 10556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Unless required by applicable law or agreed to in writing, software 11556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * distributed under the License is distributed on an "AS IS" BASIS, 12556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * See the License for the specific language governing permissions and 14556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * limitations under the License. 15556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 16556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 1793445689c714e53cabf347da4321ecf3023e926cRoland Levillain#include <functional> 1893445689c714e53cabf347da4321ecf3023e926cRoland Levillain 191ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray#include "constant_propagation.h" 20556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "dead_code_elimination.h" 211ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray#include "pretty_printer.h" 22556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "graph_checker.h" 23556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "optimizing_unit_test.h" 24556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 25556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "gtest/gtest.h" 26556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 27556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainnamespace art { 28556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 29556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainstatic void TestCode(const uint16_t* data, 30556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const std::string& expected_before, 31556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const std::string& expected_after_cp, 327fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const std::string& expected_after_dce, 3393445689c714e53cabf347da4321ecf3023e926cRoland Levillain std::function<void(HGraph*)> check_after_cp, 347fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray Primitive::Type return_type = Primitive::kPrimInt) { 35556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ArenaPool pool; 36556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ArenaAllocator allocator(&pool); 377fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray HGraph* graph = CreateCFG(&allocator, data, return_type); 38556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ASSERT_NE(graph, nullptr); 39556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 40556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain graph->BuildDominatorTree(); 41556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain graph->TransformToSSA(); 42556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 43556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain StringPrettyPrinter printer_before(graph); 44556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain printer_before.VisitInsertionOrder(); 45556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string actual_before = printer_before.str(); 46556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ASSERT_EQ(expected_before, actual_before); 47556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 481ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray ConstantPropagation(graph).Run(); 49556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 50556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain StringPrettyPrinter printer_after_cp(graph); 51556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain printer_after_cp.VisitInsertionOrder(); 52556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string actual_after_cp = printer_after_cp.str(); 53556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ASSERT_EQ(expected_after_cp, actual_after_cp); 54556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 5593445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp(graph); 5693445689c714e53cabf347da4321ecf3023e926cRoland Levillain 571ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray DeadCodeElimination(graph).Run(); 58556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 59556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain StringPrettyPrinter printer_after_dce(graph); 60556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain printer_after_dce.VisitInsertionOrder(); 61556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string actual_after_dce = printer_after_dce.str(); 62556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain ASSERT_EQ(expected_after_dce, actual_after_dce); 631ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray 641ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray SSAChecker ssa_checker(&allocator, graph); 651ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray ssa_checker.VisitInsertionOrder(); 661ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray ASSERT_TRUE(ssa_checker.IsValid()); 67556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 68556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 69556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 70556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 71556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on addition. 72556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 73556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 74556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 75556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 76556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- 1 0. const/4 v0, #+1 77556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 2 1. const/4 v1, #+2 78556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v2 <- v0 + v1 2. add-int v2, v0, v1 79556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return v2 4. return v2 80556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 811ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnAddition1) { 82556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( 83556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 0 << 8 | 1 << 12, 84556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 2 << 12, 85556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT | 2 << 8, 0 | 1 << 8, 86556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN | 2 << 8); 87556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 88556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 89556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 90556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 3: IntConstant [9]\n" 91556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 5: IntConstant [9]\n" 92556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 14: SuspendCheck\n" 93556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 15: Goto 1\n" 94556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 2\n" 95556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 9: Add(3, 5) [12]\n" 96556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 12: Return(9)\n" 97556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1\n" 98556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 13: Exit\n"; 99556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 1001ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 101556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 102556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [9]\n", " 3: IntConstant\n" }, 103556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant [9]\n", " 5: IntConstant\n" }, 104556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 9: Add(3, 5) [12]\n", " 16: IntConstant [12]\n" }, 105556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 12: Return(9)\n", " 12: Return(16)\n" } 106556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 107556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 108556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 10993445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the value of the computed constant. 11093445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 11193445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction(); 11293445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst->IsIntConstant()); 11393445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3); 11493445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 11593445689c714e53cabf347da4321ecf3023e926cRoland Levillain 116556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 117556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 118556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant\n", removed }, 119556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant\n", removed } 120556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 121556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 122556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 12393445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 12493445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 12593445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 12693445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 12793445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp); 128556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 129556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 130556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 131556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Small three-register program exercising int constant folding on addition. 132556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 133556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 134556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 135556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 136556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- 1 0. const/4 v0, #+1 137556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 2 1. const/4 v1, #+2 138556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- v0 + v1 2. add-int/2addr v0, v1 139556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 3 3. const/4 v1, #+3 140556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v2 <- 4 4. const/4 v2, #+4 141556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- v1 + v2 5. add-int/2addr v1, v2 142556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v2 <- v0 + v1 6. add-int v2, v0, v1 143556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return v2 8. return v2 144556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 1451ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnAddition2) { 146556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( 147556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 0 << 8 | 1 << 12, 148556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 2 << 12, 149556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12, 150556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 3 << 12, 151556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 2 << 8 | 4 << 12, 152556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12, 153556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT | 2 << 8, 0 | 1 << 8, 154556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN | 2 << 8); 155556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 156556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 157556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 158556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 3: IntConstant [9]\n" 159556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 5: IntConstant [9]\n" 160556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 11: IntConstant [17]\n" 161556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 13: IntConstant [17]\n" 162556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 26: SuspendCheck\n" 163556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 27: Goto 1\n" 164556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 2\n" 165556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 9: Add(3, 5) [21]\n" 166556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 17: Add(11, 13) [21]\n" 167556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 21: Add(9, 17) [24]\n" 168556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 24: Return(21)\n" 169556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1\n" 170556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 25: Exit\n"; 171556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 1721ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 173556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 174556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [9]\n", " 3: IntConstant\n" }, 175556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant [9]\n", " 5: IntConstant\n" }, 176556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 11: IntConstant [17]\n", " 11: IntConstant\n" }, 177556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 13: IntConstant [17]\n", " 13: IntConstant\n" }, 178556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 9: Add(3, 5) [21]\n", " 28: IntConstant\n" }, 179556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 17: Add(11, 13) [21]\n", " 29: IntConstant\n" }, 180556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 21: Add(9, 17) [24]\n", " 30: IntConstant [24]\n" }, 181556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 24: Return(21)\n", " 24: Return(30)\n" } 182556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 183556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 184556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 18593445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the values of the computed constants. 18693445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 18793445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction(); 18893445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst1->IsIntConstant()); 18993445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 3); 19093445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst2 = inst1->GetNext(); 19193445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst2->IsIntConstant()); 19293445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 7); 19393445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst3 = inst2->GetNext(); 19493445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst3->IsIntConstant()); 19593445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 10); 19693445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 19793445689c714e53cabf347da4321ecf3023e926cRoland Levillain 198556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 199556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 200556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant\n", removed }, 201556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant\n", removed }, 202556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 11: IntConstant\n", removed }, 203556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 13: IntConstant\n", removed }, 204556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 28: IntConstant\n", removed }, 205556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 29: IntConstant\n", removed } 206556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 207556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 208556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 20993445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 21093445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 21193445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 21293445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 21393445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp); 214556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 215556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 216556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 217556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on subtraction. 218556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 219556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 220556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 221556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 222556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- 3 0. const/4 v0, #+3 223556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 2 1. const/4 v1, #+2 224556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v2 <- v0 - v1 2. sub-int v2, v0, v1 225556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return v2 4. return v2 226556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 2271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnSubtraction) { 228556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( 229556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 0 << 8 | 3 << 12, 230556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 2 << 12, 231556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::SUB_INT | 2 << 8, 0 | 1 << 8, 232556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN | 2 << 8); 233556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 234556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 235556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 236556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 3: IntConstant [9]\n" 237556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 5: IntConstant [9]\n" 238556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 14: SuspendCheck\n" 239556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 15: Goto 1\n" 240556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 2\n" 241556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 9: Sub(3, 5) [12]\n" 242556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 12: Return(9)\n" 243556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1\n" 244556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 13: Exit\n"; 245556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 2461ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 247556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 248556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [9]\n", " 3: IntConstant\n" }, 249556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant [9]\n", " 5: IntConstant\n" }, 250556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 9: Sub(3, 5) [12]\n", " 16: IntConstant [12]\n" }, 251556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 12: Return(9)\n", " 12: Return(16)\n" } 252556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 253556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 254556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 25593445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the value of the computed constant. 25693445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 25793445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction(); 25893445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst->IsIntConstant()); 25993445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1); 26093445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 26193445689c714e53cabf347da4321ecf3023e926cRoland Levillain 262556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 263556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 264556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant\n", removed }, 265556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant\n", removed } 266556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 267556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 268556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 26993445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 27093445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 27193445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 27293445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 27393445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp); 274556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 275556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 276556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#define SIX_REGISTERS_CODE_ITEM(...) \ 277556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { 6, 0, 0, 0, 0, 0, NUM_INSTRUCTIONS(__VA_ARGS__), 0, __VA_ARGS__ } 278556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 279556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 280556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding 281556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on addition. 282556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 283556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 284556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 285556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 286556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v0, v1) <- 1 0. const-wide/16 v0, #+1 287556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v2, v3) <- 2 2. const-wide/16 v2, #+2 288556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v4, v5) <- 289556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v0, v1) + (v1, v2) 4. add-long v4, v0, v2 290556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return (v4, v5) 6. return-wide v4 291556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 2921ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, LongConstantFoldingOnAddition) { 293556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = SIX_REGISTERS_CODE_ITEM( 294556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_WIDE_16 | 0 << 8, 1, 295556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_WIDE_16 | 2 << 8, 2, 296556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8, 297556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN_WIDE | 4 << 8); 298556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 299556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 300556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 301556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 6: LongConstant [12]\n" 302556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 8: LongConstant [12]\n" 303556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 17: SuspendCheck\n" 304556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 18: Goto 1\n" 305556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 2\n" 306556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 12: Add(6, 8) [15]\n" 307556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 15: Return(12)\n" 308556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1\n" 309556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 16: Exit\n"; 310556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 3111ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 312556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 313556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 6: LongConstant [12]\n", " 6: LongConstant\n" }, 314556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 8: LongConstant [12]\n", " 8: LongConstant\n" }, 315556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 12: Add(6, 8) [15]\n", " 19: LongConstant [15]\n" }, 316556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 15: Return(12)\n", " 15: Return(19)\n" } 317556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 318556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 319556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 32093445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the value of the computed constant. 32193445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 32293445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction(); 32393445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst->IsLongConstant()); 32493445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3); 32593445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 32693445689c714e53cabf347da4321ecf3023e926cRoland Levillain 327556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 328556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 329556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 6: LongConstant\n", removed }, 330556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 8: LongConstant\n", removed } 331556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 332556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 333556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 33493445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 33593445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 33693445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 33793445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 33893445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp, 33993445689c714e53cabf347da4321ecf3023e926cRoland Levillain Primitive::kPrimLong); 340556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 341556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 342556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 343556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding 344556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on subtraction. 345556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 346556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 347556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 348556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 349556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v0, v1) <- 3 0. const-wide/16 v0, #+3 350556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v2, v3) <- 2 2. const-wide/16 v2, #+2 351556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v4, v5) <- 352556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (v0, v1) - (v1, v2) 4. sub-long v4, v0, v2 353556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return (v4, v5) 6. return-wide v4 354556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 3551ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, LongConstantFoldingOnSubtraction) { 356556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = SIX_REGISTERS_CODE_ITEM( 357556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_WIDE_16 | 0 << 8, 3, 358556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_WIDE_16 | 2 << 8, 2, 359556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8, 360556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN_WIDE | 4 << 8); 361556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 362556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 363556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 364556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 6: LongConstant [12]\n" 365556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 8: LongConstant [12]\n" 366556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 17: SuspendCheck\n" 367556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 18: Goto 1\n" 368556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 2\n" 369556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 12: Sub(6, 8) [15]\n" 370556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 15: Return(12)\n" 371556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1\n" 372556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 16: Exit\n"; 373556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 3741ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 375556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 376556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 6: LongConstant [12]\n", " 6: LongConstant\n" }, 377556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 8: LongConstant [12]\n", " 8: LongConstant\n" }, 378556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 12: Sub(6, 8) [15]\n", " 19: LongConstant [15]\n" }, 379556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 15: Return(12)\n", " 15: Return(19)\n" } 380556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 381556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 382556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 38393445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the value of the computed constant. 38493445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 38593445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction(); 38693445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst->IsLongConstant()); 38793445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1); 38893445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 38993445689c714e53cabf347da4321ecf3023e926cRoland Levillain 390556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 391556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 392556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 6: LongConstant\n", removed }, 393556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 8: LongConstant\n", removed } 394556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 395556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 396556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 39793445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 39893445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 39993445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 40093445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 40193445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp, 40293445689c714e53cabf347da4321ecf3023e926cRoland Levillain Primitive::kPrimLong); 403556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 404556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 405556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 406556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with jumps leading to the creation of many 407556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * blocks. 408556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 409556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * The intent of this test is to ensure that all constant expressions 410556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * are actually evaluated at compile-time, thanks to the reverse 411556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (forward) post-order traversal of the the dominator tree. 412556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 413556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 414556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 415556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 416556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- 0 0. const/4 v0, #+0 417556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 1 1. const/4 v1, #+1 418556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v2 <- v0 + v1 2. add-int v2, v0, v1 419556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * goto L2 4. goto +4 420556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v1 <- v0 + 3 5. add-int/lit16 v1, v0, #+3 421556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * goto L3 7. goto +4 422556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L2: v0 <- v2 + 2 8. add-int/lit16 v0, v2, #+2 423556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * goto L1 10. goto +(-5) 424556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L3: v2 <- v1 + 4 11. add-int/lit16 v2, v1, #+4 425556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return v2 13. return v2 426556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 4271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingAndJumps) { 428556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( 429556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 0 << 8 | 0 << 12, 430556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 1 << 12, 431556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT | 2 << 8, 0 | 1 << 8, 432556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::GOTO | 4 << 8, 433556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 3, 434556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::GOTO | 4 << 8, 435556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 2, 436556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain static_cast<uint16_t>(Instruction::GOTO | -5 << 8), 437556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 4, 438556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN | 2 << 8); 439556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 440556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 441556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 44293445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 3: IntConstant [9]\n" // v0 <- 0 44393445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 5: IntConstant [9]\n" // v1 <- 1 44493445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 13: IntConstant [14]\n" // const 3 44593445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 18: IntConstant [19]\n" // const 2 44693445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 24: IntConstant [25]\n" // const 4 447556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 30: SuspendCheck\n" 448556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 31: Goto 1\n" 449556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 3\n" 45093445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 9: Add(3, 5) [19]\n" // v2 <- v0 + v1 = 0 + 1 = 1 45193445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 11: Goto 3\n" // goto L2 45293445689c714e53cabf347da4321ecf3023e926cRoland Levillain "BasicBlock 2, pred: 3, succ: 4\n" // L1: 45393445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 14: Add(19, 13) [25]\n" // v1 <- v0 + 3 = 3 + 3 = 6 45493445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 16: Goto 4\n" // goto L3 45593445689c714e53cabf347da4321ecf3023e926cRoland Levillain "BasicBlock 3, pred: 1, succ: 2\n" // L2: 45693445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 19: Add(9, 18) [14]\n" // v0 <- v2 + 2 = 1 + 2 = 3 457556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 21: SuspendCheck\n" 45893445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 22: Goto 2\n" // goto L1 45993445689c714e53cabf347da4321ecf3023e926cRoland Levillain "BasicBlock 4, pred: 2, succ: 5\n" // L3: 46093445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 25: Add(14, 24) [28]\n" // v2 <- v1 + 4 = 6 + 4 = 10 46193445689c714e53cabf347da4321ecf3023e926cRoland Levillain " 28: Return(25)\n" // return v2 462556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 5, pred: 4\n" 463556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 29: Exit\n"; 464556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 4651ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 466556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 467556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [9]\n", " 3: IntConstant\n" }, 468556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant [9]\n", " 5: IntConstant []\n" }, 469556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 13: IntConstant [14]\n", " 13: IntConstant\n" }, 470556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 18: IntConstant [19]\n", " 18: IntConstant\n" }, 471556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 24: IntConstant [25]\n", " 24: IntConstant\n" }, 472556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 9: Add(3, 5) [19]\n", " 32: IntConstant []\n" }, 473556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 14: Add(19, 13) [25]\n", " 34: IntConstant\n" }, 474556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 19: Add(9, 18) [14]\n", " 33: IntConstant []\n" }, 475556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 25: Add(14, 24) [28]\n", " 35: IntConstant [28]\n" }, 476556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 28: Return(25)\n", " 28: Return(35)\n"} 477556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 478556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 479556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 48093445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the values of the computed constants. 48193445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 48293445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction(); 48393445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst1->IsIntConstant()); 48493445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 1); 48593445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst2 = graph->GetBlock(2)->GetFirstInstruction(); 48693445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst2->IsIntConstant()); 48793445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 6); 48893445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst3 = graph->GetBlock(3)->GetFirstInstruction(); 48993445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst3->IsIntConstant()); 49093445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3); 49193445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst4 = graph->GetBlock(4)->GetFirstInstruction(); 49293445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst4->IsIntConstant()); 49393445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 10); 49493445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 49593445689c714e53cabf347da4321ecf3023e926cRoland Levillain 496556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 497556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 498556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant\n", removed }, 499556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 13: IntConstant\n", removed }, 500556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 18: IntConstant\n", removed }, 501556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 24: IntConstant\n", removed }, 502556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 34: IntConstant\n", removed }, 503556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 504556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 505556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 50693445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 50793445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 50893445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 50993445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 51093445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp); 511556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 512556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 513556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 514556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/** 515556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with a constant (static) condition. 516556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 517556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * 16-bit 518556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * offset 519556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * ------ 520556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v1 <- 1 0. const/4 v1, #+1 521556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- 0 1. const/4 v0, #+0 522556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * if v1 >= 0 goto L1 2. if-gez v1, +3 523556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * v0 <- v1 4. move v0, v1 524556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v2 <- v0 + v1 5. add-int v2, v0, v1 525556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * return-void 7. return 526556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */ 5271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, ConstantCondition) { 528556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( 529556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 1 << 8 | 1 << 12, 530556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::CONST_4 | 0 << 8 | 0 << 12, 531556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::IF_GEZ | 1 << 8, 3, 532556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::MOVE | 0 << 8 | 1 << 12, 533556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::ADD_INT | 2 << 8, 0 | 1 << 8, 534556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain Instruction::RETURN_VOID); 535556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 536556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_before = 537556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 0, succ: 1\n" 538556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 3: IntConstant [15, 22, 8]\n" 539556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 5: IntConstant [22, 8]\n" 540556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 19: SuspendCheck\n" 541556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 20: Goto 1\n" 542556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 1, pred: 0, succ: 5, 2\n" 543556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 8: GreaterThanOrEqual(3, 5) [9]\n" 544556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 9: If(8)\n" 545556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 2, pred: 1, succ: 3\n" 546556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 12: Goto 3\n" 547556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 3, pred: 2, 5, succ: 4\n" 548556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 22: Phi(3, 5) [15]\n" 549556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 15: Add(22, 3)\n" 550556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 17: ReturnVoid\n" 551556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 4, pred: 3\n" 552556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 18: Exit\n" 553556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain "BasicBlock 5, pred: 1, succ: 3\n" 554556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain " 21: Goto 3\n"; 555556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 5561ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray // Expected difference after constant propagation. 557556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_cp_diff = { 558556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [15, 22, 8]\n", " 3: IntConstant [15, 22]\n" }, 559556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 5: IntConstant [22, 8]\n", " 5: IntConstant [22]\n" }, 560556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 8: GreaterThanOrEqual(3, 5) [9]\n", " 23: IntConstant [9]\n" }, 561556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 9: If(8)\n", " 9: If(23)\n" } 562556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 563556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_cp = Patch(expected_before, expected_cp_diff); 564556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 56593445689c714e53cabf347da4321ecf3023e926cRoland Levillain // Check the values of the computed constants. 56693445689c714e53cabf347da4321ecf3023e926cRoland Levillain auto check_after_cp = [](HGraph* graph) { 56793445689c714e53cabf347da4321ecf3023e926cRoland Levillain HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction(); 56893445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_TRUE(inst->IsIntConstant()); 56993445689c714e53cabf347da4321ecf3023e926cRoland Levillain ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1); 57093445689c714e53cabf347da4321ecf3023e926cRoland Levillain }; 57193445689c714e53cabf347da4321ecf3023e926cRoland Levillain 572556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain // Expected difference after dead code elimination. 573556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain diff_t expected_dce_diff = { 574556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 3: IntConstant [15, 22]\n", " 3: IntConstant [22]\n" }, 575556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 22: Phi(3, 5) [15]\n", " 22: Phi(3, 5)\n" }, 576556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain { " 15: Add(22, 3)\n", removed } 577556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain }; 578556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff); 579556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 58093445689c714e53cabf347da4321ecf3023e926cRoland Levillain TestCode(data, 58193445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_before, 58293445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_cp, 58393445689c714e53cabf347da4321ecf3023e926cRoland Levillain expected_after_dce, 58493445689c714e53cabf347da4321ecf3023e926cRoland Levillain check_after_cp); 585556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} 586556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain 587556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain} // namespace art 588