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