mirror of
https://github.com/danog/ir.git
synced 2024-11-30 04:39:43 +01:00
x86_64: Optimize integer comparison with zero
This commit is contained in:
parent
1210b5814e
commit
552aeec7d5
115
ir_x86.dasc
115
ir_x86.dasc
@ -1960,6 +1960,7 @@ void ir_emit_cmp_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
ir_reg op2_reg = ir_ref_reg(ctx, insn->op2);
|
||||
ir_reg def_reg = ir_ref_reg(ctx, def);
|
||||
ir_reg reg;
|
||||
ir_op op;
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
@ -1978,12 +1979,34 @@ void ir_emit_cmp_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
op = insn->op;
|
||||
if (op2_reg >= 0) {
|
||||
| ASM_REF_REG_OP cmp, type, insn->op1, op2_reg
|
||||
} else if (op1_reg >= 0) {
|
||||
| ASM_REG_REF_OP cmp, type, op1_reg, insn->op2
|
||||
if (IR_IS_CONST_REF(insn->op2) && ctx->ir_base[insn->op2].val.u64 == 0) {
|
||||
if (op == IR_ULT) {
|
||||
/* always false */
|
||||
if (def_reg >= 0) {
|
||||
| xor Ra(def_reg), Ra(def_reg)
|
||||
} else {
|
||||
| ASM_REF_IMM_OP mov, insn->type, def, 0
|
||||
}
|
||||
return;
|
||||
} else if (op == IR_UGE) {
|
||||
/* always true */
|
||||
| ASM_REF_IMM_OP mov, insn->type, def, 1
|
||||
return;
|
||||
} else if (op == IR_ULE) {
|
||||
op = IR_EQ;
|
||||
} else if (op == IR_UGT) {
|
||||
op = IR_NE;
|
||||
}
|
||||
| ASM_REG_REG_OP test, type, op1_reg, op1_reg
|
||||
} else {
|
||||
| ASM_REG_REF_OP cmp, type, op1_reg, insn->op2
|
||||
}
|
||||
}
|
||||
switch (insn->op) {
|
||||
switch (op) {
|
||||
case IR_EQ:
|
||||
| sete Rb(reg)
|
||||
break;
|
||||
@ -2082,12 +2105,74 @@ void ir_emit_cmp_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_jmp_true(ir_ctx *ctx, int b, ir_ref def)
|
||||
{
|
||||
ir_use_list *use_list;
|
||||
ir_insn *use_insn;
|
||||
ir_ref i, *p, use, n;
|
||||
int true_block = 0, false_block = 0, next_block;
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
use_list = &ctx->use_lists[def];
|
||||
n = use_list->count;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
use = *p;
|
||||
use_insn = &ctx->ir_base[use];
|
||||
if (use_insn->op == IR_IF_TRUE) {
|
||||
true_block = ir_skip_empty_blocks(ctx, ctx->bb_num[use]);
|
||||
} else if (use_insn->op == IR_IF_FALSE) {
|
||||
false_block = ir_skip_empty_blocks(ctx, ctx->bb_num[use]);
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
}
|
||||
}
|
||||
IR_ASSERT(true_block && false_block);
|
||||
|
||||
next_block = ir_skip_empty_blocks(ctx, b + 1);
|
||||
if (true_block != next_block) {
|
||||
| jmp =>true_block
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_jmp_false(ir_ctx *ctx, int b, ir_ref def)
|
||||
{
|
||||
ir_use_list *use_list;
|
||||
ir_insn *use_insn;
|
||||
ir_ref i, *p, use, n;
|
||||
int true_block = 0, false_block = 0, next_block;
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
use_list = &ctx->use_lists[def];
|
||||
n = use_list->count;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
use = *p;
|
||||
use_insn = &ctx->ir_base[use];
|
||||
if (use_insn->op == IR_IF_TRUE) {
|
||||
true_block = ir_skip_empty_blocks(ctx, ctx->bb_num[use]);
|
||||
} else if (use_insn->op == IR_IF_FALSE) {
|
||||
false_block = ir_skip_empty_blocks(ctx, ctx->bb_num[use]);
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
}
|
||||
}
|
||||
IR_ASSERT(true_block && false_block);
|
||||
|
||||
next_block = ir_skip_empty_blocks(ctx, b + 1);
|
||||
if (false_block != next_block) {
|
||||
| jmp =>false_block
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_jcc(ir_ctx *ctx, uint8_t op, int b, ir_ref def, ir_insn *insn, bool int_cmp)
|
||||
{
|
||||
ir_use_list *use_list;
|
||||
ir_insn *use_insn;
|
||||
ir_ref i, *p, use, n;
|
||||
int true_block = 0, false_block = 0, next_block;
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
use_list = &ctx->use_lists[def];
|
||||
n = use_list->count;
|
||||
@ -2117,8 +2202,6 @@ static void ir_emit_jcc(ir_ctx *ctx, uint8_t op, int b, ir_ref def, ir_insn *ins
|
||||
false_block = 0;
|
||||
}
|
||||
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
if (int_cmp) {
|
||||
switch (op) {
|
||||
case IR_EQ:
|
||||
@ -2195,6 +2278,7 @@ void ir_emit_cmp_and_branch_int(ir_ctx *ctx, int b, ir_ref def, ir_insn *insn)
|
||||
ir_type type = ctx->ir_base[cmp_insn->op1].type;
|
||||
ir_reg op1_reg = ir_ref_reg(ctx, cmp_insn->op1);
|
||||
ir_reg op2_reg = ir_ref_reg(ctx, cmp_insn->op2);
|
||||
ir_op op;
|
||||
|
||||
if (op1_reg < 0 && op2_reg < 0) {
|
||||
if (IR_IS_CONST_REF(cmp_insn->op2)) {
|
||||
@ -2208,12 +2292,31 @@ void ir_emit_cmp_and_branch_int(ir_ctx *ctx, int b, ir_ref def, ir_insn *insn)
|
||||
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
op = cmp_insn->op;
|
||||
if (op2_reg >= 0) {
|
||||
| ASM_REF_REG_OP cmp, type, cmp_insn->op1, op2_reg
|
||||
} else if (op1_reg >= 0) {
|
||||
| ASM_REG_REF_OP cmp, type, op1_reg, cmp_insn->op2
|
||||
if (IR_IS_CONST_REF(cmp_insn->op2) && ctx->ir_base[cmp_insn->op2].val.u64 == 0) {
|
||||
if (op == IR_ULT) {
|
||||
/* always false */
|
||||
ir_emit_jmp_false(ctx, b, def);
|
||||
return;
|
||||
} else if (op == IR_UGE) {
|
||||
/* always true */
|
||||
ir_emit_jmp_true(ctx, b, def);
|
||||
return;
|
||||
} else if (op == IR_ULE) {
|
||||
op = IR_EQ;
|
||||
} else if (op == IR_UGT) {
|
||||
op = IR_NE;
|
||||
}
|
||||
| ASM_REG_REG_OP test, type, op1_reg, op1_reg
|
||||
} else {
|
||||
| ASM_REG_REF_OP cmp, type, op1_reg, cmp_insn->op2
|
||||
}
|
||||
}
|
||||
ir_emit_jcc(ctx, cmp_insn->op, b, def, insn, 1);
|
||||
ir_emit_jcc(ctx, op, b, def, insn, 1);
|
||||
}
|
||||
|
||||
void ir_emit_cmp_and_branch_fp(ir_ctx *ctx, int b, ir_ref def, ir_insn *insn)
|
||||
|
17
tests/x86_64/eq_003.irt
Normal file
17
tests/x86_64/eq_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: eq function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = EQ(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
sete %al
|
||||
retq
|
17
tests/x86_64/ge_003.irt
Normal file
17
tests/x86_64/ge_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: ge function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = GE(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setge %al
|
||||
retq
|
17
tests/x86_64/gt_003.irt
Normal file
17
tests/x86_64/gt_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: gt function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = GT(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setg %al
|
||||
retq
|
17
tests/x86_64/le_003.irt
Normal file
17
tests/x86_64/le_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: le function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = LE(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setle %al
|
||||
retq
|
17
tests/x86_64/lt_003.irt
Normal file
17
tests/x86_64/lt_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: lt function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = LT(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setl %al
|
||||
retq
|
17
tests/x86_64/ne_003.irt
Normal file
17
tests/x86_64/ne_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: ne function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
int32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
int32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = NE(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setne %al
|
||||
retq
|
16
tests/x86_64/uge_003.irt
Normal file
16
tests/x86_64/uge_003.irt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
003: uge function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
uint32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
uint32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = UGE(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
movb $1, %al
|
||||
retq
|
17
tests/x86_64/ugt_003.irt
Normal file
17
tests/x86_64/ugt_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: ugt function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
uint32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
uint32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = UGT(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
setne %al
|
||||
retq
|
17
tests/x86_64/ule_003.irt
Normal file
17
tests/x86_64/ule_003.irt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
003: ule function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
uint32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
uint32_t x = PARAM(l_1, "x", 2);
|
||||
bool ret = ULE(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
testl %edi, %edi
|
||||
sete %al
|
||||
retq
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
001: ult function
|
||||
002: ult function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
|
16
tests/x86_64/ult_003.irt
Normal file
16
tests/x86_64/ult_003.irt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
003: ult function
|
||||
--ARGS--
|
||||
-S
|
||||
--CODE--
|
||||
{
|
||||
uint32_t c = 0;
|
||||
l_1 = START(l_4);
|
||||
uint32_t x = PARAM(l_1, "x", 1);
|
||||
bool ret = ULT(x, c);
|
||||
l_4 = RETURN(l_1, ret);
|
||||
}
|
||||
--EXPECT--
|
||||
test:
|
||||
xorq %rax, %rax
|
||||
retq
|
Loading…
Reference in New Issue
Block a user