mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
v: optimize literal string comparison (match
, in
and ==
) (#22643)
This commit is contained in:
parent
f715d49156
commit
4e9f7c21aa
3 changed files with 53 additions and 12 deletions
|
@ -220,11 +220,11 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
|
|||
if field.typ.has_flag(.option) {
|
||||
left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ)
|
||||
right_arg_opt := g.read_opt_field(left_type, field_name, 'b', field.typ)
|
||||
fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || string__eq(${left_arg_opt}, ${right_arg_opt}))')
|
||||
fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || fast_string_eq(${left_arg_opt}, ${right_arg_opt}))')
|
||||
} else if field.typ.is_ptr() {
|
||||
fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || string__eq(*(${left_arg}), *(${right_arg})))')
|
||||
fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || fast_string_eq(*(${left_arg}), *(${right_arg})))')
|
||||
} else {
|
||||
fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || string__eq(${left_arg}, ${right_arg}))')
|
||||
fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || fast_string_eq(${left_arg}, ${right_arg}))')
|
||||
}
|
||||
} else if field_type.sym.kind == .sum_type && !field.typ.is_ptr() {
|
||||
eq_fn := g.gen_sumtype_equality_fn(field.typ)
|
||||
|
@ -294,7 +294,7 @@ fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string {
|
|||
if info.parent_type.has_flag(.option) {
|
||||
left_var = '*' + g.read_opt(info.parent_type, 'a')
|
||||
right_var = '*' + g.read_opt(info.parent_type, 'b')
|
||||
fn_builder.writeln('\treturn ((${left_var}).len == (${right_var}).len && (${left_var}).len == 0) || string__eq(${left_var}, ${right_var});')
|
||||
fn_builder.writeln('\treturn ((${left_var}).len == (${right_var}).len && (${left_var}).len == 0) || fast_string_eq(${left_var}, ${right_var});')
|
||||
} else {
|
||||
fn_builder.writeln('\treturn string__eq(a, b);')
|
||||
}
|
||||
|
|
|
@ -129,7 +129,8 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
|||
g.gen_plain_infix_expr(node)
|
||||
} else if (left.typ.idx() == ast.string_type_idx || (!has_defined_eq_operator
|
||||
&& left.unaliased.idx() == ast.string_type_idx)) && node.right is ast.StringLiteral
|
||||
&& (node.right.val == '' || (node.left is ast.Ident && node.left.or_expr.kind == .absent)) {
|
||||
&& (node.right.val == '' || (node.left is ast.SelectorExpr
|
||||
|| (node.left is ast.Ident && node.left.or_expr.kind == .absent))) {
|
||||
if node.right.val == '' {
|
||||
// `str == ''` -> `str.len == 0` optimization
|
||||
g.write('(')
|
||||
|
@ -137,7 +138,7 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
|||
g.write(')')
|
||||
arrow := if left.typ.is_ptr() { '->' } else { '.' }
|
||||
g.write('${arrow}len ${node.op} 0')
|
||||
} else {
|
||||
} else if node.left is ast.Ident {
|
||||
// vmemcmp(left, "str", sizeof("str")) optimization
|
||||
slit := cescape_nonascii(util.smart_quote(node.right.val, node.right.is_raw))
|
||||
var := g.expr_string(node.left)
|
||||
|
@ -147,6 +148,17 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
|||
} else {
|
||||
g.write('_SLIT_NE(${var}${arrow}str, ${var}${arrow}len, "${slit}")')
|
||||
}
|
||||
} else {
|
||||
// fast_string_eq optimization for string selector comparison to literals
|
||||
if node.op == .ne {
|
||||
g.write('!fast_string_eq(')
|
||||
} else {
|
||||
g.write('fast_string_eq(')
|
||||
}
|
||||
g.expr(node.left)
|
||||
g.write(', ')
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
}
|
||||
} else if has_defined_eq_operator {
|
||||
if node.op == .ne {
|
||||
|
@ -636,8 +648,26 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, right ast.ArrayInit) {
|
|||
match elem_sym.kind {
|
||||
.string, .alias, .sum_type, .map, .interface, .array, .struct {
|
||||
if elem_sym.kind == .string {
|
||||
g.write('string__eq(')
|
||||
if left.is_auto_deref_var() || (left is ast.Ident && left.info is ast.IdentVar
|
||||
is_auto_deref_var := left.is_auto_deref_var()
|
||||
if left is ast.Ident && left.or_expr.kind == .absent
|
||||
&& array_expr is ast.StringLiteral {
|
||||
var := g.expr_string(left)
|
||||
slit := cescape_nonascii(util.smart_quote(array_expr.val, array_expr.is_raw))
|
||||
if is_auto_deref_var || (left.info is ast.IdentVar
|
||||
&& g.table.sym(left.obj.typ).kind in [.interface, .sum_type]) {
|
||||
g.write('_SLIT_EQ(${var}->str, ${var}->len, "${slit}")')
|
||||
} else {
|
||||
g.write('_SLIT_EQ(${var}.str, ${var}.len, "${slit}")')
|
||||
}
|
||||
unsafe {
|
||||
goto end
|
||||
}
|
||||
} else if array_expr is ast.StringLiteral {
|
||||
g.write('fast_string_eq(')
|
||||
} else {
|
||||
g.write('string__eq(')
|
||||
}
|
||||
if is_auto_deref_var || (left is ast.Ident && left.info is ast.IdentVar
|
||||
&& g.table.sym(left.obj.typ).kind in [.interface, .sum_type]) {
|
||||
g.write('*')
|
||||
}
|
||||
|
@ -668,6 +698,7 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, right ast.ArrayInit) {
|
|||
g.expr(array_expr)
|
||||
}
|
||||
}
|
||||
end:
|
||||
if i < right.exprs.len - 1 {
|
||||
g.write(' || ')
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module c
|
||||
|
||||
import v.ast
|
||||
import v.util
|
||||
|
||||
fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool {
|
||||
if node.is_expr && node.return_type != ast.void_type && node.return_type != 0 {
|
||||
|
@ -491,10 +492,19 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
|||
g.write(')')
|
||||
}
|
||||
.string {
|
||||
ptr_str := if node.cond_type.is_ptr() { '*' } else { '' }
|
||||
g.write('string__eq(${ptr_str}${cond_var}, ')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
if expr is ast.StringLiteral {
|
||||
slit := cescape_nonascii(util.smart_quote(expr.val, expr.is_raw))
|
||||
if node.cond_type.is_ptr() {
|
||||
g.write('_SLIT_EQ(${cond_var}->str, ${cond_var}->len, "${slit}")')
|
||||
} else {
|
||||
g.write('_SLIT_EQ(${cond_var}.str, ${cond_var}.len, "${slit}")')
|
||||
}
|
||||
} else {
|
||||
ptr_str := if node.cond_type.is_ptr() { '*' } else { '' }
|
||||
g.write('fast_string_eq(${ptr_str}${cond_var}, ')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
}
|
||||
.struct {
|
||||
derefs_expr := '*'.repeat(g.get_expr_type(expr).nr_muls())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue