Commit c03a5ca1 authored by Dusan Milosavljevic's avatar Dusan Milosavljevic

MIPS:[turbofan] Reland "Improve unordered comparisons for boolean materialization.".

BUG=
R=paul.lind@imgtec.com

Review URL: https://codereview.chromium.org/905493002

Cr-Commit-Position: refs/heads/master@{#26469}
parent 3cd88975
......@@ -262,6 +262,39 @@ Condition FlagsConditionToConditionOvf(FlagsCondition condition) {
return kNoCondition;
}
FPUCondition FlagsConditionToConditionCmpD(bool& predicate,
FlagsCondition condition) {
switch (condition) {
case kEqual:
predicate = true;
return EQ;
case kNotEqual:
predicate = false;
return EQ;
case kUnsignedLessThan:
predicate = true;
return OLT;
case kUnsignedGreaterThanOrEqual:
predicate = false;
return ULT;
case kUnsignedLessThanOrEqual:
predicate = true;
return OLE;
case kUnsignedGreaterThan:
predicate = false;
return ULE;
case kUnorderedEqual:
case kUnorderedNotEqual:
predicate = true;
break;
default:
predicate = true;
break;
}
UNREACHABLE();
return kNoFPUCondition;
}
} // namespace
......@@ -790,8 +823,6 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
// in the false case, where we fall thru the branch, we reset the result
// false.
// TODO(plind): Add CHECK() to ensure that test/cmp and this branch were
// not separated by other instructions.
if (instr->arch_opcode() == kMipsTst) {
cc = FlagsConditionToConditionTst(condition);
__ And(at, i.InputRegister(0), i.InputOperand(1));
......@@ -805,7 +836,6 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
__ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg));
__ li(result, Operand(1)); // In delay slot.
} else if (instr->arch_opcode() == kMipsCmp) {
Register left = i.InputRegister(0);
Operand right = i.InputOperand(1);
......@@ -816,54 +846,33 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
} else if (instr->arch_opcode() == kMipsCmpD) {
FPURegister left = i.InputDoubleRegister(0);
FPURegister right = i.InputDoubleRegister(1);
// TODO(plind): Provide NaN-testing macro-asm function without need for
// BranchF.
FPURegister dummy1 = f0;
FPURegister dummy2 = f2;
switch (condition) {
case kEqual:
// TODO(plind): improve the NaN testing throughout this function.
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = eq;
break;
case kNotEqual:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = ne;
break;
case kUnsignedLessThan:
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = lt;
break;
case kUnsignedGreaterThanOrEqual:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = ge;
break;
case kUnsignedLessThanOrEqual:
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = le;
break;
case kUnsignedGreaterThan:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = gt;
break;
default:
UNSUPPORTED_COND(kMipsCmp, condition);
break;
}
__ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right);
__ li(result, Operand(1)); // In delay slot - branch taken returns 1.
// Fall-thru (branch not taken) returns 0.
bool predicate;
FPUCondition cc = FlagsConditionToConditionCmpD(predicate, condition);
if (!IsMipsArchVariant(kMips32r6)) {
__ li(result, Operand(1));
__ c(cc, D, left, right);
if (predicate) {
__ Movf(result, zero_reg);
} else {
__ Movt(result, zero_reg);
}
} else {
__ cmp(cc, L, kDoubleCompareReg, left, right);
__ mfc1(at, kDoubleCompareReg);
__ srl(result, at, 31); // Cmp returns all 1s for true.
if (!predicate) // Toggle result for not equal.
__ xori(result, result, 1);
}
return;
} else {
PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n",
instr->arch_opcode());
TRACE_UNIMPL();
UNIMPLEMENTED();
}
// Fallthru case is the false materialization.
// Fallthrough case is the false materialization.
__ bind(&false_value);
__ li(result, Operand(0));
__ bind(&done);
......
......@@ -262,6 +262,40 @@ Condition FlagsConditionToConditionOvf(FlagsCondition condition) {
return kNoCondition;
}
FPUCondition FlagsConditionToConditionCmpD(bool& predicate,
FlagsCondition condition) {
switch (condition) {
case kEqual:
predicate = true;
return EQ;
case kNotEqual:
predicate = false;
return EQ;
case kUnsignedLessThan:
predicate = true;
return OLT;
case kUnsignedGreaterThanOrEqual:
predicate = false;
return ULT;
case kUnsignedLessThanOrEqual:
predicate = true;
return OLE;
case kUnsignedGreaterThan:
predicate = false;
return ULE;
case kUnorderedEqual:
case kUnorderedNotEqual:
predicate = true;
break;
default:
predicate = true;
break;
}
UNREACHABLE();
return kNoFPUCondition;
}
} // namespace
......@@ -968,47 +1002,25 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
} else if (instr->arch_opcode() == kMips64CmpD) {
FPURegister left = i.InputDoubleRegister(0);
FPURegister right = i.InputDoubleRegister(1);
// TODO(plind): Provide NaN-testing macro-asm function without need for
// BranchF.
FPURegister dummy1 = f0;
FPURegister dummy2 = f2;
switch (condition) {
case kEqual:
// TODO(plind): improve the NaN testing throughout this function.
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = eq;
break;
case kNotEqual:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = ne;
break;
case kUnsignedLessThan:
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = lt;
break;
case kUnsignedGreaterThanOrEqual:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = ge;
break;
case kUnsignedLessThanOrEqual:
__ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2);
cc = le;
break;
case kUnsignedGreaterThan:
__ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2);
__ li(result, Operand(1)); // In delay slot - returns 1 on NaN.
cc = gt;
break;
default:
UNSUPPORTED_COND(kMips64Cmp, condition);
break;
}
__ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right);
__ li(result, Operand(1)); // In delay slot - branch taken returns 1.
// Fall-thru (branch not taken) returns 0.
bool predicate;
FPUCondition cc = FlagsConditionToConditionCmpD(predicate, condition);
if (kArchVariant != kMips64r6) {
__ li(result, Operand(1));
__ c(cc, D, left, right);
if (predicate) {
__ Movf(result, zero_reg);
} else {
__ Movt(result, zero_reg);
}
} else {
__ cmp(cc, L, kDoubleCompareReg, left, right);
__ dmfc1(at, kDoubleCompareReg);
__ dsrl32(result, at, 31); // Cmp returns all 1s for true.
if (!predicate) // Toggle result for not equal.
__ xori(result, result, 1);
}
return;
} else {
PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n",
instr->arch_opcode());
......
......@@ -323,6 +323,8 @@ const FPURegister f31 = { 31 };
#define kLithiumScratchReg2 s4
#define kLithiumScratchDouble f30
#define kDoubleRegZero f28
// Used on mips64r6 for compare operations.
#define kDoubleCompareReg f31
// FPU (coprocessor 1) control registers.
// Currently only FCSR (#31) is implemented.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment