diff options
Diffstat (limited to 'compiler')
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(¶llel_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(¶llel_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; - } -} |