mirror of
https://github.com/danog/ir.git
synced 2024-12-02 09:38:29 +01:00
mplemented code-generation for bit counting instructions
This commit is contained in:
parent
92ef948caf
commit
688f876928
1
ir.h
1
ir.h
@ -840,6 +840,7 @@ int ir_patch(const void *code, size_t size, uint32_t jmp_table_size, const void
|
||||
# define IR_X86_SSE42 (1<<4)
|
||||
# define IR_X86_AVX (1<<5)
|
||||
# define IR_X86_AVX2 (1<<6)
|
||||
# define IR_X86_BMI1 (1<<7)
|
||||
#endif
|
||||
|
||||
uint32_t ir_cpuinfo(void);
|
||||
|
@ -655,6 +655,8 @@ binop_fp:
|
||||
return IR_BINOP_INT;
|
||||
case IR_BSWAP:
|
||||
case IR_NOT:
|
||||
case IR_CTLZ:
|
||||
case IR_CTTZ:
|
||||
IR_ASSERT(IR_IS_TYPE_INT(insn->type));
|
||||
return IR_OP_INT;
|
||||
case IR_NEG:
|
||||
@ -1880,6 +1882,21 @@ static void ir_emit_op_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
| cmp Rw(op1_reg), #0
|
||||
| cneg Rw(def_reg), Rw(op1_reg), lt
|
||||
}
|
||||
} else if (insn->op == IR_CTLZ) {
|
||||
if (ir_type_size[type] == 1) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xff
|
||||
| clz Rw(def_reg), Rw(def_reg)
|
||||
| sub Rw(def_reg), Rw(def_reg), #24
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xffff
|
||||
| clz Rw(def_reg), Rw(def_reg)
|
||||
| sub Rw(def_reg), Rw(def_reg), #16
|
||||
} else {
|
||||
| ASM_REG_REG_OP clz, type, def_reg, op1_reg
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
| ASM_REG_REG_OP rbit, insn->type, def_reg, op1_reg
|
||||
| ASM_REG_REG_OP clz, insn->type, def_reg, def_reg
|
||||
} else {
|
||||
IR_ASSERT(insn->op == IR_BSWAP);
|
||||
| ASM_REG_REG_OP rev, insn->type, def_reg, op1_reg
|
||||
@ -1911,14 +1928,14 @@ static void ir_emit_ctpop(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case 1:
|
||||
| and Rw(def_reg-IR_REG_FP_FIRST), Rw(op1_reg), #0xff
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xff
|
||||
| fmov Rs(tmp_reg-IR_REG_FP_FIRST), Rw(def_reg)
|
||||
| .long code1 // cnt v0.8b, v0.8b
|
||||
| .long code2 // addv b0, v0.8b
|
||||
| fmov Rw(def_reg), Rs(tmp_reg-IR_REG_FP_FIRST)
|
||||
break;
|
||||
case 2:
|
||||
| and Rw(def_reg-IR_REG_FP_FIRST), Rw(op1_reg), #0xffff
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xffff
|
||||
| fmov Rs(tmp_reg-IR_REG_FP_FIRST), Rw(def_reg)
|
||||
| .long code1 // cnt v0.8b, v0.8b
|
||||
| .long code2 // addv b0, v0.8b
|
||||
|
@ -46,6 +46,7 @@ uint32_t ir_cpuinfo(void)
|
||||
|
||||
ir_cpuid_ex(info_0x7_0, 0x7, 0);
|
||||
if (bit(info_0x7_0[1], 5U)) ret |= IR_X86_AVX2;
|
||||
if (bit(info_0x7_0[1], 3U)) ret |= IR_X86_BMI1;
|
||||
|
||||
#undef bit
|
||||
|
||||
|
10
ir_main.c
10
ir_main.c
@ -27,7 +27,7 @@ static void help(const char *cmd)
|
||||
" -S - dump final target assembler code\n"
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
" -mavx - use AVX instruction set\n"
|
||||
" -mno-sse41 - disable SSE 4.1 instruction set\n"
|
||||
" -mno-bmi1 - disable BMI1 instruction set\n"
|
||||
#endif
|
||||
" -muse-fp - use base frame pointer register\n"
|
||||
" --emit-c [file-name] - convert to C source\n"
|
||||
@ -740,8 +740,8 @@ int main(int argc, char **argv)
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
} else if (strcmp(argv[i], "-mavx") == 0) {
|
||||
mflags |= IR_X86_AVX;
|
||||
} else if (strcmp(argv[i], "-mno-sse41") == 0) {
|
||||
mflags_disabled |= IR_X86_SSE41;
|
||||
} else if (strcmp(argv[i], "-mno-bmi1") == 0) {
|
||||
mflags_disabled |= IR_X86_BMI1;
|
||||
#endif
|
||||
} else if (strcmp(argv[i], "-muse-fp") == 0) {
|
||||
flags |= IR_USE_FRAME_POINTER;
|
||||
@ -819,8 +819,8 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "ERROR: -mavx is not compatible with CPU (AVX is not supported)\n");
|
||||
return 1;
|
||||
}
|
||||
if ((cpuinfo & IR_X86_SSE41) && !(mflags_disabled & IR_X86_SSE41)) {
|
||||
mflags |= IR_X86_SSE41;
|
||||
if ((cpuinfo & IR_X86_BMI1) && !(mflags_disabled & IR_X86_BMI1)) {
|
||||
mflags |= IR_X86_BMI1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
182
ir_x86.dasc
182
ir_x86.dasc
@ -547,7 +547,7 @@ const char *ir_reg_name(int8_t reg, ir_type type)
|
||||
_(RETURN_VOID) \
|
||||
_(RETURN_INT) \
|
||||
_(RETURN_FP) \
|
||||
_(CTPOP_POPCNT) \
|
||||
_(BIT_COUNT) \
|
||||
|
||||
#define IR_RULE_ENUM(name) IR_ ## name,
|
||||
|
||||
@ -804,7 +804,7 @@ op2_const:
|
||||
case IR_OP_FP:
|
||||
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
|
||||
break;
|
||||
case IR_CTPOP_POPCNT:
|
||||
case IR_BIT_COUNT:
|
||||
insn = &ctx->ir_base[ref];
|
||||
if (ir_type_size[insn->type] == 1) {
|
||||
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG;
|
||||
@ -1913,9 +1913,13 @@ store_int:
|
||||
case IR_FP2FP:
|
||||
ir_match_fuse_load(ctx, insn->op1, ref);
|
||||
return insn->op;
|
||||
case IR_CTLZ:
|
||||
case IR_CTTZ:
|
||||
ir_match_fuse_load(ctx, insn->op1, ref);
|
||||
return IR_BIT_COUNT;
|
||||
case IR_CTPOP:
|
||||
ir_match_fuse_load(ctx, insn->op1, ref);
|
||||
return (ctx->mflags & IR_X86_SSE41) ? IR_CTPOP_POPCNT : IR_CTPOP;
|
||||
return (ctx->mflags & IR_X86_BMI1) ? IR_BIT_COUNT : IR_CTPOP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3181,7 +3185,7 @@ static void ir_emit_op_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_ctpop_popcnt(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
static void ir_emit_bit_count(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
@ -3201,17 +3205,75 @@ static void ir_emit_ctpop_popcnt(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case 2:
|
||||
| popcnt Rw(def_reg), Rw(op1_reg)
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rw(def_reg), Rw(op1_reg)
|
||||
} else {
|
||||
| bsr Rw(def_reg), Rw(op1_reg)
|
||||
| xor Rw(def_reg), 0xf
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rw(def_reg), Rw(op1_reg)
|
||||
} else {
|
||||
| bsf Rw(def_reg), Rw(op1_reg)
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(insn->op == IR_CTPOP);
|
||||
| popcnt Rw(def_reg), Rw(op1_reg)
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
| movzx Rd(op1_reg), Rb(op1_reg)
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rd(def_reg), Rd(op1_reg)
|
||||
| sub Rd(def_reg), 24
|
||||
} else {
|
||||
| bsr Rd(def_reg), Rd(op1_reg)
|
||||
| xor Rw(def_reg), 0x7
|
||||
}
|
||||
break;
|
||||
}
|
||||
IR_FALLTHROUGH;
|
||||
case 4:
|
||||
| popcnt Rd(def_reg), Rd(op1_reg)
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rd(def_reg), Rd(op1_reg)
|
||||
} else {
|
||||
| bsr Rd(def_reg), Rd(op1_reg)
|
||||
| xor Rw(def_reg), 0x1f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rd(def_reg), Rd(op1_reg)
|
||||
} else {
|
||||
| bsf Rd(def_reg), Rd(op1_reg)
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(insn->op == IR_CTPOP);
|
||||
| popcnt Rd(def_reg), Rd(op1_reg)
|
||||
}
|
||||
break;
|
||||
|.if X64
|
||||
case 8:
|
||||
| popcnt Rq(def_reg), Rq(op1_reg)
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rq(def_reg), Rq(op1_reg)
|
||||
} else {
|
||||
| bsr Rq(def_reg), Rq(op1_reg)
|
||||
| xor Rw(def_reg), 0x3f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rq(def_reg), Rq(op1_reg)
|
||||
} else {
|
||||
| bsf Rq(def_reg), Rq(op1_reg)
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(insn->op == IR_CTPOP);
|
||||
| popcnt Rq(def_reg), Rq(op1_reg)
|
||||
}
|
||||
break;
|
||||
|.endif
|
||||
}
|
||||
@ -3228,14 +3290,59 @@ static void ir_emit_ctpop_popcnt(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case 2:
|
||||
| popcnt Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsr Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
| xor Rw(def_reg), 0xf
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsf Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rw(def_reg), word [Ra(op1_reg)+offset]
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
| popcnt Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsr Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
| xor Rw(def_reg), 0x1f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsf Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rd(def_reg), dword [Ra(op1_reg)+offset]
|
||||
}
|
||||
break;
|
||||
|.if X64
|
||||
case 8:
|
||||
| popcnt Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsr Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
| xor Rw(def_reg), 0x3f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
} else {
|
||||
| bsf Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rq(def_reg), qword [Ra(op1_reg)+offset]
|
||||
}
|
||||
break;
|
||||
|.endif
|
||||
}
|
||||
@ -3244,14 +3351,59 @@ static void ir_emit_ctpop_popcnt(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case 2:
|
||||
| popcnt Rw(def_reg), word [offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rw(def_reg), word [offset]
|
||||
} else {
|
||||
| bsr Rw(def_reg), word [offset]
|
||||
| xor Rw(def_reg), 0xf
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rw(def_reg), word [offset]
|
||||
} else {
|
||||
| bsf Rw(def_reg), word [offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rw(def_reg), word [offset]
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
| popcnt Rd(def_reg), dword [offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rd(def_reg), dword [offset]
|
||||
} else {
|
||||
| bsr Rw(def_reg), word [offset]
|
||||
| xor Rw(def_reg), 0x1f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rd(def_reg), dword [offset]
|
||||
} else {
|
||||
| bsf Rd(def_reg), dword [offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rd(def_reg), dword [offset]
|
||||
}
|
||||
break;
|
||||
|.if X64
|
||||
case 8:
|
||||
| popcnt Rq(def_reg), qword [offset]
|
||||
if (insn->op == IR_CTLZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| lzcnt Rq(def_reg), qword [offset]
|
||||
} else {
|
||||
| bsr Rw(def_reg), word [offset]
|
||||
| xor Rw(def_reg), 0x1f
|
||||
}
|
||||
} else if (insn->op == IR_CTTZ) {
|
||||
if (ctx->mflags & IR_X86_BMI1) {
|
||||
| tzcnt Rq(def_reg), qword [offset]
|
||||
} else {
|
||||
| bsf Rq(def_reg), qword [offset]
|
||||
}
|
||||
} else {
|
||||
| popcnt Rq(def_reg), qword [offset]
|
||||
}
|
||||
break;
|
||||
|.endif
|
||||
}
|
||||
@ -8764,8 +8916,8 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
case IR_SHIFT_CONST:
|
||||
ir_emit_shift_const(ctx, i, insn);
|
||||
break;
|
||||
case IR_CTPOP_POPCNT:
|
||||
ir_emit_ctpop_popcnt(ctx, i, insn);
|
||||
case IR_BIT_COUNT:
|
||||
ir_emit_bit_count(ctx, i, insn);
|
||||
break;
|
||||
case IR_CTPOP:
|
||||
ir_emit_ctpop(ctx, i, insn);
|
||||
|
88
tests/run/ctlz_001.irt
Normal file
88
tests/run/ctlz_001.irt
Normal file
@ -0,0 +1,88 @@
|
||||
--TEST--
|
||||
CTLZ 001:
|
||||
--ARGS--
|
||||
--run
|
||||
--CODE--
|
||||
extern func printf(uintptr_t, ...): int32_t;
|
||||
func ctlz8(int8_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int8_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int8_t d_3 = CTLZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func ctlz16(int16_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int16_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int16_t d_3 = CTLZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func ctlz32(int32_t): int32_t
|
||||
{
|
||||
l_1 = START(l_4);
|
||||
int32_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int32_t d_3 = CTLZ(d_2);
|
||||
l_4 = RETURN(l_1, d_3);
|
||||
}
|
||||
#func ctlz64(int64_t): int32_t
|
||||
#{
|
||||
# l_1 = START(l_5);
|
||||
# int64_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
# int64_t d_3 = CTLZ(d_2);
|
||||
# int32_t d_4 = TRUNC(d_3);
|
||||
# l_5 = RETURN(l_1, d_4);
|
||||
#}
|
||||
func main(void): int32_t
|
||||
{
|
||||
uintptr_t c_1 = 0;
|
||||
bool c_2 = 0;
|
||||
bool c_3 = 1;
|
||||
int8_t c_4 = 1;
|
||||
uintptr_t c_5 = func(ctlz8);
|
||||
int8_t c_6 = 96;
|
||||
int8_t c_7 = -128;
|
||||
uintptr_t c_8 = "u8 : %2d %2d %2d\n";
|
||||
uintptr_t c_9 = func(printf);
|
||||
int16_t c_10 = 1;
|
||||
uintptr_t c_11 = func(ctlz16);
|
||||
int16_t c_12 = 1536;
|
||||
int16_t c_13 = -32768;
|
||||
uintptr_t c_14 = "u16: %2d %2d %2d\n";
|
||||
int32_t c_15 = 1;
|
||||
uintptr_t c_16 = func(ctlz32);
|
||||
int32_t c_17 = 393216;
|
||||
int32_t c_18 = -2147483648;
|
||||
uintptr_t c_19 = "u32: %2d %2d %2d\n";
|
||||
int64_t c_20 = 1;
|
||||
uintptr_t c_21 = func(ctlz64);
|
||||
int64_t c_22 = 25769803776;
|
||||
int64_t c_23 = -9223372036854775808;
|
||||
uintptr_t c_24 = "u64: %2d %2d %2d\n";
|
||||
int32_t c_25 = 0;
|
||||
l_1 = START(l_22);
|
||||
int32_t d_2, l_2 = CALL/1(l_1, c_5, c_4);
|
||||
int32_t d_3, l_3 = CALL/1(l_2, c_5, c_6);
|
||||
int32_t d_4, l_4 = CALL/1(l_3, c_5, c_7);
|
||||
int32_t d_5, l_5 = CALL/4(l_4, c_9, c_8, d_2, d_3, d_4);
|
||||
int32_t d_7, l_7 = CALL/1(l_5, c_11, c_10);
|
||||
int32_t d_8, l_8 = CALL/1(l_7, c_11, c_12);
|
||||
int32_t d_9, l_9 = CALL/1(l_8, c_11, c_13);
|
||||
int32_t d_10, l_10 = CALL/4(l_9, c_9, c_14, d_7, d_8, d_9);
|
||||
int32_t d_12, l_12 = CALL/1(l_10, c_16, c_15);
|
||||
int32_t d_13, l_13 = CALL/1(l_12, c_16, c_17);
|
||||
int32_t d_14, l_14 = CALL/1(l_13, c_16, c_18);
|
||||
int32_t d_15, l_15 = CALL/4(l_14, c_9, c_19, d_12, d_13, d_14);
|
||||
# int32_t d_17, l_17 = CALL/1(l_15, c_21, c_20);
|
||||
# int32_t d_18, l_18 = CALL/1(l_17, c_21, c_22);
|
||||
# int32_t d_19, l_19 = CALL/1(l_18, c_21, c_23);
|
||||
# int32_t d_20, l_20 = CALL/4(l_19, c_9, c_24, d_17, d_18, d_19);
|
||||
# l_22 = RETURN(l_20, c_25);
|
||||
l_22 = RETURN(l_15, c_25);
|
||||
}
|
||||
--EXPECT--
|
||||
u8 : 7 1 0
|
||||
u16: 15 5 0
|
||||
u32: 31 13 0
|
90
tests/run/ctlz_002.irt
Normal file
90
tests/run/ctlz_002.irt
Normal file
@ -0,0 +1,90 @@
|
||||
--TEST--
|
||||
CTLZ 002: -mno-bmi1
|
||||
--TARGET--
|
||||
x86_64
|
||||
--ARGS--
|
||||
-mno-bmi1 --run
|
||||
--CODE--
|
||||
extern func printf(uintptr_t, ...): int32_t;
|
||||
func ctlz8(int8_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int8_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int8_t d_3 = CTLZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func ctlz16(int16_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int16_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int16_t d_3 = CTLZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func ctlz32(int32_t): int32_t
|
||||
{
|
||||
l_1 = START(l_4);
|
||||
int32_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int32_t d_3 = CTLZ(d_2);
|
||||
l_4 = RETURN(l_1, d_3);
|
||||
}
|
||||
func ctlz64(int64_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int64_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int64_t d_3 = CTLZ(d_2);
|
||||
int32_t d_4 = TRUNC(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func main(void): int32_t
|
||||
{
|
||||
uintptr_t c_1 = 0;
|
||||
bool c_2 = 0;
|
||||
bool c_3 = 1;
|
||||
int8_t c_4 = 1;
|
||||
uintptr_t c_5 = func(ctlz8);
|
||||
int8_t c_6 = 96;
|
||||
int8_t c_7 = -128;
|
||||
uintptr_t c_8 = "u8 : %2d %2d %2d\n";
|
||||
uintptr_t c_9 = func(printf);
|
||||
int16_t c_10 = 1;
|
||||
uintptr_t c_11 = func(ctlz16);
|
||||
int16_t c_12 = 1536;
|
||||
int16_t c_13 = -32768;
|
||||
uintptr_t c_14 = "u16: %2d %2d %2d\n";
|
||||
int32_t c_15 = 1;
|
||||
uintptr_t c_16 = func(ctlz32);
|
||||
int32_t c_17 = 393216;
|
||||
int32_t c_18 = -2147483648;
|
||||
uintptr_t c_19 = "u32: %2d %2d %2d\n";
|
||||
int64_t c_20 = 1;
|
||||
uintptr_t c_21 = func(ctlz64);
|
||||
int64_t c_22 = 25769803776;
|
||||
int64_t c_23 = -9223372036854775808;
|
||||
uintptr_t c_24 = "u64: %2d %2d %2d\n";
|
||||
int32_t c_25 = 0;
|
||||
l_1 = START(l_22);
|
||||
int32_t d_2, l_2 = CALL/1(l_1, c_5, c_4);
|
||||
int32_t d_3, l_3 = CALL/1(l_2, c_5, c_6);
|
||||
int32_t d_4, l_4 = CALL/1(l_3, c_5, c_7);
|
||||
int32_t d_5, l_5 = CALL/4(l_4, c_9, c_8, d_2, d_3, d_4);
|
||||
int32_t d_7, l_7 = CALL/1(l_5, c_11, c_10);
|
||||
int32_t d_8, l_8 = CALL/1(l_7, c_11, c_12);
|
||||
int32_t d_9, l_9 = CALL/1(l_8, c_11, c_13);
|
||||
int32_t d_10, l_10 = CALL/4(l_9, c_9, c_14, d_7, d_8, d_9);
|
||||
int32_t d_12, l_12 = CALL/1(l_10, c_16, c_15);
|
||||
int32_t d_13, l_13 = CALL/1(l_12, c_16, c_17);
|
||||
int32_t d_14, l_14 = CALL/1(l_13, c_16, c_18);
|
||||
int32_t d_15, l_15 = CALL/4(l_14, c_9, c_19, d_12, d_13, d_14);
|
||||
int32_t d_17, l_17 = CALL/1(l_15, c_21, c_20);
|
||||
int32_t d_18, l_18 = CALL/1(l_17, c_21, c_22);
|
||||
int32_t d_19, l_19 = CALL/1(l_18, c_21, c_23);
|
||||
int32_t d_20, l_20 = CALL/4(l_19, c_9, c_24, d_17, d_18, d_19);
|
||||
l_22 = RETURN(l_20, c_25);
|
||||
}
|
||||
--EXPECT--
|
||||
u8 : 7 1 0
|
||||
u16: 15 5 0
|
||||
u32: 31 13 0
|
||||
u64: 63 29 0
|
@ -1,9 +1,9 @@
|
||||
--TEST--
|
||||
CTPOP 002:
|
||||
CTPOP 002: -mno-bmi1
|
||||
--TARGET--
|
||||
x86_64
|
||||
--ARGS--
|
||||
-mno-sse41 --run
|
||||
-mno-bmi1 --run
|
||||
--CODE--
|
||||
extern func printf(uintptr_t, ...): int32_t;
|
||||
func ctpop8(int8_t): int32_t
|
||||
|
88
tests/run/cttz_001.irt
Normal file
88
tests/run/cttz_001.irt
Normal file
@ -0,0 +1,88 @@
|
||||
--TEST--
|
||||
CTTZ 001:
|
||||
--ARGS--
|
||||
--run
|
||||
--CODE--
|
||||
extern func printf(uintptr_t, ...): int32_t;
|
||||
func cttz8(int8_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int8_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int8_t d_3 = CTTZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func cttz16(int16_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int16_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int16_t d_3 = CTTZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func cttz32(int32_t): int32_t
|
||||
{
|
||||
l_1 = START(l_4);
|
||||
int32_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int32_t d_3 = CTTZ(d_2);
|
||||
l_4 = RETURN(l_1, d_3);
|
||||
}
|
||||
#func cttz64(int64_t): int32_t
|
||||
#{
|
||||
# l_1 = START(l_5);
|
||||
# int64_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
# int64_t d_3 = CTTZ(d_2);
|
||||
# int32_t d_4 = TRUNC(d_3);
|
||||
# l_5 = RETURN(l_1, d_4);
|
||||
#}
|
||||
func main(void): int32_t
|
||||
{
|
||||
uintptr_t c_1 = 0;
|
||||
bool c_2 = 0;
|
||||
bool c_3 = 1;
|
||||
int8_t c_4 = 1;
|
||||
uintptr_t c_5 = func(cttz8);
|
||||
int8_t c_6 = 96;
|
||||
int8_t c_7 = -128;
|
||||
uintptr_t c_8 = "u8 : %2d %2d %2d\n";
|
||||
uintptr_t c_9 = func(printf);
|
||||
int16_t c_10 = 1;
|
||||
uintptr_t c_11 = func(cttz16);
|
||||
int16_t c_12 = 1536;
|
||||
int16_t c_13 = -32768;
|
||||
uintptr_t c_14 = "u16: %2d %2d %2d\n";
|
||||
int32_t c_15 = 1;
|
||||
uintptr_t c_16 = func(cttz32);
|
||||
int32_t c_17 = 393216;
|
||||
int32_t c_18 = -2147483648;
|
||||
uintptr_t c_19 = "u32: %2d %2d %2d\n";
|
||||
int64_t c_20 = 1;
|
||||
uintptr_t c_21 = func(cttz64);
|
||||
int64_t c_22 = 25769803776;
|
||||
int64_t c_23 = -9223372036854775808;
|
||||
uintptr_t c_24 = "u64: %2d %2d %2d\n";
|
||||
int32_t c_25 = 0;
|
||||
l_1 = START(l_22);
|
||||
int32_t d_2, l_2 = CALL/1(l_1, c_5, c_4);
|
||||
int32_t d_3, l_3 = CALL/1(l_2, c_5, c_6);
|
||||
int32_t d_4, l_4 = CALL/1(l_3, c_5, c_7);
|
||||
int32_t d_5, l_5 = CALL/4(l_4, c_9, c_8, d_2, d_3, d_4);
|
||||
int32_t d_7, l_7 = CALL/1(l_5, c_11, c_10);
|
||||
int32_t d_8, l_8 = CALL/1(l_7, c_11, c_12);
|
||||
int32_t d_9, l_9 = CALL/1(l_8, c_11, c_13);
|
||||
int32_t d_10, l_10 = CALL/4(l_9, c_9, c_14, d_7, d_8, d_9);
|
||||
int32_t d_12, l_12 = CALL/1(l_10, c_16, c_15);
|
||||
int32_t d_13, l_13 = CALL/1(l_12, c_16, c_17);
|
||||
int32_t d_14, l_14 = CALL/1(l_13, c_16, c_18);
|
||||
int32_t d_15, l_15 = CALL/4(l_14, c_9, c_19, d_12, d_13, d_14);
|
||||
# int32_t d_17, l_17 = CALL/1(l_15, c_21, c_20);
|
||||
# int32_t d_18, l_18 = CALL/1(l_17, c_21, c_22);
|
||||
# int32_t d_19, l_19 = CALL/1(l_18, c_21, c_23);
|
||||
# int32_t d_20, l_20 = CALL/4(l_19, c_9, c_24, d_17, d_18, d_19);
|
||||
# l_22 = RETURN(l_20, c_25);
|
||||
l_22 = RETURN(l_15, c_25);
|
||||
}
|
||||
--EXPECT--
|
||||
u8 : 0 5 7
|
||||
u16: 0 9 15
|
||||
u32: 0 17 31
|
90
tests/run/cttz_002.irt
Normal file
90
tests/run/cttz_002.irt
Normal file
@ -0,0 +1,90 @@
|
||||
--TEST--
|
||||
CTTZ 002: -mno-bmi1
|
||||
--TARGET--
|
||||
x86_64
|
||||
--ARGS--
|
||||
-mno-bmi1 --run
|
||||
--CODE--
|
||||
extern func printf(uintptr_t, ...): int32_t;
|
||||
func cttz8(int8_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int8_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int8_t d_3 = CTTZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func cttz16(int16_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int16_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int16_t d_3 = CTTZ(d_2);
|
||||
int32_t d_4 = ZEXT(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func cttz32(int32_t): int32_t
|
||||
{
|
||||
l_1 = START(l_4);
|
||||
int32_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int32_t d_3 = CTTZ(d_2);
|
||||
l_4 = RETURN(l_1, d_3);
|
||||
}
|
||||
func cttz64(int64_t): int32_t
|
||||
{
|
||||
l_1 = START(l_5);
|
||||
int64_t d_2 = PARAM(l_1, "arg_1", 1);
|
||||
int64_t d_3 = CTTZ(d_2);
|
||||
int32_t d_4 = TRUNC(d_3);
|
||||
l_5 = RETURN(l_1, d_4);
|
||||
}
|
||||
func main(void): int32_t
|
||||
{
|
||||
uintptr_t c_1 = 0;
|
||||
bool c_2 = 0;
|
||||
bool c_3 = 1;
|
||||
int8_t c_4 = 1;
|
||||
uintptr_t c_5 = func(cttz8);
|
||||
int8_t c_6 = 96;
|
||||
int8_t c_7 = -128;
|
||||
uintptr_t c_8 = "u8 : %2d %2d %2d\n";
|
||||
uintptr_t c_9 = func(printf);
|
||||
int16_t c_10 = 1;
|
||||
uintptr_t c_11 = func(cttz16);
|
||||
int16_t c_12 = 1536;
|
||||
int16_t c_13 = -32768;
|
||||
uintptr_t c_14 = "u16: %2d %2d %2d\n";
|
||||
int32_t c_15 = 1;
|
||||
uintptr_t c_16 = func(cttz32);
|
||||
int32_t c_17 = 393216;
|
||||
int32_t c_18 = -2147483648;
|
||||
uintptr_t c_19 = "u32: %2d %2d %2d\n";
|
||||
int64_t c_20 = 1;
|
||||
uintptr_t c_21 = func(cttz64);
|
||||
int64_t c_22 = 25769803776;
|
||||
int64_t c_23 = -9223372036854775808;
|
||||
uintptr_t c_24 = "u64: %2d %2d %2d\n";
|
||||
int32_t c_25 = 0;
|
||||
l_1 = START(l_22);
|
||||
int32_t d_2, l_2 = CALL/1(l_1, c_5, c_4);
|
||||
int32_t d_3, l_3 = CALL/1(l_2, c_5, c_6);
|
||||
int32_t d_4, l_4 = CALL/1(l_3, c_5, c_7);
|
||||
int32_t d_5, l_5 = CALL/4(l_4, c_9, c_8, d_2, d_3, d_4);
|
||||
int32_t d_7, l_7 = CALL/1(l_5, c_11, c_10);
|
||||
int32_t d_8, l_8 = CALL/1(l_7, c_11, c_12);
|
||||
int32_t d_9, l_9 = CALL/1(l_8, c_11, c_13);
|
||||
int32_t d_10, l_10 = CALL/4(l_9, c_9, c_14, d_7, d_8, d_9);
|
||||
int32_t d_12, l_12 = CALL/1(l_10, c_16, c_15);
|
||||
int32_t d_13, l_13 = CALL/1(l_12, c_16, c_17);
|
||||
int32_t d_14, l_14 = CALL/1(l_13, c_16, c_18);
|
||||
int32_t d_15, l_15 = CALL/4(l_14, c_9, c_19, d_12, d_13, d_14);
|
||||
int32_t d_17, l_17 = CALL/1(l_15, c_21, c_20);
|
||||
int32_t d_18, l_18 = CALL/1(l_17, c_21, c_22);
|
||||
int32_t d_19, l_19 = CALL/1(l_18, c_21, c_23);
|
||||
int32_t d_20, l_20 = CALL/4(l_19, c_9, c_24, d_17, d_18, d_19);
|
||||
l_22 = RETURN(l_20, c_25);
|
||||
}
|
||||
--EXPECT--
|
||||
u8 : 0 5 7
|
||||
u16: 0 9 15
|
||||
u32: 0 17 31
|
||||
u64: 0 33 63
|
Loading…
Reference in New Issue
Block a user