Files
sdk/runtime/vm/compiler/backend/block_builder.h
T
Alexander Markov 52cb60b34e [vm/compiler] Rename Comparison to Condition, introduce proper Comparison
Previously, ComparisonInstr base class represented arbitrary conditions
used in Branch, IfThenElse and CheckCondition instructions and included
subclasses TestInt, TestCids, TestRange and unary DoubleTestOp which are
not comparisons. So this refactoring renames ComparisonInstr to
ConditionInstr.

In addition, a new Comparison instruction is added as a base class for
StrictCompare, EqualityCompare and RelationalOp.

TEST=ci (pure refactoring)

Change-Id: Ic8756ee5913ff2bc974c95cea8004370c9f5527f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/393420
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
2024-11-05 13:50:08 +00:00

172 lines
6.0 KiB
C++

// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_COMPILER_BACKEND_BLOCK_BUILDER_H_
#define RUNTIME_VM_COMPILER_BACKEND_BLOCK_BUILDER_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/il.h"
namespace dart {
namespace compiler {
// Helper class for building basic blocks in SSA form.
class BlockBuilder : public ValueObject {
public:
BlockBuilder(FlowGraph* flow_graph,
BlockEntryInstr* entry,
bool with_frame = true)
: flow_graph_(flow_graph),
source_(InstructionSource(flow_graph_->function().token_pos(),
flow_graph->inlining_id())),
entry_(entry),
current_(entry),
dummy_env_(new Environment(0, 0, 0, flow_graph->function(), nullptr)),
with_frame_(with_frame) {
// Some graph transformations use environments from block entries.
entry->SetEnvironment(dummy_env_);
}
Definition* AddToInitialDefinitions(Definition* def) {
flow_graph_->AllocateSSAIndex(def);
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
flow_graph_->AddToInitialDefinitions(normal_entry, def);
return def;
}
template <typename T>
T* AddDefinition(T* def) {
flow_graph_->AllocateSSAIndex(def);
AddInstruction(def);
return def;
}
template <typename T>
T* AddInstruction(T* instr) {
if (instr->ComputeCanDeoptimize() ||
instr->ComputeCanDeoptimizeAfterCall() ||
instr->CanBecomeDeoptimizationTarget()) {
// All instructions that can deoptimize must have an environment attached
// to them.
instr->SetEnvironment(dummy_env_);
}
current_ = current_->AppendInstruction(instr);
return instr;
}
const Function& function() const { return flow_graph_->function(); }
DartReturnInstr* AddReturn(Value* value) {
const auto& function = flow_graph_->function();
const auto representation = FlowGraph::ReturnRepresentationOf(function);
return AddReturn(value, representation);
}
DartReturnInstr* AddReturn(Value* value, Representation representation) {
DartReturnInstr* instr = new DartReturnInstr(
Source(), value, CompilerState::Current().GetNextDeoptId(),
representation);
AddInstruction(instr);
entry_->set_last_instruction(instr);
return instr;
}
Definition* AddParameter(intptr_t index) {
const auto [location, representation] =
flow_graph_->GetDirectParameterInfoAt(index);
return AddParameter(index, representation,
with_frame_ ? location : location.ToEntrySpRelative());
}
Definition* AddParameter(intptr_t index,
Representation representation,
Location location = Location()) {
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
return AddToInitialDefinitions(
new ParameterInstr(normal_entry,
/*env_index=*/index,
/*param_index=*/index, location, representation));
}
TokenPosition TokenPos() const { return source_.token_pos; }
const InstructionSource& Source() const { return source_; }
Definition* AddNullDefinition() {
return flow_graph_->GetConstant(Object::ZoneHandle());
}
Definition* AddUnboxInstr(Representation rep,
Value* value,
UnboxInstr::ValueMode value_mode) {
// Unbox floats by first unboxing a double then converting it to a float.
auto const unbox_rep = rep == kUnboxedFloat
? kUnboxedDouble
: Boxing::NativeRepresentation(rep);
Definition* unboxed_value = AddDefinition(
UnboxInstr::Create(unbox_rep, value, DeoptId::kNone, value_mode));
ASSERT((rep == unbox_rep) || !unboxed_value->IsUnboxInteger() ||
(RepresentationUtils::ValueSize(rep) <
RepresentationUtils::ValueSize(unbox_rep)));
if (value_mode == UnboxInstr::ValueMode::kHasValidType) {
// The type of |value| has already been checked and it is safe to
// adjust reaching type. This is done manually because there is no type
// propagation when building intrinsics.
unboxed_value->AsUnbox()->value()->SetReachingType(
new CompileType(CompileType::FromUnboxedRepresentation(rep)));
}
if (rep == kUnboxedFloat) {
unboxed_value = AddDefinition(
new DoubleToFloatInstr(new Value(unboxed_value), DeoptId::kNone));
}
return unboxed_value;
}
Definition* AddUnboxInstr(Representation rep,
Definition* boxed,
UnboxInstr::ValueMode value_mode) {
return AddUnboxInstr(rep, new Value(boxed), value_mode);
}
BranchInstr* AddBranch(ConditionInstr* cond,
TargetEntryInstr* true_successor,
TargetEntryInstr* false_successor) {
auto branch =
new BranchInstr(cond, CompilerState::Current().GetNextDeoptId());
// Some graph transformations use environments from branches.
branch->SetEnvironment(dummy_env_);
current_->AppendInstruction(branch);
current_ = nullptr;
*branch->true_successor_address() = true_successor;
*branch->false_successor_address() = false_successor;
return branch;
}
void AddPhi(PhiInstr* phi) {
flow_graph_->AllocateSSAIndex(phi);
phi->mark_alive();
entry_->AsJoinEntry()->InsertPhi(phi);
}
Instruction* last() const { return current_; }
private:
FlowGraph* const flow_graph_;
const InstructionSource source_;
BlockEntryInstr* entry_;
Instruction* current_;
Environment* dummy_env_;
const bool with_frame_;
};
} // namespace compiler
} // namespace dart
#endif // RUNTIME_VM_COMPILER_BACKEND_BLOCK_BUILDER_H_