Commit af2663af authored by titzer@chromium.org's avatar titzer@chromium.org

Remove instructions and infrastructure related to IDEFs that is now obsolete...

Remove instructions and infrastructure related to IDEFs that is now obsolete (and was never turned on). The new bounds check elimination phase doesn't make use of these features, as they were the first parts of the previous approach which was never completed.
BUG=
R=danno@chromium.org

Review URL: https://codereview.chromium.org/21579003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16027 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a37040b2
......@@ -1832,17 +1832,6 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
HInductionVariableAnnotation* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
......
......@@ -267,7 +267,6 @@ DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
DEFINE_bool(use_osr, true, "use on-stack replacement")
DEFINE_bool(idefs, false, "use informative definitions")
DEFINE_bool(array_bounds_checks_elimination, true,
"perform array bounds checks elimination")
DEFINE_bool(array_bounds_checks_hoisting, false,
......
......@@ -149,116 +149,6 @@ void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
}
// This method is recursive but it is guaranteed to terminate because
// RedefinedOperand() always dominates "this".
bool HValue::IsRelationTrue(NumericRelation relation,
HValue* other,
int offset,
int scale) {
if (this == other) {
return scale == 0 && relation.IsExtendable(offset);
}
// Test the direct relation.
if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
// If scale is 0 try the reversed relation.
if (scale == 0 &&
// TODO(mmassi): do we need the full, recursive IsRelationTrue?
other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
return true;
}
// Try decomposition (but do not accept scaled compounds).
DecompositionResult decomposition;
if (TryDecompose(&decomposition) &&
decomposition.scale() == 0 &&
decomposition.base()->IsRelationTrue(relation, other,
offset + decomposition.offset(),
scale)) {
return true;
}
// Pass the request to the redefined value.
HValue* redefined = RedefinedOperand();
return redefined != NULL && redefined->IsRelationTrue(relation, other,
offset, scale);
}
bool HValue::TryGuaranteeRange(HValue* upper_bound) {
RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
TryGuaranteeRangeRecursive(&context);
bool result = context.is_range_satisfied();
if (result) {
context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
}
return result;
}
void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
// Check if we already know that this value satisfies the lower bound.
if (context->lower_bound_guarantee() == NULL) {
if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
context->offset(), context->scale())) {
context->set_lower_bound_guarantee(this);
}
}
// Check if we already know that this value satisfies the upper bound.
if (context->upper_bound_guarantee() == NULL) {
if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
context->offset(), context->scale()) ||
(context->scale() == 0 &&
context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
this, -context->offset()))) {
context->set_upper_bound_guarantee(this);
}
}
if (context->is_range_satisfied()) return;
// See if our RedefinedOperand() satisfies the constraints.
if (RedefinedOperand() != NULL) {
RedefinedOperand()->TryGuaranteeRangeRecursive(context);
}
if (context->is_range_satisfied()) return;
// See if the constraints can be satisfied by decomposition.
DecompositionResult decomposition;
if (TryDecompose(&decomposition)) {
context->swap_candidate(&decomposition);
context->candidate()->TryGuaranteeRangeRecursive(context);
context->swap_candidate(&decomposition);
}
if (context->is_range_satisfied()) return;
// Try to modify this to satisfy the constraint.
TryGuaranteeRangeChanging(context);
}
RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
: lower_bound_(upper->block()->graph()->GetConstant0()),
lower_bound_guarantee_(NULL),
candidate_(value),
upper_bound_(upper),
upper_bound_guarantee_(NULL),
offset_(0),
scale_(0) {
}
HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
return guarantee->IsBoundsCheckBaseIndexInformation()
? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
: guarantee;
}
static int32_t ConvertAndSetOverflow(Representation r,
int64_t result,
bool* overflow) {
......@@ -484,55 +374,6 @@ HType HType::TypeFromValue(Handle<Object> value) {
}
bool HValue::Dominates(HValue* dominator, HValue* dominated) {
if (dominator->block() != dominated->block()) {
// If they are in different blocks we can use the dominance relation
// between the blocks.
return dominator->block()->Dominates(dominated->block());
} else {
// Otherwise we must see which instruction comes first, considering
// that phis always precede regular instructions.
if (dominator->IsInstruction()) {
if (dominated->IsInstruction()) {
for (HInstruction* next = HInstruction::cast(dominator)->next();
next != NULL;
next = next->next()) {
if (next == dominated) return true;
}
return false;
} else if (dominated->IsPhi()) {
return false;
} else {
UNREACHABLE();
}
} else if (dominator->IsPhi()) {
if (dominated->IsInstruction()) {
return true;
} else {
// We cannot compare which phi comes first.
UNREACHABLE();
}
} else {
UNREACHABLE();
}
return false;
}
}
bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator,
HValue* dominated) {
if (dominator->block() != dominated->block()) {
return dominator->block()->Dominates(dominated->block());
} else {
// If both arguments are in the same block we check if dominator is a phi
// or if dominated has not already been processed: in either case we know
// that dominator precedes dominated.
return dominator->IsPhi() || !dominated->CheckFlag(kIDefsProcessingDone);
}
}
bool HValue::IsDefinedAfter(HBasicBlock* other) const {
return block()->block_id() > other->block_id();
}
......@@ -960,58 +801,6 @@ void HInstruction::Verify() {
#endif
HNumericConstraint* HNumericConstraint::AddToGraph(
HValue* constrained_value,
NumericRelation relation,
HValue* related_value,
HInstruction* insertion_point) {
if (insertion_point == NULL) {
if (constrained_value->IsInstruction()) {
insertion_point = HInstruction::cast(constrained_value);
} else if (constrained_value->IsPhi()) {
insertion_point = constrained_value->block()->first();
} else {
UNREACHABLE();
}
}
HNumericConstraint* result =
new(insertion_point->block()->zone()) HNumericConstraint(
constrained_value, relation, related_value);
result->InsertAfter(insertion_point);
return result;
}
void HNumericConstraint::PrintDataTo(StringStream* stream) {
stream->Add("(");
constrained_value()->PrintNameTo(stream);
stream->Add(" %s ", relation().Mnemonic());
related_value()->PrintNameTo(stream);
stream->Add(")");
}
HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph(
HPhi* phi,
NumericRelation relation,
int operand_index) {
HInductionVariableAnnotation* result =
new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation,
operand_index);
result->InsertAfter(phi->block()->first());
return result;
}
void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) {
stream->Add("(");
RedefinedOperand()->PrintNameTo(stream);
stream->Add(" %s ", relation().Mnemonic());
induction_base()->PrintNameTo(stream);
stream->Add(")");
}
void HDummyUse::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
}
......@@ -1038,40 +827,6 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
}
void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
if (context->candidate()->ActualValue() != base()->ActualValue() ||
context->scale() < scale()) {
return;
}
// TODO(mmassi)
// Instead of checking for "same basic block" we should check for
// "dominates and postdominates".
if (context->upper_bound() == length() &&
context->lower_bound_guarantee() != NULL &&
context->lower_bound_guarantee() != this &&
context->lower_bound_guarantee()->block() != block() &&
offset() < context->offset() &&
index_can_increase() &&
context->upper_bound_guarantee() == NULL) {
offset_ = context->offset();
SetResponsibilityForRange(DIRECTION_UPPER);
context->set_upper_bound_guarantee(this);
isolate()->counters()->bounds_checks_eliminated()->Increment();
} else if (context->upper_bound_guarantee() != NULL &&
context->upper_bound_guarantee() != this &&
context->upper_bound_guarantee()->block() != block() &&
offset() > context->offset() &&
index_can_decrease() &&
context->lower_bound_guarantee() == NULL) {
offset_ = context->offset();
SetResponsibilityForRange(DIRECTION_LOWER);
context->set_lower_bound_guarantee(this);
isolate()->counters()->bounds_checks_eliminated()->Increment();
}
}
void HBoundsCheck::ApplyIndexChange() {
if (skip_check()) return;
......@@ -1119,40 +874,6 @@ void HBoundsCheck::ApplyIndexChange() {
base_ = NULL;
offset_ = 0;
scale_ = 0;
responsibility_direction_ = DIRECTION_NONE;
}
void HBoundsCheck::AddInformativeDefinitions() {
// TODO(mmassi): Executing this code during AddInformativeDefinitions
// is a hack. Move it to some other HPhase.
if (FLAG_array_bounds_checks_elimination) {
if (index()->TryGuaranteeRange(length())) {
set_skip_check();
}
if (DetectCompoundIndex()) {
HBoundsCheckBaseIndexInformation* base_index_info =
new(block()->graph()->zone())
HBoundsCheckBaseIndexInformation(this);
base_index_info->InsertAfter(this);
}
}
}
bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
HValue* related_value,
int offset,
int scale) {
if (related_value == length()) {
// A HBoundsCheck is smaller than the length it compared against.
return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
} else if (related_value == block()->graph()->GetConstant0()) {
// A HBoundsCheck is greater than or equal to zero.
return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
} else {
return false;
}
}
......@@ -1195,25 +916,6 @@ void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
}
bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
NumericRelation relation,
HValue* related_value,
int offset,
int scale) {
if (related_value == bounds_check()->length()) {
return NumericRelation::Lt().CompoundImplies(
relation,
bounds_check()->offset(), bounds_check()->scale(), offset, scale);
} else if (related_value == block()->graph()->GetConstant0()) {
return NumericRelation::Ge().CompoundImplies(
relation,
bounds_check()->offset(), bounds_check()->scale(), offset, scale);
} else {
return false;
}
}
void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
stream->Add("base: ");
base_index()->PrintNameTo(stream);
......@@ -1950,60 +1652,6 @@ Range* HMod::InferRange(Zone* zone) {
}
void HPhi::AddInformativeDefinitions() {
if (OperandCount() == 2) {
// If one of the operands is an OSR block give up (this cannot be an
// induction variable).
if (OperandAt(0)->block()->is_osr_entry() ||
OperandAt(1)->block()->is_osr_entry()) return;
for (int operand_index = 0; operand_index < 2; operand_index++) {
int other_operand_index = (operand_index + 1) % 2;
static NumericRelation relations[] = {
NumericRelation::Ge(),
NumericRelation::Le()
};
// Check if this phi is an induction variable. If, e.g., we know that
// its first input is greater than the phi itself, then that must be
// the back edge, and the phi is always greater than its second input.
for (int relation_index = 0; relation_index < 2; relation_index++) {
if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index],
this)) {
HInductionVariableAnnotation::AddToGraph(this,
relations[relation_index],
other_operand_index);
}
}
}
}
}
bool HPhi::IsRelationTrueInternal(NumericRelation relation,
HValue* other,
int offset,
int scale) {
if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
SetFlag(kNumericConstraintEvaluationInProgress);
bool result = true;
for (int i = 0; i < OperandCount(); i++) {
// Skip OSR entry blocks
if (OperandAt(i)->block()->is_osr_entry()) continue;
if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
result = false;
break;
}
}
ClearFlag(kNumericConstraintEvaluationInProgress);
return result;
}
InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) {
if (phi->block()->loop_information() == NULL) return NULL;
if (phi->OperandCount() != 2) return NULL;
......@@ -3090,16 +2738,6 @@ void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
}
void HCompareNumericAndBranch::AddInformativeDefinitions() {
NumericRelation r = NumericRelation::FromToken(token());
if (r.IsNone()) return;
HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first());
HNumericConstraint::AddToGraph(
left(), r.Negated(), right(), SuccessorAt(1)->first());
}
void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
stream->Add(Token::Name(token()));
stream->Add(" ");
......
......@@ -122,7 +122,6 @@ class LChunkBuilder;
V(Goto) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceTypeAndBranch) \
V(InductionVariableAnnotation) \
V(InnerAllocatedObject) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
......@@ -151,7 +150,6 @@ class LChunkBuilder;
V(MathMinMax) \
V(Mod) \
V(Mul) \
V(NumericConstraint) \
V(OsrEntry) \
V(OuterContext) \
V(Parameter) \
......@@ -542,158 +540,6 @@ enum GVNFlag {
};
class NumericRelation {
public:
enum Kind { NONE, EQ, GT, GE, LT, LE, NE };
static const char* MnemonicFromKind(Kind kind) {
switch (kind) {
case NONE: return "NONE";
case EQ: return "EQ";
case GT: return "GT";
case GE: return "GE";
case LT: return "LT";
case LE: return "LE";
case NE: return "NE";
}
UNREACHABLE();
return NULL;
}
const char* Mnemonic() const { return MnemonicFromKind(kind_); }
static NumericRelation None() { return NumericRelation(NONE); }
static NumericRelation Eq() { return NumericRelation(EQ); }
static NumericRelation Gt() { return NumericRelation(GT); }
static NumericRelation Ge() { return NumericRelation(GE); }
static NumericRelation Lt() { return NumericRelation(LT); }
static NumericRelation Le() { return NumericRelation(LE); }
static NumericRelation Ne() { return NumericRelation(NE); }
bool IsNone() { return kind_ == NONE; }
static NumericRelation FromToken(Token::Value token) {
switch (token) {
case Token::EQ: return Eq();
case Token::EQ_STRICT: return Eq();
case Token::LT: return Lt();
case Token::GT: return Gt();
case Token::LTE: return Le();
case Token::GTE: return Ge();
case Token::NE: return Ne();
case Token::NE_STRICT: return Ne();
default: return None();
}
}
// The semantics of "Reversed" is that if "x rel y" is true then also
// "y rel.Reversed() x" is true, and that rel.Reversed().Reversed() == rel.
NumericRelation Reversed() {
switch (kind_) {
case NONE: return None();
case EQ: return Eq();
case GT: return Lt();
case GE: return Le();
case LT: return Gt();
case LE: return Ge();
case NE: return Ne();
}
UNREACHABLE();
return None();
}
// The semantics of "Negated" is that if "x rel y" is true then also
// "!(x rel.Negated() y)" is true.
NumericRelation Negated() {
switch (kind_) {
case NONE: return None();
case EQ: return Ne();
case GT: return Le();
case GE: return Lt();
case LT: return Ge();
case LE: return Gt();
case NE: return Eq();
}
UNREACHABLE();
return None();
}
// The semantics of "Implies" is that if "x rel y" is true
// then also "x other_relation y" is true.
bool Implies(NumericRelation other_relation) {
switch (kind_) {
case NONE: return false;
case EQ: return (other_relation.kind_ == EQ)
|| (other_relation.kind_ == GE)
|| (other_relation.kind_ == LE);
case GT: return (other_relation.kind_ == GT)
|| (other_relation.kind_ == GE)
|| (other_relation.kind_ == NE);
case LT: return (other_relation.kind_ == LT)
|| (other_relation.kind_ == LE)
|| (other_relation.kind_ == NE);
case GE: return (other_relation.kind_ == GE);
case LE: return (other_relation.kind_ == LE);
case NE: return (other_relation.kind_ == NE);
}
UNREACHABLE();
return false;
}
// The semantics of "IsExtendable" is that if
// "rel.IsExtendable(direction)" is true then
// "x rel y" implies "(x + direction) rel y" .
bool IsExtendable(int direction) {
switch (kind_) {
case NONE: return false;
case EQ: return false;
case GT: return (direction >= 0);
case GE: return (direction >= 0);
case LT: return (direction <= 0);
case LE: return (direction <= 0);
case NE: return false;
}
UNREACHABLE();
return false;
}
// CompoundImplies returns true when
// "((x + my_offset) >> my_scale) rel y" implies
// "((x + other_offset) >> other_scale) other_relation y".
bool CompoundImplies(NumericRelation other_relation,
int my_offset,
int my_scale,
int other_offset = 0,
int other_scale = 0) {
return Implies(other_relation) && ComponentsImply(
my_offset, my_scale, other_offset, other_scale);
}
private:
// ComponentsImply returns true when
// "((x + my_offset) >> my_scale) rel y" implies
// "((x + other_offset) >> other_scale) rel y".
bool ComponentsImply(int my_offset,
int my_scale,
int other_offset,
int other_scale) {
switch (kind_) {
case NONE: break; // Fall through to UNREACHABLE().
case EQ:
case NE: return my_offset == other_offset && my_scale == other_scale;
case GT:
case GE: return my_offset <= other_offset && my_scale >= other_scale;
case LT:
case LE: return my_offset >= other_offset && my_scale <= other_scale;
}
UNREACHABLE();
return false;
}
explicit NumericRelation(Kind kind) : kind_(kind) {}
Kind kind_;
};
class DecompositionResult BASE_EMBEDDED {
public:
DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
......@@ -739,46 +585,6 @@ class DecompositionResult BASE_EMBEDDED {
};
class RangeEvaluationContext BASE_EMBEDDED {
public:
RangeEvaluationContext(HValue* value, HValue* upper);
HValue* lower_bound() { return lower_bound_; }
HValue* lower_bound_guarantee() { return lower_bound_guarantee_; }
HValue* candidate() { return candidate_; }
HValue* upper_bound() { return upper_bound_; }
HValue* upper_bound_guarantee() { return upper_bound_guarantee_; }
int offset() { return offset_; }
int scale() { return scale_; }
bool is_range_satisfied() {
return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL;
}
void set_lower_bound_guarantee(HValue* guarantee) {
lower_bound_guarantee_ = ConvertGuarantee(guarantee);
}
void set_upper_bound_guarantee(HValue* guarantee) {
upper_bound_guarantee_ = ConvertGuarantee(guarantee);
}
void swap_candidate(DecompositionResult* other_candicate) {
other_candicate->SwapValues(&candidate_, &offset_, &scale_);
}
private:
HValue* ConvertGuarantee(HValue* guarantee);
HValue* lower_bound_;
HValue* lower_bound_guarantee_;
HValue* candidate_;
HValue* upper_bound_;
HValue* upper_bound_guarantee_;
int offset_;
int scale_;
};
typedef EnumSet<GVNFlag> GVNFlagSet;
......@@ -816,12 +622,6 @@ class HValue: public ZoneObject {
// HGraph::ComputeSafeUint32Operations is responsible for setting this
// flag.
kUint32,
// If a phi is involved in the evaluation of a numeric constraint the
// recursion can cause an endless cycle: we use this flag to exit the loop.
kNumericConstraintEvaluationInProgress,
// This flag is set to true after the SetupInformativeDefinitions() pass
// has processed this instruction.
kIDefsProcessingDone,
kHasNoObservableSideEffects,
// Indicates the instruction is live during dead code elimination.
kIsLive,
......@@ -959,8 +759,8 @@ class HValue: public ZoneObject {
return RedefinedOperandIndex() != kNoRedefinedOperand;
}
HValue* RedefinedOperand() {
return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
: NULL;
int index = RedefinedOperandIndex();
return index == kNoRedefinedOperand ? NULL : OperandAt(index);
}
// A purely informative definition is an idef that will not emit code and
......@@ -971,17 +771,8 @@ class HValue: public ZoneObject {
// This method must always return the original HValue SSA definition
// (regardless of any iDef of this value).
HValue* ActualValue() {
return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
: this;
}
virtual void AddInformativeDefinitions() {}
void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
}
void UpdateRedefinedUses() {
UpdateRedefinedUsesInner<Dominates>();
int index = RedefinedOperandIndex();
return index == kNoRedefinedOperand ? this : OperandAt(index);
}
bool IsInteger32Constant();
......@@ -1132,12 +923,6 @@ class HValue: public ZoneObject {
virtual void Verify() = 0;
#endif
bool IsRelationTrue(NumericRelation relation,
HValue* other,
int offset = 0,
int scale = 0);
bool TryGuaranteeRange(HValue* upper_bound);
virtual bool TryDecompose(DecompositionResult* decomposition) {
if (RedefinedOperand() != NULL) {
return RedefinedOperand()->TryDecompose(decomposition);
......@@ -1159,17 +944,6 @@ class HValue: public ZoneObject {
}
protected:
void TryGuaranteeRangeRecursive(RangeEvaluationContext* context);
enum RangeGuaranteeDirection {
DIRECTION_NONE = 0,
DIRECTION_UPPER = 1,
DIRECTION_LOWER = 2,
DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER
};
virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {}
virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {}
// This function must be overridden for instructions with flag kUseGVN, to
// compare the non-Operand parts of the instruction.
virtual bool DataEquals(HValue* other) {
......@@ -1203,47 +977,6 @@ class HValue: public ZoneObject {
representation_ = r;
}
// Signature of a function testing if a HValue properly dominates another.
typedef bool (*DominanceTest)(HValue*, HValue*);
// Simple implementation of DominanceTest implemented walking the chain
// of Hinstructions (used in UpdateRedefinedUsesInner).
static bool Dominates(HValue* dominator, HValue* dominated);
// A fast implementation of DominanceTest that works only for the
// "current" instruction in the SetupInformativeDefinitions() phase.
// During that phase we use a flag to mark processed instructions, and by
// checking the flag we can quickly test if an instruction comes before or
// after the "current" one.
static bool TestDominanceUsingProcessedFlag(HValue* dominator,
HValue* dominated);
// If we are redefining an operand, update all its dominated uses (the
// function that checks if a use is dominated is the template argument).
template<DominanceTest TestDominance>
void UpdateRedefinedUsesInner() {
HValue* input = RedefinedOperand();
if (input != NULL) {
for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) {
HValue* use = uses.value();
if (TestDominance(this, use)) {
use->SetOperandAt(uses.index(), this);
}
}
}
}
// Informative definitions can override this method to state any numeric
// relation they provide on the redefined value.
// Returns true if it is guaranteed that:
// ((this + offset) >> scale) relation other
virtual bool IsRelationTrueInternal(NumericRelation relation,
HValue* other,
int offset = 0,
int scale = 0) {
return false;
}
static GVNFlagSet AllDependsOnFlagSet() {
GVNFlagSet result;
// Create changes mask.
......@@ -1514,52 +1247,6 @@ class HDummyUse: public HTemplateInstruction<1> {
};
class HNumericConstraint : public HTemplateInstruction<2> {
public:
static HNumericConstraint* AddToGraph(HValue* constrained_value,
NumericRelation relation,
HValue* related_value,
HInstruction* insertion_point = NULL);
HValue* constrained_value() { return OperandAt(0); }
HValue* related_value() { return OperandAt(1); }
NumericRelation relation() { return relation_; }
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return true; }
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
virtual void PrintDataTo(StringStream* stream);
virtual bool IsRelationTrueInternal(NumericRelation other_relation,
HValue* other_related_value,
int offset = 0,
int scale = 0) {
if (related_value() == other_related_value) {
return relation().CompoundImplies(other_relation, offset, scale);
} else {
return false;
}
}
DECLARE_CONCRETE_INSTRUCTION(NumericConstraint)
private:
HNumericConstraint(HValue* constrained_value,
NumericRelation relation,
HValue* related_value)
: relation_(relation) {
SetOperandAt(0, constrained_value);
SetOperandAt(1, related_value);
}
NumericRelation relation_;
};
class HDeoptimize: public HTemplateInstruction<0> {
public:
DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType);
......@@ -3480,8 +3167,6 @@ class HPhi: public HValue {
induction_variable_data_ = InductionVariableData::ExaminePhi(this);
}
virtual void AddInformativeDefinitions();
virtual void PrintTo(StringStream* stream);
#ifdef DEBUG
......@@ -3532,11 +3217,6 @@ class HPhi: public HValue {
inputs_[index] = value;
}
virtual bool IsRelationTrueInternal(NumericRelation relation,
HValue* other,
int offset = 0,
int scale = 0);
private:
ZoneList<HValue*> inputs_;
int merged_index_;
......@@ -3551,53 +3231,6 @@ class HPhi: public HValue {
};
class HInductionVariableAnnotation : public HUnaryOperation {
public:
static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
NumericRelation relation,
int operand_index);
NumericRelation relation() { return relation_; }
HValue* induction_base() { return phi_->OperandAt(operand_index_); }
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return true; }
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
virtual void PrintDataTo(StringStream* stream);
virtual bool IsRelationTrueInternal(NumericRelation other_relation,
HValue* other_related_value,
int offset = 0,
int scale = 0) {
if (induction_base() == other_related_value) {
return relation().CompoundImplies(other_relation, offset, scale);
} else {
return false;
}
}
DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
private:
HInductionVariableAnnotation(HPhi* phi,
NumericRelation relation,
int operand_index)
: HUnaryOperation(phi),
phi_(phi), relation_(relation), operand_index_(operand_index) {
}
// We need to store the phi both here and in the instruction operand because
// the operand can change if a new idef of the phi is added between the phi
// and this instruction (inserting an idef updates every use).
HPhi* phi_;
NumericRelation relation_;
int operand_index_;
};
class HArgumentsObject: public HTemplateInstruction<0> {
public:
static HArgumentsObject* New(Zone* zone,
......@@ -4115,12 +3748,6 @@ class HBoundsCheck: public HTemplateInstruction<2> {
HValue* base() { return base_; }
int offset() { return offset_; }
int scale() { return scale_; }
bool index_can_increase() {
return (responsibility_direction_ & DIRECTION_LOWER) == 0;
}
bool index_can_decrease() {
return (responsibility_direction_ & DIRECTION_UPPER) == 0;
}
void ApplyIndexChange();
bool DetectCompoundIndex() {
......@@ -4144,11 +3771,6 @@ class HBoundsCheck: public HTemplateInstruction<2> {
return representation();
}
virtual bool IsRelationTrueInternal(NumericRelation relation,
HValue* related_value,
int offset = 0,
int scale = 0);
virtual void PrintDataTo(StringStream* stream);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
......@@ -4159,25 +3781,17 @@ class HBoundsCheck: public HTemplateInstruction<2> {
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
virtual void AddInformativeDefinitions();
DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
protected:
friend class HBoundsCheckBaseIndexInformation;
virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
responsibility_direction_ | direction);
}
virtual bool DataEquals(HValue* other) { return true; }
virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
bool skip_check_;
HValue* base_;
int offset_;
int scale_;
RangeGuaranteeDirection responsibility_direction_;
bool allow_equality_;
private:
......@@ -4188,7 +3802,6 @@ class HBoundsCheck: public HTemplateInstruction<2> {
HBoundsCheck(HValue* index, HValue* length)
: skip_check_(false),
base_(NULL), offset_(0), scale_(0),
responsibility_direction_(DIRECTION_NONE),
allow_equality_(false) {
SetOperandAt(0, index);
SetOperandAt(1, length);
......@@ -4223,22 +3836,10 @@ class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
return representation();
}
virtual bool IsRelationTrueInternal(NumericRelation relation,
HValue* related_value,
int offset = 0,
int scale = 0);
virtual void PrintDataTo(StringStream* stream);
virtual int RedefinedOperandIndex() { return 0; }
virtual bool IsPurelyInformativeDefinition() { return true; }
protected:
virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
bounds_check()->SetResponsibilityForRange(direction);
}
virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
bounds_check()->TryGuaranteeRangeChanging(context);
}
};
......@@ -4411,8 +4012,6 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
}
virtual void PrintDataTo(StringStream* stream);
virtual void AddInformativeDefinitions();
DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
private:
......
......@@ -2979,11 +2979,10 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
// Eliminate redundant stack checks on backwards branches.
Run<HStackCheckEliminationPhase>();
if (FLAG_idefs) SetupInformativeDefinitions();
if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
if (FLAG_array_bounds_checks_elimination) {
Run<HBoundsCheckEliminationPhase>();
}
if (FLAG_array_bounds_checks_hoisting && !FLAG_idefs) {
if (FLAG_array_bounds_checks_hoisting) {
Run<HBoundsCheckHoistingPhase>();
}
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
......@@ -2995,50 +2994,6 @@ bool HGraph::Optimize(BailoutReason* bailout_reason) {
}
void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) {
for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) {
HPhi* phi = block->phis()->at(phi_index);
phi->AddInformativeDefinitions();
phi->SetFlag(HValue::kIDefsProcessingDone);
// We do not support phis that "redefine just one operand".
ASSERT(!phi->IsInformativeDefinition());
}
for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
HInstruction* i = it.Current();
i->AddInformativeDefinitions();
i->SetFlag(HValue::kIDefsProcessingDone);
i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions();
}
}
// This method is recursive, so if its stack frame is large it could
// cause a stack overflow.
// To keep the individual stack frames small we do the actual work inside
// SetupInformativeDefinitionsInBlock();
void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) {
SetupInformativeDefinitionsInBlock(block);
for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i));
}
for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
HInstruction* i = it.Current();
if (i->IsBoundsCheck()) {
HBoundsCheck* check = HBoundsCheck::cast(i);
check->ApplyIndexChange();
}
}
}
void HGraph::SetupInformativeDefinitions() {
HPhase phase("H_Setup informative definitions", this);
SetupInformativeDefinitionsRecursively(entry_block());
}
void HGraph::RestoreActualValues() {
HPhase phase("H_Restore actual values", this);
......
......@@ -1851,17 +1851,6 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
HInductionVariableAnnotation* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
return AssignEnvironment(new(zone()) LBoundsCheck(
UseRegisterOrConstantAtStart(instr->index()),
......
......@@ -1753,17 +1753,6 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
HInductionVariableAnnotation* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
......
......@@ -1745,17 +1745,6 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
}
LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
HInductionVariableAnnotation* instr) {
return NULL;
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = Use(instr->length());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment