Commit 7a3dec45 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[x64 ia32] add SpeculationFence instruction, lowered to lfence

Bug: 
Change-Id: Icf0c43ef5bd3b3d3055d9606f22d3126b31016e3
Reviewed-on: https://chromium-review.googlesource.com/866930
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50595}
parent 96de054c
......@@ -1121,6 +1121,7 @@ void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
ArmOperandGenerator g(this);
......
......@@ -1258,6 +1258,8 @@ void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Popcnt(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
Arm64OperandGenerator g(this);
Int32BinopMatcher m(node);
......
......@@ -1019,6 +1019,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kIA32Popcnt:
__ Popcnt(i.OutputRegister(), i.InputOperand(0));
break;
case kLFence:
__ lfence();
break;
case kSSEFloat32Cmp:
__ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
break;
......
......@@ -43,6 +43,7 @@ namespace compiler {
V(IA32Lzcnt) \
V(IA32Tzcnt) \
V(IA32Popcnt) \
V(LFence) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \
......
......@@ -281,6 +281,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32PushFloat64:
case kIA32PushSimd128:
case kIA32Poke:
case kLFence:
return kHasSideEffect;
#define CASE(Name) case k##Name:
......
......@@ -225,6 +225,11 @@ void InstructionSelector::VisitDebugAbort(Node* node) {
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), edx));
}
void InstructionSelector::VisitSpeculationFence(Node* node) {
IA32OperandGenerator g(this);
Emit(kLFence, g.NoOutput());
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
......@@ -1970,7 +1975,8 @@ MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz;
MachineOperatorBuilder::kWord32Ctz |
MachineOperatorBuilder::kSpeculationFence;
if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt;
}
......
......@@ -1531,6 +1531,8 @@ void InstructionSelector::VisitNode(Node* node) {
ATOMIC_CASE(Or)
ATOMIC_CASE(Xor)
#undef ATOMIC_CASE
case IrOpcode::kSpeculationFence:
return VisitSpeculationFence(node);
case IrOpcode::kProtectedLoad: {
LoadRepresentation type = LoadRepresentationOf(node->op());
MarkAsRepresentation(type.representation(), node);
......
......@@ -625,6 +625,13 @@ struct MachineOperatorGlobalCache {
};
BitcastTaggedToWordOperator kBitcastTaggedToWord;
struct SpeculationFenceOperator : public Operator {
SpeculationFenceOperator()
: Operator(IrOpcode::kSpeculationFence, Operator::kNoThrow,
"SpeculationFence", 0, 1, 1, 0, 1, 0) {}
};
SpeculationFenceOperator kSpeculationFence;
struct DebugAbortOperator : public Operator {
DebugAbortOperator()
: Operator(IrOpcode::kDebugAbort, Operator::kNoThrow, "DebugAbort", 1,
......@@ -906,6 +913,11 @@ const Operator* MachineOperatorBuilder::AtomicXor(MachineType rep) {
UNREACHABLE();
}
const OptionalOperator MachineOperatorBuilder::SpeculationFence() {
return OptionalOperator(flags_ & kSpeculationFence,
&cache_.kSpeculationFence);
}
#define SIMD_LANE_OPS(Type, lane_count) \
const Operator* MachineOperatorBuilder::Type##ExtractLane( \
int32_t lane_index) { \
......
......@@ -143,13 +143,15 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
kWord64ReverseBytes = 1u << 19,
kInt32AbsWithOverflow = 1u << 20,
kInt64AbsWithOverflow = 1u << 21,
kSpeculationFence = 1u << 22,
kAllOptionalOps =
kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate |
kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven |
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
kWord32ReverseBits | kWord64ReverseBits | kWord32ReverseBytes |
kWord64ReverseBytes | kInt32AbsWithOverflow | kInt64AbsWithOverflow
kWord64ReverseBytes | kInt32AbsWithOverflow | kInt64AbsWithOverflow |
kSpeculationFence
};
typedef base::Flags<Flag, unsigned> Flags;
......@@ -614,6 +616,8 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
// atomic-xor [base + index], value
const Operator* AtomicXor(MachineType rep);
const OptionalOperator SpeculationFence();
// Target machine word-size assumed by this builder.
bool Is32() const { return word() == MachineRepresentation::kWord32; }
bool Is64() const { return word() == MachineRepresentation::kWord64; }
......
......@@ -1988,6 +1988,8 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
#define SIMD_TYPE_LIST(V) \
V(F32x4) \
V(I32x4) \
......
......@@ -2640,6 +2640,8 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
#define SIMD_TYPE_LIST(V) \
V(F32x4) \
V(I32x4) \
......
......@@ -616,6 +616,7 @@
V(AtomicAnd) \
V(AtomicOr) \
V(AtomicXor) \
V(SpeculationFence) \
V(UnsafePointerAdd)
#define MACHINE_SIMD_OP_LIST(V) \
......
......@@ -939,6 +939,8 @@ void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32Add(Node* node) {
VisitBinop<Int32BinopMatcher>(this, node, kPPC_Add32, kInt16Imm);
}
......
......@@ -186,6 +186,10 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
old_value, new_value);
}
Node* SpeculationFence() {
return AddNode(machine()->SpeculationFence().op());
}
// Arithmetic Operations.
Node* WordAnd(Node* a, Node* b) {
return AddNode(machine()->WordAnd(), a, b);
......
......@@ -1158,6 +1158,8 @@ void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64ReverseBits(Node* node) { UNREACHABLE(); }
#endif
void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32AbsWithOverflow(Node* node) {
VisitWord32UnaryOp(this, node, kS390_Abs32, OperandMode::kNone);
}
......
......@@ -1627,6 +1627,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kAtomicAnd:
case IrOpcode::kAtomicOr:
case IrOpcode::kAtomicXor:
case IrOpcode::kSpeculationFence:
#define SIMD_MACHINE_OP_CASE(Name) case IrOpcode::k##Name:
MACHINE_SIMD_OP_LIST(SIMD_MACHINE_OP_CASE)
......
......@@ -846,6 +846,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ bind(ool->exit());
break;
}
case kLFence:
__ lfence();
break;
case kArchStackSlot: {
FrameOffset offset =
frame_access_state()->GetFrameOffset(i.InputInt32(0));
......
......@@ -56,6 +56,7 @@ namespace compiler {
V(X64Tzcnt32) \
V(X64Popcnt) \
V(X64Popcnt32) \
V(LFence) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \
V(SSEFloat32Sub) \
......
......@@ -261,6 +261,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Poke:
return kHasSideEffect;
case kLFence:
return kHasSideEffect;
#define CASE(Name) case k##Name:
COMMON_ARCH_OPCODE_LIST(CASE)
#undef CASE
......
......@@ -289,6 +289,11 @@ void InstructionSelector::VisitDebugAbort(Node* node) {
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), rdx));
}
void InstructionSelector::VisitSpeculationFence(Node* node) {
X64OperandGenerator g(this);
Emit(kLFence, g.NoOutput());
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
X64OperandGenerator g(this);
......@@ -2530,7 +2535,8 @@ MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz;
MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz |
MachineOperatorBuilder::kSpeculationFence;
if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt |
MachineOperatorBuilder::kWord64Popcnt;
......
......@@ -796,6 +796,13 @@ void Assembler::cmpxchg_w(const Operand& dst, Register src) {
emit_operand(src, dst);
}
void Assembler::lfence() {
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0xAE);
EMIT(0xE8);
}
void Assembler::adc(Register dst, int32_t imm32) {
EnsureSpace ensure_space(this);
emit_arith(2, Operand(dst), Immediate(imm32));
......
......@@ -684,6 +684,9 @@ class Assembler : public AssemblerBase {
void cmpxchg_b(const Operand& dst, Register src);
void cmpxchg_w(const Operand& dst, Register src);
// Memory Fence
void lfence();
// Arithmetics
void adc(Register dst, int32_t imm32);
void adc(Register dst, const Operand& src);
......
......@@ -1756,6 +1756,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
get_modrm(*data, &mod, &regop, &rm);
AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
data += PrintRightOperand(data);
} else if (f0byte == 0xAE && (data[2] & 0xF8) == 0xE8) {
AppendToBuffer("lfence");
data += 3;
} else {
UnimplementedInstruction();
}
......
......@@ -1140,6 +1140,13 @@ void Assembler::emit_cmpxchg(const Operand& dst, Register src, int size) {
emit_operand(src, dst);
}
void Assembler::lfence() {
EnsureSpace ensure_space(this);
emit(0x0F);
emit(0xAE);
emit(0xE8);
}
void Assembler::cpuid() {
EnsureSpace ensure_space(this);
emit(0x0F);
......
......@@ -1909,6 +1909,8 @@ class Assembler : public AssemblerBase {
void rorxl(Register dst, Register src, byte imm8);
void rorxl(Register dst, const Operand& src, byte imm8);
void lfence();
// Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos();
......
......@@ -2208,6 +2208,9 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
byte_size_operand_ = true;
}
current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
} else if (opcode == 0xAE && (*(data + 2) & 0xF8) == 0xE8) {
AppendToBuffer("lfence");
current = data + 3;
} else {
UnimplementedInstruction();
}
......
......@@ -864,6 +864,15 @@ TEST_F(InstructionSelectorTest, Word32Clz) {
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
TEST_F(InstructionSelectorTest, SpeculationFence) {
StreamBuilder m(this, MachineType::Int32());
m.SpeculationFence();
m.Return(m.Int32Constant(0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kLFence, s[0]->arch_opcode());
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -1641,6 +1641,15 @@ TEST_F(InstructionSelectorTest, LoadAndWord64ShiftRight32) {
}
}
TEST_F(InstructionSelectorTest, SpeculationFence) {
StreamBuilder m(this, MachineType::Int32());
m.SpeculationFence();
m.Return(m.Int32Constant(0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kLFence, s[0]->arch_opcode());
}
} // namespace compiler
} // namespace internal
} // namespace v8
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