Commit e862ced3 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[codegen] Use separate fields for access mode and lane size

The same bit field (MiscField) is currently used to encode either a SIMD
lane size or a memory access mode depending on the instruction.

For now this does not conflict, but in order to support protected loads
and stores on arm64, we will need to add a protected access mode to some
SIMD instructions that already encode a lane size (kArm64LoadSplat,
kArm64LoadLane, kArm64StoreLane).

To prepare for this, use non-overlapping bits of the Misc field to
encode the two properties.

R=zhin@chromium.org
CC=ahaas@chromium.org

Bug: v8:11098
Change-Id: I2320b2be74d023429f8b8c78a5736b13f53c0399
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2643390
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarZhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72312}
parent fcf28e83
......@@ -378,8 +378,7 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr,
Arm64OperandConverter const& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
const MemoryAccessMode access_mode = AccessModeField::decode(opcode);
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
Register poison = value.Is64Bits() ? kSpeculationPoisonRegister
......@@ -390,8 +389,7 @@ void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
void EmitMaybePoisonedFPLoad(CodeGenerator* codegen, InstructionCode opcode,
Arm64OperandConverter* i, VRegister output_reg) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
const MemoryAccessMode access_mode = AccessModeField::decode(opcode);
AddressingMode address_mode = AddressingModeField::decode(opcode);
if (access_mode == kMemoryAccessPoisoned && address_mode != kMode_Root) {
UseScratchRegisterScope temps(codegen->tasm());
......@@ -1110,14 +1108,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Mul(i.OutputRegister32(), i.InputRegister32(0), i.InputRegister32(1));
break;
case kArm64Saddlp: {
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidthDoubleLanes(dst_f);
__ Saddlp(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f));
break;
}
case kArm64Uaddlp: {
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidthDoubleLanes(dst_f);
__ Uaddlp(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f));
......@@ -1129,7 +1127,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
i.InputRegister32(1));
} else {
DCHECK(instr->InputAt(0)->IsSimd128Register());
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidth(dst_f);
__ Smull(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f),
......@@ -1138,7 +1136,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kArm64Smull2: {
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidthDoubleLanes(dst_f);
__ Smull2(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f),
......@@ -1151,7 +1149,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
i.InputRegister32(1));
} else {
DCHECK(instr->InputAt(0)->IsSimd128Register());
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidth(dst_f);
__ Umull(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f),
......@@ -1160,7 +1158,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kArm64Umull2: {
VectorFormat dst_f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat dst_f = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat src_f = VectorFormatHalfWidthDoubleLanes(dst_f);
__ Umull2(i.OutputSimd128Register().Format(dst_f),
i.InputSimd128Register(0).Format(src_f),
......@@ -1447,7 +1445,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Cmn(i.InputOrZeroRegister32(0), i.InputOperand2_32(1));
break;
case kArm64Cnt: {
VectorFormat f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat f = VectorFormatFillQ(LaneSizeField::decode(opcode));
__ Cnt(i.OutputSimd128Register().Format(f),
i.InputSimd128Register(0).Format(f));
break;
......@@ -1930,28 +1928,28 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
case kArm64Sxtl: {
VectorFormat wide = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat wide = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat narrow = VectorFormatHalfWidth(wide);
__ Sxtl(i.OutputSimd128Register().Format(wide),
i.InputSimd128Register(0).Format(narrow));
break;
}
case kArm64Sxtl2: {
VectorFormat wide = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat wide = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat narrow = VectorFormatHalfWidthDoubleLanes(wide);
__ Sxtl2(i.OutputSimd128Register().Format(wide),
i.InputSimd128Register(0).Format(narrow));
break;
}
case kArm64Uxtl: {
VectorFormat wide = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat wide = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat narrow = VectorFormatHalfWidth(wide);
__ Uxtl(i.OutputSimd128Register().Format(wide),
i.InputSimd128Register(0).Format(narrow));
break;
}
case kArm64Uxtl2: {
VectorFormat wide = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat wide = VectorFormatFillQ(LaneSizeField::decode(opcode));
VectorFormat narrow = VectorFormatHalfWidthDoubleLanes(wide);
__ Uxtl2(i.OutputSimd128Register().Format(wide),
i.InputSimd128Register(0).Format(narrow));
......@@ -2497,7 +2495,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kArm64SignSelect: {
VectorFormat f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat f = VectorFormatFillQ(LaneSizeField::decode(opcode));
__ Cmlt(i.OutputSimd128Register().Format(f),
i.InputSimd128Register(2).Format(f), 0);
__ Bsl(i.OutputSimd128Register().V16B(), i.InputSimd128Register(0).V16B(),
......@@ -2632,19 +2630,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
SIMD_UNOP_CASE(kArm64S8x4Reverse, Rev32, 16B);
SIMD_UNOP_CASE(kArm64S8x2Reverse, Rev16, 16B);
case kArm64LoadSplat: {
VectorFormat f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat f = VectorFormatFillQ(LaneSizeField::decode(opcode));
__ ld1r(i.OutputSimd128Register().Format(f), i.MemoryOperand(0));
break;
}
case kArm64LoadLane: {
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
VectorFormat f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat f = VectorFormatFillQ(LaneSizeField::decode(opcode));
int laneidx = i.InputInt8(1);
__ ld1(i.OutputSimd128Register().Format(f), laneidx, i.MemoryOperand(2));
break;
}
case kArm64StoreLane: {
VectorFormat f = VectorFormatFillQ(MiscField::decode(opcode));
VectorFormat f = VectorFormatFillQ(LaneSizeField::decode(opcode));
int laneidx = i.InputInt8(1);
__ st1(i.InputSimd128Register(0).Format(f), laneidx, i.MemoryOperand(2));
break;
......
......@@ -672,7 +672,7 @@ void InstructionSelector::VisitLoadLane(Node* node) {
params.rep == MachineType::Int32() || params.rep == MachineType::Int64());
InstructionCode opcode = kArm64LoadLane;
opcode |= MiscField::encode(params.rep.MemSize() * kBitsPerByte);
opcode |= LaneSizeField::encode(params.rep.MemSize() * kBitsPerByte);
Arm64OperandGenerator g(this);
InstructionOperand addr = EmitAddBeforeLoadOrStore(this, node, &opcode);
......@@ -686,7 +686,8 @@ void InstructionSelector::VisitStoreLane(Node* node) {
DCHECK_GE(MachineRepresentation::kWord64, params.rep);
InstructionCode opcode = kArm64StoreLane;
opcode |= MiscField::encode(ElementSizeInBytes(params.rep) * kBitsPerByte);
opcode |=
LaneSizeField::encode(ElementSizeInBytes(params.rep) * kBitsPerByte);
Arm64OperandGenerator g(this);
InstructionOperand addr = EmitAddBeforeLoadOrStore(this, node, &opcode);
......@@ -707,22 +708,22 @@ void InstructionSelector::VisitLoadTransform(Node* node) {
switch (params.transformation) {
case LoadTransformation::kS128Load8Splat:
opcode = kArm64LoadSplat;
opcode |= MiscField::encode(8);
opcode |= LaneSizeField::encode(8);
require_add = true;
break;
case LoadTransformation::kS128Load16Splat:
opcode = kArm64LoadSplat;
opcode |= MiscField::encode(16);
opcode |= LaneSizeField::encode(16);
require_add = true;
break;
case LoadTransformation::kS128Load32Splat:
opcode = kArm64LoadSplat;
opcode |= MiscField::encode(32);
opcode |= LaneSizeField::encode(32);
require_add = true;
break;
case LoadTransformation::kS128Load64Splat:
opcode = kArm64LoadSplat;
opcode |= MiscField::encode(64);
opcode |= LaneSizeField::encode(64);
require_add = true;
break;
case LoadTransformation::kS128Load8x8S:
......@@ -844,7 +845,7 @@ void InstructionSelector::VisitLoad(Node* node) {
}
if (node->opcode() == IrOpcode::kPoisonedLoad) {
CHECK_NE(poisoning_level_, PoisoningMitigationLevel::kDontPoison);
opcode |= MiscField::encode(kMemoryAccessPoisoned);
opcode |= AccessModeField::encode(kMemoryAccessPoisoned);
}
EmitLoad(this, node, opcode, immediate_mode, rep);
......@@ -1735,7 +1736,7 @@ namespace {
void VisitExtMul(InstructionSelector* selector, ArchOpcode opcode, Node* node,
int dst_lane_size) {
InstructionCode code = opcode;
code |= MiscField::encode(dst_lane_size);
code |= LaneSizeField::encode(dst_lane_size);
VisitRRR(selector, code, node);
}
} // namespace
......@@ -1792,7 +1793,7 @@ namespace {
void VisitExtAddPairwise(InstructionSelector* selector, ArchOpcode opcode,
Node* node, int dst_lane_size) {
InstructionCode code = opcode;
code |= MiscField::encode(dst_lane_size);
code |= LaneSizeField::encode(dst_lane_size);
VisitRR(selector, code, node);
}
} // namespace
......@@ -3604,7 +3605,7 @@ SIMD_BINOP_LIST(SIMD_VISIT_BINOP)
#define VISIT_SIGN_SELECT(NAME, SIZE) \
void InstructionSelector::Visit##NAME(Node* node) { \
InstructionCode opcode = kArm64SignSelect; \
opcode |= MiscField::encode(SIZE); \
opcode |= LaneSizeField::encode(SIZE); \
VisitRRRR(this, opcode, node); \
}
......@@ -3887,7 +3888,7 @@ namespace {
void VisitSignExtendLong(InstructionSelector* selector, ArchOpcode opcode,
Node* node, int lane_size) {
InstructionCode code = opcode;
code |= MiscField::encode(lane_size);
code |= LaneSizeField::encode(lane_size);
VisitRR(selector, code, node);
}
} // namespace
......@@ -3942,7 +3943,7 @@ void InstructionSelector::VisitI16x8UConvertI8x16High(Node* node) {
void InstructionSelector::VisitI8x16Popcnt(Node* node) {
InstructionCode code = kArm64Cnt;
code |= MiscField::encode(8);
code |= LaneSizeField::encode(8);
VisitRR(this, code, node);
}
......
......@@ -280,6 +280,10 @@ using FlagsModeField = base::BitField<FlagsMode, 14, 3>;
using FlagsConditionField = base::BitField<FlagsCondition, 17, 5>;
using DeoptImmedArgsCountField = base::BitField<int, 22, 2>;
using DeoptFrameStateOffsetField = base::BitField<int, 24, 8>;
// LaneSizeField and AccessModeField are helper types to encode/decode a lane
// size, an access mode, or both inside the overlapping MiscField.
using LaneSizeField = base::BitField<int, 22, 8>;
using AccessModeField = base::BitField<MemoryAccessMode, 30, 2>;
using MiscField = base::BitField<int, 22, 10>;
} // namespace compiler
......
......@@ -365,8 +365,7 @@ class WasmProtectedInstructionTrap final : public WasmOutOfLineTrap {
void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr,
int pc) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
const MemoryAccessMode access_mode = AccessModeField::decode(opcode);
if (access_mode == kMemoryAccessProtected) {
zone->New<WasmProtectedInstructionTrap>(codegen, pc, instr);
}
......@@ -375,8 +374,7 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr,
X64OperandConverter const& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
const MemoryAccessMode access_mode = AccessModeField::decode(opcode);
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
codegen->tasm()->andq(value, kSpeculationPoisonRegister);
......@@ -2126,8 +2124,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kX64Movsd: {
EmitOOLTrapIfNeeded(zone(), this, opcode, instr, __ pc_offset());
if (instr->HasOutput()) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
const MemoryAccessMode access_mode = AccessModeField::decode(opcode);
if (access_mode == kMemoryAccessPoisoned) {
// If we have to poison the loaded value, we load into a general
// purpose register first, mask it with the poison, and move the
......
......@@ -383,7 +383,7 @@ void InstructionSelector::VisitLoadLane(Node* node) {
// x64 supports unaligned loads.
DCHECK_NE(params.kind, MemoryAccessKind::kUnaligned);
if (params.kind == MemoryAccessKind::kProtected) {
opcode |= MiscField::encode(kMemoryAccessProtected);
opcode |= AccessModeField::encode(kMemoryAccessProtected);
}
Emit(opcode, 1, outputs, input_count, inputs);
}
......@@ -435,7 +435,7 @@ void InstructionSelector::VisitLoadTransform(Node* node) {
DCHECK_NE(params.kind, MemoryAccessKind::kUnaligned);
InstructionCode code = opcode;
if (params.kind == MemoryAccessKind::kProtected) {
code |= MiscField::encode(kMemoryAccessProtected);
code |= AccessModeField::encode(kMemoryAccessProtected);
}
VisitLoad(node, node, code);
}
......@@ -450,10 +450,10 @@ void InstructionSelector::VisitLoad(Node* node, Node* value,
g.GetEffectiveAddressMemoryOperand(value, inputs, &input_count);
InstructionCode code = opcode | AddressingModeField::encode(mode);
if (node->opcode() == IrOpcode::kProtectedLoad) {
code |= MiscField::encode(kMemoryAccessProtected);
code |= AccessModeField::encode(kMemoryAccessProtected);
} else if (node->opcode() == IrOpcode::kPoisonedLoad) {
CHECK_NE(poisoning_level_, PoisoningMitigationLevel::kDontPoison);
code |= MiscField::encode(kMemoryAccessPoisoned);
code |= AccessModeField::encode(kMemoryAccessPoisoned);
}
Emit(code, 1, outputs, input_count, inputs);
}
......@@ -528,7 +528,7 @@ void InstructionSelector::VisitProtectedStore(Node* node) {
AddressingMode addressing_mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode) |
MiscField::encode(kMemoryAccessProtected);
AccessModeField::encode(kMemoryAccessProtected);
InstructionOperand value_operand =
g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
inputs[input_count++] = value_operand;
......@@ -565,7 +565,7 @@ void InstructionSelector::VisitStoreLane(Node* node) {
opcode |= AddressingModeField::encode(addressing_mode);
if (params.kind == MemoryAccessKind::kProtected) {
opcode |= MiscField::encode(kMemoryAccessProtected);
opcode |= AccessModeField::encode(kMemoryAccessProtected);
}
InstructionOperand value_operand = g.UseRegister(node->InputAt(2));
......
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