During working on my performance branch (BTW interim state: 8.6th is ca. 6-7 times faster now, but I'm confident it'll outperform 10x plank soon), I found strange discrepancy between two almost equal code-pieces.

If one take a look into the byte-code of following scripts, he notes each set-command in first body receives additionally a 9-byte instruction "startCommand" (INST_START_CMD). This is good so (is also very fast command), but the second body totally misses it.

Just compare both disassemble-outputs of:
<code><verbatim>
proc x {} {while {[t]} {set i0 0; set i1 1; set i2 2; set i3 3}}; tcl::unsupported::disassemble proc x
proc x {} {while {$va} {set i0 0; set i1 1; set i2 2; set i3 3}}; tcl::unsupported::disassemble proc x

Therefore it results in:

<code><verbatim>
Source "while {[t]} {set i0 0; set i1 1; set i2 2; set i3 3}"
Cmds 6, src 52, inst 68, litObjs 6, aux 0, stkDepth 1, code/src 0.00
...
Source "while {$va} {set i0 0; set i1 1; set i2 2; set i3 3}"
Cmds 5, src 52, inst 30, litObjs 5, aux 0, stkDepth 1, code/src 0.00
...


The same is valid for all cycles (resp. body compilations so different if it does or does not contain invocation), e. g. on following "foreach":

<code><verbatim>
proc x {} {set i1 0; unset i1; foreach a [test_itr] {set i0 0; set i1 1; set i2 2; set i3 3}}; tcl::unsupported::disassemble proc x
proc x {} {set i1 0; unset i1; foreach a {a1 a2 a3} {set i0 0; set i1 1; set i2 2; set i3 3}}; tcl::unsupported::disassemble proc x


results in:

<code><verbatim>
Source "set i1 0; unset i1; foreach a [test_itr] {set i0 0; set..."
Cmds 8, src 81, inst 102, litObjs 6, aux 1, stkDepth 4, code/src 0.00
...
Source "set i1 0; unset i1; foreach a {a1 a2 a3} {set i0 0; set..."
Cmds 7, src 81, inst 46, litObjs 6, aux 1, stkDepth 4, code/src 0.00
...


And each 68 vs 30 resp. 74 vs 36 bytes of code.
This is wrong (and weird at all).

BTW. Strange is also, in 8.5 as well as in my (own) another TclSE-edition, I can't see the same behavior (but some time ago I've rewritten there the handling round about "startCommand", so for example I don't have there `envPtr->atCmdStart` at all, it was implemented other way).

I'm relative sure, this 4 extra "startCommand" commands in body are missed in both second variants (I'm sure this will wrong calculate the count of interpreted command).
So for example "info cmdcount" as well as interpreter limit will work totally wrong.

Following example illustrates the issue:

<code><verbatim>
proc retv {v} {return $v}
set i 0
foreach c {
    { set j 10; while {[retv [incr j -1]]} {set i0 0; set i1 1; set i2 2; set i3 3} }
    { set j 10; while {      [incr j -1] } {set i0 0; set i1 1; set i2 2; set i3 3} }
    { foreach j [retv {9 8 7 6 4 3 2 1}]   {set i0 0; set i1 1; set i2 2; set i3 3} }
    { foreach j       {9 8 7 6 4 3 2 1}    {set i0 0; set i1 1; set i2 2; set i3 3} }
} {
    proc test_[incr i] {} $c
}
proc test {} {
    foreach i {1 2 3 4} {
        puts "[set cc [info cmdcount]]"
        test_$i
        puts "++ [expr {[info cmdcount] - $cc}]"
    }
}
test


Result should be:
<code><verbatim>
++ 62
++ 52
++ 38
++ 37

And in current 8.6th it results in:
<code><verbatim>
++ 62
++ 5     *WRONG*
++ 38
++ 5     *WRONG*