}
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
}
+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);
}
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;
- // Add an idef that "discards" the OSR entry block branch.
- if (OperandAt(operand_index)->block()->is_osr_entry()) {
- HNumericConstraint::AddToGraph(
- this, NumericRelation::Eq(), OperandAt(other_operand_index));
- }
-
static NumericRelation relations[] = {
NumericRelation::Ge(),
NumericRelation::Le()
for (int relation_index = 0; relation_index < 2; relation_index++) {
if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index],
this)) {
- HNumericConstraint::AddToGraph(this,
- relations[relation_index],
- OperandAt(other_operand_index));
+ HInductionVariableAnnotation::AddToGraph(this,
+ relations[relation_index],
+ other_operand_index);
}
}
}
}
+bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) {
+ 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)) {
+ result = false;
+ break;
+ }
+ }
+ ClearFlag(kNumericConstraintEvaluationInProgress);
+
+ return result;
+}
+
+
Range* HMathMinMax::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
V(Goto) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceTypeAndBranch) \
+ V(InductionVariableAnnotation) \
V(In) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
// 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,
inputs_[index] = value;
}
+ virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other);
+
private:
ZoneList<HValue*> inputs_;
int merged_index_;
};
+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) {
+ if (induction_base() == other_related_value) {
+ return relation().Implies(other_relation);
+ } 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) {
+ set_representation(phi->representation());
+ }
+
+ // 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:
HArgumentsObject() {
}
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
return AssignEnvironment(new(zone()) LBoundsCheck(
UseRegisterOrConstantAtStart(instr->index()),
}
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
}
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+ HInductionVariableAnnotation* instr) {
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = Use(instr->length());