diff options
Diffstat (limited to 'deps/v8/src/compiler/arm/instruction-selector-arm.cc')
-rw-r--r-- | deps/v8/src/compiler/arm/instruction-selector-arm.cc | 515 |
1 files changed, 375 insertions, 140 deletions
diff --git a/deps/v8/src/compiler/arm/instruction-selector-arm.cc b/deps/v8/src/compiler/arm/instruction-selector-arm.cc index 0cffff7a1c..d69a82c608 100644 --- a/deps/v8/src/compiler/arm/instruction-selector-arm.cc +++ b/deps/v8/src/compiler/arm/instruction-selector-arm.cc @@ -426,8 +426,10 @@ void InstructionSelector::VisitLoad(Node* node) { case MachineRepresentation::kWord32: opcode = kArmLdr; break; + case MachineRepresentation::kSimd128: + opcode = kArmVld1S128; + break; case MachineRepresentation::kWord64: // Fall through. - case MachineRepresentation::kSimd128: // Fall through. case MachineRepresentation::kSimd1x4: // Fall through. case MachineRepresentation::kSimd1x8: // Fall through. case MachineRepresentation::kSimd1x16: // Fall through. @@ -514,8 +516,10 @@ void InstructionSelector::VisitStore(Node* node) { case MachineRepresentation::kWord32: opcode = kArmStr; break; + case MachineRepresentation::kSimd128: + opcode = kArmVst1S128; + break; case MachineRepresentation::kWord64: // Fall through. - case MachineRepresentation::kSimd128: // Fall through. case MachineRepresentation::kSimd1x4: // Fall through. case MachineRepresentation::kSimd1x8: // Fall through. case MachineRepresentation::kSimd1x16: // Fall through. @@ -538,8 +542,8 @@ void InstructionSelector::VisitProtectedStore(Node* node) { } void InstructionSelector::VisitUnalignedLoad(Node* node) { - UnalignedLoadRepresentation load_rep = - UnalignedLoadRepresentationOf(node->op()); + MachineRepresentation load_rep = + UnalignedLoadRepresentationOf(node->op()).representation(); ArmOperandGenerator g(this); Node* base = node->InputAt(0); Node* index = node->InputAt(1); @@ -547,17 +551,18 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) { InstructionCode opcode = kArmLdr; // Only floating point loads need to be specially handled; integer loads // support unaligned access. We support unaligned FP loads by loading to - // integer registers first, then moving to the destination FP register. - switch (load_rep.representation()) { + // integer registers first, then moving to the destination FP register. If + // NEON is supported, we use the vld1.8 instruction. + switch (load_rep) { case MachineRepresentation::kFloat32: { InstructionOperand temp = g.TempRegister(); EmitLoad(this, opcode, &temp, base, index); Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); return; } - case MachineRepresentation::kFloat64: { - // TODO(arm): use vld1.8 for this when NEON is available. - // Compute the address of the least-significant half of the FP value. + case MachineRepresentation::kFloat64: + case MachineRepresentation::kSimd128: { + // Compute the address of the least-significant byte of the FP value. // We assume that the base node is unlikely to be an encodable immediate // or the result of a shift operation, so only consider the addressing // mode that should be used for the index node. @@ -568,8 +573,8 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) { size_t input_count; if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, &inputs[1])) { - // input_count has been set by TryMatchImmediateOrShift(), so increment - // it to account for the base register in inputs[0]. + // input_count has been set by TryMatchImmediateOrShift(), so + // increment it to account for the base register in inputs[0]. input_count++; } else { add_opcode |= AddressingModeField::encode(kMode_Operand2_R); @@ -580,13 +585,22 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) { InstructionOperand addr = g.TempRegister(); Emit(add_opcode, 1, &addr, input_count, inputs); - // Load both halves and move to an FP register. - InstructionOperand fp_lo = g.TempRegister(); - InstructionOperand fp_hi = g.TempRegister(); - opcode |= AddressingModeField::encode(kMode_Offset_RI); - Emit(opcode, fp_lo, addr, g.TempImmediate(0)); - Emit(opcode, fp_hi, addr, g.TempImmediate(4)); - Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); + if (CpuFeatures::IsSupported(NEON)) { + // With NEON we can load directly from the calculated address. + ArchOpcode op = load_rep == MachineRepresentation::kFloat64 + ? kArmVld1F64 + : kArmVld1S128; + Emit(op, g.DefineAsRegister(node), addr); + } else { + DCHECK_NE(MachineRepresentation::kSimd128, load_rep); + // Load both halves and move to an FP register. + InstructionOperand fp_lo = g.TempRegister(); + InstructionOperand fp_hi = g.TempRegister(); + opcode |= AddressingModeField::encode(kMode_Offset_RI); + Emit(opcode, fp_lo, addr, g.TempImmediate(0)); + Emit(opcode, fp_hi, addr, g.TempImmediate(4)); + Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); + } return; } default: @@ -611,6 +625,7 @@ void InstructionSelector::VisitUnalignedStore(Node* node) { // Only floating point stores need to be specially handled; integer stores // support unaligned access. We support unaligned FP stores by moving the // value to integer registers first, then storing to the destination address. + // If NEON is supported, we use the vst1.8 instruction. switch (store_rep) { case MachineRepresentation::kFloat32: { inputs[input_count++] = g.TempRegister(); @@ -619,31 +634,63 @@ void InstructionSelector::VisitUnalignedStore(Node* node) { EmitStore(this, kArmStr, input_count, inputs, index); return; } - case MachineRepresentation::kFloat64: { - // TODO(arm): use vst1.8 for this when NEON is available. - // Store a 64-bit floating point value using two 32-bit integer stores. - // Computing the store address here would require three live temporary - // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after - // storing the least-significant half of the value. - - // First, move the 64-bit FP value into two temporary integer registers. - InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; - inputs[input_count++] = g.UseRegister(value); - Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, - inputs); - - // Store the least-significant half. - inputs[0] = fp[0]; // Low 32-bits of FP value. - inputs[input_count++] = g.UseRegister(base); // First store base address. - EmitStore(this, kArmStr, input_count, inputs, index); + case MachineRepresentation::kFloat64: + case MachineRepresentation::kSimd128: { + if (CpuFeatures::IsSupported(NEON)) { + InstructionOperand address = g.TempRegister(); + { + // First we have to calculate the actual address. + InstructionCode add_opcode = kArmAdd; + InstructionOperand inputs[3]; + inputs[0] = g.UseRegister(base); + + size_t input_count; + if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, + &inputs[1])) { + // input_count has been set by TryMatchImmediateOrShift(), so + // increment it to account for the base register in inputs[0]. + input_count++; + } else { + add_opcode |= AddressingModeField::encode(kMode_Operand2_R); + inputs[1] = g.UseRegister(index); + input_count = 2; // Base register and index. + } - // Store the most-significant half. - InstructionOperand base4 = g.TempRegister(); - Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4, - g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4. - inputs[0] = fp[1]; // High 32-bits of FP value. - inputs[1] = base4; // Second store base + 4 address. - EmitStore(this, kArmStr, input_count, inputs, index); + Emit(add_opcode, 1, &address, input_count, inputs); + } + + inputs[input_count++] = g.UseRegister(value); + inputs[input_count++] = address; + ArchOpcode op = store_rep == MachineRepresentation::kFloat64 + ? kArmVst1F64 + : kArmVst1S128; + Emit(op, 0, nullptr, input_count, inputs); + } else { + DCHECK_NE(MachineRepresentation::kSimd128, store_rep); + // Store a 64-bit floating point value using two 32-bit integer stores. + // Computing the store address here would require three live temporary + // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after + // storing the least-significant half of the value. + + // First, move the 64-bit FP value into two temporary integer registers. + InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; + inputs[input_count++] = g.UseRegister(value); + Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, inputs); + + // Store the least-significant half. + inputs[0] = fp[0]; // Low 32-bits of FP value. + inputs[input_count++] = + g.UseRegister(base); // First store base address. + EmitStore(this, kArmStr, input_count, inputs, index); + + // Store the most-significant half. + InstructionOperand base4 = g.TempRegister(); + Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4, + g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4. + inputs[0] = fp[1]; // High 32-bits of FP value. + inputs[1] = base4; // Second store base + 4 address. + EmitStore(this, kArmStr, input_count, inputs, index); + } return; } default: @@ -2181,99 +2228,271 @@ void InstructionSelector::VisitAtomicStore(Node* node) { Emit(code, 0, nullptr, input_count, inputs); } +void InstructionSelector::VisitAtomicExchange(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + ArchOpcode opcode = kArchNop; + MachineType type = AtomicOpRepresentationOf(node->op()); + if (type == MachineType::Int8()) { + opcode = kAtomicExchangeInt8; + } else if (type == MachineType::Uint8()) { + opcode = kAtomicExchangeUint8; + } else if (type == MachineType::Int16()) { + opcode = kAtomicExchangeInt16; + } else if (type == MachineType::Uint16()) { + opcode = kAtomicExchangeUint16; + } else if (type == MachineType::Int32() || type == MachineType::Uint32()) { + opcode = kAtomicExchangeWord32; + } else { + UNREACHABLE(); + return; + } + + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[3]; + size_t input_count = 0; + inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseUniqueRegister(index); + inputs[input_count++] = g.UseUniqueRegister(value); + InstructionOperand outputs[1]; + outputs[0] = g.UseUniqueRegister(node); + InstructionOperand temp[1]; + temp[0] = g.TempRegister(); + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + Emit(code, 1, outputs, input_count, inputs, 1, temp); +} + +void InstructionSelector::VisitAtomicCompareExchange(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* old_value = node->InputAt(2); + Node* new_value = node->InputAt(3); + ArchOpcode opcode = kArchNop; + MachineType type = AtomicOpRepresentationOf(node->op()); + if (type == MachineType::Int8()) { + opcode = kAtomicCompareExchangeInt8; + } else if (type == MachineType::Uint8()) { + opcode = kAtomicCompareExchangeUint8; + } else if (type == MachineType::Int16()) { + opcode = kAtomicCompareExchangeInt16; + } else if (type == MachineType::Uint16()) { + opcode = kAtomicCompareExchangeUint16; + } else if (type == MachineType::Int32() || type == MachineType::Uint32()) { + opcode = kAtomicCompareExchangeWord32; + } else { + UNREACHABLE(); + return; + } + + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[4]; + size_t input_count = 0; + inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseUniqueRegister(index); + inputs[input_count++] = g.UseUniqueRegister(old_value); + inputs[input_count++] = g.UseUniqueRegister(new_value); + InstructionOperand outputs[1]; + outputs[0] = g.UseUniqueRegister(node); + InstructionOperand temp[2]; + temp[0] = g.TempRegister(); + temp[1] = g.TempRegister(); + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + Emit(code, 1, outputs, input_count, inputs, 2, temp); +} + +void InstructionSelector::VisitAtomicBinaryOperation( + Node* node, ArchOpcode int8_op, ArchOpcode uint8_op, ArchOpcode int16_op, + ArchOpcode uint16_op, ArchOpcode word32_op) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + ArchOpcode opcode = kArchNop; + MachineType type = AtomicOpRepresentationOf(node->op()); + if (type == MachineType::Int8()) { + opcode = int8_op; + } else if (type == MachineType::Uint8()) { + opcode = uint8_op; + } else if (type == MachineType::Int16()) { + opcode = int16_op; + } else if (type == MachineType::Uint16()) { + opcode = uint16_op; + } else if (type == MachineType::Int32() || type == MachineType::Uint32()) { + opcode = word32_op; + } else { + UNREACHABLE(); + return; + } + + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[3]; + size_t input_count = 0; + inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseUniqueRegister(index); + inputs[input_count++] = g.UseUniqueRegister(value); + InstructionOperand outputs[1]; + outputs[0] = g.UseUniqueRegister(node); + InstructionOperand temps[2]; + temps[0] = g.TempRegister(); + temps[1] = g.TempRegister(); + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + Emit(code, 1, outputs, input_count, inputs, 2, temps); +} + +#define VISIT_ATOMIC_BINOP(op) \ + void InstructionSelector::VisitAtomic##op(Node* node) { \ + VisitAtomicBinaryOperation(node, kAtomic##op##Int8, kAtomic##op##Uint8, \ + kAtomic##op##Int16, kAtomic##op##Uint16, \ + kAtomic##op##Word32); \ + } +VISIT_ATOMIC_BINOP(Add) +VISIT_ATOMIC_BINOP(Sub) +VISIT_ATOMIC_BINOP(And) +VISIT_ATOMIC_BINOP(Or) +VISIT_ATOMIC_BINOP(Xor) +#undef VISIT_ATOMIC_BINOP + #define SIMD_TYPE_LIST(V) \ - V(Float32x4) \ - V(Int32x4) \ - V(Int16x8) \ - V(Int8x16) + V(F32x4) \ + V(I32x4) \ + V(I16x8) \ + V(I8x16) #define SIMD_FORMAT_LIST(V) \ V(32x4) \ V(16x8) \ V(8x16) -#define SIMD_UNOP_LIST(V) \ - V(Float32x4FromInt32x4) \ - V(Float32x4FromUint32x4) \ - V(Float32x4Abs) \ - V(Float32x4Neg) \ - V(Int32x4FromFloat32x4) \ - V(Uint32x4FromFloat32x4) \ - V(Int32x4Neg) \ - V(Int16x8Neg) \ - V(Int8x16Neg) \ - V(Simd128Not) - -#define SIMD_BINOP_LIST(V) \ - V(Float32x4Add) \ - V(Float32x4Sub) \ - V(Float32x4Equal) \ - V(Float32x4NotEqual) \ - V(Int32x4Add) \ - V(Int32x4Sub) \ - V(Int32x4Mul) \ - V(Int32x4Min) \ - V(Int32x4Max) \ - V(Int32x4Equal) \ - V(Int32x4NotEqual) \ - V(Int32x4GreaterThan) \ - V(Int32x4GreaterThanOrEqual) \ - V(Uint32x4Min) \ - V(Uint32x4Max) \ - V(Uint32x4GreaterThan) \ - V(Uint32x4GreaterThanOrEqual) \ - V(Int16x8Add) \ - V(Int16x8AddSaturate) \ - V(Int16x8Sub) \ - V(Int16x8SubSaturate) \ - V(Int16x8Mul) \ - V(Int16x8Min) \ - V(Int16x8Max) \ - V(Int16x8Equal) \ - V(Int16x8NotEqual) \ - V(Int16x8GreaterThan) \ - V(Int16x8GreaterThanOrEqual) \ - V(Uint16x8AddSaturate) \ - V(Uint16x8SubSaturate) \ - V(Uint16x8Min) \ - V(Uint16x8Max) \ - V(Uint16x8GreaterThan) \ - V(Uint16x8GreaterThanOrEqual) \ - V(Int8x16Add) \ - V(Int8x16AddSaturate) \ - V(Int8x16Sub) \ - V(Int8x16SubSaturate) \ - V(Int8x16Mul) \ - V(Int8x16Min) \ - V(Int8x16Max) \ - V(Int8x16Equal) \ - V(Int8x16NotEqual) \ - V(Int8x16GreaterThan) \ - V(Int8x16GreaterThanOrEqual) \ - V(Uint8x16AddSaturate) \ - V(Uint8x16SubSaturate) \ - V(Uint8x16Min) \ - V(Uint8x16Max) \ - V(Uint8x16GreaterThan) \ - V(Uint8x16GreaterThanOrEqual) \ - V(Simd128And) \ - V(Simd128Or) \ - V(Simd128Xor) - -#define SIMD_SHIFT_OP_LIST(V) \ - V(Int32x4ShiftLeftByScalar) \ - V(Int32x4ShiftRightByScalar) \ - V(Uint32x4ShiftRightByScalar) \ - V(Int16x8ShiftLeftByScalar) \ - V(Int16x8ShiftRightByScalar) \ - V(Uint16x8ShiftRightByScalar) \ - V(Int8x16ShiftLeftByScalar) \ - V(Int8x16ShiftRightByScalar) \ - V(Uint8x16ShiftRightByScalar) - -#define SIMD_VISIT_SPLAT(Type) \ - void InstructionSelector::VisitCreate##Type(Node* node) { \ - VisitRR(this, kArm##Type##Splat, node); \ +#define SIMD_ZERO_OP_LIST(V) \ + V(S128Zero) \ + V(S1x4Zero) \ + V(S1x8Zero) \ + V(S1x16Zero) + +#define SIMD_UNOP_LIST(V) \ + V(F32x4SConvertI32x4, kArmF32x4SConvertI32x4) \ + V(F32x4UConvertI32x4, kArmF32x4UConvertI32x4) \ + V(F32x4Abs, kArmF32x4Abs) \ + V(F32x4Neg, kArmF32x4Neg) \ + V(F32x4RecipApprox, kArmF32x4RecipApprox) \ + V(F32x4RecipSqrtApprox, kArmF32x4RecipSqrtApprox) \ + V(I32x4SConvertF32x4, kArmI32x4SConvertF32x4) \ + V(I32x4SConvertI16x8Low, kArmI32x4SConvertI16x8Low) \ + V(I32x4SConvertI16x8High, kArmI32x4SConvertI16x8High) \ + V(I32x4Neg, kArmI32x4Neg) \ + V(I32x4UConvertF32x4, kArmI32x4UConvertF32x4) \ + V(I32x4UConvertI16x8Low, kArmI32x4UConvertI16x8Low) \ + V(I32x4UConvertI16x8High, kArmI32x4UConvertI16x8High) \ + V(I16x8SConvertI8x16Low, kArmI16x8SConvertI8x16Low) \ + V(I16x8SConvertI8x16High, kArmI16x8SConvertI8x16High) \ + V(I16x8Neg, kArmI16x8Neg) \ + V(I16x8UConvertI8x16Low, kArmI16x8UConvertI8x16Low) \ + V(I16x8UConvertI8x16High, kArmI16x8UConvertI8x16High) \ + V(I8x16Neg, kArmI8x16Neg) \ + V(S128Not, kArmS128Not) \ + V(S1x4Not, kArmS128Not) \ + V(S1x4AnyTrue, kArmS1x4AnyTrue) \ + V(S1x4AllTrue, kArmS1x4AllTrue) \ + V(S1x8Not, kArmS128Not) \ + V(S1x8AnyTrue, kArmS1x8AnyTrue) \ + V(S1x8AllTrue, kArmS1x8AllTrue) \ + V(S1x16Not, kArmS128Not) \ + V(S1x16AnyTrue, kArmS1x16AnyTrue) \ + V(S1x16AllTrue, kArmS1x16AllTrue) + +#define SIMD_SHIFT_OP_LIST(V) \ + V(I32x4Shl) \ + V(I32x4ShrS) \ + V(I32x4ShrU) \ + V(I16x8Shl) \ + V(I16x8ShrS) \ + V(I16x8ShrU) \ + V(I8x16Shl) \ + V(I8x16ShrS) \ + V(I8x16ShrU) + +#define SIMD_BINOP_LIST(V) \ + V(F32x4Add, kArmF32x4Add) \ + V(F32x4Sub, kArmF32x4Sub) \ + V(F32x4Mul, kArmF32x4Mul) \ + V(F32x4Min, kArmF32x4Min) \ + V(F32x4Max, kArmF32x4Max) \ + V(F32x4RecipRefine, kArmF32x4RecipRefine) \ + V(F32x4RecipSqrtRefine, kArmF32x4RecipSqrtRefine) \ + V(F32x4Eq, kArmF32x4Eq) \ + V(F32x4Ne, kArmF32x4Ne) \ + V(F32x4Lt, kArmF32x4Lt) \ + V(F32x4Le, kArmF32x4Le) \ + V(I32x4Add, kArmI32x4Add) \ + V(I32x4Sub, kArmI32x4Sub) \ + V(I32x4Mul, kArmI32x4Mul) \ + V(I32x4MinS, kArmI32x4MinS) \ + V(I32x4MaxS, kArmI32x4MaxS) \ + V(I32x4Eq, kArmI32x4Eq) \ + V(I32x4Ne, kArmI32x4Ne) \ + V(I32x4LtS, kArmI32x4LtS) \ + V(I32x4LeS, kArmI32x4LeS) \ + V(I32x4MinU, kArmI32x4MinU) \ + V(I32x4MaxU, kArmI32x4MaxU) \ + V(I32x4LtU, kArmI32x4LtU) \ + V(I32x4LeU, kArmI32x4LeU) \ + V(I16x8SConvertI32x4, kArmI16x8SConvertI32x4) \ + V(I16x8Add, kArmI16x8Add) \ + V(I16x8AddSaturateS, kArmI16x8AddSaturateS) \ + V(I16x8Sub, kArmI16x8Sub) \ + V(I16x8SubSaturateS, kArmI16x8SubSaturateS) \ + V(I16x8Mul, kArmI16x8Mul) \ + V(I16x8MinS, kArmI16x8MinS) \ + V(I16x8MaxS, kArmI16x8MaxS) \ + V(I16x8Eq, kArmI16x8Eq) \ + V(I16x8Ne, kArmI16x8Ne) \ + V(I16x8LtS, kArmI16x8LtS) \ + V(I16x8LeS, kArmI16x8LeS) \ + V(I16x8UConvertI32x4, kArmI16x8UConvertI32x4) \ + V(I16x8AddSaturateU, kArmI16x8AddSaturateU) \ + V(I16x8SubSaturateU, kArmI16x8SubSaturateU) \ + V(I16x8MinU, kArmI16x8MinU) \ + V(I16x8MaxU, kArmI16x8MaxU) \ + V(I16x8LtU, kArmI16x8LtU) \ + V(I16x8LeU, kArmI16x8LeU) \ + V(I8x16SConvertI16x8, kArmI8x16SConvertI16x8) \ + V(I8x16Add, kArmI8x16Add) \ + V(I8x16AddSaturateS, kArmI8x16AddSaturateS) \ + V(I8x16Sub, kArmI8x16Sub) \ + V(I8x16SubSaturateS, kArmI8x16SubSaturateS) \ + V(I8x16Mul, kArmI8x16Mul) \ + V(I8x16MinS, kArmI8x16MinS) \ + V(I8x16MaxS, kArmI8x16MaxS) \ + V(I8x16Eq, kArmI8x16Eq) \ + V(I8x16Ne, kArmI8x16Ne) \ + V(I8x16LtS, kArmI8x16LtS) \ + V(I8x16LeS, kArmI8x16LeS) \ + V(I8x16UConvertI16x8, kArmI8x16UConvertI16x8) \ + V(I8x16AddSaturateU, kArmI8x16AddSaturateU) \ + V(I8x16SubSaturateU, kArmI8x16SubSaturateU) \ + V(I8x16MinU, kArmI8x16MinU) \ + V(I8x16MaxU, kArmI8x16MaxU) \ + V(I8x16LtU, kArmI8x16LtU) \ + V(I8x16LeU, kArmI8x16LeU) \ + V(S128And, kArmS128And) \ + V(S128Or, kArmS128Or) \ + V(S128Xor, kArmS128Xor) \ + V(S1x4And, kArmS128And) \ + V(S1x4Or, kArmS128Or) \ + V(S1x4Xor, kArmS128Xor) \ + V(S1x8And, kArmS128And) \ + V(S1x8Or, kArmS128Or) \ + V(S1x8Xor, kArmS128Xor) \ + V(S1x16And, kArmS128And) \ + V(S1x16Or, kArmS128Or) \ + V(S1x16Xor, kArmS128Xor) + +#define SIMD_VISIT_SPLAT(Type) \ + void InstructionSelector::Visit##Type##Splat(Node* node) { \ + VisitRR(this, kArm##Type##Splat, node); \ } SIMD_TYPE_LIST(SIMD_VISIT_SPLAT) #undef SIMD_VISIT_SPLAT @@ -2292,19 +2511,20 @@ SIMD_TYPE_LIST(SIMD_VISIT_EXTRACT_LANE) SIMD_TYPE_LIST(SIMD_VISIT_REPLACE_LANE) #undef SIMD_VISIT_REPLACE_LANE -#define SIMD_VISIT_UNOP(Name) \ - void InstructionSelector::Visit##Name(Node* node) { \ - VisitRR(this, kArm##Name, node); \ +#define SIMD_VISIT_ZERO_OP(Name) \ + void InstructionSelector::Visit##Name(Node* node) { \ + ArmOperandGenerator g(this); \ + Emit(kArmS128Zero, g.DefineAsRegister(node), g.DefineAsRegister(node)); \ } -SIMD_UNOP_LIST(SIMD_VISIT_UNOP) -#undef SIMD_VISIT_UNOP +SIMD_ZERO_OP_LIST(SIMD_VISIT_ZERO_OP) +#undef SIMD_VISIT_ZERO_OP -#define SIMD_VISIT_BINOP(Name) \ +#define SIMD_VISIT_UNOP(Name, instruction) \ void InstructionSelector::Visit##Name(Node* node) { \ - VisitRRR(this, kArm##Name, node); \ + VisitRR(this, instruction, node); \ } -SIMD_BINOP_LIST(SIMD_VISIT_BINOP) -#undef SIMD_VISIT_BINOP +SIMD_UNOP_LIST(SIMD_VISIT_UNOP) +#undef SIMD_VISIT_UNOP #define SIMD_VISIT_SHIFT_OP(Name) \ void InstructionSelector::Visit##Name(Node* node) { \ @@ -2313,13 +2533,28 @@ SIMD_BINOP_LIST(SIMD_VISIT_BINOP) SIMD_SHIFT_OP_LIST(SIMD_VISIT_SHIFT_OP) #undef SIMD_VISIT_SHIFT_OP -#define SIMD_VISIT_SELECT_OP(format) \ - void InstructionSelector::VisitSimd##format##Select(Node* node) { \ - VisitRRRR(this, kArmSimd##format##Select, node); \ +#define SIMD_VISIT_BINOP(Name, instruction) \ + void InstructionSelector::Visit##Name(Node* node) { \ + VisitRRR(this, instruction, node); \ + } +SIMD_BINOP_LIST(SIMD_VISIT_BINOP) +#undef SIMD_VISIT_BINOP + +#define SIMD_VISIT_SELECT_OP(format) \ + void InstructionSelector::VisitS##format##Select(Node* node) { \ + VisitRRRR(this, kArmS128Select, node); \ } SIMD_FORMAT_LIST(SIMD_VISIT_SELECT_OP) #undef SIMD_VISIT_SELECT_OP +void InstructionSelector::VisitInt32AbsWithOverflow(Node* node) { + UNREACHABLE(); +} + +void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) { + UNREACHABLE(); +} + // static MachineOperatorBuilder::Flags InstructionSelector::SupportedMachineOperatorFlags() { |