 Bug#30237 (Performance regression in boolean expressions)
This is a performance bug, related to the parsing or 'OR' and 'AND' boolean
expressions.
Let N be the number of expressions involved in a OR (respectively AND).
When N=1
For example, "select 1" involve only 1 term: there is no OR operator.
In 4.0 and 4.1, parsing expressions not involving OR had no overhead.
In 5.0, parsing adds some overhead, with Select->expr_list.
With this patch, the overhead introduced in 5.0 has been removed,
so that performances for N=1 should be identical to the 4.0 performances,
which are optimal (there is no code executed at all)
The overhead in 5.0 was in fact affecting significantly some operations.
For example, loading 1 Million rows into a table with INSERTs,
for a table that has 100 columns, leads to parsing 100 Millions of
expressions, which means that the overhead related to Select->expr_list
is executed 100 Million times ...
Considering that N=1 is by far the most probable expression,
this case should be optimal.
When N=2
For example, "select a OR b" involves 2 terms in the OR operator.
In 4.0 and 4.1, parsing expressions involving 2 terms created 1 Item_cond_or
node, which is the expected result.
In 5.0, parsing these expression also produced 1 node, but with some extra
overhead related to Select->expr_list : creating 1 list in Select->expr_list
and another in Item_cond::list is inefficient.
With this patch, the overhead introduced in 5.0 has been removed
so that performances for N=2 should be identical to the 4.0 performances.
Note that the memory allocation uses the new (thd->mem_root) syntax
directly.
The cost of "is_cond_or" is estimated to be neglectable: the real problem
of the performance degradation comes from unneeded memory allocations.
When N>=3
For example, "select a OR b OR c ...", which involves 3 or more terms.
In 4.0 and 4.1, the parser had no significant cost overhead, but produced
an Item tree which is difficult to evaluate / optimize during runtime.
In 5.0, the parser produces a better Item tree, using the Item_cond
constructor that accepts a list of children directly, but at an extra cost
related to Select->expr_list.
With this patch, the code is implemented to take the best of the two
implementations:
- there is no overhead with Select->expr_list
- the Item tree generated is optimized and flattened.
This is achieved by adding children nodes into the Item tree directly,
with Item_cond::add(), which avoids the need for temporary lists and memory
allocation
Note that this patch also provide an extra optimization, that the previous
code in 5.0 did not provide: expressions are flattened in the Item tree,
based on what the expression already parsed is, and not based on the order
in which rules are reduced.
For example : "(a OR b) OR c", "a OR (b OR c)" would both be represented
with 2 Item_cond_or nodes before this patch, and with 1 node only with this
patch. The logic used is based on the mathematical properties of the OR
operator (it's associative), and produces a simpler tree.
sql/item_cmpfunc.h:
Improved performances for parsing boolean expressions
sql/sql_yacc.yy:
Improved performances for parsing boolean expressions
mysql-test/r/parser_precedence.result:
Added test cases to cover boolean operator precedence
mysql-test/t/parser_precedence.test:
Added test cases to cover boolean operator precedence
19 years ago |
|
drop table if exists t1_30237_bool;create table t1_30237_bool(A boolean, B boolean, C boolean);insert into t1_30237_bool values(FALSE, FALSE, FALSE),(FALSE, FALSE, NULL),(FALSE, FALSE, TRUE),(FALSE, NULL, FALSE),(FALSE, NULL, NULL),(FALSE, NULL, TRUE),(FALSE, TRUE, FALSE),(FALSE, TRUE, NULL),(FALSE, TRUE, TRUE),(NULL, FALSE, FALSE),(NULL, FALSE, NULL),(NULL, FALSE, TRUE),(NULL, NULL, FALSE),(NULL, NULL, NULL),(NULL, NULL, TRUE),(NULL, TRUE, FALSE),(NULL, TRUE, NULL),(NULL, TRUE, TRUE),(TRUE, FALSE, FALSE),(TRUE, FALSE, NULL),(TRUE, FALSE, TRUE),(TRUE, NULL, FALSE),(TRUE, NULL, NULL),(TRUE, NULL, TRUE),(TRUE, TRUE, FALSE),(TRUE, TRUE, NULL),(TRUE, TRUE, TRUE) ;Testing OR, XOR, ANDselect A, B, A OR B, A XOR B, A AND Bfrom t1_30237_bool where C is null order by A, B;A B A OR B A XOR B A AND BNULL NULL NULL NULL NULLNULL 0 NULL NULL 0NULL 1 1 NULL NULL0 NULL NULL NULL 00 0 0 0 00 1 1 1 01 NULL 1 NULL NULL1 0 1 1 01 1 1 0 1Testing that OR is associative select A, B, C, (A OR B) OR C, A OR (B OR C), A OR B OR Cfrom t1_30237_bool order by A, B, C;A B C (A OR B) OR C A OR (B OR C) A OR B OR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 1 1 1NULL 0 NULL NULL NULL NULLNULL 0 0 NULL NULL NULLNULL 0 1 1 1 1NULL 1 NULL 1 1 1NULL 1 0 1 1 1NULL 1 1 1 1 10 NULL NULL NULL NULL NULL0 NULL 0 NULL NULL NULL0 NULL 1 1 1 10 0 NULL NULL NULL NULL0 0 0 0 0 00 0 1 1 1 10 1 NULL 1 1 10 1 0 1 1 10 1 1 1 1 11 NULL NULL 1 1 11 NULL 0 1 1 11 NULL 1 1 1 11 0 NULL 1 1 11 0 0 1 1 11 0 1 1 1 11 1 NULL 1 1 11 1 0 1 1 11 1 1 1 1 1select count(*) from t1_30237_boolwhere ((A OR B) OR C) != (A OR (B OR C));count(*)0Testing that XOR is associative select A, B, C, (A XOR B) XOR C, A XOR (B XOR C), A XOR B XOR Cfrom t1_30237_bool order by A, B, C;A B C (A XOR B) XOR C A XOR (B XOR C) A XOR B XOR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 NULL NULL NULLNULL 0 NULL NULL NULL NULLNULL 0 0 NULL NULL NULLNULL 0 1 NULL NULL NULLNULL 1 NULL NULL NULL NULLNULL 1 0 NULL NULL NULLNULL 1 1 NULL NULL NULL0 NULL NULL NULL NULL NULL0 NULL 0 NULL NULL NULL0 NULL 1 NULL NULL NULL0 0 NULL NULL NULL NULL0 0 0 0 0 00 0 1 1 1 10 1 NULL NULL NULL NULL0 1 0 1 1 10 1 1 0 0 01 NULL NULL NULL NULL NULL1 NULL 0 NULL NULL NULL1 NULL 1 NULL NULL NULL1 0 NULL NULL NULL NULL1 0 0 1 1 11 0 1 0 0 01 1 NULL NULL NULL NULL1 1 0 0 0 01 1 1 1 1 1select count(*) from t1_30237_boolwhere ((A XOR B) XOR C) != (A XOR (B XOR C));count(*)0Testing that AND is associative select A, B, C, (A AND B) AND C, A AND (B AND C), A AND B AND Cfrom t1_30237_bool order by A, B, C;A B C (A AND B) AND C A AND (B AND C) A AND B AND CNULL NULL NULL NULL NULL NULLNULL NULL 0 0 0 0NULL NULL 1 NULL NULL NULLNULL 0 NULL 0 0 0NULL 0 0 0 0 0NULL 0 1 0 0 0NULL 1 NULL NULL NULL NULLNULL 1 0 0 0 0NULL 1 1 NULL NULL NULL0 NULL NULL 0 0 00 NULL 0 0 0 00 NULL 1 0 0 00 0 NULL 0 0 00 0 0 0 0 00 0 1 0 0 00 1 NULL 0 0 00 1 0 0 0 00 1 1 0 0 01 NULL NULL NULL NULL NULL1 NULL 0 0 0 01 NULL 1 NULL NULL NULL1 0 NULL 0 0 01 0 0 0 0 01 0 1 0 0 01 1 NULL NULL NULL NULL1 1 0 0 0 01 1 1 1 1 1select count(*) from t1_30237_boolwhere ((A AND B) AND C) != (A AND (B AND C));count(*)0Testing that AND has precedence over ORselect A, B, C, (A OR B) AND C, A OR (B AND C), A OR B AND Cfrom t1_30237_bool order by A, B, C;A B C (A OR B) AND C A OR (B AND C) A OR B AND CNULL NULL NULL NULL NULL NULLNULL NULL 0 0 NULL NULLNULL NULL 1 NULL NULL NULLNULL 0 NULL NULL NULL NULLNULL 0 0 0 NULL NULLNULL 0 1 NULL NULL NULLNULL 1 NULL NULL NULL NULLNULL 1 0 0 NULL NULLNULL 1 1 1 1 10 NULL NULL NULL NULL NULL0 NULL 0 0 0 00 NULL 1 NULL NULL NULL0 0 NULL 0 0 00 0 0 0 0 00 0 1 0 0 00 1 NULL NULL NULL NULL0 1 0 0 0 00 1 1 1 1 11 NULL NULL NULL 1 11 NULL 0 0 1 11 NULL 1 1 1 11 0 NULL NULL 1 11 0 0 0 1 11 0 1 1 1 11 1 NULL NULL 1 11 1 0 0 1 11 1 1 1 1 1select count(*) from t1_30237_boolwhere (A OR (B AND C)) != (A OR B AND C);count(*)0select A, B, C, (A AND B) OR C, A AND (B OR C), A AND B OR Cfrom t1_30237_bool order by A, B, C;A B C (A AND B) OR C A AND (B OR C) A AND B OR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 1 NULL 1NULL 0 NULL NULL NULL NULLNULL 0 0 0 0 0NULL 0 1 1 NULL 1NULL 1 NULL NULL NULL NULLNULL 1 0 NULL NULL NULLNULL 1 1 1 NULL 10 NULL NULL NULL 0 NULL0 NULL 0 0 0 00 NULL 1 1 0 10 0 NULL NULL 0 NULL0 0 0 0 0 00 0 1 1 0 10 1 NULL NULL 0 NULL0 1 0 0 0 00 1 1 1 0 11 NULL NULL NULL NULL NULL1 NULL 0 NULL NULL NULL1 NULL 1 1 1 11 0 NULL NULL NULL NULL1 0 0 0 0 01 0 1 1 1 11 1 NULL 1 1 11 1 0 1 1 11 1 1 1 1 1select count(*) from t1_30237_boolwhere ((A AND B) OR C) != (A AND B OR C);count(*)0Testing that AND has precedence over XORselect A, B, C, (A XOR B) AND C, A XOR (B AND C), A XOR B AND Cfrom t1_30237_bool order by A, B, C;A B C (A XOR B) AND C A XOR (B AND C) A XOR B AND CNULL NULL NULL NULL NULL NULLNULL NULL 0 0 NULL NULLNULL NULL 1 NULL NULL NULLNULL 0 NULL NULL NULL NULLNULL 0 0 0 NULL NULLNULL 0 1 NULL NULL NULLNULL 1 NULL NULL NULL NULLNULL 1 0 0 NULL NULLNULL 1 1 NULL NULL NULL0 NULL NULL NULL NULL NULL0 NULL 0 0 0 00 NULL 1 NULL NULL NULL0 0 NULL 0 0 00 0 0 0 0 00 0 1 0 0 00 1 NULL NULL NULL NULL0 1 0 0 0 00 1 1 1 1 11 NULL NULL NULL NULL NULL1 NULL 0 0 1 11 NULL 1 NULL NULL NULL1 0 NULL NULL 1 11 0 0 0 1 11 0 1 1 1 11 1 NULL 0 NULL NULL1 1 0 0 1 11 1 1 0 0 0select count(*) from t1_30237_boolwhere (A XOR (B AND C)) != (A XOR B AND C);count(*)0select A, B, C, (A AND B) XOR C, A AND (B XOR C), A AND B XOR Cfrom t1_30237_bool order by A, B, C;A B C (A AND B) XOR C A AND (B XOR C) A AND B XOR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 NULL NULL NULLNULL 0 NULL NULL NULL NULLNULL 0 0 0 0 0NULL 0 1 1 NULL 1NULL 1 NULL NULL NULL NULLNULL 1 0 NULL NULL NULLNULL 1 1 NULL 0 NULL0 NULL NULL NULL 0 NULL0 NULL 0 0 0 00 NULL 1 1 0 10 0 NULL NULL 0 NULL0 0 0 0 0 00 0 1 1 0 10 1 NULL NULL 0 NULL0 1 0 0 0 00 1 1 1 0 11 NULL NULL NULL NULL NULL1 NULL 0 NULL NULL NULL1 NULL 1 NULL NULL NULL1 0 NULL NULL NULL NULL1 0 0 0 0 01 0 1 1 1 11 1 NULL NULL NULL NULL1 1 0 1 1 11 1 1 0 0 0select count(*) from t1_30237_boolwhere ((A AND B) XOR C) != (A AND B XOR C);count(*)0Testing that XOR has precedence over ORselect A, B, C, (A XOR B) OR C, A XOR (B OR C), A XOR B OR Cfrom t1_30237_bool order by A, B, C;A B C (A XOR B) OR C A XOR (B OR C) A XOR B OR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 1 NULL 1NULL 0 NULL NULL NULL NULLNULL 0 0 NULL NULL NULLNULL 0 1 1 NULL 1NULL 1 NULL NULL NULL NULLNULL 1 0 NULL NULL NULLNULL 1 1 1 NULL 10 NULL NULL NULL NULL NULL0 NULL 0 NULL NULL NULL0 NULL 1 1 1 10 0 NULL NULL NULL NULL0 0 0 0 0 00 0 1 1 1 10 1 NULL 1 1 10 1 0 1 1 10 1 1 1 1 11 NULL NULL NULL NULL NULL1 NULL 0 NULL NULL NULL1 NULL 1 1 0 11 0 NULL 1 NULL 11 0 0 1 1 11 0 1 1 0 11 1 NULL NULL 0 NULL1 1 0 0 0 01 1 1 1 0 1select count(*) from t1_30237_boolwhere ((A XOR B) OR C) != (A XOR B OR C);count(*)0select A, B, C, (A OR B) XOR C, A OR (B XOR C), A OR B XOR Cfrom t1_30237_bool order by A, B, C;A B C (A OR B) XOR C A OR (B XOR C) A OR B XOR CNULL NULL NULL NULL NULL NULLNULL NULL 0 NULL NULL NULLNULL NULL 1 NULL NULL NULLNULL 0 NULL NULL NULL NULLNULL 0 0 NULL NULL NULLNULL 0 1 NULL 1 1NULL 1 NULL NULL NULL NULLNULL 1 0 1 1 1NULL 1 1 0 NULL NULL0 NULL NULL NULL NULL NULL0 NULL 0 NULL NULL NULL0 NULL 1 NULL NULL NULL0 0 NULL NULL NULL NULL0 0 0 0 0 00 0 1 1 1 10 1 NULL NULL NULL NULL0 1 0 1 1 10 1 1 0 0 01 NULL NULL NULL 1 11 NULL 0 1 1 11 NULL 1 0 1 11 0 NULL NULL 1 11 0 0 1 1 11 0 1 0 1 11 1 NULL NULL 1 11 1 0 1 1 11 1 1 0 1 1select count(*) from t1_30237_boolwhere (A OR (B XOR C)) != (A OR B XOR C);count(*)0drop table t1_30237_bool;Testing that NOT has precedence over ORselect (NOT FALSE) OR TRUE, NOT (FALSE OR TRUE), NOT FALSE OR TRUE;(NOT FALSE) OR TRUE NOT (FALSE OR TRUE) NOT FALSE OR TRUE1 0 1Testing that NOT has precedence over XORselect (NOT FALSE) XOR FALSE, NOT (FALSE XOR FALSE), NOT FALSE XOR FALSE;(NOT FALSE) XOR FALSE NOT (FALSE XOR FALSE) NOT FALSE XOR FALSE1 1 1Testing that NOT has precedence over ANDselect (NOT FALSE) AND FALSE, NOT (FALSE AND FALSE), NOT FALSE AND FALSE;(NOT FALSE) AND FALSE NOT (FALSE AND FALSE) NOT FALSE AND FALSE0 1 0Testing that NOT is associativeselect NOT NOT TRUE, NOT NOT NOT FALSE;NOT NOT TRUE NOT NOT NOT FALSE1 1Testing that IS has precedence over NOTselect (NOT NULL) IS TRUE, NOT (NULL IS TRUE), NOT NULL IS TRUE;(NOT NULL) IS TRUE NOT (NULL IS TRUE) NOT NULL IS TRUE0 1 1select (NOT NULL) IS NOT TRUE, NOT (NULL IS NOT TRUE), NOT NULL IS NOT TRUE;(NOT NULL) IS NOT TRUE NOT (NULL IS NOT TRUE) NOT NULL IS NOT TRUE1 0 0select (NOT NULL) IS FALSE, NOT (NULL IS FALSE), NOT NULL IS FALSE;(NOT NULL) IS FALSE NOT (NULL IS FALSE) NOT NULL IS FALSE0 1 1select (NOT NULL) IS NOT FALSE, NOT (NULL IS NOT FALSE), NOT NULL IS NOT FALSE;(NOT NULL) IS NOT FALSE NOT (NULL IS NOT FALSE) NOT NULL IS NOT FALSE1 0 0select (NOT TRUE) IS UNKNOWN, NOT (TRUE IS UNKNOWN), NOT TRUE IS UNKNOWN;(NOT TRUE) IS UNKNOWN NOT (TRUE IS UNKNOWN) NOT TRUE IS UNKNOWN0 1 1select (NOT TRUE) IS NOT UNKNOWN, NOT (TRUE IS NOT UNKNOWN), NOT TRUE IS NOT UNKNOWN;(NOT TRUE) IS NOT UNKNOWN NOT (TRUE IS NOT UNKNOWN) NOT TRUE IS NOT UNKNOWN1 0 0select (NOT TRUE) IS NULL, NOT (TRUE IS NULL), NOT TRUE IS NULL;(NOT TRUE) IS NULL NOT (TRUE IS NULL) NOT TRUE IS NULL0 1 1select (NOT TRUE) IS NOT NULL, NOT (TRUE IS NOT NULL), NOT TRUE IS NOT NULL;(NOT TRUE) IS NOT NULL NOT (TRUE IS NOT NULL) NOT TRUE IS NOT NULL1 0 0Testing that IS [NOT] TRUE/FALSE/UNKNOWN predicates are not associativeselect TRUE IS TRUE IS TRUE IS TRUE;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS TRUE IS TRUE' at line 1select FALSE IS NOT TRUE IS NOT TRUE IS NOT TRUE;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS NOT TRUE IS NOT TRUE' at line 1select NULL IS FALSE IS FALSE IS FALSE;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS FALSE IS FALSE' at line 1select TRUE IS NOT FALSE IS NOT FALSE IS NOT FALSE;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS NOT FALSE IS NOT FALSE' at line 1select FALSE IS UNKNOWN IS UNKNOWN IS UNKNOWN;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS UNKNOWN IS UNKNOWN' at line 1select TRUE IS NOT UNKNOWN IS NOT UNKNOWN IS NOT UNKNOWN;ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IS NOT UNKNOWN IS NOT UNKNOWN' at line 1Testing that IS [NOT] NULL predicates are associativeselect FALSE IS NULL IS NULL IS NULL;FALSE IS NULL IS NULL IS NULL0select TRUE IS NOT NULL IS NOT NULL IS NOT NULL;TRUE IS NOT NULL IS NOT NULL IS NOT NULL1Testing that comparison operators are left associativeselect 1 <=> 2 <=> 2, (1 <=> 2) <=> 2, 1 <=> (2 <=> 2);1 <=> 2 <=> 2 (1 <=> 2) <=> 2 1 <=> (2 <=> 2)0 0 1select 1 = 2 = 2, (1 = 2) = 2, 1 = (2 = 2);1 = 2 = 2 (1 = 2) = 2 1 = (2 = 2)0 0 1select 1 != 2 != 3, (1 != 2) != 3, 1 != (2 != 3);1 != 2 != 3 (1 != 2) != 3 1 != (2 != 3)1 1 0select 1 <> 2 <> 3, (1 <> 2) <> 3, 1 <> (2 <> 3);1 <> 2 <> 3 (1 <> 2) <> 3 1 <> (2 <> 3)1 1 0select 1 < 2 < 3, (1 < 2) < 3, 1 < (2 < 3);1 < 2 < 3 (1 < 2) < 3 1 < (2 < 3)1 1 0select 3 <= 2 <= 1, (3 <= 2) <= 1, 3 <= (2 <= 1);3 <= 2 <= 1 (3 <= 2) <= 1 3 <= (2 <= 1)1 1 0select 1 > 2 > 3, (1 > 2) > 3, 1 > (2 > 3);1 > 2 > 3 (1 > 2) > 3 1 > (2 > 3)0 0 1select 1 >= 2 >= 3, (1 >= 2) >= 3, 1 >= (2 >= 3);1 >= 2 >= 3 (1 >= 2) >= 3 1 >= (2 >= 3)0 0 1Testing that | is associativeselect 0xF0 | 0x0F | 0x55, (0xF0 | 0x0F) | 0x55, 0xF0 | (0x0F | 0x55);0xF0 | 0x0F | 0x55 (0xF0 | 0x0F) | 0x55 0xF0 | (0x0F | 0x55)255 255 255Testing that & is associativeselect 0xF5 & 0x5F & 0x55, (0xF5 & 0x5F) & 0x55, 0xF5 & (0x5F & 0x55);0xF5 & 0x5F & 0x55 (0xF5 & 0x5F) & 0x55 0xF5 & (0x5F & 0x55)85 85 85Testing that << is left associativeselect 4 << 3 << 2, (4 << 3) << 2, 4 << (3 << 2);4 << 3 << 2 (4 << 3) << 2 4 << (3 << 2)128 128 16384Testing that >> is left associativeselect 256 >> 3 >> 2, (256 >> 3) >> 2, 256 >> (3 >> 2);256 >> 3 >> 2 (256 >> 3) >> 2 256 >> (3 >> 2)8 8 256Testing that & has precedence over |select 0xF0 & 0x0F | 0x55, (0xF0 & 0x0F) | 0x55, 0xF0 & (0x0F | 0x55);0xF0 & 0x0F | 0x55 (0xF0 & 0x0F) | 0x55 0xF0 & (0x0F | 0x55)85 85 80select 0x55 | 0xF0 & 0x0F, (0x55 | 0xF0) & 0x0F, 0x55 | (0xF0 & 0x0F);0x55 | 0xF0 & 0x0F (0x55 | 0xF0) & 0x0F 0x55 | (0xF0 & 0x0F)85 5 85Testing that << has precedence over |select 0x0F << 4 | 0x0F, (0x0F << 4) | 0x0F, 0x0F << (4 | 0x0F);0x0F << 4 | 0x0F (0x0F << 4) | 0x0F 0x0F << (4 | 0x0F)255 255 491520select 0x0F | 0x0F << 4, (0x0F | 0x0F) << 4, 0x0F | (0x0F << 4);0x0F | 0x0F << 4 (0x0F | 0x0F) << 4 0x0F | (0x0F << 4)255 240 255Testing that >> has precedence over |select 0xF0 >> 4 | 0xFF, (0xF0 >> 4) | 0xFF, 0xF0 >> (4 | 0xFF);0xF0 >> 4 | 0xFF (0xF0 >> 4) | 0xFF 0xF0 >> (4 | 0xFF)255 255 0select 0xFF | 0xF0 >> 4, (0xFF | 0xF0) >> 4, 0xFF | (0xF0 >> 4);0xFF | 0xF0 >> 4 (0xFF | 0xF0) >> 4 0xFF | (0xF0 >> 4)255 15 255Testing that << has precedence over &select 0x0F << 4 & 0xF0, (0x0F << 4) & 0xF0, 0x0F << (4 & 0xF0);0x0F << 4 & 0xF0 (0x0F << 4) & 0xF0 0x0F << (4 & 0xF0)240 240 15select 0xF0 & 0x0F << 4, (0xF0 & 0x0F) << 4, 0xF0 & (0x0F << 4);0xF0 & 0x0F << 4 (0xF0 & 0x0F) << 4 0xF0 & (0x0F << 4)240 0 240Testing that >> has precedence over &select 0xF0 >> 4 & 0x55, (0xF0 >> 4) & 0x55, 0xF0 >> (4 & 0x55);0xF0 >> 4 & 0x55 (0xF0 >> 4) & 0x55 0xF0 >> (4 & 0x55)5 5 15select 0x0F & 0xF0 >> 4, (0x0F & 0xF0) >> 4, 0x0F & (0xF0 >> 4);0x0F & 0xF0 >> 4 (0x0F & 0xF0) >> 4 0x0F & (0xF0 >> 4)15 0 15Testing that >> and << have the same precedenceselect 0xFF >> 4 << 2, (0xFF >> 4) << 2, 0xFF >> (4 << 2);0xFF >> 4 << 2 (0xFF >> 4) << 2 0xFF >> (4 << 2)60 60 0select 0x0F << 4 >> 2, (0x0F << 4) >> 2, 0x0F << (4 >> 2);0x0F << 4 >> 2 (0x0F << 4) >> 2 0x0F << (4 >> 2)60 60 30Testing that binary + is associativeselect 1 + 2 + 3, (1 + 2) + 3, 1 + (2 + 3);1 + 2 + 3 (1 + 2) + 3 1 + (2 + 3)6 6 6Testing that binary - is left associativeselect 1 - 2 - 3, (1 - 2) - 3, 1 - (2 - 3);1 - 2 - 3 (1 - 2) - 3 1 - (2 - 3)-4 -4 2Testing that binary + and binary - have the same precedenceselect 1 + 2 - 3, (1 + 2) - 3, 1 + (2 - 3);1 + 2 - 3 (1 + 2) - 3 1 + (2 - 3)0 0 0select 1 - 2 + 3, (1 - 2) + 3, 1 - (2 + 3);1 - 2 + 3 (1 - 2) + 3 1 - (2 + 3)2 2 -4Testing that binary + has precedence over |select 0xF0 + 0x0F | 0x55, (0xF0 + 0x0F) | 0x55, 0xF0 + (0x0F | 0x55);0xF0 + 0x0F | 0x55 (0xF0 + 0x0F) | 0x55 0xF0 + (0x0F | 0x55)255 255 335select 0x55 | 0xF0 + 0x0F, (0x55 | 0xF0) + 0x0F, 0x55 | (0xF0 + 0x0F);0x55 | 0xF0 + 0x0F (0x55 | 0xF0) + 0x0F 0x55 | (0xF0 + 0x0F)255 260 255Testing that binary + has precedence over &select 0xF0 + 0x0F & 0x55, (0xF0 + 0x0F) & 0x55, 0xF0 + (0x0F & 0x55);0xF0 + 0x0F & 0x55 (0xF0 + 0x0F) & 0x55 0xF0 + (0x0F & 0x55)85 85 245select 0x55 & 0xF0 + 0x0F, (0x55 & 0xF0) + 0x0F, 0x55 & (0xF0 + 0x0F);0x55 & 0xF0 + 0x0F (0x55 & 0xF0) + 0x0F 0x55 & (0xF0 + 0x0F)85 95 85Testing that binary + has precedence over <<select 2 + 3 << 4, (2 + 3) << 4, 2 + (3 << 4);2 + 3 << 4 (2 + 3) << 4 2 + (3 << 4)80 80 50select 3 << 4 + 2, (3 << 4) + 2, 3 << (4 + 2);3 << 4 + 2 (3 << 4) + 2 3 << (4 + 2)192 50 192Testing that binary + has precedence over >>select 4 + 3 >> 2, (4 + 3) >> 2, 4 + (3 >> 2);4 + 3 >> 2 (4 + 3) >> 2 4 + (3 >> 2)1 1 4select 3 >> 2 + 1, (3 >> 2) + 1, 3 >> (2 + 1);3 >> 2 + 1 (3 >> 2) + 1 3 >> (2 + 1)0 1 0Testing that binary - has precedence over |select 0xFF - 0x0F | 0x55, (0xFF - 0x0F) | 0x55, 0xFF - (0x0F | 0x55);0xFF - 0x0F | 0x55 (0xFF - 0x0F) | 0x55 0xFF - (0x0F | 0x55)245 245 160select 0x55 | 0xFF - 0xF0, (0x55 | 0xFF) - 0xF0, 0x55 | (0xFF - 0xF0);0x55 | 0xFF - 0xF0 (0x55 | 0xFF) - 0xF0 0x55 | (0xFF - 0xF0)95 15 95Testing that binary - has precedence over &select 0xFF - 0xF0 & 0x55, (0xFF - 0xF0) & 0x55, 0xFF - (0xF0 & 0x55);0xFF - 0xF0 & 0x55 (0xFF - 0xF0) & 0x55 0xFF - (0xF0 & 0x55)5 5 175select 0x55 & 0xFF - 0xF0, (0x55 & 0xFF) - 0xF0, 0x55 & (0xFF - 0xF0);0x55 & 0xFF - 0xF0 (0x55 & 0xFF) - 0xF0 0x55 & (0xFF - 0xF0)5 -155 5Testing that binary - has precedence over <<select 16 - 3 << 2, (16 - 3) << 2, 16 - (3 << 2);16 - 3 << 2 (16 - 3) << 2 16 - (3 << 2)52 52 4select 4 << 3 - 2, (4 << 3) - 2, 4 << (3 - 2);4 << 3 - 2 (4 << 3) - 2 4 << (3 - 2)8 30 8Testing that binary - has precedence over >>select 16 - 3 >> 2, (16 - 3) >> 2, 16 - (3 >> 2);16 - 3 >> 2 (16 - 3) >> 2 16 - (3 >> 2)3 3 16select 16 >> 3 - 2, (16 >> 3) - 2, 16 >> (3 - 2);16 >> 3 - 2 (16 >> 3) - 2 16 >> (3 - 2)8 0 8Testing that * is associativeselect 2 * 3 * 4, (2 * 3) * 4, 2 * (3 * 4);2 * 3 * 4 (2 * 3) * 4 2 * (3 * 4)24 24 24Testing that * has precedence over |select 2 * 0x40 | 0x0F, (2 * 0x40) | 0x0F, 2 * (0x40 | 0x0F);2 * 0x40 | 0x0F (2 * 0x40) | 0x0F 2 * (0x40 | 0x0F)143 143 158select 0x0F | 2 * 0x40, (0x0F | 2) * 0x40, 0x0F | (2 * 0x40);0x0F | 2 * 0x40 (0x0F | 2) * 0x40 0x0F | (2 * 0x40)143 960 143Testing that * has precedence over &select 2 * 0x40 & 0x55, (2 * 0x40) & 0x55, 2 * (0x40 & 0x55);2 * 0x40 & 0x55 (2 * 0x40) & 0x55 2 * (0x40 & 0x55)0 0 128select 0xF0 & 2 * 0x40, (0xF0 & 2) * 0x40, 0xF0 & (2 * 0x40);0xF0 & 2 * 0x40 (0xF0 & 2) * 0x40 0xF0 & (2 * 0x40)128 0 128Testing that * has precedence over << select 5 * 3 << 4, (5 * 3) << 4, 5 * (3 << 4);5 * 3 << 4 (5 * 3) << 4 5 * (3 << 4)240 240 240select 2 << 3 * 4, (2 << 3) * 4, 2 << (3 * 4);2 << 3 * 4 (2 << 3) * 4 2 << (3 * 4)8192 64 8192Testing that * has precedence over >>select 3 * 4 >> 2, (3 * 4) >> 2, 3 * (4 >> 2);3 * 4 >> 2 (3 * 4) >> 2 3 * (4 >> 2)3 3 3select 4 >> 2 * 3, (4 >> 2) * 3, 4 >> (2 * 3);4 >> 2 * 3 (4 >> 2) * 3 4 >> (2 * 3)0 3 0Testing that * has precedence over binary +select 2 * 3 + 4, (2 * 3) + 4, 2 * (3 + 4);2 * 3 + 4 (2 * 3) + 4 2 * (3 + 4)10 10 14select 2 + 3 * 4, (2 + 3) * 4, 2 + (3 * 4);2 + 3 * 4 (2 + 3) * 4 2 + (3 * 4)14 20 14Testing that * has precedence over binary -select 4 * 3 - 2, (4 * 3) - 2, 4 * (3 - 2);4 * 3 - 2 (4 * 3) - 2 4 * (3 - 2)10 10 4select 4 - 3 * 2, (4 - 3) * 2, 4 - (3 * 2);4 - 3 * 2 (4 - 3) * 2 4 - (3 * 2)-2 2 -2Testing that / is left associativeselect 15 / 5 / 3, (15 / 5) / 3, 15 / (5 / 3);15 / 5 / 3 (15 / 5) / 3 15 / (5 / 3)1.00000000 1.00000000 9.0000Testing that / has precedence over |select 105 / 5 | 2, (105 / 5) | 2, 105 / (5 | 2);105 / 5 | 2 (105 / 5) | 2 105 / (5 | 2)23 23 15.0000select 105 | 2 / 5, (105 | 2) / 5, 105 | (2 / 5);105 | 2 / 5 (105 | 2) / 5 105 | (2 / 5)105 21.4000 105Testing that / has precedence over &select 105 / 5 & 0x0F, (105 / 5) & 0x0F, 105 / (5 & 0x0F);105 / 5 & 0x0F (105 / 5) & 0x0F 105 / (5 & 0x0F)5 5 21.0000select 0x0F & 105 / 5, (0x0F & 105) / 5, 0x0F & (105 / 5);0x0F & 105 / 5 (0x0F & 105) / 5 0x0F & (105 / 5)5 1.8000 5Testing that / has precedence over << select 0x80 / 4 << 2, (0x80 / 4) << 2, 0x80 / (4 << 2);0x80 / 4 << 2 (0x80 / 4) << 2 0x80 / (4 << 2)128 128 8.0000select 0x80 << 4 / 2, (0x80 << 4) / 2, 0x80 << (4 / 2);0x80 << 4 / 2 (0x80 << 4) / 2 0x80 << (4 / 2)512 1024.0000 512Testing that / has precedence over >>select 0x80 / 4 >> 2, (0x80 / 4) >> 2, 0x80 / (4 >> 2);0x80 / 4 >> 2 (0x80 / 4) >> 2 0x80 / (4 >> 2)8 8 128.0000select 0x80 >> 4 / 2, (0x80 >> 4) / 2, 0x80 >> (4 / 2);0x80 >> 4 / 2 (0x80 >> 4) / 2 0x80 >> (4 / 2)32 4.0000 32Testing that / has precedence over binary +select 0x80 / 2 + 2, (0x80 / 2) + 2, 0x80 / (2 + 2);0x80 / 2 + 2 (0x80 / 2) + 2 0x80 / (2 + 2)66.0000 66.0000 32.0000select 0x80 + 2 / 2, (0x80 + 2) / 2, 0x80 + (2 / 2);0x80 + 2 / 2 (0x80 + 2) / 2 0x80 + (2 / 2)129.0000 65.0000 129.0000Testing that / has precedence over binary -select 0x80 / 4 - 2, (0x80 / 4) - 2, 0x80 / (4 - 2);0x80 / 4 - 2 (0x80 / 4) - 2 0x80 / (4 - 2)30.0000 30.0000 64.0000select 0x80 - 4 / 2, (0x80 - 4) / 2, 0x80 - (4 / 2);0x80 - 4 / 2 (0x80 - 4) / 2 0x80 - (4 / 2)126.0000 62.0000 126.0000Testing that ^ is associativeselect 0xFF ^ 0xF0 ^ 0x0F, (0xFF ^ 0xF0) ^ 0x0F, 0xFF ^ (0xF0 ^ 0x0F);0xFF ^ 0xF0 ^ 0x0F (0xFF ^ 0xF0) ^ 0x0F 0xFF ^ (0xF0 ^ 0x0F)0 0 0select 0xFF ^ 0xF0 ^ 0x55, (0xFF ^ 0xF0) ^ 0x55, 0xFF ^ (0xF0 ^ 0x55);0xFF ^ 0xF0 ^ 0x55 (0xFF ^ 0xF0) ^ 0x55 0xFF ^ (0xF0 ^ 0x55)90 90 90Testing that ^ has precedence over |select 0xFF ^ 0xF0 | 0x0F, (0xFF ^ 0xF0) | 0x0F, 0xFF ^ (0xF0 | 0x0F);0xFF ^ 0xF0 | 0x0F (0xFF ^ 0xF0) | 0x0F 0xFF ^ (0xF0 | 0x0F)15 15 0select 0xF0 | 0xFF ^ 0xF0, (0xF0 | 0xFF) ^ 0xF0, 0xF0 | (0xFF ^ 0xF0);0xF0 | 0xFF ^ 0xF0 (0xF0 | 0xFF) ^ 0xF0 0xF0 | (0xFF ^ 0xF0)255 15 255Testing that ^ has precedence over &select 0xFF ^ 0xF0 & 0x0F, (0xFF ^ 0xF0) & 0x0F, 0xFF ^ (0xF0 & 0x0F);0xFF ^ 0xF0 & 0x0F (0xFF ^ 0xF0) & 0x0F 0xFF ^ (0xF0 & 0x0F)15 15 255select 0x0F & 0xFF ^ 0xF0, (0x0F & 0xFF) ^ 0xF0, 0x0F & (0xFF ^ 0xF0);0x0F & 0xFF ^ 0xF0 (0x0F & 0xFF) ^ 0xF0 0x0F & (0xFF ^ 0xF0)15 255 15Testing that ^ has precedence over <<select 0xFF ^ 0xF0 << 2, (0xFF ^ 0xF0) << 2, 0xFF ^ (0xF0 << 2);0xFF ^ 0xF0 << 2 (0xFF ^ 0xF0) << 2 0xFF ^ (0xF0 << 2)60 60 831select 0x0F << 2 ^ 0xFF, (0x0F << 2) ^ 0xFF, 0x0F << (2 ^ 0xFF);0x0F << 2 ^ 0xFF (0x0F << 2) ^ 0xFF 0x0F << (2 ^ 0xFF)0 195 0Testing that ^ has precedence over >>select 0xFF ^ 0xF0 >> 2, (0xFF ^ 0xF0) >> 2, 0xFF ^ (0xF0 >> 2);0xFF ^ 0xF0 >> 2 (0xFF ^ 0xF0) >> 2 0xFF ^ (0xF0 >> 2)3 3 195select 0xFF >> 2 ^ 0xF0, (0xFF >> 2) ^ 0xF0, 0xFF >> (2 ^ 0xF0);0xFF >> 2 ^ 0xF0 (0xFF >> 2) ^ 0xF0 0xFF >> (2 ^ 0xF0)0 207 0Testing that ^ has precedence over binary +select 0xFF ^ 0xF0 + 0x0F, (0xFF ^ 0xF0) + 0x0F, 0xFF ^ (0xF0 + 0x0F);0xFF ^ 0xF0 + 0x0F (0xFF ^ 0xF0) + 0x0F 0xFF ^ (0xF0 + 0x0F)30 30 0select 0x0F + 0xFF ^ 0xF0, (0x0F + 0xFF) ^ 0xF0, 0x0F + (0xFF ^ 0xF0);0x0F + 0xFF ^ 0xF0 (0x0F + 0xFF) ^ 0xF0 0x0F + (0xFF ^ 0xF0)30 510 30Testing that ^ has precedence over binary -select 0xFF ^ 0xF0 - 1, (0xFF ^ 0xF0) - 1, 0xFF ^ (0xF0 - 1);0xFF ^ 0xF0 - 1 (0xFF ^ 0xF0) - 1 0xFF ^ (0xF0 - 1)14 14 16select 0x55 - 0x0F ^ 0x55, (0x55 - 0x0F) ^ 0x55, 0x55 - (0x0F ^ 0x55);0x55 - 0x0F ^ 0x55 (0x55 - 0x0F) ^ 0x55 0x55 - (0x0F ^ 0x55)-5 19 -5Testing that ^ has precedence over *select 0xFF ^ 0xF0 * 2, (0xFF ^ 0xF0) * 2, 0xFF ^ (0xF0 * 2);0xFF ^ 0xF0 * 2 (0xFF ^ 0xF0) * 2 0xFF ^ (0xF0 * 2)30 30 287select 2 * 0xFF ^ 0xF0, (2 * 0xFF) ^ 0xF0, 2 * (0xFF ^ 0xF0);2 * 0xFF ^ 0xF0 (2 * 0xFF) ^ 0xF0 2 * (0xFF ^ 0xF0)30 270 30Testing that ^ has precedence over /select 0xFF ^ 0xF0 / 2, (0xFF ^ 0xF0) / 2, 0xFF ^ (0xF0 / 2);0xFF ^ 0xF0 / 2 (0xFF ^ 0xF0) / 2 0xFF ^ (0xF0 / 2)7.5000 7.5000 135select 0xF2 / 2 ^ 0xF0, (0xF2 / 2) ^ 0xF0, 0xF2 / (2 ^ 0xF0);0xF2 / 2 ^ 0xF0 (0xF2 / 2) ^ 0xF0 0xF2 / (2 ^ 0xF0)1.0000 137 1.0000Testing that ^ has precedence over %select 0xFF ^ 0xF0 % 0x20, (0xFF ^ 0xF0) % 0x20, 0xFF ^ (0xF0 % 0x20);0xFF ^ 0xF0 % 0x20 (0xFF ^ 0xF0) % 0x20 0xFF ^ (0xF0 % 0x20)15 15 239select 0xFF % 0x20 ^ 0xF0, (0xFF % 0x20) ^ 0xF0, 0xFF % (0x20 ^ 0xF0);0xFF % 0x20 ^ 0xF0 (0xFF % 0x20) ^ 0xF0 0xFF % (0x20 ^ 0xF0)47 239 47Testing that ^ has precedence over DIVselect 0xFF ^ 0xF0 DIV 2, (0xFF ^ 0xF0) DIV 2, 0xFF ^ (0xF0 DIV 2);0xFF ^ 0xF0 DIV 2 (0xFF ^ 0xF0) DIV 2 0xFF ^ (0xF0 DIV 2)7 7 135select 0xF2 DIV 2 ^ 0xF0, (0xF2 DIV 2) ^ 0xF0, 0xF2 DIV (2 ^ 0xF0);0xF2 DIV 2 ^ 0xF0 (0xF2 DIV 2) ^ 0xF0 0xF2 DIV (2 ^ 0xF0)1 137 1Testing that ^ has precedence over MODselect 0xFF ^ 0xF0 MOD 0x20, (0xFF ^ 0xF0) MOD 0x20, 0xFF ^ (0xF0 MOD 0x20);0xFF ^ 0xF0 MOD 0x20 (0xFF ^ 0xF0) MOD 0x20 0xFF ^ (0xF0 MOD 0x20)15 15 239select 0xFF MOD 0x20 ^ 0xF0, (0xFF MOD 0x20) ^ 0xF0, 0xFF MOD (0x20 ^ 0xF0);0xFF MOD 0x20 ^ 0xF0 (0xFF MOD 0x20) ^ 0xF0 0xFF MOD (0x20 ^ 0xF0)47 239 47
|