diff options
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 88 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 116 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/nodes_x86.h | 19 | ||||
-rw-r--r-- | compiler/optimizing/pc_relative_fixups_x86.cc | 77 | ||||
-rw-r--r-- | test/458-checker-instruction-simplification/src/Main.java | 4 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/build | 46 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/expected.txt | 0 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/info.txt | 2 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/run | 18 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/src/Main.java | 41 | ||||
-rw-r--r-- | test/555-checker-regression-x86const/src/Unresolved.java | 18 | ||||
-rw-r--r-- | test/565-checker-condition-liveness/src/Main.java | 18 |
14 files changed, 403 insertions, 47 deletions
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index da054baa1c..6304fb503d 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1389,6 +1389,40 @@ void InstructionCodeGeneratorX86::GenerateLongComparesAndJumps(HCondition* cond, __ j(final_condition, true_label); } +void InstructionCodeGeneratorX86::GenerateFPCompare(Location lhs, + Location rhs, + HInstruction* insn, + bool is_double) { + HX86LoadFromConstantTable* const_area = insn->InputAt(1)->AsX86LoadFromConstantTable(); + if (is_double) { + if (rhs.IsFpuRegister()) { + __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>()); + } else if (const_area != nullptr) { + DCHECK(const_area->IsEmittedAtUseSite()); + __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), + codegen_->LiteralDoubleAddress( + const_area->GetConstant()->AsDoubleConstant()->GetValue(), + const_area->GetLocations()->InAt(0).AsRegister<Register>())); + } else { + DCHECK(rhs.IsDoubleStackSlot()); + __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), Address(ESP, rhs.GetStackIndex())); + } + } else { + if (rhs.IsFpuRegister()) { + __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>()); + } else if (const_area != nullptr) { + DCHECK(const_area->IsEmittedAtUseSite()); + __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), + codegen_->LiteralFloatAddress( + const_area->GetConstant()->AsFloatConstant()->GetValue(), + const_area->GetLocations()->InAt(0).AsRegister<Register>())); + } else { + DCHECK(rhs.IsStackSlot()); + __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), Address(ESP, rhs.GetStackIndex())); + } + } +} + template<class LabelType> void InstructionCodeGeneratorX86::GenerateCompareTestAndBranch(HCondition* condition, LabelType* true_target_in, @@ -1409,11 +1443,11 @@ void InstructionCodeGeneratorX86::GenerateCompareTestAndBranch(HCondition* condi GenerateLongComparesAndJumps(condition, true_target, false_target); break; case Primitive::kPrimFloat: - __ ucomiss(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(left, right, condition, false); GenerateFPJumps(condition, true_target, false_target); break; case Primitive::kPrimDouble: - __ ucomisd(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(left, right, condition, true); GenerateFPJumps(condition, true_target, false_target); break; default: @@ -1665,7 +1699,13 @@ void LocationsBuilderX86::HandleCondition(HCondition* cond) { case Primitive::kPrimFloat: case Primitive::kPrimDouble: { locations->SetInAt(0, Location::RequiresFpuRegister()); - locations->SetInAt(1, Location::RequiresFpuRegister()); + if (cond->InputAt(1)->IsX86LoadFromConstantTable()) { + DCHECK(cond->InputAt(1)->IsEmittedAtUseSite()); + } else if (cond->InputAt(1)->IsConstant()) { + locations->SetInAt(1, Location::RequiresFpuRegister()); + } else { + locations->SetInAt(1, Location::Any()); + } if (!cond->IsEmittedAtUseSite()) { locations->SetOut(Location::RequiresRegister()); } @@ -1719,11 +1759,11 @@ void InstructionCodeGeneratorX86::HandleCondition(HCondition* cond) { GenerateLongComparesAndJumps(cond, &true_label, &false_label); break; case Primitive::kPrimFloat: - __ ucomiss(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(lhs, rhs, cond, false); GenerateFPJumps(cond, &true_label, &false_label); break; case Primitive::kPrimDouble: - __ ucomisd(lhs.AsFpuRegister<XmmRegister>(), rhs.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(lhs, rhs, cond, true); GenerateFPJumps(cond, &true_label, &false_label); break; } @@ -2159,6 +2199,32 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { } } +void LocationsBuilderX86::VisitX86FPNeg(HX86FPNeg* neg) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); + DCHECK(Primitive::IsFloatingPointType(neg->GetType())); + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresRegister()); + locations->SetOut(Location::SameAsFirstInput()); + locations->AddTemp(Location::RequiresFpuRegister()); +} + +void InstructionCodeGeneratorX86::VisitX86FPNeg(HX86FPNeg* neg) { + LocationSummary* locations = neg->GetLocations(); + Location out = locations->Out(); + DCHECK(locations->InAt(0).Equals(out)); + + Register constant_area = locations->InAt(1).AsRegister<Register>(); + XmmRegister mask = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + if (neg->GetType() == Primitive::kPrimFloat) { + __ movss(mask, codegen_->LiteralInt32Address(INT32_C(0x80000000), constant_area)); + __ xorps(out.AsFpuRegister<XmmRegister>(), mask); + } else { + __ movsd(mask, codegen_->LiteralInt64Address(INT64_C(0x8000000000000000), constant_area)); + __ xorpd(out.AsFpuRegister<XmmRegister>(), mask); + } +} + void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); @@ -4086,7 +4152,13 @@ void LocationsBuilderX86::VisitCompare(HCompare* compare) { case Primitive::kPrimFloat: case Primitive::kPrimDouble: { locations->SetInAt(0, Location::RequiresFpuRegister()); - locations->SetInAt(1, Location::RequiresFpuRegister()); + if (compare->InputAt(1)->IsX86LoadFromConstantTable()) { + DCHECK(compare->InputAt(1)->IsEmittedAtUseSite()); + } else if (compare->InputAt(1)->IsConstant()) { + locations->SetInAt(1, Location::RequiresFpuRegister()); + } else { + locations->SetInAt(1, Location::Any()); + } locations->SetOut(Location::RequiresRegister()); break; } @@ -4147,12 +4219,12 @@ void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) { break; } case Primitive::kPrimFloat: { - __ ucomiss(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(left, right, compare, false); __ j(kUnordered, compare->IsGtBias() ? &greater : &less); break; } case Primitive::kPrimDouble: { - __ ucomisd(left.AsFpuRegister<XmmRegister>(), right.AsFpuRegister<XmmRegister>()); + GenerateFPCompare(left, right, compare, true); __ j(kUnordered, compare->IsGtBias() ? &greater : &less); break; } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 0aef478569..d51b96f85f 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -296,6 +296,8 @@ class InstructionCodeGeneratorX86 : public InstructionCodeGenerator { HBasicBlock* switch_block, HBasicBlock* default_block); + void GenerateFPCompare(Location lhs, Location rhs, HInstruction* insn, bool is_double); + X86Assembler* const assembler_; CodeGeneratorX86* const codegen_; diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index acc40bc998..529f678761 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -37,10 +37,12 @@ namespace x86 { static constexpr int kDoubleNaNHigh = 0x7FF80000; static constexpr int kDoubleNaNLow = 0x00000000; -static constexpr int kFloatNaN = 0x7FC00000; +static constexpr int64_t kDoubleNaN = INT64_C(0x7FF8000000000000); +static constexpr int32_t kFloatNaN = INT32_C(0x7FC00000); IntrinsicLocationsBuilderX86::IntrinsicLocationsBuilderX86(CodeGeneratorX86* codegen) - : arena_(codegen->GetGraph()->GetArena()), codegen_(codegen) { + : arena_(codegen->GetGraph()->GetArena()), + codegen_(codegen) { } @@ -256,15 +258,37 @@ static void CreateFloatToFloat(ArenaAllocator* arena, HInvoke* invoke) { LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresFpuRegister()); - // TODO: Allow x86 to work with memory. This requires assembler support, see below. - // locations->SetInAt(0, Location::Any()); // X86 can work on memory directly. locations->SetOut(Location::SameAsFirstInput()); + HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(static_or_direct != nullptr); + if (invoke->InputAt(static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) { + // We need addressibility for the constant area. + locations->SetInAt(1, Location::RequiresRegister()); + // We need a temporary to hold the constant. + locations->AddTemp(Location::RequiresFpuRegister()); + } } -static void MathAbsFP(LocationSummary* locations, bool is64bit, X86Assembler* assembler) { +static void MathAbsFP(LocationSummary* locations, + bool is64bit, + X86Assembler* assembler, + CodeGeneratorX86* codegen) { Location output = locations->Out(); - if (output.IsFpuRegister()) { + DCHECK(output.IsFpuRegister()); + if (locations->InAt(1).IsValid()) { + DCHECK(locations->InAt(1).IsRegister()); + // We also have a constant area pointer. + Register constant_area = locations->InAt(1).AsRegister<Register>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + if (is64bit) { + __ movsd(temp, codegen->LiteralInt64Address(INT64_C(0x7FFFFFFFFFFFFFFF), constant_area)); + __ andpd(output.AsFpuRegister<XmmRegister>(), temp); + } else { + __ movss(temp, codegen->LiteralInt32Address(INT32_C(0x7FFFFFFF), constant_area)); + __ andps(output.AsFpuRegister<XmmRegister>(), temp); + } + } else { // Create the right constant on an aligned stack. if (is64bit) { __ subl(ESP, Immediate(8)); @@ -277,19 +301,6 @@ static void MathAbsFP(LocationSummary* locations, bool is64bit, X86Assembler* as __ andps(output.AsFpuRegister<XmmRegister>(), Address(ESP, 0)); } __ addl(ESP, Immediate(16)); - } else { - // TODO: update when assember support is available. - UNIMPLEMENTED(FATAL) << "Needs assembler support."; -// Once assembler support is available, in-memory operations look like this: -// if (is64bit) { -// DCHECK(output.IsDoubleStackSlot()); -// __ andl(Address(Register(RSP), output.GetHighStackIndex(kX86WordSize)), -// Immediate(0x7FFFFFFF)); -// } else { -// DCHECK(output.IsStackSlot()); -// // Can use and with a literal directly. -// __ andl(Address(Register(RSP), output.GetStackIndex()), Immediate(0x7FFFFFFF)); -// } } } @@ -298,7 +309,7 @@ void IntrinsicLocationsBuilderX86::VisitMathAbsDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathAbsDouble(HInvoke* invoke) { - MathAbsFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); + MathAbsFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler(), codegen_); } void IntrinsicLocationsBuilderX86::VisitMathAbsFloat(HInvoke* invoke) { @@ -306,7 +317,7 @@ void IntrinsicLocationsBuilderX86::VisitMathAbsFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathAbsFloat(HInvoke* invoke) { - MathAbsFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); + MathAbsFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler(), codegen_); } static void CreateAbsIntLocation(ArenaAllocator* arena, HInvoke* invoke) { @@ -388,8 +399,11 @@ void IntrinsicCodeGeneratorX86::VisitMathAbsLong(HInvoke* invoke) { GenAbsLong(invoke->GetLocations(), GetAssembler()); } -static void GenMinMaxFP(LocationSummary* locations, bool is_min, bool is_double, - X86Assembler* assembler) { +static void GenMinMaxFP(LocationSummary* locations, + bool is_min, + bool is_double, + X86Assembler* assembler, + CodeGeneratorX86* codegen) { Location op1_loc = locations->InAt(0); Location op2_loc = locations->InAt(1); Location out_loc = locations->Out(); @@ -450,15 +464,26 @@ static void GenMinMaxFP(LocationSummary* locations, bool is_min, bool is_double, // NaN handling. __ Bind(&nan); - if (is_double) { - __ pushl(Immediate(kDoubleNaNHigh)); - __ pushl(Immediate(kDoubleNaNLow)); - __ movsd(out, Address(ESP, 0)); - __ addl(ESP, Immediate(8)); + // Do we have a constant area pointer? + if (locations->InAt(2).IsValid()) { + DCHECK(locations->InAt(2).IsRegister()); + Register constant_area = locations->InAt(2).AsRegister<Register>(); + if (is_double) { + __ movsd(out, codegen->LiteralInt64Address(kDoubleNaN, constant_area)); + } else { + __ movss(out, codegen->LiteralInt32Address(kFloatNaN, constant_area)); + } } else { - __ pushl(Immediate(kFloatNaN)); - __ movss(out, Address(ESP, 0)); - __ addl(ESP, Immediate(4)); + if (is_double) { + __ pushl(Immediate(kDoubleNaNHigh)); + __ pushl(Immediate(kDoubleNaNLow)); + __ movsd(out, Address(ESP, 0)); + __ addl(ESP, Immediate(8)); + } else { + __ pushl(Immediate(kFloatNaN)); + __ movss(out, Address(ESP, 0)); + __ addl(ESP, Immediate(4)); + } } __ jmp(&done); @@ -483,6 +508,11 @@ static void CreateFPFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { // The following is sub-optimal, but all we can do for now. It would be fine to also accept // the second input to be the output (we can simply swap inputs). locations->SetOut(Location::SameAsFirstInput()); + HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(static_or_direct != nullptr); + if (invoke->InputAt(static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) { + locations->SetInAt(2, Location::RequiresRegister()); + } } void IntrinsicLocationsBuilderX86::VisitMathMinDoubleDouble(HInvoke* invoke) { @@ -490,7 +520,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMinDoubleDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMinDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, /* is_double */ true, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ true, + /* is_double */ true, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMinFloatFloat(HInvoke* invoke) { @@ -498,7 +532,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMinFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMinFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, /* is_double */ false, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ true, + /* is_double */ false, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { @@ -506,7 +544,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, /* is_double */ true, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ false, + /* is_double */ true, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMaxFloatFloat(HInvoke* invoke) { @@ -514,7 +556,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMaxFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMaxFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, /* is_double */ false, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ false, + /* is_double */ false, + GetAssembler(), + codegen_); } static void GenMinMax(LocationSummary* locations, bool is_min, bool is_long, diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index b8083477cf..6c63af71a3 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1259,6 +1259,7 @@ class HLoopInformationOutwardIterator : public ValueObject { #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \ M(X86ComputeBaseMethodAddress, Instruction) \ M(X86LoadFromConstantTable, Instruction) \ + M(X86FPNeg, Instruction) \ M(X86PackedSwitch, Instruction) #endif diff --git a/compiler/optimizing/nodes_x86.h b/compiler/optimizing/nodes_x86.h index b1bf939b36..0b3a84d3d3 100644 --- a/compiler/optimizing/nodes_x86.h +++ b/compiler/optimizing/nodes_x86.h @@ -56,6 +56,25 @@ class HX86LoadFromConstantTable : public HExpression<2> { DISALLOW_COPY_AND_ASSIGN(HX86LoadFromConstantTable); }; +// Version of HNeg with access to the constant table for FP types. +class HX86FPNeg : public HExpression<2> { + public: + HX86FPNeg(Primitive::Type result_type, + HInstruction* input, + HX86ComputeBaseMethodAddress* method_base, + uint32_t dex_pc) + : HExpression(result_type, SideEffects::None(), dex_pc) { + DCHECK(Primitive::IsFloatingPointType(result_type)); + SetRawInputAt(0, input); + SetRawInputAt(1, method_base); + } + + DECLARE_INSTRUCTION(X86FPNeg); + + private: + DISALLOW_COPY_AND_ASSIGN(HX86FPNeg); +}; + // X86 version of HPackedSwitch that holds a pointer to the base method address. class HX86PackedSwitch : public HTemplateInstruction<2> { public: diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc index a2180bc9d7..a6f14616bf 100644 --- a/compiler/optimizing/pc_relative_fixups_x86.cc +++ b/compiler/optimizing/pc_relative_fixups_x86.cc @@ -53,6 +53,10 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { BinaryFP(div); } + void VisitCompare(HCompare* compare) OVERRIDE { + BinaryFP(compare); + } + void VisitReturn(HReturn* ret) OVERRIDE { HConstant* value = ret->InputAt(0)->AsConstant(); if ((value != nullptr && Primitive::IsFloatingPointType(value->GetType()))) { @@ -74,11 +78,50 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { void BinaryFP(HBinaryOperation* bin) { HConstant* rhs = bin->InputAt(1)->AsConstant(); - if (rhs != nullptr && Primitive::IsFloatingPointType(bin->GetResultType())) { + if (rhs != nullptr && Primitive::IsFloatingPointType(rhs->GetType())) { ReplaceInput(bin, rhs, 1, false); } } + void VisitEqual(HEqual* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitNotEqual(HNotEqual* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitLessThan(HLessThan* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitLessThanOrEqual(HLessThanOrEqual* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitGreaterThan(HGreaterThan* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitGreaterThanOrEqual(HGreaterThanOrEqual* cond) OVERRIDE { + BinaryFP(cond); + } + + void VisitNeg(HNeg* neg) OVERRIDE { + if (Primitive::IsFloatingPointType(neg->GetType())) { + // We need to replace the HNeg with a HX86FPNeg in order to address the constant area. + InitializePCRelativeBasePointer(); + HGraph* graph = GetGraph(); + HBasicBlock* block = neg->GetBlock(); + HX86FPNeg* x86_fp_neg = new (graph->GetArena()) HX86FPNeg( + neg->GetType(), + neg->InputAt(0), + base_, + neg->GetDexPc()); + block->ReplaceAndRemoveInstructionWith(neg, x86_fp_neg); + } + } + void VisitPackedSwitch(HPackedSwitch* switch_insn) OVERRIDE { if (switch_insn->GetNumEntries() <= InstructionCodeGeneratorX86::kPackedSwitchJumpTableThreshold) { @@ -127,12 +170,23 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { // If this is an invoke-static/-direct with PC-relative dex cache array // addressing, we need the PC-relative address base. HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect(); + // We can't add a pointer to the constant area if we already have a current + // method pointer. This may arise when sharpening doesn't remove the current + // method pointer from the invoke. + if (invoke_static_or_direct != nullptr && + invoke_static_or_direct->HasCurrentMethodInput()) { + DCHECK(!invoke_static_or_direct->HasPcRelativeDexCache()); + return; + } + + bool base_added = false; if (invoke_static_or_direct != nullptr && invoke_static_or_direct->HasPcRelativeDexCache()) { InitializePCRelativeBasePointer(); // Add the extra parameter base_. - DCHECK(!invoke_static_or_direct->HasCurrentMethodInput()); invoke_static_or_direct->AddSpecialInput(base_); + base_added = true; } + // Ensure that we can load FP arguments from the constant area. for (size_t i = 0, e = invoke->InputCount(); i < e; i++) { HConstant* input = invoke->InputAt(i)->AsConstant(); @@ -140,6 +194,25 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { ReplaceInput(invoke, input, i, true); } } + + // These intrinsics need the constant area. + switch (invoke->GetIntrinsic()) { + case Intrinsics::kMathAbsDouble: + case Intrinsics::kMathAbsFloat: + case Intrinsics::kMathMaxDoubleDouble: + case Intrinsics::kMathMaxFloatFloat: + case Intrinsics::kMathMinDoubleDouble: + case Intrinsics::kMathMinFloatFloat: + if (!base_added) { + DCHECK(invoke_static_or_direct != nullptr); + DCHECK(!invoke_static_or_direct->HasCurrentMethodInput()); + InitializePCRelativeBasePointer(); + invoke_static_or_direct->AddSpecialInput(base_); + } + break; + default: + break; + } } // The generated HX86ComputeBaseMethodAddress in the entry block needed as an diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java index 3c8abeb841..2f80470cb3 100644 --- a/test/458-checker-instruction-simplification/src/Main.java +++ b/test/458-checker-instruction-simplification/src/Main.java @@ -1404,7 +1404,7 @@ public class Main { /// CHECK-START: int Main.floatConditionNotEqualOne(float) ssa_builder (after) /// CHECK: LessThanOrEqual - /// CHECK-START: int Main.floatConditionNotEqualOne(float) register (before) + /// CHECK-START: int Main.floatConditionNotEqualOne(float) instruction_simplifier_before_codegen (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 @@ -1420,7 +1420,7 @@ public class Main { /// CHECK-START: int Main.doubleConditionEqualZero(double) ssa_builder (after) /// CHECK: LessThanOrEqual - /// CHECK-START: int Main.doubleConditionEqualZero(double) register (before) + /// CHECK-START: int Main.doubleConditionEqualZero(double) instruction_simplifier_before_codegen (after) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 diff --git a/test/555-checker-regression-x86const/build b/test/555-checker-regression-x86const/build new file mode 100644 index 0000000000..09dcc363dd --- /dev/null +++ b/test/555-checker-regression-x86const/build @@ -0,0 +1,46 @@ +#!/bin/bash +# +# Copyright (C) 2015 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. + +# Stop if something fails. +set -e + +# We can't use src-ex testing infrastructure because src and src-ex are compiled +# with javac independetely and can't share code (without reflection). + +mkdir classes +${JAVAC} -d classes `find src -name '*.java'` + +mkdir classes-ex +mv classes/UnresolvedClass.class classes-ex + +if [ ${USE_JACK} = "true" ]; then + # Create .jack files from classes generated with javac. + ${JILL} classes --output classes.jack + ${JILL} classes-ex --output classes-ex.jack + + # Create DEX files from .jack files. + ${JACK} --import classes.jack --output-dex . + zip $TEST_NAME.jar classes.dex + ${JACK} --import classes-ex.jack --output-dex . + zip ${TEST_NAME}-ex.jar classes.dex +else + if [ ${NEED_DEX} = "true" ]; then + ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes + zip $TEST_NAME.jar classes.dex + ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex + zip ${TEST_NAME}-ex.jar classes.dex + fi +fi diff --git a/test/555-checker-regression-x86const/expected.txt b/test/555-checker-regression-x86const/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/555-checker-regression-x86const/expected.txt diff --git a/test/555-checker-regression-x86const/info.txt b/test/555-checker-regression-x86const/info.txt new file mode 100644 index 0000000000..c4037fa88f --- /dev/null +++ b/test/555-checker-regression-x86const/info.txt @@ -0,0 +1,2 @@ +Check that X86 FP constant-area handling handles intrinsics with CurrentMethod +on the call. diff --git a/test/555-checker-regression-x86const/run b/test/555-checker-regression-x86const/run new file mode 100644 index 0000000000..63fdb8c749 --- /dev/null +++ b/test/555-checker-regression-x86const/run @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Copyright (C) 2015 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. + +# Use secondary switch to add secondary dex file to class path. +exec ${RUN} "${@}" --secondary diff --git a/test/555-checker-regression-x86const/src/Main.java b/test/555-checker-regression-x86const/src/Main.java new file mode 100644 index 0000000000..914cfde74f --- /dev/null +++ b/test/555-checker-regression-x86const/src/Main.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 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 Main extends UnresolvedClass { + + /// CHECK-START: float Main.callAbs(float) register (before) + /// CHECK: <<CurrentMethod:[ij]\d+>> CurrentMethod + /// CHECK: <<ParamValue:f\d+>> ParameterValue + /// CHECK: InvokeStaticOrDirect [<<ParamValue>>,<<CurrentMethod>>] method_name:java.lang.Math.abs + static public float callAbs(float f) { + // An intrinsic invoke in a method that has unresolved references will still + // have a CurrentMethod as an argument. The X86 pc_relative_fixups_x86 pass + // must be able to handle Math.abs invokes that have a CurrentMethod, as both + // the CurrentMethod and the HX86LoadFromConstantTable (for the bitmask) + // expect to be in the 'SpecialInputIndex' input index. + return Math.abs(f); + } + + static public void main(String[] args) { + expectEquals(callAbs(-6.5f), 6.5f); + } + + public static void expectEquals(float expected, float result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/555-checker-regression-x86const/src/Unresolved.java b/test/555-checker-regression-x86const/src/Unresolved.java new file mode 100644 index 0000000000..e98bdbf8fb --- /dev/null +++ b/test/555-checker-regression-x86const/src/Unresolved.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2016 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. + */ + +class UnresolvedClass { +} diff --git a/test/565-checker-condition-liveness/src/Main.java b/test/565-checker-condition-liveness/src/Main.java index a811e5bb16..dc4cb76258 100644 --- a/test/565-checker-condition-liveness/src/Main.java +++ b/test/565-checker-condition-liveness/src/Main.java @@ -16,6 +16,24 @@ public class Main { + /// CHECK-START-X86: int Main.p(float) liveness (after) + /// CHECK: <<Arg:f\d+>> ParameterValue uses:[<<UseInput:\d+>>] + /// CHECK-DAG: <<Five:f\d+>> FloatConstant 5 uses:[<<UseInput>>] + /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 + /// CHECK-DAG: <<MinusOne:i\d+>> IntConstant -1 uses:[<<UseInput>>] + /// CHECK: <<Base:i\d+>> X86ComputeBaseMethodAddress uses:[<<UseInput>>] + /// CHECK-NEXT: <<Load:f\d+>> X86LoadFromConstantTable [<<Base>>,<<Five>>] + /// CHECK-NEXT: <<Cond:z\d+>> LessThanOrEqual [<<Arg>>,<<Load>>] + /// CHECK-NEXT: Select [<<Zero>>,<<MinusOne>>,<<Cond>>] liveness:<<LivSel:\d+>> + /// CHECK-EVAL: <<UseInput>> == <<LivSel>> + 1 + + public static int p(float arg) { + if (arg > 5.0f) { + return 0; + } + return -1; + } + /// CHECK-START: void Main.main(java.lang.String[]) liveness (after) /// CHECK: <<X:i\d+>> ArrayLength uses:[<<UseInput:\d+>>] /// CHECK: <<Y:i\d+>> StaticFieldGet uses:[<<UseInput>>] |