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