Merge "ART: Invoke Checker from run-test scripts"
diff --git a/compiler/dex/bb_optimizations.cc b/compiler/dex/bb_optimizations.cc
index e535813..11a7e44 100644
--- a/compiler/dex/bb_optimizations.cc
+++ b/compiler/dex/bb_optimizations.cc
@@ -51,4 +51,32 @@
return false;
}
+/*
+ * MethodUseCount pass implementation start.
+ */
+bool MethodUseCount::Gate(const PassDataHolder* data) const {
+ DCHECK(data != nullptr);
+ CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+ DCHECK(c_unit != nullptr);
+ // First initialize the data.
+ c_unit->mir_graph->InitializeMethodUses();
+
+ // Now check if the pass is to be ignored.
+ bool res = ((c_unit->disable_opt & (1 << kPromoteRegs)) == 0);
+
+ return res;
+}
+
+bool MethodUseCount::Worker(PassDataHolder* data) const {
+ DCHECK(data != nullptr);
+ PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
+ CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+ DCHECK(c_unit != nullptr);
+ BasicBlock* bb = pass_me_data_holder->bb;
+ DCHECK(bb != nullptr);
+ c_unit->mir_graph->CountUses(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
} // namespace art
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
index b07a415..aac2644 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -171,27 +171,6 @@
}
};
-/**
- * @class TypeInference
- * @brief Type inference pass.
- */
-class TypeInference : public PassME {
- public:
- TypeInference()
- : PassME("TypeInference", kRepeatingPreOrderDFSTraversal, "4_post_type_cfg") {
- }
-
- bool Worker(PassDataHolder* data) const {
- DCHECK(data != nullptr);
- PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
- CompilationUnit* c_unit = pass_me_data_holder->c_unit;
- DCHECK(c_unit != nullptr);
- BasicBlock* bb = pass_me_data_holder->bb;
- DCHECK(bb != nullptr);
- return c_unit->mir_graph->InferTypes(bb);
- }
-};
-
class ClassInitCheckElimination : public PassME {
public:
ClassInitCheckElimination()
@@ -279,6 +258,48 @@
};
/**
+ * @class ConstantPropagation
+ * @brief Perform a constant propagation pass.
+ */
+class ConstantPropagation : public PassME {
+ public:
+ ConstantPropagation() : PassME("ConstantPropagation") {
+ }
+
+ void Start(PassDataHolder* data) const {
+ DCHECK(data != nullptr);
+ CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+ DCHECK(c_unit != nullptr);
+ c_unit->mir_graph->InitializeConstantPropagation();
+ }
+
+ bool Worker(PassDataHolder* data) const {
+ DCHECK(data != nullptr);
+ CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+ DCHECK(c_unit != nullptr);
+ BasicBlock* bb = down_cast<PassMEDataHolder*>(data)->bb;
+ DCHECK(bb != nullptr);
+ c_unit->mir_graph->DoConstantPropagation(bb);
+ // No need of repeating, so just return false.
+ return false;
+ }
+};
+
+/**
+ * @class MethodUseCount
+ * @brief Count the register uses of the method
+ */
+class MethodUseCount : public PassME {
+ public:
+ MethodUseCount() : PassME("UseCount") {
+ }
+
+ bool Worker(PassDataHolder* data) const;
+
+ bool Gate(const PassDataHolder* data) const;
+};
+
+/**
* @class BasicBlock Optimizations
* @brief Any simple BasicBlock optimization can be put here.
*/
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 15b8341..ebbd28f 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -35,6 +35,7 @@
void MIRGraph::SetConstant(int32_t ssa_reg, int32_t value) {
is_constant_v_->SetBit(ssa_reg);
constant_values_[ssa_reg] = value;
+ reg_location_[ssa_reg].is_const = true;
}
void MIRGraph::SetConstantWide(int32_t ssa_reg, int64_t value) {
@@ -42,6 +43,8 @@
is_constant_v_->SetBit(ssa_reg + 1);
constant_values_[ssa_reg] = Low32Bits(value);
constant_values_[ssa_reg + 1] = High32Bits(value);
+ reg_location_[ssa_reg].is_const = true;
+ reg_location_[ssa_reg + 1].is_const = true;
}
void MIRGraph::DoConstantPropagation(BasicBlock* bb) {
diff --git a/compiler/dex/pass_driver_me_opts.cc b/compiler/dex/pass_driver_me_opts.cc
index c476b2a..6bb94c3 100644
--- a/compiler/dex/pass_driver_me_opts.cc
+++ b/compiler/dex/pass_driver_me_opts.cc
@@ -43,8 +43,9 @@
GetPassInstance<NullCheckElimination>(),
GetPassInstance<BBCombine>(),
GetPassInstance<CodeLayout>(),
- GetPassInstance<TypeInference>(),
GetPassInstance<GlobalValueNumberingPass>(),
+ GetPassInstance<ConstantPropagation>(),
+ GetPassInstance<MethodUseCount>(),
GetPassInstance<BBOptimizations>(),
GetPassInstance<SuspendCheckElimination>(),
};
diff --git a/compiler/dex/pass_driver_me_post_opt.cc b/compiler/dex/pass_driver_me_post_opt.cc
index 9b56c0d..5e2140d 100644
--- a/compiler/dex/pass_driver_me_post_opt.cc
+++ b/compiler/dex/pass_driver_me_post_opt.cc
@@ -40,9 +40,8 @@
GetPassInstance<CreatePhiNodes>(),
GetPassInstance<SSAConversion>(),
GetPassInstance<PhiNodeOperands>(),
- GetPassInstance<ConstantPropagation>(),
GetPassInstance<PerformInitRegLocations>(),
- GetPassInstance<MethodUseCount>(),
+ GetPassInstance<TypeInference>(),
GetPassInstance<FinishSSATransformation>(),
};
diff --git a/compiler/dex/post_opt_passes.cc b/compiler/dex/post_opt_passes.cc
index 675dbcf..92078b4 100644
--- a/compiler/dex/post_opt_passes.cc
+++ b/compiler/dex/post_opt_passes.cc
@@ -20,35 +20,6 @@
namespace art {
-/*
- * MethodUseCount pass implementation start.
- */
-bool MethodUseCount::Gate(const PassDataHolder* data) const {
- DCHECK(data != nullptr);
- CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
- DCHECK(c_unit != nullptr);
- // First initialize the data.
- c_unit->mir_graph->InitializeMethodUses();
-
- // Now check if the pass is to be ignored.
- bool res = ((c_unit->disable_opt & (1 << kPromoteRegs)) == 0);
-
- return res;
-}
-
-bool MethodUseCount::Worker(PassDataHolder* data) const {
- DCHECK(data != nullptr);
- PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
- CompilationUnit* c_unit = pass_me_data_holder->c_unit;
- DCHECK(c_unit != nullptr);
- BasicBlock* bb = pass_me_data_holder->bb;
- DCHECK(bb != nullptr);
- c_unit->mir_graph->CountUses(bb);
- // No need of repeating, so just return false.
- return false;
-}
-
-
bool ClearPhiInstructions::Worker(PassDataHolder* data) const {
DCHECK(data != nullptr);
PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
diff --git a/compiler/dex/post_opt_passes.h b/compiler/dex/post_opt_passes.h
index 964355b..55ae874 100644
--- a/compiler/dex/post_opt_passes.h
+++ b/compiler/dex/post_opt_passes.h
@@ -63,20 +63,6 @@
};
/**
- * @class MethodUseCount
- * @brief Count the register uses of the method
- */
-class MethodUseCount : public PassME {
- public:
- MethodUseCount() : PassME("UseCount") {
- }
-
- bool Worker(PassDataHolder* data) const;
-
- bool Gate(const PassDataHolder* data) const;
-};
-
-/**
* @class ClearPhiInformation
* @brief Clear the PHI nodes from the CFG.
*/
@@ -274,30 +260,22 @@
};
/**
- * @class ConstantPropagation
- * @brief Perform a constant propagation pass.
+ * @class TypeInference
+ * @brief Type inference pass.
*/
-class ConstantPropagation : public PassMEMirSsaRep {
+class TypeInference : public PassMEMirSsaRep {
public:
- ConstantPropagation() : PassMEMirSsaRep("ConstantPropagation") {
+ TypeInference() : PassMEMirSsaRep("TypeInference", kRepeatingPreOrderDFSTraversal) {
}
bool Worker(PassDataHolder* data) const {
DCHECK(data != nullptr);
- CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+ PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
+ CompilationUnit* c_unit = pass_me_data_holder->c_unit;
DCHECK(c_unit != nullptr);
- BasicBlock* bb = down_cast<PassMEDataHolder*>(data)->bb;
+ BasicBlock* bb = pass_me_data_holder->bb;
DCHECK(bb != nullptr);
- c_unit->mir_graph->DoConstantPropagation(bb);
- // No need of repeating, so just return false.
- return false;
- }
-
- void Start(PassDataHolder* data) const {
- DCHECK(data != nullptr);
- CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
- DCHECK(c_unit != nullptr);
- c_unit->mir_graph->InitializeConstantPropagation();
+ return c_unit->mir_graph->InferTypes(bb);
}
};
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 03e0e92..eb15611 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -573,6 +573,7 @@
// GenArithOpIntLit will directly generate exception-throwing code, and multiply-by-zero will
// have been optimized away earlier.
op->op = kOpInvalid;
+ op->shift = 0;
return true;
}
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index a541c7d..62c4089 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -442,7 +442,7 @@
for (int i = 0; i < GetNumSSARegs(); i++) {
loc[i] = fresh_loc;
loc[i].s_reg_low = i;
- loc[i].is_const = is_constant_v_->IsBitSet(i);
+ loc[i].is_const = false; // Constants will be marked by constant propagation pass later.
loc[i].wide = false;
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 7ece4b2e..d40c2d1 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -785,7 +785,7 @@
__ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
}
} else {
- DCHECK(const_to_move->IsLongConstant()) << const_to_move;
+ DCHECK(const_to_move->IsLongConstant()) << const_to_move->DebugName();
int64_t value = const_to_move->AsLongConstant()->GetValue();
if (location.IsRegisterPair()) {
__ LoadImmediate(location.AsRegisterPairLow<Register>(), Low32Bits(value));
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index e55175f..b20d589 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -363,9 +363,29 @@
}
}
+void SSAChecker::VisitIf(HIf* instruction) {
+ VisitInstruction(instruction);
+ HInstruction* input = instruction->InputAt(0);
+ if (input->IsIntConstant()) {
+ int value = input->AsIntConstant()->GetValue();
+ if (value != 0 && value != 1) {
+ std::stringstream error;
+ error << "If instruction " << instruction->GetId()
+ << " has a non-boolean constant input whose value is: "
+ << value << ".";
+ errors_.push_back(error.str());
+ }
+ } else if (instruction->InputAt(0)->GetType() != Primitive::kPrimBoolean) {
+ std::stringstream error;
+ error << "If instruction " << instruction->GetId()
+ << " has a non-boolean input type: "
+ << instruction->InputAt(0)->GetType() << ".";
+ errors_.push_back(error.str());
+ }
+}
+
void SSAChecker::VisitCondition(HCondition* op) {
VisitInstruction(op);
- // TODO: check inputs types, and special case the `null` check.
if (op->GetType() != Primitive::kPrimBoolean) {
std::stringstream error;
error << "Condition " << op->DebugName() << " " << op->GetId()
@@ -373,6 +393,34 @@
<< op->GetType() << ".";
errors_.push_back(error.str());
}
+ HInstruction* lhs = op->InputAt(0);
+ HInstruction* rhs = op->InputAt(1);
+ if (lhs->GetType() == Primitive::kPrimNot && rhs->IsIntConstant()) {
+ if (rhs->AsIntConstant()->GetValue() != 0) {
+ std::stringstream error;
+ error << "Condition " << op->DebugName() << " " << op->GetId()
+ << " compares an object with a non-0 integer: "
+ << rhs->AsIntConstant()->GetValue()
+ << ".";
+ errors_.push_back(error.str());
+ }
+ } else if (rhs->GetType() == Primitive::kPrimNot && lhs->IsIntConstant()) {
+ if (lhs->AsIntConstant()->GetValue() != 0) {
+ std::stringstream error;
+ error << "Condition " << op->DebugName() << " " << op->GetId()
+ << " compares a non-0 integer with an object: "
+ << lhs->AsIntConstant()->GetValue()
+ << ".";
+ errors_.push_back(error.str());
+ }
+ } else if (PrimitiveKind(lhs->GetType()) != PrimitiveKind(rhs->GetType())) {
+ std::stringstream error;
+ error << "Condition " << op->DebugName() << " " << op->GetId()
+ << " has inputs of different type: "
+ << lhs->GetType() << ", and " << rhs->GetType()
+ << ".";
+ errors_.push_back(error.str());
+ }
}
void SSAChecker::VisitBinaryOperation(HBinaryOperation* op) {
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index ba60cb9..ae1557b 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -101,6 +101,7 @@
void VisitPhi(HPhi* phi) OVERRIDE;
void VisitBinaryOperation(HBinaryOperation* op) OVERRIDE;
void VisitCondition(HCondition* op) OVERRIDE;
+ void VisitIf(HIf* instruction) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(SSAChecker);
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 4133cf6..ade3138 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -643,7 +643,12 @@
} else if (GetLeft()->IsLongConstant() && GetRight()->IsLongConstant()) {
int64_t value = Evaluate(GetLeft()->AsLongConstant()->GetValue(),
GetRight()->AsLongConstant()->GetValue());
- return new(GetBlock()->GetGraph()->GetArena()) HLongConstant(value);
+ if (GetResultType() == Primitive::kPrimLong) {
+ return new(GetBlock()->GetGraph()->GetArena()) HLongConstant(value);
+ } else {
+ DCHECK(GetResultType() == Primitive::kPrimInt);
+ return new(GetBlock()->GetGraph()->GetArena()) HIntConstant(value);
+ }
}
return nullptr;
}
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 6056373..ad48198 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -208,11 +208,12 @@
SsaRedundantPhiElimination redundant_phi(graph);
SsaDeadPhiElimination dead_phi(graph);
HDeadCodeElimination dce(graph);
- HConstantFolding fold(graph);
+ HConstantFolding fold1(graph);
InstructionSimplifier simplify1(graph);
HInliner inliner(graph, dex_compilation_unit, driver, stats);
+ HConstantFolding fold2(graph);
GVNOptimization gvn(graph);
BoundsCheckElimination bce(graph);
InstructionSimplifier simplify2(graph);
@@ -224,9 +225,10 @@
&dead_phi,
&intrinsics,
&dce,
- &fold,
+ &fold1,
&simplify1,
&inliner,
+ &fold2,
&gvn,
&bce,
&simplify2
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index b632c4d..a123313 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -530,7 +530,7 @@
bool SameRegisterKind(Location other) const;
bool HasHighInterval() const {
- return !IsHighInterval() && (GetParent()->high_or_low_interval_ != nullptr);
+ return IsLowInterval();
}
bool HasLowInterval() const {
diff --git a/tools/checker.py b/tools/checker.py
index 24784ce..b71eac6 100755
--- a/tools/checker.py
+++ b/tools/checker.py
@@ -700,8 +700,6 @@
help="print the contents of an output group")
parser.add_argument("-q", "--quiet", action="store_true",
help="print only errors")
- parser.add_argument("--no-clean", dest="no_clean", action="store_true",
- help="don't clean up generated files")
return parser.parse_args()
@@ -725,6 +723,9 @@
Logger.fail("Group \"" + groupName + "\" not found in the output")
+# Returns a list of files to scan for check annotations in the given path. Path
+# to a file is returned as a single-element list, directories are recursively
+# traversed and all '.java' files returned.
def FindCheckFiles(path):
if not path:
Logger.fail("No source path provided")
@@ -753,19 +754,13 @@
if __name__ == "__main__":
args = ParseArguments()
+
if args.quiet:
Logger.Verbosity = Logger.Level.Error
- tempFolder = tempfile.mkdtemp()
- try:
- if args.list_groups:
- ListGroups(args.tested_file)
- elif args.dump_group:
- DumpGroup(args.tested_file, args.dump_group)
- else:
- RunChecks(args.check_prefix, args.source_path, args.tested_file)
- finally:
- if args.no_clean:
- print("Files left in %s" % tempFolder)
- else:
- shutil.rmtree(tempFolder)
+ if args.list_groups:
+ ListGroups(args.tested_file)
+ elif args.dump_group:
+ DumpGroup(args.tested_file, args.dump_group)
+ else:
+ RunChecks(args.check_prefix, args.source_path, args.tested_file)