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

TEST=
BUG=
R=paul.lind@imgtec.com

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

Cr-Commit-Position: refs/heads/master@{#26422}
This commit is contained in:
Dusan Milosavljevic 2015-02-04 11:52:16 +01:00
parent d923864c79
commit 8f9a62d312
3 changed files with 95 additions and 84 deletions

View File

@ -262,6 +262,33 @@ 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 kUnsignedLessThanOrEqual:
predicate = true;
return OLE;
case kUnorderedEqual:
case kUnorderedNotEqual:
predicate = true;
break;
default:
predicate = true;
break;
}
UNREACHABLE();
return kNoFPUCondition;
}
} // namespace
@ -790,8 +817,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 +830,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 +840,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);

View File

@ -262,6 +262,34 @@ 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 kUnsignedLessThanOrEqual:
predicate = true;
return OLE;
case kUnorderedEqual:
case kUnorderedNotEqual:
predicate = true;
break;
default:
predicate = true;
break;
}
UNREACHABLE();
return kNoFPUCondition;
}
} // namespace
@ -968,47 +996,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());

View File

@ -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.