Revision: 13543
Author: [email protected]
Date: Tue Jan 29 07:46:34 2013
Log: Foundation for the use of informative definitions in Crankshaft.
Review URL: https://codereview.chromium.org/12090021
http://code.google.com/p/v8/source/detail?r=13543
Modified:
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 29
07:28:05 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 29
07:46:34 2013
@@ -501,8 +501,6 @@
int LCodeGen::ToInteger32(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
- ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
- ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Jan 28 05:24:41
2013
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Jan 29 07:46:34
2013
@@ -35,7 +35,6 @@
namespace internal {
-// TODO(svenpanne) Merge with OptimizingCompiler::OptimizeGraph().
static LChunk* OptimizeGraph(HGraph* graph) {
AssertNoAllocation no_gc;
NoHandleAllocation no_handles;
@@ -129,7 +128,8 @@
HInstruction* load = BuildUncheckedMonomorphicElementAccess(
GetParameter(0), GetParameter(1), NULL, NULL,
- casted_stub()->is_js_array(), casted_stub()->elements_kind(), false);
+ casted_stub()->is_js_array(), casted_stub()->elements_kind(),
+ false, Representation::Tagged());
AddInstruction(load);
HReturn* ret = new(zone) HReturn(load, context());
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Thu Jan 24
09:54:30 2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Jan 29
07:46:34 2013
@@ -772,6 +772,28 @@
stream->Add(" ");
length()->PrintNameTo(stream);
}
+
+
+void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
+ ASSERT(CheckFlag(kFlexibleRepresentation));
+ Representation r;
+ if (key_mode_ == DONT_ALLOW_SMI_KEY ||
+ !length()->representation().IsTagged()) {
+ r = Representation::Integer32();
+ } else if (index()->representation().IsTagged() ||
+ (index()->IsConstant() &&
+ HConstant::cast(index())->HasInteger32Value() &&
+ Smi::IsValid(HConstant::cast(index())->Integer32Value()))) {
+ // If the index is tagged, or a constant that holds a Smi, allow the
length
+ // to be tagged, since it is usually already tagged from loading it
out of
+ // the length field of a JSArray. This allows for direct comparison
without
+ // untagging.
+ r = Representation::Tagged();
+ } else {
+ r = Representation::Integer32();
+ }
+ UpdateRepresentation(r, h_infer, "boundscheck");
+}
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Jan 24 09:54:30
2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Jan 29 07:46:34
2013
@@ -672,6 +672,31 @@
visited->Add(id());
return NULL;
}
+
+ // There are HInstructions that do not really change a value, they
+ // only add pieces of information to it (like bounds checks, map checks,
+ // smi checks...).
+ // We call these instructions "informative definitions", or "iDef".
+ // One of the iDef operands is special because it is the value that is
+ // "transferred" to the output, we call it the "redefined operand".
+ // If an HValue is an iDef it must override RedefinedOperandIndex() so
that
+ // it does not return kNoRedefinedOperand;
+ static const int kNoRedefinedOperand = -1;
+ virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
+ bool IsInformativeDefinition() {
+ return RedefinedOperandIndex() != kNoRedefinedOperand;
+ }
+ HValue* RedefinedOperand() {
+ ASSERT(IsInformativeDefinition());
+ return OperandAt(RedefinedOperandIndex());
+ }
+
+ // This method must always return the original HValue SSA definition
+ // (regardless of any iDef of this value).
+ HValue* ActualValue() {
+ return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
+ : this;
+ }
bool IsDefinedAfter(HBasicBlock* other) const;
@@ -3020,43 +3045,37 @@
class HBoundsCheck: public HTemplateInstruction<2> {
public:
HBoundsCheck(HValue* index, HValue* length,
- BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
+ BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY,
+ Representation r = Representation::None())
: key_mode_(key_mode) {
SetOperandAt(0, index);
SetOperandAt(1, length);
- set_representation(Representation::Integer32());
+ if (r.IsNone()) {
+ // In the normal compilation pipeline the representation is flexible
+ // (see comment to RequiredInputRepresentation).
+ SetFlag(kFlexibleRepresentation);
+ } else {
+ // When compiling stubs we want to set the representation explicitly
+ // so the compilation pipeline can skip the HInferRepresentation
phase.
+ set_representation(r);
+ }
SetFlag(kUseGVN);
}
virtual Representation RequiredInputRepresentation(int arg_index) {
- if (key_mode_ == DONT_ALLOW_SMI_KEY ||
- !length()->representation().IsTagged()) {
- return Representation::Integer32();
- }
- // If the index is tagged and isn't constant, then allow the length
- // to be tagged, since it is usually already tagged from loading it
out of
- // the length field of a JSArray. This allows for direct comparison
without
- // untagging.
- if (index()->representation().IsTagged() && !index()->IsConstant()) {
- return Representation::Tagged();
- }
- // Also allow the length to be tagged if the index is constant, because
- // it can be tagged to allow direct comparison.
- if (index()->IsConstant() &&
- index()->representation().IsInteger32() &&
- arg_index == 1) {
- return Representation::Tagged();
- }
- return Representation::Integer32();
+ return representation();
}
virtual Representation observed_input_representation(int index) {
return Representation::Integer32();
}
virtual void PrintDataTo(StringStream* stream);
+ virtual void InferRepresentation(HInferRepresentation* h_infer);
HValue* index() { return OperandAt(0); }
HValue* length() { return OperandAt(1); }
+
+ virtual int RedefinedOperandIndex() { return 0; }
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
@@ -4433,6 +4452,11 @@
virtual bool IsDehoisted() = 0;
virtual void SetDehoisted(bool is_dehoisted) = 0;
virtual ~ArrayInstructionInterface() { };
+
+ static Representation KeyedAccessIndexRequirement(Representation r) {
+ return r.IsInteger32() ? Representation::Integer32()
+ : Representation::Tagged();
+ }
};
@@ -4516,7 +4540,10 @@
return is_external() ? Representation::External()
: Representation::Tagged();
}
- if (index == 1) return Representation::Integer32();
+ if (index == 1) {
+ return ArrayInstructionInterface::KeyedAccessIndexRequirement(
+ OperandAt(1)->representation());
+ }
return Representation::None();
}
@@ -4731,7 +4758,8 @@
return is_external() ? Representation::External()
: Representation::Tagged();
} else if (index == 1) {
- return Representation::Integer32();
+ return ArrayInstructionInterface::KeyedAccessIndexRequirement(
+ OperandAt(1)->representation());
}
ASSERT_EQ(index, 2);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Fri Jan 25 08:55:00 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Tue Jan 29 07:46:34 2013
@@ -745,7 +745,8 @@
HCheckMaps* mapcheck,
bool is_js_array,
ElementsKind elements_kind,
- bool is_store) {
+ bool is_store,
+ Representation checked_index_representation) {
Zone* zone = this->zone();
// No GVNFlag is necessary for ElementsKind if there is an explicit
dependency
// on a HElementsTransition instruction. The flag can also be removed if
the
@@ -773,8 +774,8 @@
HInstruction* checked_key = NULL;
if (IsExternalArrayElementsKind(elements_kind)) {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
- checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
- ALLOW_SMI_KEY));
+ checked_key = AddInstruction(new(zone) HBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation));
HLoadExternalArrayPointer* external_elements =
new(zone) HLoadExternalArrayPointer(elements);
AddInstruction(external_elements);
@@ -791,8 +792,8 @@
} else {
length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
}
- checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
- ALLOW_SMI_KEY));
+ checked_key = AddInstruction(new(zone) HBoundsCheck(
+ key, length, ALLOW_SMI_KEY, checked_index_representation));
return BuildFastElementAccess(elements, checked_key, val, mapcheck,
elements_kind, is_store);
}
@@ -3586,10 +3587,12 @@
HStackCheckEliminator sce(this);
sce.Process();
- EliminateRedundantBoundsChecks();
- DehoistSimpleArrayIndexComputations();
+ if (FLAG_array_bounds_checks_elimination)
EliminateRedundantBoundsChecks();
+ if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
if (FLAG_dead_code_elimination) DeadCodeElimination();
+ RestoreActualValues();
+
return true;
}
@@ -3727,6 +3730,7 @@
new_check->index()->representation(),
new_offset);
if (!result) return false;
+ upper_check_->ReplaceAllUsesWith(upper_check_->index());
upper_check_->SetOperandAt(0, added_upper_index_);
}
} else if (new_offset < lower_offset_) {
@@ -3742,6 +3746,7 @@
new_check->index()->representation(),
new_offset);
if (!result) return false;
+ lower_check_->ReplaceAllUsesWith(lower_check_->index());
lower_check_->SetOperandAt(0, added_lower_index_);
}
} else {
@@ -3749,7 +3754,7 @@
}
if (!keep_new_check) {
- new_check->DeleteAndReplaceWith(NULL);
+ new_check->DeleteAndReplaceWith(new_check->ActualValue());
}
return true;
@@ -3885,10 +3890,6 @@
if (!i->IsBoundsCheck()) continue;
HBoundsCheck* check = HBoundsCheck::cast(i);
- check->ReplaceAllUsesWith(check->index());
-
- if (!FLAG_array_bounds_checks_elimination) continue;
-
int32_t offset;
BoundsCheckKey* key =
BoundsCheckKey::Create(zone(), check, &offset);
@@ -3906,7 +3907,7 @@
NULL);
*data_p = bb_data_list;
} else if (data->OffsetIsCovered(offset)) {
- check->DeleteAndReplaceWith(NULL);
+ check->DeleteAndReplaceWith(check->ActualValue());
} else if (data->BasicBlock() != bb ||
!data->CoverCheck(check, offset)) {
// If the check is in the current BB we try to modify it by calling
@@ -3955,7 +3956,7 @@
static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
- HValue* index = array_operation->GetKey();
+ HValue* index = array_operation->GetKey()->ActualValue();
if (!index->representation().IsInteger32()) return;
HConstant* constant;
@@ -4003,8 +4004,6 @@
void HGraph::DehoistSimpleArrayIndexComputations() {
- if (!FLAG_array_index_dehoisting) return;
-
HPhase phase("H_Dehoist index computations", this);
for (int i = 0; i < blocks()->length(); ++i) {
for (HInstruction* instr = blocks()->at(i)->first();
@@ -4054,6 +4053,30 @@
}
}
}
+
+
+void HGraph::RestoreActualValues() {
+ HPhase phase("H_Restore actual values", this);
+
+ for (int block_index = 0; block_index < blocks()->length();
block_index++) {
+ HBasicBlock* block = blocks()->at(block_index);
+
+#ifdef DEBUG
+ for (int i = 0; i < block->phis()->length(); i++) {
+ HPhi* phi = block->phis()->at(i);
+ ASSERT(phi->ActualValue() == phi);
+ }
+#endif
+
+ for (HInstruction* instruction = block->first();
+ instruction != NULL;
+ instruction = instruction->next()) {
+ if (instruction->ActualValue() != instruction) {
+ instruction->ReplaceAllUsesWith(instruction->ActualValue());
+ }
+ }
+ }
+}
void HOptimizedGraphBuilder::AddPhi(HPhi* instr) {
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Wed Jan 23 05:52:00 2013
+++ /branches/bleeding_edge/src/hydrogen.h Tue Jan 29 07:46:34 2013
@@ -273,6 +273,7 @@
void EliminateRedundantBoundsChecks();
void DehoistSimpleArrayIndexComputations();
void DeadCodeElimination();
+ void RestoreActualValues();
void PropagateDeoptimizingMark();
void EliminateUnusedInstructions();
@@ -897,7 +898,8 @@
HCheckMaps* mapcheck,
bool is_js_array,
ElementsKind elements_kind,
- bool is_store);
+ bool is_store,
+ Representation checked_index_representation =
Representation::None());
private:
HGraphBuilder();
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 29
07:28:05 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 29
07:46:34 2013
@@ -502,8 +502,6 @@
int LCodeGen::ToInteger32(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
- ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
- ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
@@ -3207,13 +3205,6 @@
uint32_t additional_index) {
Register elements_pointer_reg = ToRegister(elements_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
- // Even though the HLoad/StoreKeyed instructions force the input
- // representation for the key to be an integer, the input gets replaced
during
- // bound check elimination with the index argument to the bounds check,
which
- // can be tagged, so that case must be handled here, too.
- if (key_representation.IsTagged() && (shift_size >= 1)) {
- shift_size -= kSmiTagSize;
- }
if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key));
if (constant_value & 0xF0000000) {
@@ -3223,6 +3214,10 @@
((constant_value + additional_index) << shift_size)
+ offset);
} else {
+ // Take the tag bit into account while computing the shift size.
+ if (key_representation.IsTagged() && (shift_size >= 1)) {
+ shift_size -= kSmiTagSize;
+ }
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
return Operand(elements_pointer_reg,
ToRegister(key),
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Mon Jan 28
06:50:47 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue Jan 29
07:46:34 2013
@@ -490,8 +490,6 @@
int LCodeGen::ToInteger32(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
- ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
- ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Jan 28
06:50:47 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Jan 29
07:46:34 2013
@@ -425,8 +425,6 @@
int LCodeGen::ToInteger32(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
- ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
- ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.