• 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 "optimizer/analysis/alias_analysis.h"
19 #include "optimizer/analysis/bounds_analysis.h"
20 #include "lowering.h"
21 
22 namespace panda::compiler {
VisitIfImm(GraphVisitor * v,Inst * inst)23 void Lowering::VisitIfImm([[maybe_unused]] GraphVisitor *v, Inst *inst)
24 {
25     ASSERT(inst->GetOpcode() == Opcode::IfImm);
26     LowerIf(inst->CastToIfImm());
27 }
28 
29 // Ask encoder whether Constant can be an immediate for Compare
ConstantFitsCompareImm(Inst * cst,uint32_t size,ConditionCode cc)30 bool Lowering::ConstantFitsCompareImm(Inst *cst, uint32_t size, ConditionCode cc)
31 {
32     ASSERT(cst->GetOpcode() == Opcode::Constant);
33     if (DataType::IsFloatType(cst->GetType())) {
34         return false;
35     }
36     int64_t val = cst->CastToConstant()->GetRawValue();
37     return (size == HALF_SIZE) && (val == 0);
38 }
39 
LowerCastValueToAnyTypeWithConst(Inst * inst)40 bool Lowering::LowerCastValueToAnyTypeWithConst(Inst *inst)
41 {
42     auto graph = inst->GetBasicBlock()->GetGraph();
43     auto any_type = inst->CastToCastValueToAnyType()->GetAnyType();
44     auto base_type = AnyBaseTypeToDataType(any_type);
45     if (!IsTypeNumeric(base_type) || base_type == DataType::POINTER) {
46         return false;
47     }
48     auto input_inst = inst->GetInput(0).GetInst();
49     if (!input_inst->IsConst()) {
50         return false;
51     }
52     auto imm = input_inst->CastToConstant()->GetRawValue();
53     auto pack_imm = graph->GetRuntime()->GetPackConstantByPrimitiveType(any_type, imm);
54     auto any_const = inst->GetBasicBlock()->GetGraph()->FindOrCreateConstant(DataType::Any(pack_imm));
55     inst->ReplaceUsers(any_const);
56     return true;
57 }
58 
59 // We'd like to swap only to make second operand immediate
BetterToSwapCompareInputs(Inst * cmp)60 bool Lowering::BetterToSwapCompareInputs(Inst *cmp)
61 {
62     ASSERT(cmp->GetOpcode() == Opcode::Compare);
63     auto in0 = cmp->GetInput(0).GetInst();
64     auto in1 = cmp->GetInput(1).GetInst();
65     if (DataType::IsFloatType(in0->GetType())) {
66         return false;
67     }
68 
69     if (in0->IsConst()) {
70         if (in1->IsConst()) {
71             DataType::Type type = cmp->CastToCompare()->GetOperandsType();
72             uint32_t size = (type == DataType::UINT64 || type == DataType::INT64) ? WORD_SIZE : HALF_SIZE;
73             auto cc = cmp->CastToCompare()->GetCc();
74             return ConstantFitsCompareImm(in0, size, cc) && !ConstantFitsCompareImm(in1, size, cc);
75         }
76         return true;
77     }
78     return false;
79 }
80 
81 // Optimize order of input arguments for decreasing using accumulator (Bytecodeoptimizer only).
OptimizeIfInput(compiler::Inst * if_inst)82 void Lowering::OptimizeIfInput(compiler::Inst *if_inst)
83 {
84     ASSERT(if_inst->GetOpcode() == compiler::Opcode::If);
85     compiler::Inst *input_0 = if_inst->GetInput(0).GetInst();
86     compiler::Inst *input_1 = if_inst->GetInput(1).GetInst();
87 
88     if (input_0->IsDominate(input_1)) {
89         if_inst->SetInput(0, input_1);
90         if_inst->SetInput(1, input_0);
91         // And change CC
92         auto cc = if_inst->CastToIf()->GetCc();
93         cc = SwapOperandsConditionCode(cc);
94         if_inst->CastToIf()->SetCc(cc);
95     }
96 }
97 
LowerIf(IfImmInst * inst)98 void Lowering::LowerIf(IfImmInst *inst)
99 {
100     auto graph = inst->GetBasicBlock()->GetGraph();
101     ASSERT(inst->GetCc() == ConditionCode::CC_NE || inst->GetCc() == ConditionCode::CC_EQ);
102     ASSERT(inst->GetImm() == 0);
103     if (inst->GetOperandsType() != DataType::BOOL) {
104         ASSERT(!graph->SupportManagedCode() || graph->IsDynamicMethod());
105         return;
106     }
107     auto input = inst->GetInput(0).GetInst();
108     if (input->GetOpcode() != Opcode::Compare) {
109         return;
110     }
111     // Check, that inst have only IfImm user
112     for (auto &user : input->GetUsers()) {
113         if (user.GetInst()->GetOpcode() != Opcode::IfImm) {
114             return;
115         }
116     }
117     // Try put constant in second input
118     if (BetterToSwapCompareInputs(input)) {
119         // Swap inputs
120         auto in0 = input->GetInput(0).GetInst();
121         auto in1 = input->GetInput(1).GetInst();
122         input->SetInput(0, in1);
123         input->SetInput(1, in0);
124         // And change CC
125         auto cc = input->CastToCompare()->GetCc();
126         cc = SwapOperandsConditionCode(cc);
127         input->CastToCompare()->SetCc(cc);
128     }
129     auto cst = input->GetInput(1).GetInst();
130     DataType::Type type = input->CastToCompare()->GetOperandsType();
131     uint32_t size = (type == DataType::UINT64 || type == DataType::INT64) ? WORD_SIZE : HALF_SIZE;
132     auto cc = input->CastToCompare()->GetCc();
133     // IfImm can be inverted
134     if (inst->GetCc() == ConditionCode::CC_EQ && inst->GetImm() == 0) {
135         cc = GetInverseConditionCode(cc);
136     }
137 
138     if (cst->IsConst() && ConstantFitsCompareImm(cst, size, cc)) {
139         // In-place change for IfImm
140         InPlaceLowerIfImm(inst, input, cst, cc);
141     } else {
142         // New instruction
143         auto replace = graph->CreateInstIf(DataType::NO_TYPE, inst->GetPc(), cc);
144         replace->SetMethod(inst->GetMethod());
145         replace->SetOperandsType(input->CastToCompare()->GetOperandsType());
146         replace->SetInput(0, input->GetInput(0).GetInst());
147         replace->SetInput(1, input->GetInput(1).GetInst());
148         // Replace IfImm instruction immediately because it's not removable by DCE
149         inst->RemoveInputs();
150         inst->GetBasicBlock()->ReplaceInst(inst, replace);
151         graph->GetEventWriter().EventLowering(GetOpcodeString(inst->GetOpcode()), inst->GetId(), inst->GetPc());
152         if (graph->IsBytecodeOptimizer()) {
153             OptimizeIfInput(replace);
154         }
155         COMPILER_LOG(DEBUG, LOWERING) << "Lowering is applied for " << GetOpcodeString(inst->GetOpcode());
156     }
157 }
158 
InPlaceLowerIfImm(IfImmInst * inst,Inst * input,Inst * cst,ConditionCode cc)159 void Lowering::InPlaceLowerIfImm(IfImmInst *inst, Inst *input, Inst *cst, ConditionCode cc)
160 {
161     inst->SetOperandsType(input->CastToCompare()->GetOperandsType());
162     auto new_input = input->GetInput(0).GetInst();
163     inst->SetInput(0, new_input);
164 
165     uint64_t val = cst->CastToConstant()->GetRawValue();
166     inst->SetImm(val);
167     inst->SetCc(cc);
168     inst->GetBasicBlock()->GetGraph()->GetEventWriter().EventLowering(GetOpcodeString(inst->GetOpcode()), inst->GetId(),
169                                                                       inst->GetPc());
170     COMPILER_LOG(DEBUG, LOWERING) << "Lowering is applied for " << GetOpcodeString(inst->GetOpcode());
171 }
172 
InvalidateAnalyses()173 void Lowering::InvalidateAnalyses()
174 {
175     GetGraph()->InvalidateAnalysis<BoundsAnalysis>();
176     GetGraph()->InvalidateAnalysis<AliasAnalysis>();
177 }
178 
RunImpl()179 bool Lowering::RunImpl()
180 {
181     VisitGraph();
182     return true;
183 }
184 }  // namespace panda::compiler
185