Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
c1cbef15
Commit
c1cbef15
authored
Sep 03, 2015
by
Andreas Fried
Browse files
amd64: Implement builtins clz, ctz and ffs.
parent
7cf96ad6
Changes
6
Show whitespace changes
Inline
Side-by-side
ir/be/amd64/amd64_emitter.c
View file @
c1cbef15
...
@@ -389,19 +389,6 @@ emit_reg_in0:;
...
@@ -389,19 +389,6 @@ emit_reg_in0:;
panic
(
"invalid op_mode"
);
panic
(
"invalid op_mode"
);
}
}
static
amd64_insn_mode_t
get_amd64_insn_mode
(
const
ir_node
*
node
)
{
if
(
is_amd64_mov_imm
(
node
))
{
const
amd64_movimm_attr_t
*
const
attr
=
get_amd64_movimm_attr_const
(
node
);
return
attr
->
insn_mode
;
}
else
{
amd64_addr_attr_t
const
*
const
attr
=
get_amd64_addr_attr_const
(
node
);
return
attr
->
insn_mode
;
}
}
static
void
emit_shiftop
(
const
ir_node
*
const
node
)
static
void
emit_shiftop
(
const
ir_node
*
const
node
)
{
{
amd64_shift_attr_t
const
*
const
attr
=
get_amd64_shift_attr_const
(
node
);
amd64_shift_attr_t
const
*
const
attr
=
get_amd64_shift_attr_const
(
node
);
...
...
ir/be/amd64/amd64_finish.c
View file @
c1cbef15
...
@@ -58,19 +58,6 @@ static bool try_swap_inputs(ir_node *node)
...
@@ -58,19 +58,6 @@ static bool try_swap_inputs(ir_node *node)
return
false
;
return
false
;
}
}
static
int
get_insn_mode_bits
(
amd64_insn_mode_t
insn_mode
)
{
switch
(
insn_mode
)
{
case
INSN_MODE_8
:
return
8
;
case
INSN_MODE_16
:
return
16
;
case
INSN_MODE_32
:
return
32
;
case
INSN_MODE_64
:
return
64
;
case
INSN_MODE_128
:
return
128
;
case
INSN_MODE_INVALID
:
default:
panic
(
"bad insn mode"
);
}
}
/**
/**
* Transforms a Sub to a Neg + Add, which subsequently allows swapping
* Transforms a Sub to a Neg + Add, which subsequently allows swapping
* of the inputs. The swapping is also (implicitly) done here.
* of the inputs. The swapping is also (implicitly) done here.
...
...
ir/be/amd64/amd64_new_nodes.c
View file @
c1cbef15
...
@@ -29,6 +29,36 @@
...
@@ -29,6 +29,36 @@
#include "bearch_amd64_t.h"
#include "bearch_amd64_t.h"
#include "gen_amd64_regalloc_if.h"
#include "gen_amd64_regalloc_if.h"
amd64_insn_mode_t
get_amd64_insn_mode
(
const
ir_node
*
node
)
{
if
(
is_amd64_mov_imm
(
node
))
{
const
amd64_movimm_attr_t
*
const
attr
=
get_amd64_movimm_attr_const
(
node
);
return
attr
->
insn_mode
;
}
else
if
(
amd64_has_addr_attr
(
node
))
{
amd64_addr_attr_t
const
*
const
attr
=
get_amd64_addr_attr_const
(
node
);
return
attr
->
insn_mode
;
}
else
if
(
amd64_has_cc_attr
(
node
))
{
amd64_cc_attr_t
const
*
const
attr
=
get_amd64_cc_attr_const
(
node
);
return
attr
->
insn_mode
;
}
else
{
panic
(
"Node attributes do not contain insn_mode"
);
}
}
int
get_insn_mode_bits
(
amd64_insn_mode_t
insn_mode
)
{
switch
(
insn_mode
)
{
case
INSN_MODE_8
:
return
8
;
case
INSN_MODE_16
:
return
16
;
case
INSN_MODE_32
:
return
32
;
case
INSN_MODE_64
:
return
64
;
case
INSN_MODE_128
:
return
128
;
case
INSN_MODE_INVALID
:
default:
panic
(
"bad insn mode"
);
}
}
static
const
char
*
get_op_mode_string
(
amd64_op_mode_t
mode
)
static
const
char
*
get_op_mode_string
(
amd64_op_mode_t
mode
)
{
{
switch
(
mode
)
{
switch
(
mode
)
{
...
...
ir/be/amd64/amd64_new_nodes.h
View file @
c1cbef15
...
@@ -149,6 +149,9 @@ static inline amd64_call_addr_attr_t *get_amd64_call_addr_attr (ir_node *node)
...
@@ -149,6 +149,9 @@ static inline amd64_call_addr_attr_t *get_amd64_call_addr_attr (ir_node *node)
return
(
amd64_call_addr_attr_t
*
)
get_irn_generic_attr
(
node
);
return
(
amd64_call_addr_attr_t
*
)
get_irn_generic_attr
(
node
);
}
}
amd64_insn_mode_t
get_amd64_insn_mode
(
const
ir_node
*
node
);
int
get_insn_mode_bits
(
amd64_insn_mode_t
insn_mode
);
/* Include the generated headers */
/* Include the generated headers */
#include "gen_amd64_new_nodes.h"
#include "gen_amd64_new_nodes.h"
...
...
ir/be/amd64/amd64_transform.c
View file @
c1cbef15
...
@@ -274,7 +274,7 @@ static amd64_insn_mode_t get_insn_mode_from_mode(const ir_mode *mode)
...
@@ -274,7 +274,7 @@ static amd64_insn_mode_t get_insn_mode_from_mode(const ir_mode *mode)
case
64
:
return
INSN_MODE_64
;
case
64
:
return
INSN_MODE_64
;
case
128
:
return
INSN_MODE_128
;
case
128
:
return
INSN_MODE_128
;
}
}
panic
(
"unexpected mode
"
);
panic
(
"unexpected mode
%+F"
,
mode
);
}
}
ir_entity
*
create_float_const_entity
(
ir_tarval
*
const
tv
)
ir_entity
*
create_float_const_entity
(
ir_tarval
*
const
tv
)
...
@@ -1211,6 +1211,26 @@ static ir_node *gen_unop(ir_node *const node, int op_pos, unop_constructor gen,
...
@@ -1211,6 +1211,26 @@ static ir_node *gen_unop(ir_node *const node, int op_pos, unop_constructor gen,
return
be_new_Proj
(
new_node
,
pn_res
);
return
be_new_Proj
(
new_node
,
pn_res
);
}
}
typedef
ir_node
*
(
*
unop_out_constructor
)(
dbg_info
*
,
ir_node
*
block
,
ir_node
*
op
,
amd64_insn_mode_t
insn_mode
,
amd64_op_mode_t
opmode
,
amd64_addr_t
addr
);
static
ir_node
*
gen_unop_out
(
ir_node
*
const
node
,
int
op_pos
,
unop_out_constructor
gen
,
unsigned
pn_res
)
{
dbg_info
*
const
dbgi
=
get_irn_dbg_info
(
node
);
ir_node
*
const
block
=
be_transform_nodes_block
(
node
);
ir_node
*
const
op
=
get_irn_n
(
node
,
op_pos
);
ir_node
*
const
new_op
=
be_transform_node
(
op
);
ir_mode
*
const
op_mode
=
get_irn_mode
(
op
);
// TODO match_am
amd64_addr_t
const
addr
=
{
.
immediate
=
{
.
entity
=
NULL
,
},
};
amd64_insn_mode_t
insn_mode
=
get_insn_mode_from_mode
(
op_mode
);
ir_node
*
new_node
=
gen
(
dbgi
,
block
,
new_op
,
insn_mode
,
AMD64_OP_OUTREG_REG
,
addr
);
return
be_new_Proj
(
new_node
,
pn_res
);
}
/** Create a floating point negation by switching the sign bit using a xor.
/** Create a floating point negation by switching the sign bit using a xor.
*/
*/
static
ir_node
*
gen_float_neg
(
ir_node
*
const
node
)
static
ir_node
*
gen_float_neg
(
ir_node
*
const
node
)
...
@@ -2342,6 +2362,119 @@ static ir_node *gen_Proj_Alloc(ir_node *node)
...
@@ -2342,6 +2362,119 @@ static ir_node *gen_Proj_Alloc(ir_node *node)
panic
(
"invalid Proj->Alloc"
);
panic
(
"invalid Proj->Alloc"
);
}
}
static
ir_node
*
gen_clz
(
ir_node
*
node
)
{
ir_node
*
bsr
=
gen_unop_out
(
node
,
n_Builtin_max
+
1
,
new_bd_amd64_bsr
,
pn_amd64_bsr_res
);
ir_node
*
real
=
skip_Proj
(
bsr
);
dbg_info
*
dbgi
=
get_irn_dbg_info
(
real
);
ir_node
*
block
=
get_nodes_block
(
real
);
amd64_insn_mode_t
insn_mode
=
get_amd64_insn_mode
(
real
);
size_t
mask
=
get_insn_mode_bits
(
insn_mode
)
-
1
;
ir_node
*
in
[]
=
{
bsr
};
amd64_binop_addr_attr_t
attr
=
{
.
base
=
{
.
base
=
{
.
op_mode
=
AMD64_OP_REG_IMM
,
},
.
insn_mode
=
insn_mode
,
.
addr
=
{
.
immediate
=
{
.
entity
=
NULL
,
},
},
},
.
u
=
{
.
immediate
=
{
.
entity
=
NULL
,
.
offset
=
mask
,
},
},
};
ir_node
*
xor
=
new_bd_amd64_xor
(
dbgi
,
block
,
ARRAY_SIZE
(
in
),
in
,
reg_reqs
,
&
attr
);
return
be_new_Proj
(
xor
,
pn_amd64_xor_res
);
}
static
ir_node
*
gen_ctz
(
ir_node
*
node
)
{
return
gen_unop_out
(
node
,
n_Builtin_max
+
1
,
new_bd_amd64_bsf
,
pn_amd64_bsf_res
);
}
static
ir_node
*
gen_ffs
(
ir_node
*
node
)
{
/* bsf input, result */
ir_node
*
bsf_res
=
gen_unop_out
(
node
,
n_Builtin_max
+
1
,
new_bd_amd64_bsf
,
pn_amd64_bsf_res
);
ir_node
*
bsf
=
skip_Proj
(
bsf_res
);
/* seteq temp */
dbg_info
*
dbgi
=
get_irn_dbg_info
(
bsf
);
ir_node
*
block
=
get_nodes_block
(
bsf
);
ir_node
*
flags
=
be_new_Proj
(
bsf
,
pn_amd64_bsf_flags
);
ir_node
*
setcc
=
new_bd_amd64_setcc
(
dbgi
,
block
,
flags
,
x86_cc_equal
);
/* movzbl temp, temp */
ir_node
*
movzbl_in
[]
=
{
setcc
};
amd64_addr_t
movzbl_addr
=
{
.
immediate
=
{
.
entity
=
NULL
,
},
};
ir_node
*
movzbl
=
new_bd_amd64_mov_gp
(
dbgi
,
block
,
ARRAY_SIZE
(
movzbl_in
),
movzbl_in
,
reg_reqs
,
INSN_MODE_8
,
AMD64_OP_REG
,
movzbl_addr
);
ir_node
*
movzbl_res
=
be_new_Proj
(
movzbl
,
pn_amd64_mov_gp_res
);
/* neg temp */
amd64_insn_mode_t
insn_mode
=
get_amd64_insn_mode
(
bsf
);
ir_node
*
neg
=
new_bd_amd64_neg
(
dbgi
,
block
,
movzbl_res
,
insn_mode
);
ir_node
*
neg_res
=
be_new_Proj
(
neg
,
pn_amd64_neg_res
);
/* or temp, result */
ir_node
*
or_in
[]
=
{
neg_res
,
bsf_res
};
amd64_binop_addr_attr_t
or_attr
=
{
.
base
=
{
.
base
=
{
.
op_mode
=
AMD64_OP_REG_REG
,
},
.
insn_mode
=
insn_mode
,
.
addr
=
{
.
immediate
=
{
.
entity
=
NULL
,
},
},
},
.
u
=
{
.
reg_input
=
1
,
},
};
ir_node
*
or
=
new_bd_amd64_or
(
dbgi
,
block
,
ARRAY_SIZE
(
or_in
),
or_in
,
amd64_reg_reg_reqs
,
&
or_attr
);
ir_node
*
or_res
=
be_new_Proj
(
or
,
pn_amd64_or_res
);
/* add $1, result */
ir_node
*
inc_in
[]
=
{
or_res
};
amd64_binop_addr_attr_t
inc_attr
=
{
.
base
=
{
.
base
=
{
.
op_mode
=
AMD64_OP_REG_IMM
,
},
.
insn_mode
=
insn_mode
,
.
addr
=
{
.
immediate
=
{
.
entity
=
NULL
,
},
},
},
.
u
=
{
.
immediate
=
{
.
entity
=
NULL
,
.
offset
=
1
,
},
},
};
ir_node
*
inc
=
new_bd_amd64_add
(
dbgi
,
block
,
ARRAY_SIZE
(
inc_in
),
inc_in
,
reg_reqs
,
&
inc_attr
);
return
be_new_Proj
(
inc
,
pn_amd64_add_res
);
}
static
ir_node
*
gen_saturating_increment
(
ir_node
*
node
)
static
ir_node
*
gen_saturating_increment
(
ir_node
*
node
)
{
{
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
...
@@ -2393,6 +2526,12 @@ static ir_node *gen_Builtin(ir_node *node)
...
@@ -2393,6 +2526,12 @@ static ir_node *gen_Builtin(ir_node *node)
ir_builtin_kind
kind
=
get_Builtin_kind
(
node
);
ir_builtin_kind
kind
=
get_Builtin_kind
(
node
);
switch
(
kind
)
{
switch
(
kind
)
{
case
ir_bk_clz
:
return
gen_clz
(
node
);
case
ir_bk_ctz
:
return
gen_ctz
(
node
);
case
ir_bk_ffs
:
return
gen_ffs
(
node
);
case
ir_bk_saturating_increment
:
case
ir_bk_saturating_increment
:
return
gen_saturating_increment
(
node
);
return
gen_saturating_increment
(
node
);
case
ir_bk_va_start
:
case
ir_bk_va_start
:
...
@@ -2410,6 +2549,11 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
...
@@ -2410,6 +2549,11 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
ir_builtin_kind
kind
=
get_Builtin_kind
(
node
);
ir_builtin_kind
kind
=
get_Builtin_kind
(
node
);
switch
(
kind
)
{
switch
(
kind
)
{
case
ir_bk_clz
:
case
ir_bk_ctz
:
case
ir_bk_ffs
:
case
ir_bk_parity
:
return
new_node
;
case
ir_bk_saturating_increment
:
case
ir_bk_saturating_increment
:
return
be_new_Proj
(
new_node
,
pn_amd64_sbb_res
);
return
be_new_Proj
(
new_node
,
pn_amd64_sbb_res
);
case
ir_bk_va_start
:
case
ir_bk_va_start
:
...
...
ir/be/amd64/bearch_amd64.c
View file @
c1cbef15
...
@@ -714,8 +714,11 @@ static void amd64_lower_for_target(void)
...
@@ -714,8 +714,11 @@ static void amd64_lower_for_target(void)
be_after_transform
(
irg
,
"lower-copyb"
);
be_after_transform
(
irg
,
"lower-copyb"
);
}
}
ir_builtin_kind
supported
[
2
];
ir_builtin_kind
supported
[
5
];
size_t
s
=
0
;
size_t
s
=
0
;
supported
[
s
++
]
=
ir_bk_ffs
;
supported
[
s
++
]
=
ir_bk_clz
;
supported
[
s
++
]
=
ir_bk_ctz
;
supported
[
s
++
]
=
ir_bk_saturating_increment
;
supported
[
s
++
]
=
ir_bk_saturating_increment
;
supported
[
s
++
]
=
ir_bk_va_start
;
supported
[
s
++
]
=
ir_bk_va_start
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment