mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v: add compiler support for _unlikely_(x) too
This commit is contained in:
parent
c7d4360931
commit
4fc41c4bc4
@ -1700,6 +1700,9 @@ boolean expression is very likely to be true, so it can generate assembly
|
||||
code, with less chance of branch misprediction. In the JS backend,
|
||||
that does nothing.
|
||||
|
||||
`if _unlikely_(bool expression) {` similar to `_likely_(x)`, but it hints that
|
||||
the boolean expression is highly improbable. In the JS backend, that does nothing.
|
||||
|
||||
## Reflection via codegen
|
||||
|
||||
Having built-in JSON support is nice, but V also allows you to create efficient
|
||||
|
@ -759,6 +759,7 @@ pub struct Likely {
|
||||
pub:
|
||||
expr Expr
|
||||
pos token.Position
|
||||
is_likely bool // false for _unlikely_
|
||||
}
|
||||
|
||||
pub struct TypeOf {
|
||||
|
@ -1948,7 +1948,8 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||
ltype := c.expr(it.expr)
|
||||
if !c.check_types(ltype, table.bool_type) {
|
||||
ltype_sym := c.table.get_type_symbol(ltype)
|
||||
c.error('`_likely_()` expects a boolean expression, instead it got `${ltype_sym.name}`', it.pos)
|
||||
lname := if it.is_likely { '_likely_' } else { '_unlikely_' }
|
||||
c.error('`${lname}()` expects a boolean expression, instead it got `${ltype_sym.name}`', it.pos)
|
||||
}
|
||||
return table.bool_type
|
||||
}
|
||||
|
@ -735,7 +735,12 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||
f.write(')')
|
||||
}
|
||||
ast.Likely {
|
||||
f.write('_likely_(')
|
||||
if it.is_likely {
|
||||
f.write('_likely_')
|
||||
} else {
|
||||
f.write('_unlikely_')
|
||||
}
|
||||
f.write('(')
|
||||
f.expr(it.expr)
|
||||
f.write(')')
|
||||
}
|
||||
|
@ -1587,7 +1587,12 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.typeof_expr(it)
|
||||
}
|
||||
ast.Likely {
|
||||
g.write('_likely_(')
|
||||
if it.is_likely {
|
||||
g.write('_likely_')
|
||||
} else {
|
||||
g.write('_unlikely_')
|
||||
}
|
||||
g.write('(')
|
||||
g.expr(it.expr)
|
||||
g.write(')')
|
||||
}
|
||||
|
@ -255,8 +255,10 @@ void _vcleanup();
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) || defined(__TINYC__)
|
||||
#define _likely_(x) __builtin_expect(x, 1)
|
||||
#define _unlikely_(x) __builtin_expect((x), 0)
|
||||
#else
|
||||
#define _likely_(x) (x)
|
||||
#define _unlikely_(x) (x)
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_ORDER_IS_LITTLE)
|
||||
|
@ -103,7 +103,8 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||
expr: expr
|
||||
}
|
||||
}
|
||||
.key_likely {
|
||||
.key_likely, .key_unlikely {
|
||||
is_likely := p.tok.kind == .key_likely
|
||||
p.next()
|
||||
p.check(.lpar)
|
||||
lpos := p.tok.position()
|
||||
@ -112,6 +113,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||
node = ast.Likely{
|
||||
expr: expr
|
||||
pos: lpos
|
||||
is_likely: is_likely
|
||||
}
|
||||
}
|
||||
.lcbr {
|
||||
|
@ -1,24 +1,32 @@
|
||||
// _likely_(expr) should be compilable, and it should return the expr
|
||||
|
||||
fn test_likely_type(){
|
||||
fn test_likely_type() {
|
||||
assert typeof(_likely_(false)) == 'bool'
|
||||
}
|
||||
|
||||
fn test_likely(){
|
||||
if _likely_(2<10) {
|
||||
assert _likely_(false) == false
|
||||
assert _likely_(true) == true
|
||||
}
|
||||
|
||||
fn test_likely() {
|
||||
if _likely_(2 < 10) {
|
||||
assert true
|
||||
eprintln('ok, happens every time')
|
||||
} else {
|
||||
eprintln('happens *infrequently*')
|
||||
assert false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_likely_returns_the_value_of_its_bool_argument(){
|
||||
fn test_likely_returns_the_value_of_its_bool_argument() {
|
||||
i := 123
|
||||
if _likely_(i<2) {
|
||||
if _likely_(i < 2) {
|
||||
assert false
|
||||
} else {
|
||||
assert true
|
||||
}
|
||||
}
|
||||
|
||||
// _unlikely_ is the same as _likely_ from the V point of view:
|
||||
fn test_unlikely_type() {
|
||||
assert typeof(_unlikely_(false)) == 'bool'
|
||||
assert _unlikely_(false) == false
|
||||
assert _unlikely_(true) == true
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ pub enum Kind {
|
||||
key_select
|
||||
key_sizeof
|
||||
key_likely
|
||||
key_unlikely
|
||||
key_offsetof
|
||||
key_struct
|
||||
key_switch
|
||||
@ -220,6 +221,7 @@ fn build_token_str() []string {
|
||||
s[Kind.key_module] = 'module'
|
||||
s[Kind.key_sizeof] = 'sizeof'
|
||||
s[Kind.key_likely] = '_likely_'
|
||||
s[Kind.key_unlikely] = '_unlikely_'
|
||||
s[Kind.key_go] = 'go'
|
||||
s[Kind.key_goto] = 'goto'
|
||||
s[Kind.key_const] = 'const'
|
||||
|
Loading…
Reference in New Issue
Block a user