Skip to content

Commit

Permalink
Merge 32 bit binary and and branch/select operations
Browse files Browse the repository at this point in the history
Signed-off-by: Zoltan Herczeg [email protected]
  • Loading branch information
zherczeg authored and clover2123 committed Jan 6, 2025
1 parent 01b43be commit acf00db
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 26 deletions.
47 changes: 26 additions & 21 deletions src/jit/Analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -751,31 +751,36 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
VariableRef ref = *instr->getResult(0);
VariableList::Variable& variable = m_variableList->variables[ref];

if (variable.u.rangeStart == instr->id() && variable.rangeEnd == instr->id() + 1) {
ASSERT(instr->next()->isInstruction());
Instruction* nextInstr = instr->next()->asInstruction();

switch (nextInstr->opcode()) {
case ByteCode::JumpIfTrueOpcode:
case ByteCode::JumpIfFalseOpcode:
// These instructions has only one argument.
ASSERT(*nextInstr->getParam(0) == VARIABLE_SET(ref, DependencyGenContext::Variable));
variable.info |= VariableList::kIsImmediate;
variable.value = VARIABLE_SET_PTR(nullptr);
continue;
case ByteCode::SelectOpcode:
if (*nextInstr->getParam(2) == VARIABLE_SET(ref, DependencyGenContext::Variable)) {
variable.info |= VariableList::kIsImmediate;
variable.value = VARIABLE_SET_PTR(nullptr);
continue;
}
break;
default:
if (variable.u.rangeStart != instr->id() || variable.rangeEnd != instr->id() + 1) {
instr->clearInfo(Instruction::kIsMergeCompare);
continue;
}

ASSERT(instr->next()->isInstruction());
Instruction* nextInstr = instr->next()->asInstruction();

switch (nextInstr->opcode()) {
case ByteCode::JumpIfTrueOpcode:
case ByteCode::JumpIfFalseOpcode:
// These instructions has only one argument.
ASSERT(*nextInstr->getParam(0) == VARIABLE_SET(ref, DependencyGenContext::Variable));
break;
case ByteCode::SelectOpcode:
if (*nextInstr->getParam(2) == VARIABLE_SET(ref, DependencyGenContext::Variable)) {
break;
}
FALLTHROUGH;
default:
instr->clearInfo(Instruction::kIsMergeCompare);
continue;
}

instr->clearInfo(Instruction::kIsMergeCompare);
variable.info |= VariableList::kIsImmediate;
variable.value = VARIABLE_SET_PTR(nullptr);

if (instr->group() == Instruction::Binary) {
instr->convertBinaryToCompare();
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/jit/ByteCodeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,9 @@ static void compileFunction(JITCompiler* compiler)
group = Instruction::Binary;
paramType = ParamTypes::ParamSrc2Dst;
info = Instruction::kIs32Bit;
if (opcode == ByteCode::I32AndOpcode) {
info |= Instruction::kIsMergeCompare;
}
requiredInit = OTOp2I32;
break;
}
Expand Down
6 changes: 6 additions & 0 deletions src/jit/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ class InstructionListItem {
return reinterpret_cast<Label*>(this);
}

void convertBinaryToCompare()
{
ASSERT(m_group == Binary);
m_group = Compare;
}

protected:
explicit InstructionListItem(Group group)
: m_next(nullptr)
Expand Down
14 changes: 13 additions & 1 deletion src/jit/IntMath32Inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,10 @@ static bool emitCompare(sljit_compiler* compiler, Instruction* instr)
opcode = SLJIT_SUB | SLJIT_SET_GREATER_EQUAL;
type = SLJIT_GREATER_EQUAL;
break;
case ByteCode::I32AndOpcode:
opcode = SLJIT_AND | SLJIT_SET_Z;
type = SLJIT_NOT_ZERO;
break;
default:
RELEASE_ASSERT_NOT_REACHED();
break;
Expand Down Expand Up @@ -1112,7 +1116,15 @@ static bool emitCompare(sljit_compiler* compiler, Instruction* instr)
type ^= 0x1;
}

sljit_jump* jump = sljit_emit_cmp(compiler, type, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
sljit_jump* jump;

if (instr->opcode() != ByteCode::I32AndOpcode) {
jump = sljit_emit_cmp(compiler, type, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
} else {
sljit_emit_op2u(compiler, opcode, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
jump = sljit_emit_jump(compiler, type);
}

nextInstr->asExtended()->value().targetLabel->jumpFrom(jump);
return true;
}
Expand Down
24 changes: 20 additions & 4 deletions src/jit/IntMath64Inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ static bool emitCompare(sljit_compiler* compiler, Instruction* instr)
opcode = SLJIT_SUB | SLJIT_SET_GREATER_EQUAL;
type = SLJIT_GREATER_EQUAL;
break;
case ByteCode::I32AndOpcode:
opcode = SLJIT_AND | SLJIT_SET_Z;
type = SLJIT_NOT_ZERO;
break;
default:
RELEASE_ASSERT_NOT_REACHED();
break;
Expand All @@ -455,11 +459,23 @@ static bool emitCompare(sljit_compiler* compiler, Instruction* instr)
type ^= 0x1;
}

if (instr->info() & Instruction::kIs32Bit) {
type |= SLJIT_32;
}

sljit_jump* jump = sljit_emit_cmp(compiler, type, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
sljit_jump* jump;

if (instr->opcode() != ByteCode::I32AndOpcode) {
if (instr->info() & Instruction::kIs32Bit) {
type |= SLJIT_32;
}

jump = sljit_emit_cmp(compiler, type, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
} else {
if (instr->info() & Instruction::kIs32Bit) {
opcode |= SLJIT_32;
}

sljit_emit_op2u(compiler, opcode, params[0].arg, params[0].argw, params[1].arg, params[1].argw);
jump = sljit_emit_jump(compiler, type);
}
nextInstr->asExtended()->value().targetLabel->jumpFrom(jump);
return true;
}
Expand Down
27 changes: 27 additions & 0 deletions test/jit/binary-logical.wast
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,33 @@

(; 1080880403494997760, 18442521884633399280, 17361641481138401520 ;)
)

(func (export "test2") (param i32 i32) (result i32)
block
local.get 0
local.get 1
i32.and
br_if 0
i32.const 5
return
end

i32.const 6
)

(func (export "test3") (param i32 i32) (result i32)
i32.const 10
i32.const 11

local.get 0
local.get 1
i32.and
select
)
)

(assert_return (invoke "test1") (i64.const 1080880403494997760) (i64.const 18442521884633399280) (i64.const 17361641481138401520))
(assert_return (invoke "test2" (i32.const 0x100) (i32.const 0x200)) (i32.const 5))
(assert_return (invoke "test2" (i32.const 0x0ff0) (i32.const 0x1f)) (i32.const 6))
(assert_return (invoke "test3" (i32.const 0xff) (i32.const 0xff00)) (i32.const 11))
(assert_return (invoke "test3" (i32.const 0x1ff) (i32.const 0xff00)) (i32.const 10))

0 comments on commit acf00db

Please sign in to comment.