summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/bb_optimizations.cc28
-rw-r--r--compiler/dex/bb_optimizations.h63
-rw-r--r--compiler/dex/mir_optimization.cc3
-rw-r--r--compiler/dex/pass_driver_me_opts.cc3
-rw-r--r--compiler/dex/pass_driver_me_post_opt.cc3
-rw-r--r--compiler/dex/post_opt_passes.cc29
-rw-r--r--compiler/dex/post_opt_passes.h38
-rw-r--r--compiler/dex/quick/arm/int_arm.cc1
-rw-r--r--compiler/dex/vreg_analysis.cc2
-rw-r--r--compiler/optimizing/code_generator.cc6
-rw-r--r--compiler/optimizing/code_generator_arm.cc48
-rw-r--r--compiler/optimizing/code_generator_x86.cc2
-rw-r--r--compiler/optimizing/graph_checker.cc62
-rw-r--r--compiler/optimizing/graph_checker.h1
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc2
-rw-r--r--compiler/optimizing/locations.h12
-rw-r--r--compiler/optimizing/nodes.cc7
-rw-r--r--compiler/optimizing/nodes.h50
-rw-r--r--compiler/optimizing/optimizing_compiler.cc6
-rw-r--r--compiler/optimizing/parallel_move_resolver.cc3
-rw-r--r--compiler/optimizing/parallel_move_test.cc94
-rw-r--r--compiler/optimizing/register_allocator.cc10
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.h2
-rw-r--r--compiler/optimizing/test/ConstantFolding.java221
-rw-r--r--compiler/optimizing/test/Inliner.java202
25 files changed, 287 insertions, 611 deletions
diff --git a/compiler/dex/bb_optimizations.cc b/compiler/dex/bb_optimizations.cc
index e5358139d8..11a7e44f98 100644
--- a/compiler/dex/bb_optimizations.cc
+++ b/compiler/dex/bb_optimizations.cc
@@ -51,4 +51,32 @@ bool BBCombine::Worker(PassDataHolder* data) const {
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 b07a415d4a..aac2644e9b 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -171,27 +171,6 @@ class NullCheckElimination : public PassME {
}
};
-/**
- * @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 BBCombine : public PassME {
};
/**
+ * @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 15b83413b7..ebbd28f6c4 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -35,6 +35,7 @@ static unsigned int Predecessors(BasicBlock* bb) {
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 @@ void MIRGraph::SetConstantWide(int32_t ssa_reg, int64_t value) {
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 c476b2aabc..6bb94c3c0e 100644
--- a/compiler/dex/pass_driver_me_opts.cc
+++ b/compiler/dex/pass_driver_me_opts.cc
@@ -43,8 +43,9 @@ const Pass* const PassDriver<PassDriverMEOpts>::g_passes[] = {
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 9b56c0da87..5e2140d393 100644
--- a/compiler/dex/pass_driver_me_post_opt.cc
+++ b/compiler/dex/pass_driver_me_post_opt.cc
@@ -40,9 +40,8 @@ const Pass* const PassDriver<PassDriverMEPostOpt>::g_passes[] = {
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 675dbcf91d..92078b471b 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 964355bb5d..55ae874451 100644
--- a/compiler/dex/post_opt_passes.h
+++ b/compiler/dex/post_opt_passes.h
@@ -63,20 +63,6 @@ class InitializeSSATransformation : public PassMEMirSsaRep {
};
/**
- * @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 PerformInitRegLocations : public PassMEMirSsaRep {
};
/**
- * @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 03e0e92aec..eb156115ca 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -573,6 +573,7 @@ bool ArmMir2Lir::GetEasyMultiplyOp(int lit, ArmMir2Lir::EasyMultiplyOp* op) {
// 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 a541c7d7a7..62c40892cf 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -442,7 +442,7 @@ void MIRGraph::InitRegLocations() {
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.cc b/compiler/optimizing/code_generator.cc
index 08cbb20ecd..cdfd989bb8 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -698,11 +698,9 @@ void CodeGenerator::ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend
}
void CodeGenerator::EmitParallelMoves(Location from1, Location to1, Location from2, Location to2) {
- MoveOperands move1(from1, to1, nullptr);
- MoveOperands move2(from2, to2, nullptr);
HParallelMove parallel_move(GetGraph()->GetArena());
- parallel_move.AddMove(&move1);
- parallel_move.AddMove(&move2);
+ parallel_move.AddMove(from1, to1, nullptr);
+ parallel_move.AddMove(from2, to2, nullptr);
GetMoveResolver()->EmitNativeCode(&parallel_move);
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 2d3fa5f252..1ca1cee275 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -49,9 +49,6 @@ static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0, S1, S2, S3 };
static constexpr size_t kRuntimeParameterFpuRegistersLength =
arraysize(kRuntimeParameterFpuRegisters);
-static constexpr DRegister DTMP = D7;
-static constexpr SRegister STMP = S14;
-
class InvokeRuntimeCallingConvention : public CallingConvention<Register, SRegister> {
public:
InvokeRuntimeCallingConvention()
@@ -477,11 +474,6 @@ void CodeGeneratorARM::SetupBlockedRegisters() const {
blocked_core_registers_[R10] = true;
blocked_core_registers_[R11] = true;
- // Don't allocate our temporary double register.
- blocked_fpu_registers_[STMP] = true;
- blocked_fpu_registers_[STMP + 1] = true;
- DCHECK_EQ(FromLowSToD(STMP), DTMP);
-
blocked_fpu_registers_[S16] = true;
blocked_fpu_registers_[S17] = true;
blocked_fpu_registers_[S18] = true;
@@ -795,7 +787,7 @@ void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstr
__ 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));
@@ -3321,15 +3313,6 @@ void ParallelMoveResolverARM::EmitMove(size_t index) {
DCHECK(destination.IsStackSlot());
__ StoreSToOffset(source.AsFpuRegister<SRegister>(), SP, destination.GetStackIndex());
}
- } else if (source.IsFpuRegisterPair()) {
- if (destination.IsFpuRegisterPair()) {
- __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
- FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
- } else {
- DCHECK(destination.IsDoubleStackSlot()) << destination;
- __ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
- SP, destination.GetStackIndex());
- }
} else if (source.IsDoubleStackSlot()) {
if (destination.IsFpuRegisterPair()) {
__ LoadDFromOffset(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
@@ -3402,9 +3385,9 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
} else if (source.IsStackSlot() && destination.IsStackSlot()) {
Exchange(source.GetStackIndex(), destination.GetStackIndex());
} else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
- __ vmovs(STMP, source.AsFpuRegister<SRegister>());
+ __ vmovrs(IP, source.AsFpuRegister<SRegister>());
__ vmovs(source.AsFpuRegister<SRegister>(), destination.AsFpuRegister<SRegister>());
- __ vmovs(destination.AsFpuRegister<SRegister>(), STMP);
+ __ vmovsr(destination.AsFpuRegister<SRegister>(), IP);
} else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
SRegister reg = source.IsFpuRegister() ? source.AsFpuRegister<SRegister>()
: destination.AsFpuRegister<SRegister>();
@@ -3412,29 +3395,10 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
? destination.GetStackIndex()
: source.GetStackIndex();
- __ vmovs(STMP, reg);
- __ LoadSFromOffset(reg, SP, mem);
- __ StoreSToOffset(STMP, SP, mem);
- } else if (source.IsFpuRegisterPair() && destination.IsFpuRegisterPair()) {
- __ vmovd(DTMP, FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
- __ vmovd(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
- FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()));
- __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()), DTMP);
- } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
- DRegister reg = source.IsFpuRegisterPair()
- ? FromLowSToD(source.AsFpuRegisterPairLow<SRegister>())
- : FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
- int mem = source.IsFpuRegisterPair()
- ? destination.GetStackIndex()
- : source.GetStackIndex();
-
- __ vmovd(DTMP, reg);
- __ LoadDFromOffset(reg, SP, mem);
- __ StoreDToOffset(DTMP, SP, mem);
+ __ vmovrs(IP, reg);
+ __ LoadFromOffset(kLoadWord, IP, SP, mem);
+ __ StoreToOffset(kStoreWord, IP, SP, mem);
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
- // TODO: We could use DTMP and ask for a pair scratch register (float or core).
- // This would save four instructions if two scratch registers are available, and
- // two instructions if not.
Exchange(source.GetStackIndex(), destination.GetStackIndex());
Exchange(source.GetHighStackIndex(kArmWordSize), destination.GetHighStackIndex(kArmWordSize));
} else {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 22b2aa054e..9052b8fdec 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -3382,7 +3382,7 @@ void ParallelMoveResolverX86::EmitMove(size_t index) {
__ movl(Address(ESP, destination.GetStackIndex()), imm);
}
} else {
- LOG(FATAL) << "Unimplemented";
+ LOG(FATAL) << "Unimplemented move: " << destination << " <- " << source;
}
}
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index e55175faec..291b14cb52 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -363,9 +363,29 @@ static Primitive::Type PrimitiveKind(Primitive::Type type) {
}
}
+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,46 @@ void SSAChecker::VisitCondition(HCondition* op) {
<< op->GetType() << ".";
errors_.push_back(error.str());
}
+ HInstruction* lhs = op->InputAt(0);
+ HInstruction* rhs = op->InputAt(1);
+ if (lhs->GetType() == Primitive::kPrimNot) {
+ if (!op->IsEqual() && !op->IsNotEqual()) {
+ std::stringstream error;
+ error << "Condition " << op->DebugName() << " " << op->GetId()
+ << " uses an object as left-hand side input.";
+ errors_.push_back(error.str());
+ }
+ if (rhs->IsIntConstant() && 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) {
+ if (!op->IsEqual() && !op->IsNotEqual()) {
+ std::stringstream error;
+ error << "Condition " << op->DebugName() << " " << op->GetId()
+ << " uses an object as right-hand side input.";
+ errors_.push_back(error.str());
+ }
+ if (lhs->IsIntConstant() && 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 ba60cb99c6..ae1557b57c 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -101,6 +101,7 @@ class SSAChecker : public GraphChecker {
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/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index c1f4c94b7f..2c239458f1 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -116,7 +116,7 @@ static void MoveArguments(HInvoke* invoke, ArenaAllocator* arena, CodeGeneratorX
Location cc_loc = calling_convention_visitor.GetNextLocation(input->GetType());
Location actual_loc = locations->InAt(i);
- parallel_move.AddMove(new (arena) MoveOperands(actual_loc, cc_loc, nullptr));
+ parallel_move.AddMove(actual_loc, cc_loc, nullptr);
}
codegen->GetMoveResolver()->EmitNativeCode(&parallel_move);
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index d41b3aecfd..68d605957f 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -290,18 +290,6 @@ class Location : public ValueObject {
return value_ == other.value_;
}
- // Returns whether this location contains `other`.
- bool Contains(Location other) const {
- if (Equals(other)) return true;
- if (IsRegisterPair() && other.IsRegister()) {
- return low() == other.reg() || high() == other.reg();
- }
- if (IsFpuRegisterPair() && other.IsFpuRegister()) {
- return low() == other.reg() || high() == other.reg();
- }
- return false;
- }
-
const char* DebugString() const {
switch (GetKind()) {
case kInvalid: return "I";
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 4133cf676f..ade31380ec 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -643,7 +643,12 @@ HConstant* HBinaryOperation::TryStaticEvaluation() const {
} 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/nodes.h b/compiler/optimizing/nodes.h
index f2aa043849..fa51f27f0a 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2755,7 +2755,7 @@ class MoveOperands : public ArenaObject<kArenaAllocMisc> {
// True if this blocks a move from the given location.
bool Blocks(Location loc) const {
- return !IsEliminated() && source_.Contains(loc);
+ return !IsEliminated() && source_.Equals(loc);
}
// A move is redundant if it's been eliminated, if its source and
@@ -2784,8 +2784,6 @@ class MoveOperands : public ArenaObject<kArenaAllocMisc> {
// This is only used in debug mode, to ensure we do not connect interval siblings
// in the same parallel move.
HInstruction* instruction_;
-
- DISALLOW_COPY_AND_ASSIGN(MoveOperands);
};
static constexpr size_t kDefaultNumberOfMoves = 4;
@@ -2795,24 +2793,46 @@ class HParallelMove : public HTemplateInstruction<0> {
explicit HParallelMove(ArenaAllocator* arena)
: HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
- void AddMove(MoveOperands* move) {
- if (kIsDebugBuild) {
- if (move->GetInstruction() != nullptr) {
+ void AddMove(Location source, Location destination, HInstruction* instruction) {
+ DCHECK(source.IsValid());
+ DCHECK(destination.IsValid());
+ // The parallel move resolver does not handle pairs. So we decompose the
+ // pair locations into two moves.
+ if (source.IsPair() && destination.IsPair()) {
+ AddMove(source.ToLow(), destination.ToLow(), instruction);
+ AddMove(source.ToHigh(), destination.ToHigh(), nullptr);
+ } else if (source.IsPair()) {
+ DCHECK(destination.IsDoubleStackSlot());
+ AddMove(source.ToLow(), Location::StackSlot(destination.GetStackIndex()), instruction);
+ AddMove(source.ToHigh(), Location::StackSlot(destination.GetHighStackIndex(4)), nullptr);
+ } else if (destination.IsPair()) {
+ DCHECK(source.IsDoubleStackSlot());
+ AddMove(Location::StackSlot(source.GetStackIndex()), destination.ToLow(), instruction);
+ // TODO: rewrite GetHighStackIndex to not require a word size. It's supposed to
+ // always be 4.
+ static constexpr int kHighOffset = 4;
+ AddMove(Location::StackSlot(source.GetHighStackIndex(kHighOffset)),
+ destination.ToHigh(),
+ nullptr);
+ } else {
+ if (kIsDebugBuild) {
+ if (instruction != nullptr) {
+ for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
+ DCHECK_NE(moves_.Get(i).GetInstruction(), instruction)
+ << "Doing parallel moves for the same instruction.";
+ }
+ }
for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
- DCHECK_NE(moves_.Get(i)->GetInstruction(), move->GetInstruction())
- << "Doing parallel moves for the same instruction.";
+ DCHECK(!destination.Equals(moves_.Get(i).GetDestination()))
+ << "Same destination for two moves in a parallel move.";
}
}
- for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
- DCHECK(!move->GetDestination().Contains(moves_.Get(i)->GetDestination()))
- << "Same destination for two moves in a parallel move.";
- }
+ moves_.Add(MoveOperands(source, destination, instruction));
}
- moves_.Add(move);
}
MoveOperands* MoveOperandsAt(size_t index) const {
- return moves_.Get(index);
+ return moves_.GetRawStorage() + index;
}
size_t NumMoves() const { return moves_.Size(); }
@@ -2820,7 +2840,7 @@ class HParallelMove : public HTemplateInstruction<0> {
DECLARE_INSTRUCTION(ParallelMove);
private:
- GrowableArray<MoveOperands*> moves_;
+ GrowableArray<MoveOperands> moves_;
DISALLOW_COPY_AND_ASSIGN(HParallelMove);
};
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index daec0f0bef..1e0d65a945 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -208,11 +208,12 @@ static void RunOptimizations(HGraph* graph,
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 @@ static void RunOptimizations(HGraph* graph,
&dead_phi,
&intrinsics,
&dce,
- &fold,
+ &fold1,
&simplify1,
&inliner,
+ &fold2,
&gvn,
&bce,
&simplify2
diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc
index b8f5070999..debe466560 100644
--- a/compiler/optimizing/parallel_move_resolver.cc
+++ b/compiler/optimizing/parallel_move_resolver.cc
@@ -57,6 +57,9 @@ void ParallelMoveResolver::BuildInitialMoveList(HParallelMove* parallel_move) {
// unallocated, or the move was already eliminated).
for (size_t i = 0; i < parallel_move->NumMoves(); ++i) {
MoveOperands* move = parallel_move->MoveOperandsAt(i);
+ // The parallel move resolver algorithm does not work with register pairs.
+ DCHECK(!move->GetSource().IsPair());
+ DCHECK(!move->GetDestination().IsPair());
if (!move->IsRedundant()) {
moves_.Add(move);
}
diff --git a/compiler/optimizing/parallel_move_test.cc b/compiler/optimizing/parallel_move_test.cc
index 7ab41b6ddc..28b5697bbd 100644
--- a/compiler/optimizing/parallel_move_test.cc
+++ b/compiler/optimizing/parallel_move_test.cc
@@ -26,20 +26,26 @@ class TestParallelMoveResolver : public ParallelMoveResolver {
public:
explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
+ void Dump(Location location) {
+ if (location.IsConstant()) {
+ message_ << "C";
+ } else if (location.IsPair()) {
+ message_ << location.low() << "," << location.high();
+ } else {
+ message_ << location.reg();
+ }
+ }
+
virtual void EmitMove(size_t index) {
MoveOperands* move = moves_.Get(index);
if (!message_.str().empty()) {
message_ << " ";
}
message_ << "(";
- if (move->GetSource().IsConstant()) {
- message_ << "C";
- } else {
- message_ << move->GetSource().reg();
- }
- message_ << " -> "
- << move->GetDestination().reg()
- << ")";
+ Dump(move->GetSource());
+ message_ << " -> ";
+ Dump(move->GetDestination());
+ message_ << ")";
}
virtual void EmitSwap(size_t index) {
@@ -47,11 +53,11 @@ class TestParallelMoveResolver : public ParallelMoveResolver {
if (!message_.str().empty()) {
message_ << " ";
}
- message_ << "("
- << move->GetSource().reg()
- << " <-> "
- << move->GetDestination().reg()
- << ")";
+ message_ << "(";
+ Dump(move->GetSource());
+ message_ << " <-> ";
+ Dump(move->GetDestination());
+ message_ << ")";
}
virtual void SpillScratch(int reg ATTRIBUTE_UNUSED) {}
@@ -73,10 +79,10 @@ static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
size_t number_of_moves) {
HParallelMove* moves = new (allocator) HParallelMove(allocator);
for (size_t i = 0; i < number_of_moves; ++i) {
- moves->AddMove(new (allocator) MoveOperands(
+ moves->AddMove(
Location::RegisterLocation(operands[i][0]),
Location::RegisterLocation(operands[i][1]),
- nullptr));
+ nullptr);
}
return moves;
}
@@ -131,16 +137,66 @@ TEST(ParallelMoveTest, ConstantLast) {
ArenaAllocator allocator(&pool);
TestParallelMoveResolver resolver(&allocator);
HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
- moves->AddMove(new (&allocator) MoveOperands(
+ moves->AddMove(
Location::ConstantLocation(new (&allocator) HIntConstant(0)),
Location::RegisterLocation(0),
- nullptr));
- moves->AddMove(new (&allocator) MoveOperands(
+ nullptr);
+ moves->AddMove(
Location::RegisterLocation(1),
Location::RegisterLocation(2),
- nullptr));
+ nullptr);
resolver.EmitNativeCode(moves);
ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
}
+TEST(ParallelMoveTest, Pairs) {
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+
+ {
+ TestParallelMoveResolver resolver(&allocator);
+ HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
+ moves->AddMove(
+ Location::RegisterLocation(2),
+ Location::RegisterLocation(4),
+ nullptr);
+ moves->AddMove(
+ Location::RegisterPairLocation(0, 1),
+ Location::RegisterPairLocation(2, 3),
+ nullptr);
+ resolver.EmitNativeCode(moves);
+ ASSERT_STREQ("(2 -> 4) (0 -> 2) (1 -> 3)", resolver.GetMessage().c_str());
+ }
+
+ {
+ TestParallelMoveResolver resolver(&allocator);
+ HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
+ moves->AddMove(
+ Location::RegisterPairLocation(0, 1),
+ Location::RegisterPairLocation(2, 3),
+ nullptr);
+ moves->AddMove(
+ Location::RegisterLocation(2),
+ Location::RegisterLocation(4),
+ nullptr);
+ resolver.EmitNativeCode(moves);
+ ASSERT_STREQ("(2 -> 4) (0 -> 2) (1 -> 3)", resolver.GetMessage().c_str());
+ }
+
+ {
+ TestParallelMoveResolver resolver(&allocator);
+ HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
+ moves->AddMove(
+ Location::RegisterPairLocation(0, 1),
+ Location::RegisterPairLocation(2, 3),
+ nullptr);
+ moves->AddMove(
+ Location::RegisterLocation(2),
+ Location::RegisterLocation(0),
+ nullptr);
+ resolver.EmitNativeCode(moves);
+ ASSERT_STREQ("(2 <-> 0) (1 -> 3)", resolver.GetMessage().c_str());
+ }
+}
+
} // namespace art
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 93ed44ee44..1b42e94960 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -1051,7 +1051,7 @@ void RegisterAllocator::AddInputMoveFor(HInstruction* user,
move = previous->AsParallelMove();
}
DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition());
- move->AddMove(new (allocator_) MoveOperands(source, destination, nullptr));
+ move->AddMove(source, destination, nullptr);
}
static bool IsInstructionStart(size_t position) {
@@ -1123,7 +1123,7 @@ void RegisterAllocator::InsertParallelMoveAt(size_t position,
}
}
DCHECK_EQ(move->GetLifetimePosition(), position);
- move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
+ move->AddMove(source, destination, instruction);
}
void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
@@ -1153,7 +1153,7 @@ void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
} else {
move = previous->AsParallelMove();
}
- move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
+ move->AddMove(source, destination, instruction);
}
void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
@@ -1172,7 +1172,7 @@ void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
move->SetLifetimePosition(block->GetLifetimeStart());
block->InsertInstructionBefore(move, first);
}
- move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
+ move->AddMove(source, destination, instruction);
}
void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
@@ -1196,7 +1196,7 @@ void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
move->SetLifetimePosition(position);
instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
}
- move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
+ move->AddMove(source, destination, instruction);
}
void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index b632c4d05a..a123313426 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -530,7 +530,7 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> {
bool SameRegisterKind(Location other) const;
bool HasHighInterval() const {
- return !IsHighInterval() && (GetParent()->high_or_low_interval_ != nullptr);
+ return IsLowInterval();
}
bool HasLowInterval() const {
diff --git a/compiler/optimizing/test/ConstantFolding.java b/compiler/optimizing/test/ConstantFolding.java
deleted file mode 100644
index d08006b4d5..0000000000
--- a/compiler/optimizing/test/ConstantFolding.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-* Copyright (C) 2014 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-public class ConstantFolding {
-
- /**
- * Tiny three-register program exercising int constant folding
- * on negation.
- */
-
- // CHECK-START: int ConstantFolding.IntNegation() constant_folding (before)
- // CHECK-DAG: [[Const42:i\d+]] IntConstant 42
- // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Const42]] ]
- // CHECK-DAG: Return [ [[Neg]] ]
-
- // CHECK-START: int ConstantFolding.IntNegation() constant_folding (after)
- // CHECK-DAG: [[ConstN42:i\d+]] IntConstant -42
- // CHECK-DAG: Return [ [[ConstN42]] ]
-
- public static int IntNegation() {
- int x, y;
- x = 42;
- y = -x;
- return y;
- }
-
- /**
- * Tiny three-register program exercising int constant folding
- * on addition.
- */
-
- // CHECK-START: int ConstantFolding.IntAddition1() constant_folding (before)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: [[Const2:i\d+]] IntConstant 2
- // CHECK-DAG: [[Add:i\d+]] Add [ [[Const1]] [[Const2]] ]
- // CHECK-DAG: Return [ [[Add]] ]
-
- // CHECK-START: int ConstantFolding.IntAddition1() constant_folding (after)
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: Return [ [[Const3]] ]
-
- public static int IntAddition1() {
- int a, b, c;
- a = 1;
- b = 2;
- c = a + b;
- return c;
- }
-
- /**
- * Small three-register program exercising int constant folding
- * on addition.
- */
-
- // CHECK-START: int ConstantFolding.IntAddition2() constant_folding (before)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: [[Const2:i\d+]] IntConstant 2
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Const6:i\d+]] IntConstant 6
- // CHECK-DAG: [[Add1:i\d+]] Add [ [[Const1]] [[Const2]] ]
- // CHECK-DAG: [[Add2:i\d+]] Add [ [[Const5]] [[Const6]] ]
- // CHECK-DAG: [[Add3:i\d+]] Add [ [[Add1]] [[Add2]] ]
- // CHECK-DAG: Return [ [[Add3]] ]
-
- // CHECK-START: int ConstantFolding.IntAddition2() constant_folding (after)
- // CHECK-DAG: [[Const14:i\d+]] IntConstant 14
- // CHECK-DAG: Return [ [[Const14]] ]
-
- public static int IntAddition2() {
- int a, b, c;
- a = 1;
- b = 2;
- a += b;
- b = 5;
- c = 6;
- b += c;
- c = a + b;
- return c;
- }
-
- /**
- * Tiny three-register program exercising int constant folding
- * on subtraction.
- */
-
- // CHECK-START: int ConstantFolding.IntSubtraction() constant_folding (before)
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Const2:i\d+]] IntConstant 2
- // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const5]] [[Const2]] ]
- // CHECK-DAG: Return [ [[Sub]] ]
-
- // CHECK-START: int ConstantFolding.IntSubtraction() constant_folding (after)
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: Return [ [[Const3]] ]
-
- public static int IntSubtraction() {
- int a, b, c;
- a = 5;
- b = 2;
- c = a - b;
- return c;
- }
-
- /**
- * Tiny three-register program exercising long constant folding
- * on addition.
- */
-
- // CHECK-START: long ConstantFolding.LongAddition() constant_folding (before)
- // CHECK-DAG: [[Const1:j\d+]] LongConstant 1
- // CHECK-DAG: [[Const2:j\d+]] LongConstant 2
- // CHECK-DAG: [[Add:j\d+]] Add [ [[Const1]] [[Const2]] ]
- // CHECK-DAG: Return [ [[Add]] ]
-
- // CHECK-START: long ConstantFolding.LongAddition() constant_folding (after)
- // CHECK-DAG: [[Const3:j\d+]] LongConstant 3
- // CHECK-DAG: Return [ [[Const3]] ]
-
- public static long LongAddition() {
- long a, b, c;
- a = 1L;
- b = 2L;
- c = a + b;
- return c;
- }
-
- /**
- * Tiny three-register program exercising long constant folding
- * on subtraction.
- */
-
- // CHECK-START: long ConstantFolding.LongSubtraction() constant_folding (before)
- // CHECK-DAG: [[Const5:j\d+]] LongConstant 5
- // CHECK-DAG: [[Const2:j\d+]] LongConstant 2
- // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Const5]] [[Const2]] ]
- // CHECK-DAG: Return [ [[Sub]] ]
-
- // CHECK-START: long ConstantFolding.LongSubtraction() constant_folding (after)
- // CHECK-DAG: [[Const3:j\d+]] LongConstant 3
- // CHECK-DAG: Return [ [[Const3]] ]
-
- public static long LongSubtraction() {
- long a, b, c;
- a = 5L;
- b = 2L;
- c = a - b;
- return c;
- }
-
- /**
- * Three-register program with a constant (static) condition.
- */
-
- // CHECK-START: int ConstantFolding.StaticCondition() constant_folding (before)
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Const2:i\d+]] IntConstant 2
- // CHECK-DAG: [[Cond:z\d+]] GreaterThanOrEqual [ [[Const5]] [[Const2]] ]
- // CHECK-DAG: If [ [[Cond]] ]
-
- // CHECK-START: int ConstantFolding.StaticCondition() constant_folding (after)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: If [ [[Const1]] ]
-
- public static int StaticCondition() {
- int a, b, c;
- a = 5;
- b = 2;
- if (a < b)
- c = a + b;
- else
- c = a - b;
- return c;
- }
-
- /**
- * Four-variable program with jumps leading to the creation of many
- * blocks.
- *
- * The intent of this test is to ensure that all constant expressions
- * are actually evaluated at compile-time, thanks to the reverse
- * (forward) post-order traversal of the the dominator tree.
- */
-
- // CHECK-START: int ConstantFolding.JumpsAndConditionals(boolean) constant_folding (before)
- // CHECK-DAG: [[Const2:i\d+]] IntConstant 2
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Add:i\d+]] Add [ [[Const5]] [[Const2]] ]
- // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const5]] [[Const2]] ]
- // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Add]] [[Sub]] ]
- // CHECK-DAG: Return [ [[Phi]] ]
-
- // CHECK-START: int ConstantFolding.JumpsAndConditionals(boolean) constant_folding (after)
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: [[Const7:i\d+]] IntConstant 7
- // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Const7]] [[Const3]] ]
- // CHECK-DAG: Return [ [[Phi]] ]
-
- public static int JumpsAndConditionals(boolean cond) {
- int a, b, c;
- a = 5;
- b = 2;
- if (cond)
- c = a + b;
- else
- c = a - b;
- return c;
- }
-}
diff --git a/compiler/optimizing/test/Inliner.java b/compiler/optimizing/test/Inliner.java
deleted file mode 100644
index 54cce62a57..0000000000
--- a/compiler/optimizing/test/Inliner.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
-* Copyright (C) 2014 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-public class Inliner {
-
- // CHECK-START: void Inliner.InlineVoid() inliner (before)
- // CHECK-DAG: [[Const42:i\d+]] IntConstant 42
- // CHECK-DAG: InvokeStaticOrDirect
- // CHECK-DAG: InvokeStaticOrDirect [ [[Const42]] ]
-
- // CHECK-START: void Inliner.InlineVoid() inliner (after)
- // CHECK-NOT: InvokeStaticOrDirect
-
- public static void InlineVoid() {
- returnVoid();
- returnVoidWithOneParameter(42);
- }
-
- // CHECK-START: int Inliner.InlineParameter(int) inliner (before)
- // CHECK-DAG: [[Param:i\d+]] ParameterValue
- // CHECK-DAG: [[Result:i\d+]] InvokeStaticOrDirect [ [[Param]] ]
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: int Inliner.InlineParameter(int) inliner (after)
- // CHECK-DAG: [[Param:i\d+]] ParameterValue
- // CHECK-DAG: Return [ [[Param]] ]
-
- public static int InlineParameter(int a) {
- return returnParameter(a);
- }
-
- // CHECK-START: long Inliner.InlineWideParameter(long) inliner (before)
- // CHECK-DAG: [[Param:j\d+]] ParameterValue
- // CHECK-DAG: [[Result:j\d+]] InvokeStaticOrDirect [ [[Param]] ]
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: long Inliner.InlineWideParameter(long) inliner (after)
- // CHECK-DAG: [[Param:j\d+]] ParameterValue
- // CHECK-DAG: Return [ [[Param]] ]
-
- public static long InlineWideParameter(long a) {
- return returnWideParameter(a);
- }
-
- // CHECK-START: java.lang.Object Inliner.InlineReferenceParameter(java.lang.Object) inliner (before)
- // CHECK-DAG: [[Param:l\d+]] ParameterValue
- // CHECK-DAG: [[Result:l\d+]] InvokeStaticOrDirect [ [[Param]] ]
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: java.lang.Object Inliner.InlineReferenceParameter(java.lang.Object) inliner (after)
- // CHECK-DAG: [[Param:l\d+]] ParameterValue
- // CHECK-DAG: Return [ [[Param]] ]
-
- public static Object InlineReferenceParameter(Object o) {
- return returnReferenceParameter(o);
- }
-
- // CHECK-START: int Inliner.InlineInt() inliner (before)
- // CHECK-DAG: [[Result:i\d+]] InvokeStaticOrDirect
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: int Inliner.InlineInt() inliner (after)
- // CHECK-DAG: [[Const4:i\d+]] IntConstant 4
- // CHECK-DAG: Return [ [[Const4]] ]
-
- public static int InlineInt() {
- return returnInt();
- }
-
- // CHECK-START: long Inliner.InlineWide() inliner (before)
- // CHECK-DAG: [[Result:j\d+]] InvokeStaticOrDirect
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: long Inliner.InlineWide() inliner (after)
- // CHECK-DAG: [[Const8:j\d+]] LongConstant 8
- // CHECK-DAG: Return [ [[Const8]] ]
-
- public static long InlineWide() {
- return returnWide();
- }
-
- // CHECK-START: int Inliner.InlineAdd() inliner (before)
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Result:i\d+]] InvokeStaticOrDirect
- // CHECK-DAG: Return [ [[Result]] ]
-
- // CHECK-START: int Inliner.InlineAdd() inliner (after)
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Add:i\d+]] Add [ [[Const3]] [[Const5]] ]
- // CHECK-DAG: Return [ [[Add]] ]
-
- public static int InlineAdd() {
- return returnAdd(3, 5);
- }
-
- // CHECK-START: int Inliner.InlineFieldAccess() inliner (before)
- // CHECK-DAG: [[After:i\d+]] InvokeStaticOrDirect
- // CHECK-DAG: Return [ [[After]] ]
-
- // CHECK-START: int Inliner.InlineFieldAccess() inliner (after)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: [[Before:i\d+]] StaticFieldGet
- // CHECK-DAG: [[After:i\d+]] Add [ [[Before]] [[Const1]] ]
- // CHECK-DAG: StaticFieldSet [ {{l\d+}} [[After]] ]
- // CHECK-DAG: Return [ [[After]] ]
-
- // CHECK-START: int Inliner.InlineFieldAccess() inliner (after)
- // CHECK-NOT: InvokeStaticOrDirect
-
- public static int InlineFieldAccess() {
- return incCounter();
- }
-
- // CHECK-START: int Inliner.InlineWithControlFlow(boolean) inliner (before)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Add:i\d+]] InvokeStaticOrDirect [ [[Const1]] [[Const3]] ]
- // CHECK-DAG: [[Sub:i\d+]] InvokeStaticOrDirect [ [[Const5]] [[Const3]] ]
- // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Add]] [[Sub]] ]
- // CHECK-DAG: Return [ [[Phi]] ]
-
- // CHECK-START: int Inliner.InlineWithControlFlow(boolean) inliner (after)
- // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
- // CHECK-DAG: [[Const3:i\d+]] IntConstant 3
- // CHECK-DAG: [[Const5:i\d+]] IntConstant 5
- // CHECK-DAG: [[Add:i\d+]] Add [ [[Const1]] [[Const3]] ]
- // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const5]] [[Const3]] ]
- // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Add]] [[Sub]] ]
- // CHECK-DAG: Return [ [[Phi]] ]
-
- public static int InlineWithControlFlow(boolean cond) {
- int x, const1, const3, const5;
- const1 = 1;
- const3 = 3;
- const5 = 5;
- if (cond) {
- x = returnAdd(const1, const3);
- } else {
- x = returnSub(const5, const3);
- }
- return x;
- }
-
-
- private static void returnVoid() {
- return;
- }
-
- private static void returnVoidWithOneParameter(int a) {
- return;
- }
-
- private static int returnParameter(int a) {
- return a;
- }
-
- private static long returnWideParameter(long a) {
- return a;
- }
-
- private static Object returnReferenceParameter(Object o) {
- return o;
- }
-
- private static int returnInt() {
- return 4;
- }
-
- private static long returnWide() {
- return 8L;
- }
-
- private static int returnAdd(int a, int b) {
- return a + b;
- }
-
- private static int returnSub(int a, int b) {
- return a - b;
- }
-
- private static int counter = 42;
-
- private static int incCounter() {
- return ++counter;
- }
-}