Commit 3225b326 authored by jyan's avatar jyan Committed by Commit bot

s390: improve floating point and integer convertion

R=joransiu@ca.ibm.com, bjaideep@ca.ibm.com, michael_dawson@ca.ibm.com

Review-Url: https://codereview.chromium.org/2761953002
Cr-Commit-Position: refs/heads/master@{#43998}
parent fee0961f
This diff is collapsed.
......@@ -330,6 +330,8 @@ ArchOpcode SelectLoadOpcode(Node* node) {
/* Word32 unary op */ \
V(Word32Clz) \
V(Word32Popcnt) \
V(Float64ExtractLowWord32) \
V(Float64ExtractHighWord32) \
/* Word32 bin op */ \
V(Int32Add) \
V(Int32Sub) \
......@@ -1379,13 +1381,44 @@ static inline bool TryMatchInt64SubWithOverflow(InstructionSelector* selector,
}
#endif
static inline bool TryMatchDoubleConstructFromInsert(
InstructionSelector* selector, Node* node) {
S390OperandGenerator g(selector);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
Node* lo32 = NULL;
Node* hi32 = NULL;
if (node->opcode() == IrOpcode::kFloat64InsertLowWord32) {
lo32 = right;
} else if (node->opcode() == IrOpcode::kFloat64InsertHighWord32) {
hi32 = right;
} else {
return false; // doesn't match
}
if (left->opcode() == IrOpcode::kFloat64InsertLowWord32) {
lo32 = left->InputAt(1);
} else if (left->opcode() == IrOpcode::kFloat64InsertHighWord32) {
hi32 = left->InputAt(1);
} else {
return false; // doesn't match
}
if (!lo32 || !hi32) return false; // doesn't match
selector->Emit(kS390_DoubleConstruct, g.DefineAsRegister(node),
g.UseRegister(hi32), g.UseRegister(lo32));
return true;
}
#define null ([]() { return false; })
// TODO(john.yan): place kAllowRM where available
#define FLOAT_UNARY_OP_LIST_32(V) \
V(Float32, ChangeFloat32ToFloat64, kS390_Float32ToDouble, \
OperandMode::kAllowRM, null) \
V(Float32, BitcastFloat32ToInt32, kS390_BitcastFloat32ToInt32, \
OperandMode::kNone, null) \
OperandMode::kAllowRM, null) \
V(Float64, TruncateFloat64ToFloat32, kS390_DoubleToFloat32, \
OperandMode::kNone, null) \
V(Float64, TruncateFloat64ToWord32, kArchTruncateDoubleToI, \
......@@ -1419,7 +1452,12 @@ static inline bool TryMatchInt64SubWithOverflow(InstructionSelector* selector,
V(Float64, Float64RoundTiesAway, kS390_RoundDouble, OperandMode::kNone, \
null) \
V(Float32, Float32Neg, kS390_NegFloat, OperandMode::kNone, null) \
V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone, null)
V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone, null) \
/* TODO(john.yan): can use kAllowRM */ \
V(Word32, Float64ExtractLowWord32, kS390_DoubleExtractLowWord32, \
OperandMode::kNone, null) \
V(Word32, Float64ExtractHighWord32, kS390_DoubleExtractHighWord32, \
OperandMode::kNone, null)
#define FLOAT_BIN_OP_LIST(V) \
V(Float32, Float32Add, kS390_AddFloat, OperandMode::kAllowRM, null) \
......@@ -1511,7 +1549,13 @@ static inline bool TryMatchInt64SubWithOverflow(InstructionSelector* selector,
V(Word32, Word32Shl, kS390_ShiftLeft32, Shift32OperandMode, null) \
V(Word32, Word32Shr, kS390_ShiftRight32, Shift32OperandMode, null) \
V(Word32, Word32Sar, kS390_ShiftRightArith32, Shift32OperandMode, \
[&]() { return TryMatchSignExtInt16OrInt8FromWord32Sar(this, node); })
[&]() { return TryMatchSignExtInt16OrInt8FromWord32Sar(this, node); }) \
V(Word32, Float64InsertLowWord32, kS390_DoubleInsertLowWord32, \
OperandMode::kAllowRRR, \
[&]() -> bool { return TryMatchDoubleConstructFromInsert(this, node); }) \
V(Word32, Float64InsertHighWord32, kS390_DoubleInsertHighWord32, \
OperandMode::kAllowRRR, \
[&]() -> bool { return TryMatchDoubleConstructFromInsert(this, node); })
#define WORD64_UNARY_OP_LIST(V) \
V(Word64, Word64Popcnt, kS390_Popcnt64, OperandMode::kNone, null) \
......@@ -2300,48 +2344,6 @@ bool InstructionSelector::IsTailCallAddressImmediate() { return false; }
int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
S390OperandGenerator g(this);
Emit(kS390_DoubleExtractLowWord32, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
S390OperandGenerator g(this);
Emit(kS390_DoubleExtractHighWord32, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
S390OperandGenerator g(this);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 &&
CanCover(node, left)) {
left = left->InputAt(1);
Emit(kS390_DoubleConstruct, g.DefineAsRegister(node), g.UseRegister(left),
g.UseRegister(right));
return;
}
Emit(kS390_DoubleInsertLowWord32, g.DefineSameAsFirst(node),
g.UseRegister(left), g.UseRegister(right));
}
void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
S390OperandGenerator g(this);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 &&
CanCover(node, left)) {
left = left->InputAt(1);
Emit(kS390_DoubleConstruct, g.DefineAsRegister(node), g.UseRegister(right),
g.UseRegister(left));
return;
}
Emit(kS390_DoubleInsertHighWord32, g.DefineSameAsFirst(node),
g.UseRegister(left), g.UseRegister(right));
}
void InstructionSelector::VisitAtomicLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
S390OperandGenerator g(this);
......
......@@ -1359,7 +1359,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
#if V8_TARGET_ARCH_S390X
} else {
__ LoadComplementRR(result, left);
__ TestIfInt32(result, r0);
__ TestIfInt32(result);
DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow);
}
#endif
......@@ -1444,7 +1444,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ LoadRR(result, left);
__ msgr(result, right);
}
__ TestIfInt32(result, r0);
__ TestIfInt32(result);
DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow);
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiTag(result);
......@@ -1452,16 +1452,15 @@ void LCodeGen::DoMulI(LMulI* instr) {
#else
// r0:scratch = scratch * right
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(scratch, left);
__ mr_z(r0, right);
__ LoadRR(result, scratch);
__ SmiUntag(result, left);
__ lgfr(result, result);
__ msgfr(result, right);
} else {
// r0:scratch = scratch * right
__ LoadRR(scratch, left);
__ mr_z(r0, right);
__ LoadRR(result, scratch);
__ lgfr(result, left);
__ msgfr(result, right);
}
__ TestIfInt32(r0, result, scratch);
__ TestIfInt32(result);
DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow);
#endif
}
......@@ -4426,16 +4425,16 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
if (input->IsStackSlot()) {
Register scratch = scratch0();
__ LoadP(scratch, ToMemOperand(input));
__ ConvertIntToDouble(scratch, ToDoubleRegister(output));
__ ConvertIntToDouble(ToDoubleRegister(output), scratch);
} else {
__ ConvertIntToDouble(ToRegister(input), ToDoubleRegister(output));
__ ConvertIntToDouble(ToDoubleRegister(output), ToRegister(input));
}
}
void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
LOperand* input = instr->value();
LOperand* output = instr->result();
__ ConvertUnsignedIntToDouble(ToRegister(input), ToDoubleRegister(output));
__ ConvertUnsignedIntToDouble(ToDoubleRegister(output), ToRegister(input));
}
void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
......@@ -4511,9 +4510,9 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, LOperand* value,
__ SmiUntag(src, dst);
__ xilf(src, Operand(HeapNumber::kSignMask));
}
__ ConvertIntToDouble(src, dbl_scratch);
__ ConvertIntToDouble(dbl_scratch, src);
} else {
__ ConvertUnsignedIntToDouble(src, dbl_scratch);
__ ConvertUnsignedIntToDouble(dbl_scratch, src);
}
if (FLAG_inline_new) {
......@@ -4678,7 +4677,7 @@ void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
// Smi to double register conversion
__ bind(&load_smi);
// scratch: untagged value of input_reg
__ ConvertIntToDouble(scratch, result_reg);
__ ConvertIntToDouble(result_reg, scratch);
__ bind(&done);
}
......
......@@ -1596,7 +1596,9 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ mr_z(scratch1, ip); // R4:R5 = R5 * ip
// Check for overflowing the smi range - no overflow if higher 33 bits
// of the result are identical.
__ TestIfInt32(scratch1, scratch2, ip);
__ lr(ip, scratch2); // 32 bit load
__ sra(ip, Operand(31));
__ cr_z(ip, scratch1); // 32 bit compare
__ bne(&stub_call);
#endif
// Go slow on zero result to handle -0.
......
......@@ -1949,10 +1949,8 @@ void Assembler::clgebr(Condition m3, Condition m4, Register r1,
// Convert to Fixed Logical (32<-F64)
void Assembler::clfdbr(Condition m3, Condition m4, Register r1,
DoubleRegister r2) {
DCHECK_EQ(m3, Condition(0));
DCHECK_EQ(m4, Condition(0));
rrfe_form(CLFDBR, Condition(0), Condition(0), r1,
Register::from_code(r2.code()));
rrfe_form(CLFDBR, m3, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert to Fixed Logical (32<-F32)
......
......@@ -87,18 +87,10 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ LoadDouble(double_scratch, MemOperand(input_reg, double_offset));
// Do fast-path convert from double to int.
__ ConvertDoubleToInt64(double_scratch,
#if !V8_TARGET_ARCH_S390X
scratch,
#endif
result_reg, d0);
__ ConvertDoubleToInt64(result_reg, double_scratch);
// Test for overflow
#if V8_TARGET_ARCH_S390X
__ TestIfInt32(result_reg, r0);
#else
__ TestIfInt32(scratch, result_reg, r0);
#endif
// Test for overflow
__ TestIfInt32(result_reg);
__ beq(&fastpath_done, Label::kNear);
}
......@@ -746,7 +738,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
}
__ ldr(double_scratch, double_base); // Back up base.
__ LoadImmP(scratch2, Operand(1));
__ ConvertIntToDouble(scratch2, double_result);
__ ConvertIntToDouble(double_result, scratch2);
// Get absolute value of exponent.
Label positive_exponent;
......@@ -775,7 +767,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
// get 1/double_result:
__ ldr(double_scratch, double_result);
__ LoadImmP(scratch2, Operand(1));
__ ConvertIntToDouble(scratch2, double_result);
__ ConvertIntToDouble(double_result, scratch2);
__ ddbr(double_result, double_scratch);
// Test whether result is zero. Bail out to check for subnormal result.
......@@ -785,7 +777,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ bne(&done, Label::kNear);
// double_exponent may not containe the exponent value if the input was a
// smi. We set it with exponent value before bailing out.
__ ConvertIntToDouble(exponent, double_exponent);
__ ConvertIntToDouble(double_exponent, exponent);
// Returning or bailing out.
__ push(r14);
......
This diff is collapsed.
......@@ -735,26 +735,24 @@ class MacroAssembler : public Assembler {
// Converts the integer (untagged smi) in |src| to a double, storing
// the result to |dst|
void ConvertIntToDouble(Register src, DoubleRegister dst);
void ConvertIntToDouble(DoubleRegister dst, Register src);
// Converts the unsigned integer (untagged smi) in |src| to
// a double, storing the result to |dst|
void ConvertUnsignedIntToDouble(Register src, DoubleRegister dst);
void ConvertUnsignedIntToDouble(DoubleRegister dst, Register src);
// Converts the integer (untagged smi) in |src| to
// a float, storing the result in |dst|
void ConvertIntToFloat(Register src, DoubleRegister dst);
void ConvertIntToFloat(DoubleRegister dst, Register src);
// Converts the unsigned integer (untagged smi) in |src| to
// a float, storing the result in |dst|
void ConvertUnsignedIntToFloat(Register src, DoubleRegister dst);
void ConvertUnsignedIntToFloat(DoubleRegister dst, Register src);
#if V8_TARGET_ARCH_S390X
void ConvertInt64ToFloat(Register src, DoubleRegister double_dst);
void ConvertInt64ToDouble(Register src, DoubleRegister double_dst);
void ConvertUnsignedInt64ToFloat(Register src, DoubleRegister double_dst);
void ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst);
#endif
void ConvertInt64ToFloat(DoubleRegister double_dst, Register src);
void ConvertInt64ToDouble(DoubleRegister double_dst, Register src);
void ConvertUnsignedInt64ToFloat(DoubleRegister double_dst, Register src);
void ConvertUnsignedInt64ToDouble(DoubleRegister double_dst, Register src);
void MovIntToFloat(DoubleRegister dst, Register src);
void MovFloatToInt(Register dst, DoubleRegister src);
......@@ -762,43 +760,36 @@ class MacroAssembler : public Assembler {
void MovInt64ToDouble(DoubleRegister dst, Register src);
// Converts the double_input to an integer. Note that, upon return,
// the contents of double_dst will also hold the fixed point representation.
void ConvertFloat32ToInt64(const DoubleRegister double_input,
#if !V8_TARGET_ARCH_S390X
const Register dst_hi,
#endif
const Register dst,
const DoubleRegister double_dst,
void ConvertFloat32ToInt64(const Register dst,
const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
// Converts the double_input to an integer. Note that, upon return,
// the contents of double_dst will also hold the fixed point representation.
void ConvertDoubleToInt64(const DoubleRegister double_input,
#if !V8_TARGET_ARCH_S390X
const Register dst_hi,
#endif
const Register dst, const DoubleRegister double_dst,
void ConvertDoubleToInt64(const Register dst,
const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
void ConvertDoubleToInt32(const Register dst,
const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
void ConvertFloat32ToInt32(const DoubleRegister double_input,
const Register dst,
const DoubleRegister double_dst,
void ConvertFloat32ToInt32(const Register result,
const DoubleRegister double_input,
FPRoundingMode rounding_mode);
void ConvertFloat32ToUnsignedInt32(
const DoubleRegister double_input, const Register dst,
const DoubleRegister double_dst,
const Register result, const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
#if V8_TARGET_ARCH_S390X
// Converts the double_input to an unsigned integer. Note that, upon return,
// the contents of double_dst will also hold the fixed point representation.
void ConvertDoubleToUnsignedInt64(
const DoubleRegister double_input, const Register dst,
const DoubleRegister double_dst,
const Register dst, const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
void ConvertDoubleToUnsignedInt32(
const Register dst, const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
void ConvertFloat32ToUnsignedInt64(
const DoubleRegister double_input, const Register dst,
const DoubleRegister double_dst,
const Register result, const DoubleRegister double_input,
FPRoundingMode rounding_mode = kRoundToZero);
#endif
#if !V8_TARGET_ARCH_S390X
void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
......@@ -1625,20 +1616,10 @@ class MacroAssembler : public Assembler {
void AssertNotSmi(Register object);
void AssertSmi(Register object);
#if V8_TARGET_ARCH_S390X
inline void TestIfInt32(Register value, Register scratch) {
inline void TestIfInt32(Register value) {
// High bits must be identical to fit into an 32-bit integer
lgfr(scratch, value);
CmpP(scratch, value);
cgfr(value, value);
}
#else
inline void TestIfInt32(Register hi_word, Register lo_word,
Register scratch) {
// High bits must be identical to fit into an 32-bit integer
ShiftRightArith(scratch, lo_word, Operand(31));
CmpP(scratch, hi_word);
}
#endif
#if V8_TARGET_ARCH_S390X
// Ensure it is permissable to read/write int value directly from
......
......@@ -6265,10 +6265,21 @@ EVALUATE(CLFEBR) {
EVALUATE(CLFDBR) {
DCHECK_OPCODE(CLFDBR);
DECODE_RRE_INSTRUCTION(r1, r2);
double r2_val = get_double_from_d_register(r2);
uint32_t r1_val = static_cast<uint32_t>(r2_val);
double a = get_double_from_d_register(r2);
double n = std::round(a);
uint32_t r1_val = static_cast<uint32_t>(n);
set_low_register(r1, r1_val);
SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
if (std::isfinite(a) && a < 0.0) {
DCHECK(n <= 0.0 && std::isfinite(n));
condition_reg_ = (n < 0.0) ? 0x1 : 0x4;
} else if (a == 0.0) {
condition_reg_ = 0x8;
} else if (std::isfinite(a) && a > 0.0) {
DCHECK(n >= 0.0 && std::isfinite(n));
condition_reg_ = (n <= static_cast<double>(UINT32_MAX)) ? 0x2 : 0x1;
} else {
condition_reg_ = 0x1;
}
return length;
}
......
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