Commit b79d7b04 authored by epertoso's avatar epertoso Committed by Commit bot

[x64] Zero/sign-extend loads to 64-bit registers.

Before this change we would first load an 8/16/32-bit value from memory into a 32-bit register, then zero/sign-extend from that register to a 64-bit one. Now we replace that pattern with a single movsx/movzx.

Ported from http://crrev.com/2183923003

R=bmeurer@chromium.org

Committed: https://crrev.com/4abecb7a27bd5fa073d0ff5fadb0c2bb248ef9f4
Review-Url: https://codereview.chromium.org/2220483003
Cr-Original-Commit-Position: refs/heads/master@{#38388}
Cr-Commit-Position: refs/heads/master@{#38428}
parent 476f80a9
......@@ -1754,6 +1754,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_MOVX(movzxbl);
__ AssertZeroExtended(i.OutputRegister());
break;
case kX64Movsxbq:
ASSEMBLE_MOVX(movsxbq);
break;
case kX64Movzxbq:
ASSEMBLE_MOVX(movzxbq);
__ AssertZeroExtended(i.OutputRegister());
break;
case kX64Movb: {
size_t index = 0;
Operand operand = i.MemoryOperand(&index);
......@@ -1772,6 +1779,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_MOVX(movzxwl);
__ AssertZeroExtended(i.OutputRegister());
break;
case kX64Movsxwq:
ASSEMBLE_MOVX(movsxwq);
break;
case kX64Movzxwq:
ASSEMBLE_MOVX(movzxwq);
__ AssertZeroExtended(i.OutputRegister());
break;
case kX64Movw: {
size_t index = 0;
Operand operand = i.MemoryOperand(&index);
......
......@@ -117,9 +117,13 @@ namespace compiler {
V(AVXFloat32Neg) \
V(X64Movsxbl) \
V(X64Movzxbl) \
V(X64Movsxbq) \
V(X64Movzxbq) \
V(X64Movb) \
V(X64Movsxwl) \
V(X64Movzxwl) \
V(X64Movsxwq) \
V(X64Movzxwq) \
V(X64Movw) \
V(X64Movl) \
V(X64Movsxlq) \
......
......@@ -131,8 +131,12 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Movsxbl:
case kX64Movzxbl:
case kX64Movsxbq:
case kX64Movzxbq:
case kX64Movsxwl:
case kX64Movzxwl:
case kX64Movsxwq:
case kX64Movzxwq:
case kX64Movsxlq:
DCHECK(instr->InputCount() >= 1);
return instr->InputAt(0)->IsRegister() ? kNoOpcodeFlags
......
......@@ -1112,7 +1112,36 @@ void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
Node* const value = node->InputAt(0);
if (value->opcode() == IrOpcode::kLoad && CanCover(node, value)) {
LoadRepresentation load_rep = LoadRepresentationOf(value->op());
MachineRepresentation rep = load_rep.representation();
InstructionCode opcode = kArchNop;
switch (rep) {
case MachineRepresentation::kBit: // Fall through.
case MachineRepresentation::kWord8:
opcode = load_rep.IsSigned() ? kX64Movsxbq : kX64Movzxbq;
break;
case MachineRepresentation::kWord16:
opcode = load_rep.IsSigned() ? kX64Movsxwq : kX64Movzxwq;
break;
case MachineRepresentation::kWord32:
opcode = load_rep.IsSigned() ? kX64Movsxlq : kX64Movl;
break;
default:
UNREACHABLE();
return;
}
InstructionOperand outputs[] = {g.DefineAsRegister(node)};
size_t input_count = 0;
InstructionOperand inputs[3];
AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
node->InputAt(0), inputs, &input_count);
opcode |= AddressingModeField::encode(mode);
Emit(opcode, 1, outputs, input_count, inputs);
} else {
Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
}
......
......@@ -1586,6 +1586,13 @@ void Assembler::movsxbq(Register dst, const Operand& src) {
emit_operand(dst, src);
}
void Assembler::movsxbq(Register dst, Register src) {
EnsureSpace ensure_space(this);
emit_rex_64(dst, src);
emit(0x0F);
emit(0xBE);
emit_modrm(dst, src);
}
void Assembler::movsxwl(Register dst, Register src) {
EnsureSpace ensure_space(this);
......@@ -1613,6 +1620,13 @@ void Assembler::movsxwq(Register dst, const Operand& src) {
emit_operand(dst, src);
}
void Assembler::movsxwq(Register dst, Register src) {
EnsureSpace ensure_space(this);
emit_rex_64(dst, src);
emit(0x0F);
emit(0xBF);
emit_modrm(dst, src);
}
void Assembler::movsxlq(Register dst, Register src) {
EnsureSpace ensure_space(this);
......
......@@ -708,9 +708,11 @@ class Assembler : public AssemblerBase {
void movsxbl(Register dst, Register src);
void movsxbl(Register dst, const Operand& src);
void movsxbq(Register dst, Register src);
void movsxbq(Register dst, const Operand& src);
void movsxwl(Register dst, Register src);
void movsxwl(Register dst, const Operand& src);
void movsxwq(Register dst, Register src);
void movsxwq(Register dst, const Operand& src);
void movsxlq(Register dst, Register src);
void movsxlq(Register dst, const Operand& src);
......
......@@ -33,7 +33,6 @@ TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
}
TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32());
m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
......@@ -71,6 +70,41 @@ TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
}
namespace {
struct LoadWithToInt64Extension {
MachineType type;
ArchOpcode expected_opcode;
};
std::ostream& operator<<(std::ostream& os,
const LoadWithToInt64Extension& i32toi64) {
return os << i32toi64.type;
}
static const LoadWithToInt64Extension kLoadWithToInt64Extensions[] = {
{MachineType::Int8(), kX64Movsxbq},
{MachineType::Uint8(), kX64Movzxbq},
{MachineType::Int16(), kX64Movsxwq},
{MachineType::Uint16(), kX64Movzxwq},
{MachineType::Int32(), kX64Movsxlq}};
} // namespace
typedef InstructionSelectorTestWithParam<LoadWithToInt64Extension>
InstructionSelectorChangeInt32ToInt64Test;
TEST_P(InstructionSelectorChangeInt32ToInt64Test, ChangeInt32ToInt64WithLoad) {
const LoadWithToInt64Extension extension = GetParam();
StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer());
m.Return(m.ChangeInt32ToInt64(m.Load(extension.type, m.Parameter(0))));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(extension.expected_opcode, s[0]->arch_opcode());
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorChangeInt32ToInt64Test,
::testing::ValuesIn(kLoadWithToInt64Extensions));
// -----------------------------------------------------------------------------
// Loads and stores
......
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