RISCV: [Codegen] Add VisitCompare
Test: m test-art-host-gtest
Bug: 283082089
Signed-off-by: Lifang Xia <lifang_xia@linux.alibaba.com>
Signed-off-by: Wendong Wang <wangwd@xcvmbyte.com>
Change-Id: I5fdaf57baddb8a8b1fa5128cd4bd98fd73bcb65d
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 6266461..7a99adc 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -43,6 +43,21 @@
#define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kRiscv64PointerSize, x).Int32Value()
+Location RegisterOrZeroBitPatternLocation(HInstruction* instruction) {
+ return IsZeroBitPattern(instruction)
+ ? Location::ConstantLocation(instruction->AsConstant())
+ : Location::RequiresRegister();
+}
+
+XRegister InputXRegisterOrZero(Location location) {
+ if (location.IsConstant()) {
+ DCHECK(location.GetConstant()->IsZeroBitPattern());
+ return Zero;
+ } else {
+ return location.AsRegister<XRegister>();
+ }
+}
+
Location Riscv64ReturnLocation(DataType::Type return_type) {
switch (return_type) {
case DataType::Type::kBool:
@@ -1188,13 +1203,103 @@
}
void LocationsBuilderRISCV64::VisitCompare(HCompare* instruction) {
- UNUSED(instruction);
- LOG(FATAL) << "Unimplemented";
+ DataType::Type in_type = instruction->InputAt(0)->GetType();
+
+ LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+
+ switch (in_type) {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64:
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, RegisterOrZeroBitPatternLocation(instruction->InputAt(1)));
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ break;
+
+ case DataType::Type::kFloat32:
+ case DataType::Type::kFloat64:
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ break;
+
+ default:
+ LOG(FATAL) << "Unexpected type for compare operation " << in_type;
+ UNREACHABLE();
+ }
}
void InstructionCodeGeneratorRISCV64::VisitCompare(HCompare* instruction) {
- UNUSED(instruction);
- LOG(FATAL) << "Unimplemented";
+ LocationSummary* locations = instruction->GetLocations();
+ XRegister result = locations->Out().AsRegister<XRegister>();
+ DataType::Type in_type = instruction->InputAt(0)->GetType();
+
+ // 0 if: left == right
+ // 1 if: left > right
+ // -1 if: left < right
+ switch (in_type) {
+ case DataType::Type::kBool:
+ case DataType::Type::kUint8:
+ case DataType::Type::kInt8:
+ case DataType::Type::kUint16:
+ case DataType::Type::kInt16:
+ case DataType::Type::kInt32:
+ case DataType::Type::kInt64: {
+ XRegister left = locations->InAt(0).AsRegister<XRegister>();
+ XRegister right = InputXRegisterOrZero(locations->InAt(1));
+ ScratchRegisterScope srs(GetAssembler());
+ XRegister tmp = srs.AllocateXRegister();
+ __ Slt(tmp, left, right);
+ __ Slt(result, right, left);
+ __ Sub(result, result, tmp);
+ break;
+ }
+
+ case DataType::Type::kFloat32: {
+ FRegister left = locations->InAt(0).AsFpuRegister<FRegister>();
+ FRegister right = locations->InAt(1).AsFpuRegister<FRegister>();
+ ScratchRegisterScope srs(GetAssembler());
+ XRegister tmp = srs.AllocateXRegister();
+ if (instruction->IsGtBias()) {
+ __ FLeS(tmp, left, right);
+ __ FLtS(result, left, right);
+ __ Xori(tmp, tmp, 1);
+ __ Sub(result, tmp, result);
+ } else {
+ __ FLeS(tmp, right, left);
+ __ FLtS(result, right, left);
+ __ Addi(tmp, tmp, -1);
+ __ Add(result, result, tmp);
+ }
+ break;
+ }
+
+ case DataType::Type::kFloat64: {
+ FRegister left = locations->InAt(0).AsFpuRegister<FRegister>();
+ FRegister right = locations->InAt(1).AsFpuRegister<FRegister>();
+ ScratchRegisterScope srs(GetAssembler());
+ XRegister tmp = srs.AllocateXRegister();
+ if (instruction->IsGtBias()) {
+ __ FLeD(tmp, left, right);
+ __ FLtD(result, left, right);
+ __ Xori(tmp, tmp, 1);
+ __ Sub(result, tmp, result);
+ } else {
+ __ FLeD(tmp, right, left);
+ __ FLtD(result, right, left);
+ __ Addi(tmp, tmp, -1);
+ __ Add(result, result, tmp);
+ }
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unimplemented compare type " << in_type;
+ }
}
void LocationsBuilderRISCV64::VisitConstructorFence(HConstructorFence* instruction) {