Skip to content

Commit

Permalink
Merge pull request #7196 from sarwat12/NaN_fdMinMax
Browse files Browse the repository at this point in the history
Z: Support NaN values w.r.t fmax/fmin/dmax/dmin on S390
  • Loading branch information
hzongaro committed Feb 14, 2024
2 parents 823df4a + 27c1618 commit 0966eb3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 15 deletions.
23 changes: 17 additions & 6 deletions compiler/z/codegen/ControlFlowEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,18 +341,25 @@ xmaxxminHelper(TR::Node* node, TR::CodeGenerator* cg, TR::InstOpCode::Mnemonic c
generateRREInstruction(cg, compareRROp, node, lhsReg, rhsReg);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, branchCond, node, cFlowRegionEnd);

//Check for NaN operands for float and double
if (node->getOpCode().isFloatingPoint())
{
// If first operand is NaN, then we are done, otherwise fallthrough to move second operand as result
generateRREInstruction(cg, node->getOpCode().isDouble() ? TR::InstOpCode::LTDBR : TR::InstOpCode::LTEBR, node, lhsReg, lhsReg);
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC3, node, cFlowRegionEnd);
}

//Move resulting operand to lhsReg as fallthrough for alternate Condition Code
generateRREInstruction(cg, moveRROp, node, lhsReg, rhsReg);

TR::RegisterDependencyConditions* deps = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0, 2, cg);

deps->addPostConditionIfNotAlreadyInserted(lhsReg, TR::RealRegister::AssignAny);
deps->addPostConditionIfNotAlreadyInserted(rhsReg, TR::RealRegister::AssignAny);

generateS390LabelInstruction(cg, TR::InstOpCode::label, node, cFlowRegionEnd, deps);
cFlowRegionEnd->setEndInternalControlFlow();

node->setRegister(lhsReg);

cg->decReferenceCount(lhsNode);
cg->decReferenceCount(rhsNode);

Expand Down Expand Up @@ -466,13 +473,15 @@ OMR::Z::TreeEvaluator::lmaxEvaluator(TR::Node* node, TR::CodeGenerator* cg)
TR::Register*
OMR::Z::TreeEvaluator::fmaxEvaluator(TR::Node* node, TR::CodeGenerator* cg)
{
return xmaxxminHelper(node, cg, TR::InstOpCode::CEBR, TR::InstOpCode::COND_BHR, TR::InstOpCode::LER);
//Passing COND_MASK10 to check CC if operand 1 is already greater than, or equal to operand 2
return xmaxxminHelper(node, cg, TR::InstOpCode::CEBR, TR::InstOpCode::COND_MASK10, TR::InstOpCode::LER);
}

TR::Register*
OMR::Z::TreeEvaluator::dmaxEvaluator(TR::Node* node, TR::CodeGenerator* cg)
{
return xmaxxminHelper(node, cg, TR::InstOpCode::CDBR, TR::InstOpCode::COND_BHR, TR::InstOpCode::LDR);
//Passing COND_MASK10 to check CC if operand 1 is already greater than, or equal to operand 2
return xmaxxminHelper(node, cg, TR::InstOpCode::CDBR, TR::InstOpCode::COND_MASK10, TR::InstOpCode::LDR);
}

TR::Register *
Expand All @@ -490,13 +499,15 @@ OMR::Z::TreeEvaluator::lminEvaluator(TR::Node *node, TR::CodeGenerator *cg)
TR::Register*
OMR::Z::TreeEvaluator::fminEvaluator(TR::Node* node, TR::CodeGenerator* cg)
{
return xmaxxminHelper(node, cg, TR::InstOpCode::CEBR, TR::InstOpCode::COND_BLR, TR::InstOpCode::LER);
//Passing COND_MASK12 to check CC if operand 1 is already less than, or equal to operand 2
return xmaxxminHelper(node, cg, TR::InstOpCode::CEBR, TR::InstOpCode::COND_MASK12, TR::InstOpCode::LER);
}

TR::Register*
OMR::Z::TreeEvaluator::dminEvaluator(TR::Node* node, TR::CodeGenerator* cg)
{
return xmaxxminHelper(node, cg, TR::InstOpCode::CDBR, TR::InstOpCode::COND_BLR, TR::InstOpCode::LDR);
//Passing COND_MASK12 to check CC if operand 1 is already less than, or equal to operand 2
return xmaxxminHelper(node, cg, TR::InstOpCode::CDBR, TR::InstOpCode::COND_MASK12, TR::InstOpCode::LDR);
}

/**
Expand Down
13 changes: 4 additions & 9 deletions fvtest/compilertriltest/MaxMinTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ TEST_P(FloatMaxMin, UsingConst) {
auto param = TRTest::to_struct(GetParam());

if (std::isnan(param.lhs) || std::isnan(param.rhs)) {
SKIP_ON_S390(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_S390X(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_ZOS(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
}

char inputTrees[1024] = {0};
Expand Down Expand Up @@ -238,8 +237,7 @@ TEST_P(FloatMaxMin, UsingLoadParam) {
auto param = TRTest::to_struct(GetParam());

if (std::isnan(param.lhs) || std::isnan(param.rhs)) {
SKIP_ON_S390(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_S390X(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_ZOS(KnownBug) << "fmin / fmax returns wrong value for NaN on Z (see issue #5157)";
}

char inputTrees[1024] = {0};
Expand Down Expand Up @@ -281,8 +279,7 @@ TEST_P(DoubleMaxMin, UsingConst) {
auto param = TRTest::to_struct(GetParam());

if (std::isnan(param.lhs) || std::isnan(param.rhs)) {
SKIP_ON_S390(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_S390X(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_ZOS(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";
}

char inputTrees[1024] = {0};
Expand Down Expand Up @@ -316,9 +313,7 @@ TEST_P(DoubleMaxMin, UsingLoadParam) {
auto param = TRTest::to_struct(GetParam());

if (std::isnan(param.lhs) || std::isnan(param.rhs)) {
SKIP_ON_S390(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";
SKIP_ON_S390X(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";

SKIP_ON_ZOS(KnownBug) << "dmin / dmax returns wrong value for NaN on Z (see issue #5157)";
}

char inputTrees[1024] = {0};
Expand Down

0 comments on commit 0966eb3

Please sign in to comment.