Split GVN flags from flags in Hydrogen instructions.
BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/9233005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10460 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c61665604b
commit
8d741a9add
@ -416,18 +416,18 @@ void HValue::PrintRangeTo(StringStream* stream) {
|
||||
|
||||
|
||||
void HValue::PrintChangesTo(StringStream* stream) {
|
||||
int changes_flags = ChangesFlags();
|
||||
if (changes_flags == 0) return;
|
||||
GVNFlagSet changes_flags = ChangesFlags();
|
||||
if (changes_flags.IsEmpty()) return;
|
||||
stream->Add(" changes[");
|
||||
if (changes_flags == AllSideEffects()) {
|
||||
if (changes_flags == AllSideEffectsFlagSet()) {
|
||||
stream->Add("*");
|
||||
} else {
|
||||
bool add_comma = false;
|
||||
#define PRINT_DO(type) \
|
||||
if (changes_flags & (1 << kChanges##type)) { \
|
||||
if (add_comma) stream->Add(","); \
|
||||
add_comma = true; \
|
||||
stream->Add(#type); \
|
||||
#define PRINT_DO(type) \
|
||||
if (changes_flags.Contains(kChanges##type)) { \
|
||||
if (add_comma) stream->Add(","); \
|
||||
add_comma = true; \
|
||||
stream->Add(#type); \
|
||||
}
|
||||
GVN_FLAG_LIST(PRINT_DO);
|
||||
#undef PRINT_DO
|
||||
@ -1408,7 +1408,7 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
|
||||
SetOperandAt(0, context);
|
||||
SetOperandAt(1, object);
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
for (int i = 0;
|
||||
i < types->length() && types_.length() < kMaxLoadPolymorphism;
|
||||
++i) {
|
||||
@ -1420,9 +1420,9 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
|
||||
case FIELD: {
|
||||
int index = lookup.GetLocalFieldIndexFromMap(*map);
|
||||
if (index < 0) {
|
||||
SetFlag(kDependsOnInobjectFields);
|
||||
SetGVNFlag(kDependsOnInobjectFields);
|
||||
} else {
|
||||
SetFlag(kDependsOnBackingStoreFields);
|
||||
SetGVNFlag(kDependsOnBackingStoreFields);
|
||||
}
|
||||
types_.Add(types->at(i));
|
||||
break;
|
||||
|
@ -492,18 +492,26 @@ class HUseIterator BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
// There must be one corresponding kDepends flag for every kChanges flag and
|
||||
// the order of the kChanges flags must be exactly the same as of the kDepends
|
||||
// flags.
|
||||
enum GVNFlag {
|
||||
// Declare global value numbering flags.
|
||||
#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
|
||||
GVN_FLAG_LIST(DECLARE_FLAG)
|
||||
#undef DECLARE_FLAG
|
||||
kAfterLastFlag,
|
||||
kLastFlag = kAfterLastFlag - 1
|
||||
};
|
||||
|
||||
typedef EnumSet<GVNFlag> GVNFlagSet;
|
||||
|
||||
|
||||
class HValue: public ZoneObject {
|
||||
public:
|
||||
static const int kNoNumber = -1;
|
||||
|
||||
// There must be one corresponding kDepends flag for every kChanges flag and
|
||||
// the order of the kChanges flags must be exactly the same as of the kDepends
|
||||
// flags.
|
||||
enum Flag {
|
||||
// Declare global value numbering flags.
|
||||
#define DECLARE_DO(type) kChanges##type, kDependsOn##type,
|
||||
GVN_FLAG_LIST(DECLARE_DO)
|
||||
#undef DECLARE_DO
|
||||
kFlexibleRepresentation,
|
||||
// Participate in Global Value Numbering, i.e. elimination of
|
||||
// unnecessary recomputations. If an instruction sets this flag, it must
|
||||
@ -523,8 +531,8 @@ class HValue: public ZoneObject {
|
||||
|
||||
static const int kChangesToDependsFlagsLeftShift = 1;
|
||||
|
||||
static int ConvertChangesToDependsFlags(int flags) {
|
||||
return flags << kChangesToDependsFlagsLeftShift;
|
||||
static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
|
||||
return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
|
||||
}
|
||||
|
||||
static HValue* cast(HValue* value) { return value; }
|
||||
@ -622,16 +630,32 @@ class HValue: public ZoneObject {
|
||||
void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
|
||||
bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
|
||||
|
||||
void SetAllSideEffects() { flags_ |= AllSideEffects(); }
|
||||
void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
|
||||
bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
|
||||
GVNFlagSet gvn_flags() const { return gvn_flags_; }
|
||||
void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
|
||||
void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
|
||||
bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
|
||||
void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
|
||||
void ClearAllSideEffects() {
|
||||
gvn_flags_.Remove(AllSideEffectsFlagSet());
|
||||
}
|
||||
bool HasSideEffects() const {
|
||||
return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
|
||||
}
|
||||
bool HasObservableSideEffects() const {
|
||||
return (flags_ & ObservableSideEffects()) != 0;
|
||||
return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
|
||||
}
|
||||
|
||||
int ChangesFlags() const { return flags_ & ChangesFlagsMask(); }
|
||||
int ObservableChangesFlags() const {
|
||||
return flags_ & ChangesFlagsMask() & ObservableSideEffects();
|
||||
GVNFlagSet ChangesFlags() const {
|
||||
GVNFlagSet result = gvn_flags_;
|
||||
result.Intersect(AllChangesFlagSet());
|
||||
return result;
|
||||
}
|
||||
|
||||
GVNFlagSet ObservableChangesFlags() const {
|
||||
GVNFlagSet result = gvn_flags_;
|
||||
result.Intersect(AllChangesFlagSet());
|
||||
result.Intersect(AllObservableSideEffectsFlagSet());
|
||||
return result;
|
||||
}
|
||||
|
||||
Range* range() const { return range_; }
|
||||
@ -697,25 +721,28 @@ class HValue: public ZoneObject {
|
||||
representation_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
static int ChangesFlagsMask() {
|
||||
int result = 0;
|
||||
static GVNFlagSet AllChangesFlagSet() {
|
||||
GVNFlagSet result;
|
||||
// Create changes mask.
|
||||
#define ADD_FLAG(type) result |= (1 << kChanges##type);
|
||||
#define ADD_FLAG(type) result.Add(kChanges##type);
|
||||
GVN_FLAG_LIST(ADD_FLAG)
|
||||
#undef ADD_FLAG
|
||||
return result;
|
||||
}
|
||||
|
||||
// A flag mask to mark an instruction as having arbitrary side effects.
|
||||
static int AllSideEffects() {
|
||||
return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
|
||||
static GVNFlagSet AllSideEffectsFlagSet() {
|
||||
GVNFlagSet result = AllChangesFlagSet();
|
||||
result.Remove(kChangesOsrEntries);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A flag mask of all side effects that can make observable changes in
|
||||
// an executing program (i.e. are not safe to repeat, move or remove);
|
||||
static int ObservableSideEffects() {
|
||||
return ChangesFlagsMask() & ~(1 << kChangesElementsKind);
|
||||
static GVNFlagSet AllObservableSideEffectsFlagSet() {
|
||||
GVNFlagSet result = AllChangesFlagSet();
|
||||
result.Remove(kChangesElementsKind);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Remove the matching use from the use list if present. Returns the
|
||||
@ -735,6 +762,7 @@ class HValue: public ZoneObject {
|
||||
HUseListNode* use_list_;
|
||||
Range* range_;
|
||||
int flags_;
|
||||
GVNFlagSet gvn_flags_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HValue);
|
||||
};
|
||||
@ -772,7 +800,7 @@ class HInstruction: public HValue {
|
||||
: next_(NULL),
|
||||
previous_(NULL),
|
||||
position_(RelocInfo::kNoPosition) {
|
||||
SetFlag(kDependsOnOsrEntries);
|
||||
SetGVNFlag(kDependsOnOsrEntries);
|
||||
}
|
||||
|
||||
virtual void DeleteFromGraph() { Unlink(); }
|
||||
@ -1716,8 +1744,8 @@ class HJSArrayLength: public HTemplateInstruction<2> {
|
||||
SetOperandAt(1, typecheck);
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnArrayLengths);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnArrayLengths);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -1741,7 +1769,7 @@ class HFixedArrayBaseLength: public HUnaryOperation {
|
||||
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnArrayLengths);
|
||||
SetGVNFlag(kDependsOnArrayLengths);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -1760,7 +1788,7 @@ class HElementsKind: public HUnaryOperation {
|
||||
explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
|
||||
set_representation(Representation::Integer32());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnElementsKind);
|
||||
SetGVNFlag(kDependsOnElementsKind);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -1886,8 +1914,8 @@ class HLoadElements: public HUnaryOperation {
|
||||
explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetFlag(kDependsOnElementsKind);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnElementsKind);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -1937,7 +1965,7 @@ class HCheckMap: public HTemplateInstruction<2> {
|
||||
SetOperandAt(1, typecheck != NULL ? typecheck : value);
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
has_element_transitions_ =
|
||||
map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL ||
|
||||
map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL;
|
||||
@ -2105,7 +2133,7 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
||||
HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
|
||||
: prototype_(prototype), holder_(holder) {
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -3255,7 +3283,7 @@ class HSar: public HBitwiseBinaryOperation {
|
||||
class HOsrEntry: public HTemplateInstruction<0> {
|
||||
public:
|
||||
explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
|
||||
SetFlag(kChangesOsrEntries);
|
||||
SetGVNFlag(kChangesOsrEntries);
|
||||
}
|
||||
|
||||
int ast_id() const { return ast_id_; }
|
||||
@ -3343,7 +3371,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
||||
: cell_(cell), details_(details) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnGlobalVars);
|
||||
SetGVNFlag(kDependsOnGlobalVars);
|
||||
}
|
||||
|
||||
Handle<JSGlobalPropertyCell> cell() const { return cell_; }
|
||||
@ -3422,7 +3450,7 @@ class HStoreGlobalCell: public HUnaryOperation {
|
||||
: HUnaryOperation(value),
|
||||
cell_(cell),
|
||||
details_(details) {
|
||||
SetFlag(kChangesGlobalVars);
|
||||
SetGVNFlag(kChangesGlobalVars);
|
||||
}
|
||||
|
||||
Handle<JSGlobalPropertyCell> cell() const { return cell_; }
|
||||
@ -3513,7 +3541,7 @@ class HLoadContextSlot: public HUnaryOperation {
|
||||
}
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnContextSlots);
|
||||
SetGVNFlag(kDependsOnContextSlots);
|
||||
}
|
||||
|
||||
int slot_index() const { return slot_index_; }
|
||||
@ -3566,7 +3594,7 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
|
||||
: slot_index_(slot_index), mode_(mode) {
|
||||
SetOperandAt(0, context);
|
||||
SetOperandAt(1, value);
|
||||
SetFlag(kChangesContextSlots);
|
||||
SetGVNFlag(kChangesContextSlots);
|
||||
}
|
||||
|
||||
HValue* context() { return OperandAt(0); }
|
||||
@ -3608,11 +3636,11 @@ class HLoadNamedField: public HUnaryOperation {
|
||||
offset_(offset) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
if (is_in_object) {
|
||||
SetFlag(kDependsOnInobjectFields);
|
||||
SetGVNFlag(kDependsOnInobjectFields);
|
||||
} else {
|
||||
SetFlag(kDependsOnBackingStoreFields);
|
||||
SetGVNFlag(kDependsOnBackingStoreFields);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3706,7 +3734,7 @@ class HLoadFunctionPrototype: public HUnaryOperation {
|
||||
: HUnaryOperation(function) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnCalls);
|
||||
SetGVNFlag(kDependsOnCalls);
|
||||
}
|
||||
|
||||
HValue* function() { return OperandAt(0); }
|
||||
@ -3728,7 +3756,7 @@ class HLoadKeyedFastElement: public HTemplateInstruction<2> {
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, key);
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kDependsOnArrayElements);
|
||||
SetGVNFlag(kDependsOnArrayElements);
|
||||
SetFlag(kUseGVN);
|
||||
}
|
||||
|
||||
@ -3759,7 +3787,7 @@ class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
|
||||
SetOperandAt(0, elements);
|
||||
SetOperandAt(1, key);
|
||||
set_representation(Representation::Double());
|
||||
SetFlag(kDependsOnDoubleArrayElements);
|
||||
SetGVNFlag(kDependsOnDoubleArrayElements);
|
||||
SetFlag(kUseGVN);
|
||||
}
|
||||
|
||||
@ -3796,9 +3824,9 @@ class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
|
||||
} else {
|
||||
set_representation(Representation::Integer32());
|
||||
}
|
||||
SetFlag(kDependsOnSpecializedArrayElements);
|
||||
SetGVNFlag(kDependsOnSpecializedArrayElements);
|
||||
// Native code could change the specialized array.
|
||||
SetFlag(kDependsOnCalls);
|
||||
SetGVNFlag(kDependsOnCalls);
|
||||
SetFlag(kUseGVN);
|
||||
}
|
||||
|
||||
@ -3868,9 +3896,9 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, val);
|
||||
if (is_in_object_) {
|
||||
SetFlag(kChangesInobjectFields);
|
||||
SetGVNFlag(kChangesInobjectFields);
|
||||
} else {
|
||||
SetFlag(kChangesBackingStoreFields);
|
||||
SetGVNFlag(kChangesBackingStoreFields);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3945,7 +3973,7 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> {
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, key);
|
||||
SetOperandAt(2, val);
|
||||
SetFlag(kChangesArrayElements);
|
||||
SetGVNFlag(kChangesArrayElements);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -3987,7 +4015,7 @@ class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
|
||||
SetOperandAt(0, elements);
|
||||
SetOperandAt(1, key);
|
||||
SetOperandAt(2, val);
|
||||
SetFlag(kChangesDoubleArrayElements);
|
||||
SetGVNFlag(kChangesDoubleArrayElements);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -4021,7 +4049,7 @@ class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
|
||||
HValue* val,
|
||||
ElementsKind elements_kind)
|
||||
: elements_kind_(elements_kind) {
|
||||
SetFlag(kChangesSpecializedArrayElements);
|
||||
SetGVNFlag(kChangesSpecializedArrayElements);
|
||||
SetOperandAt(0, external_elements);
|
||||
SetOperandAt(1, key);
|
||||
SetOperandAt(2, val);
|
||||
@ -4099,7 +4127,8 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
|
||||
transitioned_map_(transitioned_map) {
|
||||
SetOperandAt(0, object);
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kChangesElementsKind);
|
||||
SetGVNFlag(kChangesMaps);
|
||||
SetGVNFlag(kChangesElementsKind);
|
||||
set_representation(Representation::Tagged());
|
||||
}
|
||||
|
||||
@ -4134,7 +4163,7 @@ class HStringAdd: public HBinaryOperation {
|
||||
: HBinaryOperation(context, left, right) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -4160,7 +4189,7 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
|
||||
SetOperandAt(2, index);
|
||||
set_representation(Representation::Integer32());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -4215,7 +4244,7 @@ class HStringLength: public HUnaryOperation {
|
||||
explicit HStringLength(HValue* string) : HUnaryOperation(string) {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetFlag(kDependsOnMaps);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
|
@ -1110,10 +1110,10 @@ HValueMap::HValueMap(Zone* zone, const HValueMap* other)
|
||||
}
|
||||
|
||||
|
||||
void HValueMap::Kill(int flags) {
|
||||
int depends_flags = HValue::ConvertChangesToDependsFlags(flags);
|
||||
if ((present_flags_ & depends_flags) == 0) return;
|
||||
present_flags_ = 0;
|
||||
void HValueMap::Kill(GVNFlagSet flags) {
|
||||
GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
|
||||
if (!present_flags_.ContainsAnyOf(depends_flags)) return;
|
||||
present_flags_.RemoveAll();
|
||||
for (int i = 0; i < array_size_; ++i) {
|
||||
HValue* value = array_[i].value;
|
||||
if (value != NULL) {
|
||||
@ -1122,7 +1122,8 @@ void HValueMap::Kill(int flags) {
|
||||
int next;
|
||||
for (int current = array_[i].next; current != kNil; current = next) {
|
||||
next = lists_[current].next;
|
||||
if ((lists_[current].value->flags() & depends_flags) != 0) {
|
||||
HValue* value = lists_[current].value;
|
||||
if (value->gvn_flags().ContainsAnyOf(depends_flags)) {
|
||||
// Drop it.
|
||||
count_--;
|
||||
lists_[current].next = free_list_head_;
|
||||
@ -1131,13 +1132,14 @@ void HValueMap::Kill(int flags) {
|
||||
// Keep it.
|
||||
lists_[current].next = kept;
|
||||
kept = current;
|
||||
present_flags_ |= lists_[current].value->flags();
|
||||
present_flags_.Add(value->gvn_flags());
|
||||
}
|
||||
}
|
||||
array_[i].next = kept;
|
||||
|
||||
// Now possibly drop directly indexed element.
|
||||
if ((array_[i].value->flags() & depends_flags) != 0) { // Drop it.
|
||||
value = array_[i].value;
|
||||
if (value->gvn_flags().ContainsAnyOf(depends_flags)) { // Drop it.
|
||||
count_--;
|
||||
int head = array_[i].next;
|
||||
if (head == kNil) {
|
||||
@ -1149,7 +1151,7 @@ void HValueMap::Kill(int flags) {
|
||||
free_list_head_ = head;
|
||||
}
|
||||
} else {
|
||||
present_flags_ |= array_[i].value->flags(); // Keep it.
|
||||
present_flags_.Add(value->gvn_flags()); // Keep it.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1356,8 +1358,8 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
||||
loop_side_effects_(graph->blocks()->length()),
|
||||
visited_on_paths_(graph->zone(), graph->blocks()->length()) {
|
||||
ASSERT(info->isolate()->heap()->allow_allocation(false));
|
||||
block_side_effects_.AddBlock(0, graph_->blocks()->length());
|
||||
loop_side_effects_.AddBlock(0, graph_->blocks()->length());
|
||||
block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
|
||||
loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
|
||||
}
|
||||
~HGlobalValueNumberer() {
|
||||
ASSERT(!info_->isolate()->heap()->allow_allocation(true));
|
||||
@ -1367,14 +1369,15 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
||||
bool Analyze();
|
||||
|
||||
private:
|
||||
int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator,
|
||||
HBasicBlock* dominated);
|
||||
GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
|
||||
HBasicBlock* dominator,
|
||||
HBasicBlock* dominated);
|
||||
void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
|
||||
void ComputeBlockSideEffects();
|
||||
void LoopInvariantCodeMotion();
|
||||
void ProcessLoopBlock(HBasicBlock* block,
|
||||
HBasicBlock* before_loop,
|
||||
int loop_kills);
|
||||
GVNFlagSet loop_kills);
|
||||
bool AllowCodeMotion();
|
||||
bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
|
||||
|
||||
@ -1387,10 +1390,10 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
||||
bool removed_side_effects_;
|
||||
|
||||
// A map of block IDs to their side effects.
|
||||
ZoneList<int> block_side_effects_;
|
||||
ZoneList<GVNFlagSet> block_side_effects_;
|
||||
|
||||
// A map of loop header block IDs to their loop's side effects.
|
||||
ZoneList<int> loop_side_effects_;
|
||||
ZoneList<GVNFlagSet> loop_side_effects_;
|
||||
|
||||
// Used when collecting side effects on paths from dominator to
|
||||
// dominated.
|
||||
@ -1415,23 +1418,24 @@ void HGlobalValueNumberer::ComputeBlockSideEffects() {
|
||||
HBasicBlock* block = graph_->blocks()->at(i);
|
||||
HInstruction* instr = block->first();
|
||||
int id = block->block_id();
|
||||
int side_effects = 0;
|
||||
GVNFlagSet side_effects;
|
||||
while (instr != NULL) {
|
||||
side_effects |= instr->ChangesFlags();
|
||||
side_effects.Add(instr->ChangesFlags());
|
||||
instr = instr->next();
|
||||
}
|
||||
block_side_effects_[id] |= side_effects;
|
||||
block_side_effects_[id].Add(side_effects);
|
||||
|
||||
// Loop headers are part of their loop.
|
||||
if (block->IsLoopHeader()) {
|
||||
loop_side_effects_[id] |= side_effects;
|
||||
loop_side_effects_[id].Add(side_effects);
|
||||
}
|
||||
|
||||
// Propagate loop side effects upwards.
|
||||
if (block->HasParentLoopHeader()) {
|
||||
int header_id = block->parent_loop_header()->block_id();
|
||||
loop_side_effects_[header_id] |=
|
||||
block->IsLoopHeader() ? loop_side_effects_[id] : side_effects;
|
||||
loop_side_effects_[header_id].Add(block->IsLoopHeader()
|
||||
? loop_side_effects_[id]
|
||||
: side_effects);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1441,10 +1445,10 @@ void HGlobalValueNumberer::LoopInvariantCodeMotion() {
|
||||
for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
|
||||
HBasicBlock* block = graph_->blocks()->at(i);
|
||||
if (block->IsLoopHeader()) {
|
||||
int side_effects = loop_side_effects_[block->block_id()];
|
||||
GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
|
||||
TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
|
||||
block->block_id(),
|
||||
side_effects);
|
||||
side_effects.ToIntegral());
|
||||
|
||||
HBasicBlock* last = block->loop_information()->GetLastBackEdge();
|
||||
for (int j = block->block_id(); j <= last->block_id(); ++j) {
|
||||
@ -1457,17 +1461,17 @@ void HGlobalValueNumberer::LoopInvariantCodeMotion() {
|
||||
|
||||
void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
|
||||
HBasicBlock* loop_header,
|
||||
int loop_kills) {
|
||||
GVNFlagSet loop_kills) {
|
||||
HBasicBlock* pre_header = loop_header->predecessors()->at(0);
|
||||
int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
|
||||
GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
|
||||
TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
|
||||
block->block_id(),
|
||||
depends_flags);
|
||||
depends_flags.ToIntegral());
|
||||
HInstruction* instr = block->first();
|
||||
while (instr != NULL) {
|
||||
HInstruction* next = instr->next();
|
||||
if (instr->CheckFlag(HValue::kUseGVN) &&
|
||||
(instr->flags() & depends_flags) == 0) {
|
||||
!instr->gvn_flags().ContainsAnyOf(depends_flags)) {
|
||||
TraceGVN("Checking instruction %d (%s)\n",
|
||||
instr->id(),
|
||||
instr->Mnemonic());
|
||||
@ -1503,20 +1507,20 @@ bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
|
||||
}
|
||||
|
||||
|
||||
int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
|
||||
GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
|
||||
HBasicBlock* dominator, HBasicBlock* dominated) {
|
||||
int side_effects = 0;
|
||||
GVNFlagSet side_effects;
|
||||
for (int i = 0; i < dominated->predecessors()->length(); ++i) {
|
||||
HBasicBlock* block = dominated->predecessors()->at(i);
|
||||
if (dominator->block_id() < block->block_id() &&
|
||||
block->block_id() < dominated->block_id() &&
|
||||
visited_on_paths_.Add(block->block_id())) {
|
||||
side_effects |= block_side_effects_[block->block_id()];
|
||||
side_effects.Add(block_side_effects_[block->block_id()]);
|
||||
if (block->IsLoopHeader()) {
|
||||
side_effects |= loop_side_effects_[block->block_id()];
|
||||
side_effects.Add(loop_side_effects_[block->block_id()]);
|
||||
}
|
||||
side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
|
||||
dominator, block);
|
||||
side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
|
||||
dominator, block));
|
||||
}
|
||||
}
|
||||
return side_effects;
|
||||
@ -1537,8 +1541,8 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
||||
HInstruction* instr = block->first();
|
||||
while (instr != NULL) {
|
||||
HInstruction* next = instr->next();
|
||||
int flags = instr->ChangesFlags();
|
||||
if (flags != 0) {
|
||||
GVNFlagSet flags = instr->ChangesFlags();
|
||||
if (!flags.IsEmpty()) {
|
||||
// Clear all instructions in the map that are affected by side effects.
|
||||
map->Kill(flags);
|
||||
TraceGVN("Instruction %d kills\n", instr->id());
|
||||
@ -3597,7 +3601,7 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
|
||||
instr->set_transition(transition);
|
||||
// TODO(fschneider): Record the new map type of the object in the IR to
|
||||
// enable elimination of redundant checks after the transition store.
|
||||
instr->SetFlag(HValue::kChangesMaps);
|
||||
instr->SetGVNFlag(kChangesMaps);
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -1056,10 +1056,10 @@ class HValueMap: public ZoneObject {
|
||||
Resize(kInitialSize);
|
||||
}
|
||||
|
||||
void Kill(int flags);
|
||||
void Kill(GVNFlagSet flags);
|
||||
|
||||
void Add(HValue* value) {
|
||||
present_flags_ |= value->flags();
|
||||
present_flags_.Add(value->gvn_flags());
|
||||
Insert(value);
|
||||
}
|
||||
|
||||
@ -1092,7 +1092,8 @@ class HValueMap: public ZoneObject {
|
||||
int array_size_;
|
||||
int lists_size_;
|
||||
int count_; // The number of values stored in the HValueMap.
|
||||
int present_flags_; // All flags that are in any value in the HValueMap.
|
||||
GVNFlagSet present_flags_; // All flags that are in any value in the
|
||||
// HValueMap.
|
||||
HValueMapListElement* array_; // Primary store - contains the first value
|
||||
// with a given hash. Colliding elements are stored in linked lists.
|
||||
HValueMapListElement* lists_; // The linked lists containing hash collisions.
|
||||
|
10
src/utils.h
10
src/utils.h
@ -1,4 +1,4 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -931,9 +931,17 @@ class EnumSet {
|
||||
explicit EnumSet(T bits = 0) : bits_(bits) {}
|
||||
bool IsEmpty() const { return bits_ == 0; }
|
||||
bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
|
||||
bool ContainsAnyOf(const EnumSet& set) const {
|
||||
return (bits_ & set.bits_) != 0;
|
||||
}
|
||||
void Add(E element) { bits_ |= Mask(element); }
|
||||
void Add(const EnumSet& set) { bits_ |= set.bits_; }
|
||||
void Remove(E element) { bits_ &= ~Mask(element); }
|
||||
void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
|
||||
void RemoveAll() { bits_ = 0; }
|
||||
void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
|
||||
T ToIntegral() const { return bits_; }
|
||||
bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
|
||||
|
||||
private:
|
||||
T Mask(E element) const {
|
||||
|
Loading…
Reference in New Issue
Block a user