1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#include "lowering.h" 17b1994897Sopenharmony_ci 18b1994897Sopenharmony_cinamespace panda::compiler { 19b1994897Sopenharmony_civoid Lowering::VisitIfImm([[maybe_unused]] GraphVisitor *v, Inst *inst) 20b1994897Sopenharmony_ci{ 21b1994897Sopenharmony_ci ASSERT(inst->GetOpcode() == Opcode::IfImm); 22b1994897Sopenharmony_ci LowerIf(inst->CastToIfImm()); 23b1994897Sopenharmony_ci} 24b1994897Sopenharmony_ci 25b1994897Sopenharmony_ci// Ask encoder whether Constant can be an immediate for Compare 26b1994897Sopenharmony_cibool Lowering::ConstantFitsCompareImm(Inst *cst, uint32_t size, ConditionCode cc) 27b1994897Sopenharmony_ci{ 28b1994897Sopenharmony_ci ASSERT(cst->GetOpcode() == Opcode::Constant); 29b1994897Sopenharmony_ci if (DataType::IsFloatType(cst->GetType())) { 30b1994897Sopenharmony_ci return false; 31b1994897Sopenharmony_ci } 32b1994897Sopenharmony_ci int64_t val = cst->CastToConstant()->GetRawValue(); 33b1994897Sopenharmony_ci return (size == HALF_SIZE) && (val == 0); 34b1994897Sopenharmony_ci} 35b1994897Sopenharmony_ci 36b1994897Sopenharmony_ci// We'd like to swap only to make second operand immediate 37b1994897Sopenharmony_cibool Lowering::BetterToSwapCompareInputs(Inst *cmp) 38b1994897Sopenharmony_ci{ 39b1994897Sopenharmony_ci ASSERT(cmp->GetOpcode() == Opcode::Compare); 40b1994897Sopenharmony_ci auto in0 = cmp->GetInput(0).GetInst(); 41b1994897Sopenharmony_ci auto in1 = cmp->GetInput(1).GetInst(); 42b1994897Sopenharmony_ci if (DataType::IsFloatType(in0->GetType())) { 43b1994897Sopenharmony_ci return false; 44b1994897Sopenharmony_ci } 45b1994897Sopenharmony_ci 46b1994897Sopenharmony_ci if (in0->IsConst()) { 47b1994897Sopenharmony_ci if (in1->IsConst()) { 48b1994897Sopenharmony_ci DataType::Type type = cmp->CastToCompare()->GetOperandsType(); 49b1994897Sopenharmony_ci uint32_t size = (type == DataType::UINT64 || type == DataType::INT64) ? WORD_SIZE : HALF_SIZE; 50b1994897Sopenharmony_ci auto cc = cmp->CastToCompare()->GetCc(); 51b1994897Sopenharmony_ci return ConstantFitsCompareImm(in0, size, cc) && !ConstantFitsCompareImm(in1, size, cc); 52b1994897Sopenharmony_ci } 53b1994897Sopenharmony_ci return true; 54b1994897Sopenharmony_ci } 55b1994897Sopenharmony_ci return false; 56b1994897Sopenharmony_ci} 57b1994897Sopenharmony_ci 58b1994897Sopenharmony_ci// Optimize order of input arguments for decreasing using accumulator (Bytecodeoptimizer only). 59b1994897Sopenharmony_civoid Lowering::OptimizeIfInput(compiler::Inst *if_inst) 60b1994897Sopenharmony_ci{ 61b1994897Sopenharmony_ci ASSERT(if_inst->GetOpcode() == compiler::Opcode::If); 62b1994897Sopenharmony_ci compiler::Inst *input_0 = if_inst->GetInput(0).GetInst(); 63b1994897Sopenharmony_ci compiler::Inst *input_1 = if_inst->GetInput(1).GetInst(); 64b1994897Sopenharmony_ci 65b1994897Sopenharmony_ci if (input_0->IsDominate(input_1)) { 66b1994897Sopenharmony_ci if_inst->SetInput(0, input_1); 67b1994897Sopenharmony_ci if_inst->SetInput(1, input_0); 68b1994897Sopenharmony_ci // And change CC 69b1994897Sopenharmony_ci auto cc = if_inst->CastToIf()->GetCc(); 70b1994897Sopenharmony_ci cc = SwapOperandsConditionCode(cc); 71b1994897Sopenharmony_ci if_inst->CastToIf()->SetCc(cc); 72b1994897Sopenharmony_ci } 73b1994897Sopenharmony_ci} 74b1994897Sopenharmony_ci 75b1994897Sopenharmony_civoid Lowering::LowerIf(IfImmInst *inst) 76b1994897Sopenharmony_ci{ 77b1994897Sopenharmony_ci auto graph = inst->GetBasicBlock()->GetGraph(); 78b1994897Sopenharmony_ci ASSERT(inst->GetCc() == ConditionCode::CC_NE || inst->GetCc() == ConditionCode::CC_EQ); 79b1994897Sopenharmony_ci ASSERT(inst->GetImm() == 0); 80b1994897Sopenharmony_ci if (inst->GetOperandsType() != DataType::BOOL) { 81b1994897Sopenharmony_ci ASSERT(!graph->SupportManagedCode() || graph->IsDynamicMethod()); 82b1994897Sopenharmony_ci return; 83b1994897Sopenharmony_ci } 84b1994897Sopenharmony_ci auto input = inst->GetInput(0).GetInst(); 85b1994897Sopenharmony_ci if (input->GetOpcode() != Opcode::Compare) { 86b1994897Sopenharmony_ci return; 87b1994897Sopenharmony_ci } 88b1994897Sopenharmony_ci // Check, that inst have only IfImm user 89b1994897Sopenharmony_ci for (auto &user : input->GetUsers()) { 90b1994897Sopenharmony_ci if (user.GetInst()->GetOpcode() != Opcode::IfImm) { 91b1994897Sopenharmony_ci return; 92b1994897Sopenharmony_ci } 93b1994897Sopenharmony_ci } 94b1994897Sopenharmony_ci // Try put constant in second input 95b1994897Sopenharmony_ci if (BetterToSwapCompareInputs(input)) { 96b1994897Sopenharmony_ci // Swap inputs 97b1994897Sopenharmony_ci auto in0 = input->GetInput(0).GetInst(); 98b1994897Sopenharmony_ci auto in1 = input->GetInput(1).GetInst(); 99b1994897Sopenharmony_ci input->SetInput(0, in1); 100b1994897Sopenharmony_ci input->SetInput(1, in0); 101b1994897Sopenharmony_ci // And change CC 102b1994897Sopenharmony_ci auto cc = input->CastToCompare()->GetCc(); 103b1994897Sopenharmony_ci cc = SwapOperandsConditionCode(cc); 104b1994897Sopenharmony_ci input->CastToCompare()->SetCc(cc); 105b1994897Sopenharmony_ci } 106b1994897Sopenharmony_ci auto cst = input->GetInput(1).GetInst(); 107b1994897Sopenharmony_ci DataType::Type type = input->CastToCompare()->GetOperandsType(); 108b1994897Sopenharmony_ci uint32_t size = (type == DataType::UINT64 || type == DataType::INT64) ? WORD_SIZE : HALF_SIZE; 109b1994897Sopenharmony_ci auto cc = input->CastToCompare()->GetCc(); 110b1994897Sopenharmony_ci // IfImm can be inverted 111b1994897Sopenharmony_ci if (inst->GetCc() == ConditionCode::CC_EQ && inst->GetImm() == 0) { 112b1994897Sopenharmony_ci cc = GetInverseConditionCode(cc); 113b1994897Sopenharmony_ci } 114b1994897Sopenharmony_ci 115b1994897Sopenharmony_ci if (cst->IsConst() && ConstantFitsCompareImm(cst, size, cc)) { 116b1994897Sopenharmony_ci // In-place change for IfImm 117b1994897Sopenharmony_ci InPlaceLowerIfImm(inst, input, cst, cc); 118b1994897Sopenharmony_ci } else { 119b1994897Sopenharmony_ci // New instruction 120b1994897Sopenharmony_ci auto replace = graph->CreateInstIf(DataType::NO_TYPE, inst->GetPc(), cc); 121b1994897Sopenharmony_ci replace->SetMethod(inst->GetMethod()); 122b1994897Sopenharmony_ci replace->SetOperandsType(input->CastToCompare()->GetOperandsType()); 123b1994897Sopenharmony_ci replace->SetInput(0, input->GetInput(0).GetInst()); 124b1994897Sopenharmony_ci replace->SetInput(1, input->GetInput(1).GetInst()); 125b1994897Sopenharmony_ci // Replace IfImm instruction immediately because it's not removable by DCE 126b1994897Sopenharmony_ci inst->RemoveInputs(); 127b1994897Sopenharmony_ci inst->GetBasicBlock()->ReplaceInst(inst, replace); 128b1994897Sopenharmony_ci graph->GetEventWriter().EventLowering(GetOpcodeString(inst->GetOpcode()), inst->GetId(), inst->GetPc()); 129b1994897Sopenharmony_ci if (graph->IsBytecodeOptimizer()) { 130b1994897Sopenharmony_ci OptimizeIfInput(replace); 131b1994897Sopenharmony_ci } 132b1994897Sopenharmony_ci COMPILER_LOG(DEBUG, LOWERING) << "Lowering is applied for " << GetOpcodeString(inst->GetOpcode()); 133b1994897Sopenharmony_ci } 134b1994897Sopenharmony_ci} 135b1994897Sopenharmony_ci 136b1994897Sopenharmony_civoid Lowering::InPlaceLowerIfImm(IfImmInst *inst, Inst *input, Inst *cst, ConditionCode cc) 137b1994897Sopenharmony_ci{ 138b1994897Sopenharmony_ci inst->SetOperandsType(input->CastToCompare()->GetOperandsType()); 139b1994897Sopenharmony_ci auto new_input = input->GetInput(0).GetInst(); 140b1994897Sopenharmony_ci inst->SetInput(0, new_input); 141b1994897Sopenharmony_ci 142b1994897Sopenharmony_ci uint64_t val = cst->CastToConstant()->GetRawValue(); 143b1994897Sopenharmony_ci inst->SetImm(val); 144b1994897Sopenharmony_ci inst->SetCc(cc); 145b1994897Sopenharmony_ci inst->GetBasicBlock()->GetGraph()->GetEventWriter().EventLowering(GetOpcodeString(inst->GetOpcode()), inst->GetId(), 146b1994897Sopenharmony_ci inst->GetPc()); 147b1994897Sopenharmony_ci COMPILER_LOG(DEBUG, LOWERING) << "Lowering is applied for " << GetOpcodeString(inst->GetOpcode()); 148b1994897Sopenharmony_ci} 149b1994897Sopenharmony_ci 150b1994897Sopenharmony_civoid Lowering::InvalidateAnalyses() 151b1994897Sopenharmony_ci{ 152b1994897Sopenharmony_ci} 153b1994897Sopenharmony_ci 154b1994897Sopenharmony_cibool Lowering::RunImpl() 155b1994897Sopenharmony_ci{ 156b1994897Sopenharmony_ci VisitGraph(); 157b1994897Sopenharmony_ci return true; 158b1994897Sopenharmony_ci} 159b1994897Sopenharmony_ci} // namespace panda::compiler 160