Skip to content

Commit 45f910b

Browse files
authored
Improve sljit_emit_op2_shift on x86 (#342)
1 parent 72f95ea commit 45f910b

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

sljit_src/sljitLir.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,15 +1986,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2_shift(struct sljit_co
19861986
{
19871987
SLJIT_UNUSED_ARG(shift_arg);
19881988
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1989-
CHECK_ARGUMENT(op == (SLJIT_ADD | SLJIT_SHL_IMM));
1989+
CHECK_ARGUMENT((op & ~SLJIT_SRC2_UNDEFINED) == (SLJIT_ADD | SLJIT_SHL_IMM));
19901990
FUNCTION_CHECK_DST(dst, dstw);
19911991
FUNCTION_CHECK_SRC(src1, src1w);
19921992
FUNCTION_CHECK_SRC(src2, src2w);
19931993
compiler->last_flags = 0;
19941994
#endif /* SLJIT_ARGUMENT_CHECKS */
19951995
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
19961996
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
1997-
fprintf(compiler->verbose, " %s.shl_imm ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE]);
1997+
fprintf(compiler->verbose, " %s.shl_imm%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
1998+
(op & SLJIT_SRC2_UNDEFINED) ? ".src2und" : "");
19981999

19992000
sljit_verbose_param(compiler, dst, dstw);
20002001
fprintf(compiler->verbose, ", ");

sljit_src/sljitLir.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
14681468

14691469
/* The following options are used by sljit_emit_op2_shift. */
14701470

1471+
/* The src2 argument is shifted left by an immedate value. */
14711472
#define SLJIT_SHL_IMM (1 << 9)
1473+
/* When src2 argument is a register, its value is undefined after the operation. */
1474+
#define SLJIT_SRC2_UNDEFINED (1 << 10)
14721475

14731476
/* Emits an addition operation, where the second argument is shifted by a value.
14741477

sljit_src/sljitNativeX86_common.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,11 +3094,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *c
30943094
return SLJIT_SUCCESS;
30953095
}
30963096

3097-
dst_r = FAST_IS_REG(dst) && (dst != src1) ? dst : TMP_REG1;
3097+
if ((op & SLJIT_SRC2_UNDEFINED) != 0 && FAST_IS_REG(src2) && src1 != src2)
3098+
dst_r = src2;
3099+
else {
3100+
dst_r = FAST_IS_REG(dst) && (dst != src1) ? dst : TMP_REG1;
30983101

3099-
if (src2 != dst_r) {
3100-
EMIT_MOV(compiler, dst_r, 0, src2, src2w);
3102+
if (src2 != dst_r) {
3103+
EMIT_MOV(compiler, dst_r, 0, src2, src2w);
3104+
}
31013105
}
3106+
31023107
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, shift_arg, dst_r, 0);
31033108
FAIL_IF(!inst);
31043109
inst[1] |= SHL;
@@ -3110,6 +3115,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *c
31103115
return SLJIT_SUCCESS;
31113116
}
31123117

3118+
if (FAST_IS_REG(dst) && FAST_IS_REG(src1)) {
3119+
inst = emit_x86_instruction(compiler, 1, dst, 0, SLJIT_MEM2(src1, dst_r), 0);
3120+
FAIL_IF(!inst);
3121+
*inst = LEA_r_m;
3122+
return SLJIT_SUCCESS;
3123+
}
3124+
31133125
if (src1 == SLJIT_IMM) {
31143126
BINARY_IMM(ADD, ADD_rm_r, src1w, dst_r, 0);
31153127
} else {

test_src/sljitTest.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9860,12 +9860,12 @@ static void test80(void)
98609860
executable_code code;
98619861
struct sljit_compiler *compiler = sljit_create_compiler(NULL);
98629862
sljit_s32 i;
9863-
sljit_sw buf[20];
9863+
sljit_sw buf[23];
98649864

98659865
if (verbose)
98669866
printf("Run test80\n");
98679867

9868-
for (i = 0; i < 20; i++)
9868+
for (i = 0; i < 23; i++)
98699869
buf[i] = -1;
98709870

98719871
FAILED(!compiler, "cannot create compiler\n");
@@ -9986,6 +9986,23 @@ static void test80(void)
99869986
/* buf[19] */
99879987
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_TMP_DEST_REG, 0);
99889988

9989+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x8e2c4e79b79500a8, 0x8e2c4e79));
9990+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x5ce8fa2c60c7c10c, 0x5ce8fa2c));
9991+
/* buf[20] */
9992+
sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_R1, 0, 7);
9993+
9994+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xbdfe33c03babe728, 0xbdfe33c0));
9995+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x6dda8d28a705b87a, 0x6dda8d28));
9996+
sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_R2, 0, 9);
9997+
/* buf[21] */
9998+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R2, 0);
9999+
10000+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xadb9530fe12dca23, 0xadb9530f));
10001+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, WCONST(0x678fe74fab8bcc2b, 0x678fe74f));
10002+
sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R2, 0, 11);
10003+
/* buf[22] */
10004+
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R0, 0);
10005+
998910006
sljit_emit_return_void(compiler);
999010007

999110008
code.code = sljit_generate_code(compiler, 0, NULL);
@@ -10015,6 +10032,9 @@ static void test80(void)
1001510032
FAILED(buf[17] != WCONST(0xe7204ac2adf575cd, 0xe72075cd), "test80 case 18 failed\n");
1001610033
FAILED(buf[18] != WCONST(0x90e766522922d467, 0x90e76550), "test80 case 19 failed\n");
1001710034
FAILED(buf[19] != WCONST(0xbf01437a347858bf, 0xbf014378), "test80 case 20 failed\n");
10035+
FAILED(buf[20] != WCONST(0x2a964aa1b7586a8, 0x2a96479), "test80 case 21 failed\n");
10036+
FAILED(buf[21] != WCONST(0x7318850e471cdb28, 0x731883c0), "test80 case 22 failed\n");
10037+
FAILED(buf[22] != WCONST(0x2cf3d06c3f8f2223, 0x2cf3cb0f), "test80 case 23 failed\n");
1001810038

1001910039
sljit_free_code(code.code, NULL);
1002010040
successful_tests++;

0 commit comments

Comments
 (0)