Files
sdk/runtime/vm/compiler/backend/constant_propagator.h
T
Samir Jindel c1df0d4c10 [vm] Very basic store barrier elimination.
If the left-hand side of the store is an allocation and no GC-triggering
instructions have been executed since, it is safe to elide the store barrier.

This gives a 1.4% code size reduction on Flutter Gallery ARM32.

Change-Id: Ib7227d3ef9d798d5e30f238f3f789f9a2e637d6a
Cq-Include-Trybots: luci.dart.try: vm-kernel-optcounter-threshold-linux-release-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/64687
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2018-07-17 22:59:28 +00:00

91 lines
2.8 KiB
C++

// Copyright (c) 2012, 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_CONSTANT_PROPAGATOR_H_
#define RUNTIME_VM_COMPILER_BACKEND_CONSTANT_PROPAGATOR_H_
#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/il.h"
namespace dart {
// Sparse conditional constant propagation and unreachable code elimination.
// Assumes that use lists are computed and preserves them.
class ConstantPropagator : public FlowGraphVisitor {
public:
ConstantPropagator(FlowGraph* graph,
const GrowableArray<BlockEntryInstr*>& ignored);
static void Optimize(FlowGraph* graph);
// (1) Visit branches to optimize away unreachable blocks discovered by range
// analysis.
// (2) Eliminate branches that have the same true- and false-target: For
// example, this occurs after expressions like
//
// if (a == null || b == null) {
// ...
// }
//
// where b is known to be null.
static void OptimizeBranches(FlowGraph* graph);
// Used to initialize the abstract value of definitions.
static RawObject* Unknown() { return Object::unknown_constant().raw(); }
private:
void Analyze();
void Transform();
void EliminateRedundantBranches();
void SetReachable(BlockEntryInstr* block);
bool SetValue(Definition* definition, const Object& value);
Definition* UnwrapPhi(Definition* defn);
void MarkPhi(Definition* defn);
// Assign the join (least upper bound) of a pair of abstract values to the
// first one.
void Join(Object* left, const Object& right);
bool IsUnknown(const Object& value) { return value.raw() == unknown_.raw(); }
bool IsNonConstant(const Object& value) {
return value.raw() == non_constant_.raw();
}
bool IsConstant(const Object& value) {
return !IsNonConstant(value) && !IsUnknown(value);
}
void VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op);
void VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op);
virtual void VisitBlocks() { UNREACHABLE(); }
#define DECLARE_VISIT(type, attrs) virtual void Visit##type(type##Instr* instr);
FOR_EACH_INSTRUCTION(DECLARE_VISIT)
#undef DECLARE_VISIT
Isolate* isolate() const { return graph_->isolate(); }
FlowGraph* graph_;
// Sentinels for unknown constant and non-constant values.
const Object& unknown_;
const Object& non_constant_;
// Analysis results. For each block, a reachability bit. Indexed by
// preorder number.
BitVector* reachable_;
BitVector* marked_phis_;
// Worklists of blocks and definitions.
GrowableArray<BlockEntryInstr*> block_worklist_;
DefinitionWorklist definition_worklist_;
};
} // namespace dart
#endif // RUNTIME_VM_COMPILER_BACKEND_CONSTANT_PROPAGATOR_H_