Skip to content

Commit 8bea292

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
Keep 32 -> 64 bit zero-extends as MovZX in LIR
Summary: `PostRegAllocRewrite` used to rewrite a 32 -> 64 bit `Zext` into a 32-bit `Move`, because that is how x86-64 spells the zero-extend, there is no `movzx r64, r/m32`. Doing that in LIR means the opcode no longer says what the instruction is for, and it needs the output operand to be narrowed to 32 bits, which then disagrees with the value the instruction actually produces. Leave it as a `MovZX` and let codegen pick the encoding, matching how `MovSX` now handles the same width. Reviewed By: yoney Differential Revision: D116029617 fbshipit-source-id: 28f21003d34d9c497ed3f3434d549d3d87b5390e
1 parent bf49ef0 commit 8bea292

3 files changed

Lines changed: 30 additions & 13 deletions

File tree

cinderx/Jit/codegen/autogen.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,6 +2576,27 @@ void AutoTranslator::translateInstr(Environ* env, const Instruction* instr)
25762576
auto* output = instr->output();
25772577
auto* input = instr->getInput(0);
25782578

2579+
// x86-64 has no `movzx r64, r/m32`; writing a 32-bit register already
2580+
// zeroes the upper half of its 64-bit counterpart, so a plain MOV between
2581+
// the 32-bit halves is the zero-extend. This stays a MOV even when the
2582+
// source and destination registers are the same, as the upper half is not
2583+
// known to be clear.
2584+
if (input->sizeInBits() == 32) {
2585+
JIT_THROW_IF(
2586+
output->sizeInBits() != 64,
2587+
"Zero-extend from 32-bits should always go to 64-bits, got '{}' "
2588+
"instead",
2589+
*instr);
2590+
2591+
auto output_reg = asmjit::x86::gpd(output->getPhyRegister().loc);
2592+
if (input->isReg()) {
2593+
env->as->mov(output_reg, getReg(instr, input));
2594+
} else {
2595+
env->as->mov(output_reg, getMem(instr, input));
2596+
}
2597+
return;
2598+
}
2599+
25792600
if (input->isReg()) {
25802601
env->as->movzx(getReg(instr, output), getReg(instr, input));
25812602
} else {

cinderx/Jit/lir/postalloc.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -562,17 +562,8 @@ RewriteResult rewriteBitExtensionInstrs(instr_iter_t instr_iter) {
562562
switch (in_size) {
563563
case Operand::k8bit:
564564
case Operand::k16bit:
565-
instr->setOpcode(is_sext ? Opcode::kMovSX : Opcode::kMovZX);
566-
break;
567565
case Operand::k32bit:
568-
if (is_sext) {
569-
instr->setOpcode(Opcode::kMovSX);
570-
} else {
571-
// must be unsigned extension from 32 bits to 64 bits.
572-
// in this case, a 32-bit move will do the work.
573-
instr->setOpcode(Opcode::kMove);
574-
instr->output()->setDataType(lir::Operand::k32bit);
575-
}
566+
instr->setOpcode(is_sext ? Opcode::kMovSX : Opcode::kMovZX);
576567
break;
577568
case Operand::k64bit:
578569
case Operand::kObject:

cinderx/RuntimeTests/backend_test.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,9 +1451,9 @@ BB %1
14511451
}
14521452
}
14531453

1454-
// Sign-extending 32 bits to 64 has to fill the upper half of the destination
1455-
// with the sign bit. x86-64 spells that `movsxd` rather than the `movsx` used
1456-
// for narrower widths, so it gets its own codegen path.
1454+
// Widening 32 bits to 64 has to reach the upper half of the destination: Zext
1455+
// must clear it and Sext must fill it with the sign bit. Neither lowers to the
1456+
// movzx/movsx that the narrower widths use, so both get their own codegen path.
14571457
TEST_F(BackendTest, Extend32BitsTo64Bits) {
14581458
auto compile = [this](Opcode extend) {
14591459
auto lirfunc = std::make_unique<Function>();
@@ -1480,6 +1480,11 @@ TEST_F(BackendTest, Extend32BitsTo64Bits) {
14801480
SimpleCompile(lirfunc.get()));
14811481
};
14821482

1483+
auto zext = compile(Opcode::kZext);
1484+
ASSERT_NE(zext, nullptr);
1485+
EXPECT_EQ(zext(0xDEADBEEFCAFEBABEULL), 0x00000000CAFEBABEULL);
1486+
EXPECT_EQ(zext(0xDEADBEEF0000002AULL), 0x000000000000002AULL);
1487+
14831488
auto sext = compile(Opcode::kSext);
14841489
ASSERT_NE(sext, nullptr);
14851490
EXPECT_EQ(sext(0xDEADBEEFCAFEBABEULL), 0xFFFFFFFFCAFEBABEULL);

0 commit comments

Comments
 (0)