diff options
author | 2023-12-06 09:45:23 +0000 | |
---|---|---|
committer | 2023-12-06 14:50:37 +0000 | |
commit | 541b818a1c0e6b1045a4b4f7b301a7052cc37434 (patch) | |
tree | bea998d80cdc8dcbdb349f4bf882b0b1ecdc13a5 /compiler/optimizing/intrinsics_riscv64.cc | |
parent | b03f73c06fd8549b381022249d09d07bfe43d803 (diff) |
riscv64: Implement `Integer/Long.reverse()` intrinsics.
Also move `divideUnsigned()` intrinsic implementations
together with other integral intrinsic implementations.
Test: testrunner.py --target --64 --ndebug --optimizing
Bug: 283082089
Change-Id: I57786789ce6114ee951f46b7614ce965bdce9617
Diffstat (limited to 'compiler/optimizing/intrinsics_riscv64.cc')
-rw-r--r-- | compiler/optimizing/intrinsics_riscv64.cc | 143 |
1 files changed, 102 insertions, 41 deletions
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc index cf5243da2e..524a0b7858 100644 --- a/compiler/optimizing/intrinsics_riscv64.cc +++ b/compiler/optimizing/intrinsics_riscv64.cc @@ -329,6 +329,67 @@ static void GenerateReverseBytes(CodeGeneratorRISCV64* codegen, GenerateReverseBytes(codegen, locations->Out(), locations->InAt(0).AsRegister<XRegister>(), type); } +static void GenerateReverse(CodeGeneratorRISCV64* codegen, HInvoke* invoke, DataType::Type type) { + DCHECK_EQ(type, invoke->GetType()); + Riscv64Assembler* assembler = codegen->GetAssembler(); + LocationSummary* locations = invoke->GetLocations(); + XRegister in = locations->InAt(0).AsRegister<XRegister>(); + XRegister out = locations->Out().AsRegister<XRegister>(); + ScratchRegisterScope srs(assembler); + XRegister temp1 = srs.AllocateXRegister(); + XRegister temp2 = srs.AllocateXRegister(); + + auto maybe_extend_mask = [type, assembler](XRegister mask, XRegister temp) { + if (type == DataType::Type::kInt64) { + __ Slli(temp, mask, 32); + __ Add(mask, mask, temp); + } + }; + + // Swap bits in bit pairs. + __ Li(temp1, 0x55555555); + maybe_extend_mask(temp1, temp2); + __ Srli(temp2, in, 1); + __ And(out, in, temp1); + __ And(temp2, temp2, temp1); + __ Sh1Add(out, out, temp2); + + // Swap bit pairs in 4-bit groups. + __ Li(temp1, 0x33333333); + maybe_extend_mask(temp1, temp2); + __ Srli(temp2, out, 2); + __ And(out, out, temp1); + __ And(temp2, temp2, temp1); + __ Sh2Add(out, out, temp2); + + // Swap 4-bit groups in 8-bit groups. + __ Li(temp1, 0x0f0f0f0f); + maybe_extend_mask(temp1, temp2); + __ Srli(temp2, out, 4); + __ And(out, out, temp1); + __ And(temp2, temp2, temp1); + __ Slli(out, out, 4); + __ Add(out, out, temp2); + + GenerateReverseBytes(codegen, Location::RegisterLocation(out), out, type); +} + +void IntrinsicLocationsBuilderRISCV64::VisitIntegerReverse(HInvoke* invoke) { + CreateIntToIntNoOverlapLocations(allocator_, invoke); +} + +void IntrinsicCodeGeneratorRISCV64::VisitIntegerReverse(HInvoke* invoke) { + GenerateReverse(codegen_, invoke, DataType::Type::kInt32); +} + +void IntrinsicLocationsBuilderRISCV64::VisitLongReverse(HInvoke* invoke) { + CreateIntToIntNoOverlapLocations(allocator_, invoke); +} + +void IntrinsicCodeGeneratorRISCV64::VisitLongReverse(HInvoke* invoke) { + GenerateReverse(codegen_, invoke, DataType::Type::kInt64); +} + void IntrinsicLocationsBuilderRISCV64::VisitIntegerReverseBytes(HInvoke* invoke) { CreateIntToIntNoOverlapLocations(allocator_, invoke); } @@ -475,6 +536,47 @@ void IntrinsicCodeGeneratorRISCV64::VisitLongNumberOfTrailingZeros(HInvoke* invo EmitIntegralUnOp(invoke, [&](XRegister rd, XRegister rs1) { __ Ctz(rd, rs1); }); } +static void GenerateDivideUnsigned(HInvoke* invoke, CodeGeneratorRISCV64* codegen) { + LocationSummary* locations = invoke->GetLocations(); + Riscv64Assembler* assembler = codegen->GetAssembler(); + DataType::Type type = invoke->GetType(); + DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); + + XRegister dividend = locations->InAt(0).AsRegister<XRegister>(); + XRegister divisor = locations->InAt(1).AsRegister<XRegister>(); + XRegister out = locations->Out().AsRegister<XRegister>(); + + // Check if divisor is zero, bail to managed implementation to handle. + SlowPathCodeRISCV64* slow_path = + new (codegen->GetScopedAllocator()) IntrinsicSlowPathRISCV64(invoke); + codegen->AddSlowPath(slow_path); + __ Beqz(divisor, slow_path->GetEntryLabel()); + + if (type == DataType::Type::kInt32) { + __ Divuw(out, dividend, divisor); + } else { + __ Divu(out, dividend, divisor); + } + + __ Bind(slow_path->GetExitLabel()); +} + +void IntrinsicLocationsBuilderRISCV64::VisitIntegerDivideUnsigned(HInvoke* invoke) { + CreateIntIntToIntSlowPathCallLocations(allocator_, invoke); +} + +void IntrinsicCodeGeneratorRISCV64::VisitIntegerDivideUnsigned(HInvoke* invoke) { + GenerateDivideUnsigned(invoke, codegen_); +} + +void IntrinsicLocationsBuilderRISCV64::VisitLongDivideUnsigned(HInvoke* invoke) { + CreateIntIntToIntSlowPathCallLocations(allocator_, invoke); +} + +void IntrinsicCodeGeneratorRISCV64::VisitLongDivideUnsigned(HInvoke* invoke) { + GenerateDivideUnsigned(invoke, codegen_); +} + #define VISIT_INTRINSIC(name, low, high, type, start_index) \ void IntrinsicLocationsBuilderRISCV64::Visit ##name ##ValueOf(HInvoke* invoke) { \ InvokeRuntimeCallingConvention calling_convention; \ @@ -3527,47 +3629,6 @@ void IntrinsicLocationsBuilderRISCV64::VisitReachabilityFence(HInvoke* invoke) { void IntrinsicCodeGeneratorRISCV64::VisitReachabilityFence([[maybe_unused]] HInvoke* invoke) {} -static void GenerateDivideUnsigned(HInvoke* invoke, CodeGeneratorRISCV64* codegen) { - LocationSummary* locations = invoke->GetLocations(); - Riscv64Assembler* assembler = codegen->GetAssembler(); - DataType::Type type = invoke->GetType(); - DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64); - - XRegister dividend = locations->InAt(0).AsRegister<XRegister>(); - XRegister divisor = locations->InAt(1).AsRegister<XRegister>(); - XRegister out = locations->Out().AsRegister<XRegister>(); - - // Check if divisor is zero, bail to managed implementation to handle. - SlowPathCodeRISCV64* slow_path = - new (codegen->GetScopedAllocator()) IntrinsicSlowPathRISCV64(invoke); - codegen->AddSlowPath(slow_path); - __ Beqz(divisor, slow_path->GetEntryLabel()); - - if (type == DataType::Type::kInt32) { - __ Divuw(out, dividend, divisor); - } else { - __ Divu(out, dividend, divisor); - } - - __ Bind(slow_path->GetExitLabel()); -} - -void IntrinsicLocationsBuilderRISCV64::VisitIntegerDivideUnsigned(HInvoke* invoke) { - CreateIntIntToIntSlowPathCallLocations(allocator_, invoke); -} - -void IntrinsicCodeGeneratorRISCV64::VisitIntegerDivideUnsigned(HInvoke* invoke) { - GenerateDivideUnsigned(invoke, codegen_); -} - -void IntrinsicLocationsBuilderRISCV64::VisitLongDivideUnsigned(HInvoke* invoke) { - CreateIntIntToIntSlowPathCallLocations(allocator_, invoke); -} - -void IntrinsicCodeGeneratorRISCV64::VisitLongDivideUnsigned(HInvoke* invoke) { - GenerateDivideUnsigned(invoke, codegen_); -} - void IntrinsicLocationsBuilderRISCV64::VisitMathFmaDouble(HInvoke* invoke) { CreateFpFpFpToFpNoOverlapLocations(allocator_, invoke); } |