PPC/s390: [turbofan] Masking/poisoning in codegen (optimized code, arm)

Port 2579951648

Original Commit Message:

    This introduces masking of loads with speculation bit during code generation.
    At the moment, this is done only under the
    --branch-load-poisoning flag, and this CL enlarges the set of supported
    platforms from {x64} to {x64, arm}.

    Overview of changes:
    - new register configuration configuration with one register reserved for
      the speculation poison/mask (kSpeculationPoisonRegister).
    - in codegen, we introduce an update to the poison register at the starts
      of all successors of branches (and deopts) that are marked as safety
      branches (deopts).
    - in memory optimizer, we lower all field and element loads to PoisonedLoads.
    - poisoned loads are then masked in codegen with the poison register.
      * only integer loads are masked at the moment.

R=tebbi@chromium.org, joransiu@ca.ibm.com, bjaideep@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N

Change-Id: Idda9bf06133d8999290cda5bcf6333c064b3e6dc
Reviewed-on: https://chromium-review.googlesource.com/927163
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Reviewed-by: Joran Siu <joransiu@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#51528}
This commit is contained in:
Junliang Yan 2018-02-22 17:05:28 -05:00 committed by Commit Bot
parent a988f2ecde
commit 11805b137d
8 changed files with 76 additions and 6 deletions

View File

@ -272,6 +272,16 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
UNREACHABLE();
}
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen, Instruction* instr,
PPCOperandConverter& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(instr->opcode()));
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
codegen->tasm()->and_(value, value, kSpeculationPoisonRegister);
}
}
} // namespace
#define ASSEMBLE_FLOAT_UNOP_RC(asm_instr, round) \
@ -1840,26 +1850,33 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif
case kPPC_LoadWordU8:
ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kPPC_LoadWordS8:
ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
__ extsb(i.OutputRegister(), i.OutputRegister());
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kPPC_LoadWordU16:
ASSEMBLE_LOAD_INTEGER(lhz, lhzx);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kPPC_LoadWordS16:
ASSEMBLE_LOAD_INTEGER(lha, lhax);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kPPC_LoadWordU32:
ASSEMBLE_LOAD_INTEGER(lwz, lwzx);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kPPC_LoadWordS32:
ASSEMBLE_LOAD_INTEGER(lwa, lwax);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
#if V8_TARGET_ARCH_PPC64
case kPPC_LoadWord64:
ASSEMBLE_LOAD_INTEGER(ld, ldx);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
#endif
case kPPC_LoadFloat32:
@ -1965,7 +1982,16 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
Instruction* instr) {
UNREACHABLE();
// TODO(John) Handle float comparisons (kUnordered[Not]Equal).
if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
return;
}
ArchOpcode op = instr->arch_opcode();
condition = NegateFlagsCondition(condition);
__ li(kScratchReg, Operand::Zero());
__ isel(FlagsConditionToCondition(condition, op), kSpeculationPoisonRegister,
kScratchReg, kSpeculationPoisonRegister, cr0);
}
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
@ -2212,6 +2238,7 @@ void CodeGenerator::AssembleConstructFrame() {
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset();
shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
InitializePoisonForLoadsIfNeeded();
}
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();

View File

@ -2259,7 +2259,7 @@ InstructionSelector::AlignmentRequirements() {
}
// static
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; }
bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
} // namespace compiler
} // namespace internal

View File

@ -984,6 +984,16 @@ void AdjustStackPointerForTailCall(
}
}
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen, Instruction* instr,
S390OperandConverter& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(instr->opcode()));
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
codegen->tasm()->AndP(value, kSpeculationPoisonRegister);
}
}
} // namespace
void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
@ -2142,6 +2152,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
case kS390_LoadWordS8:
ASSEMBLE_LOAD_INTEGER(LoadB);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_BitcastFloat32ToInt32:
ASSEMBLE_UNARY_OP(R_DInstr(MovFloatToInt), R_MInstr(LoadlW), nullInstr);
@ -2159,27 +2170,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif
case kS390_LoadWordU8:
ASSEMBLE_LOAD_INTEGER(LoadlB);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadWordU16:
ASSEMBLE_LOAD_INTEGER(LoadLogicalHalfWordP);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadWordS16:
ASSEMBLE_LOAD_INTEGER(LoadHalfWordP);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadWordU32:
ASSEMBLE_LOAD_INTEGER(LoadlW);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadWordS32:
ASSEMBLE_LOAD_INTEGER(LoadW);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadReverse16:
ASSEMBLE_LOAD_INTEGER(lrvh);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadReverse32:
ASSEMBLE_LOAD_INTEGER(lrv);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadReverse64:
ASSEMBLE_LOAD_INTEGER(lrvg);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadReverse16RR:
__ lrvr(i.OutputRegister(), i.InputRegister(0));
@ -2193,6 +2212,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
case kS390_LoadWord64:
ASSEMBLE_LOAD_INTEGER(lg);
EmitWordLoadPoisoningIfNeeded(this, instr, i);
break;
case kS390_LoadAndTestWord32: {
ASSEMBLE_LOADANDTEST32(ltr, lt_z);
@ -2427,7 +2447,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
Instruction* instr) {
UNREACHABLE();
// TODO(John) Handle float comparisons (kUnordered[Not]Equal).
if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
return;
}
condition = NegateFlagsCondition(condition);
__ XorP(r0, r0);
__ LoadOnConditionP(FlagsConditionToCondition(condition, kArchNop),
kSpeculationPoisonRegister, r0);
}
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
@ -2633,6 +2661,7 @@ void CodeGenerator::AssembleConstructFrame() {
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset();
shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
InitializePoisonForLoadsIfNeeded();
}
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();

View File

@ -2591,7 +2591,7 @@ InstructionSelector::AlignmentRequirements() {
}
// static
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; }
bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
} // namespace compiler
} // namespace internal

View File

@ -449,6 +449,11 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&skip);
// Reset the masking register.
if (FLAG_branch_load_poisoning) {
__ ResetSpeculationPoisonRegister();
}
// Compute the handler entry address and jump to it.
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ mov(ip, Operand(pending_handler_entrypoint_address));

View File

@ -2939,7 +2939,9 @@ bool AreAliased(DoubleRegister reg1, DoubleRegister reg2, DoubleRegister reg3,
}
#endif
void TurboAssembler::ResetSpeculationPoisonRegister() { UNREACHABLE(); }
void TurboAssembler::ResetSpeculationPoisonRegister() {
mov(kSpeculationPoisonRegister, Operand(-1));
}
} // namespace internal
} // namespace v8

View File

@ -435,6 +435,11 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&skip);
// Reset the masking register.
if (FLAG_branch_load_poisoning) {
__ ResetSpeculationPoisonRegister();
}
// Compute the handler entry address and jump to it.
__ mov(r3, Operand(pending_handler_entrypoint_address));
__ LoadP(r3, MemOperand(r3));

View File

@ -4284,7 +4284,9 @@ bool AreAliased(DoubleRegister reg1, DoubleRegister reg2, DoubleRegister reg3,
}
#endif
void TurboAssembler::ResetSpeculationPoisonRegister() { UNREACHABLE(); }
void TurboAssembler::ResetSpeculationPoisonRegister() {
mov(kSpeculationPoisonRegister, Operand(-1));
}
} // namespace internal
} // namespace v8