From 8f9a62d3120dbb346b421ee288458596cc82a9d9 Mon Sep 17 00:00:00 2001 From: Dusan Milosavljevic Date: Wed, 4 Feb 2015 11:52:16 +0100 Subject: [PATCH] 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} --- src/compiler/mips/code-generator-mips.cc | 91 ++++++++++---------- src/compiler/mips64/code-generator-mips64.cc | 86 +++++++++--------- src/mips64/assembler-mips64.h | 2 + 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/src/compiler/mips/code-generator-mips.cc b/src/compiler/mips/code-generator-mips.cc index 39d1d4ad96..67f49c6d6e 100644 --- a/src/compiler/mips/code-generator-mips.cc +++ b/src/compiler/mips/code-generator-mips.cc @@ -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); diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc index 853346f1c3..a3f47a1d78 100644 --- a/src/compiler/mips64/code-generator-mips64.cc +++ b/src/compiler/mips64/code-generator-mips64.cc @@ -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()); diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h index 5ca2f3ad03..969b31bb25 100644 --- a/src/mips64/assembler-mips64.h +++ b/src/mips64/assembler-mips64.h @@ -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.