Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 25 additions & 52 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3136,65 +3136,38 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)

if (varTypeIsFloating(op1Type))
{
bool isUnordered = (tree->gtFlags & GTF_RELOP_NAN_UN) != 0;
regNumber regOp1 = op1->GetRegNum();
regNumber regOp2 = op2->GetRegNum();
assert(!op2->isContainedIntOrIImmed());
assert(op1Type == op2Type);
genTreeOps oper = tree->OperGet();

bool isUnordered = (tree->gtFlags & GTF_RELOP_NAN_UN) != 0;
if (isUnordered)
{
if (tree->OperIs(GT_LT))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_fle_s : INS_fle_d, cmpSize, targetReg, regOp2, regOp1);
}
else if (tree->OperIs(GT_LE))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_flt_s : INS_flt_d, cmpSize, targetReg, regOp2, regOp1);
}
else if (tree->OperIs(GT_NE))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_feq_s : INS_feq_d, cmpSize, targetReg, regOp1, regOp2);
}
else if (tree->OperIs(GT_GT))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_fle_s : INS_fle_d, cmpSize, targetReg, regOp1, regOp2);
}
else if (tree->OperIs(GT_GE))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_flt_s : INS_flt_d, cmpSize, targetReg, regOp1, regOp2);
}
else
{
unreached();
}
emit->emitIns_R_R_I(INS_xori, EA_8BYTE, targetReg, targetReg, 1);
oper = GenTree::ReverseRelop(oper);
}
Comment on lines 3144 to 3147
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar swapping is done in a platform agnostic way in TryLowerConditionToFlagsNode based on GenCondition::PreferSwap. Can RISC-V use the same mechanism?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TryLowerConditionToFlagsNode is not called on RISC-V, it looks more geared for architectures with a special flag register for conditions. Floating comparisons on RISC-V are written to a normal GP register.

Maybe I can swap it in LowerCompare in a separate PR? Some of the stuff from #115039 also looks suitable for moving from codegen to lowering (there's similar swapping and negating going on when the integer comparison is not fed into a branch), which would simplify register allocation, containing immediates, and also sign-extension elimination in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, makes sense.

else
if (oper == GT_GT || oper == GT_GE)
{
if (tree->OperIs(GT_LT))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_flt_s : INS_flt_d, cmpSize, targetReg, regOp1, regOp2);
}
else if (tree->OperIs(GT_LE))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_fle_s : INS_fle_d, cmpSize, targetReg, regOp1, regOp2);
}
else if (tree->OperIs(GT_EQ))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_feq_s : INS_feq_d, cmpSize, targetReg, regOp1, regOp2);
}
else if (tree->OperIs(GT_GT))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_flt_s : INS_flt_d, cmpSize, targetReg, regOp2, regOp1);
}
else if (tree->OperIs(GT_GE))
{
emit->emitIns_R_R_R(cmpSize == EA_4BYTE ? INS_fle_s : INS_fle_d, cmpSize, targetReg, regOp2, regOp1);
}
else
{
oper = GenTree::SwapRelop(oper);
std::swap(op1, op2);
}
instruction instr = INS_none;
switch (oper)
{
case GT_LT:
instr = (cmpSize == EA_4BYTE) ? INS_flt_s : INS_flt_d;
break;
case GT_LE:
instr = (cmpSize == EA_4BYTE) ? INS_fle_s : INS_fle_d;
break;
case GT_EQ:
instr = (cmpSize == EA_4BYTE) ? INS_feq_s : INS_feq_d;
break;
default:
unreached();
}
}
emit->emitIns_R_R_R(instr, cmpSize, targetReg, op1->GetRegNum(), op2->GetRegNum());
if (isUnordered)
emit->emitIns_R_R_I(INS_xori, EA_8BYTE, targetReg, targetReg, 1);
}
else
{
Expand Down
16 changes: 12 additions & 4 deletions src/coreclr/jit/lowerriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,10 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue)
GenTree* cmpOp1;
GenTree* cmpOp2;

assert(!op->OperIsCompare() || op->OperIsCmpCompare()); // We do not expect any other relops on RISCV64

if (op->OperIsCompare() && !varTypeIsFloating(op->gtGetOp1()))
{
// We do not expect any other relops on RISCV64
assert(op->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT));

cond = GenCondition::FromRelop(op);

cmpOp1 = op->gtGetOp1();
Expand All @@ -151,7 +150,16 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue)
}
else
{
cond = GenCondition(GenCondition::NE);
GenCondition::Code code = GenCondition::NE;
if (op->OperIsCompare() && varTypeIsFloating(op->gtGetOp1()) && (op->gtFlags & GTF_RELOP_NAN_UN) != 0)
{
// Unordered floating-point comparisons are achieved by neg'ing the ordered counterparts. Avoid that by
// reversing both the FP comparison and the zero-comparison fused with the branch.
op->ChangeOper(GenTree::ReverseRelop(op->OperGet()));
op->gtFlags &= ~GTF_RELOP_NAN_UN;
code = GenCondition::EQ;
}
cond = GenCondition(code);

cmpOp1 = op;
cmpOp2 = comp->gtNewZeroConNode(cmpOp1->TypeGet());
Expand Down
Loading