C++ Logo

std-proposals

Advanced search

Re: Proposal for Switch(Constraints=Both/Upper/Lower/Neither/NoDefault/Sequenced)- improved assembly.

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Fri, 5 Feb 2021 13:46:11 +0100
pt., 5 lut 2021 o 13:12 Wesley Oliver via Std-Proposals
<std-proposals_at_[hidden]> napisaƂ(a):
>
> Hi,
>
> I have been looking to optimize an algorithm execution, with some adaptations and improved logic.
> One of the things I can across is that I could improve performance by handling a few special end condition cases differently and further again by adding upper bounder range check,
> The upper bound range check along for default gave me 5-6% performance increase, giving me a total of like 10-14% overall, by combination of a if upper range check and switch.
> I am sure with this suggested improvement, the compiler will be able to improve this even further with a single compound statement switch statement as I proposed below.
> So for example:
> case - 2: at times.
> case -1: continue/runout/run-on with instructions.
> case 0: the same thing.
> for these case just run out.
> case 1: optimize section of handling .
> break or goto
> case 2: optimize section of handling.
> break or goto
> case 3: optimize section of handling.
> break or goto
> default: complex logic.
> break or goto
>
> What I have found is that since switch typically gets compiled down to if statements or range checks for default. There is a nice optimization here, which I implemented manual, which speeds things save about 5-6% off, but may have room for more assemble optimization.
> At moment I see sub, he, sub, jne optimization for the switch, but feel could be more if one included the boundaries checking of default in switch statement. As there is still another default boundaries checking of cmp, jle, to the switch.
>
> What I would like to propose is SwitchLower and SwitchUpper, which determines,
> how upper bound can be checked, this saving a bounds check statement and then
> with this new statement it enforcing a constraint that all case have sequential identifier, no gaps.
> The code can still be re-ordered for optimization.
>
> With knowledge of this, typically translate the switch to a jump switchValue that is already in register that just got ranged checked for the default case, subtract the sequentialOffset, then jump by the switchValue or relative memory offset or instruction offset, depending on instruction set. Then jump one more time to the correct address to continue executing from for that case.
> Essentially this is a const stack array of positional jump offset encoding directly into the instructions, which should never be exicuted, unless random mistake jump to this data.
>
> ASSEMBLE.
> if(switchValue < Upper | Lower | Both range check)
> default code
> else
> {
> switchValue -= SequentialOffset;
> Jump SwitchValue;
> Jump currentcaseinstructionvalue.
> }
>
>
> I would like to recommend/propose
> switch(SwitchValue, SwitchConstrainsModifierHint) , where SwitchConstrainsModifierHint = NoCheck | Both | Upper | Lower | NoDefault | Seqeuenced.
>
> With this additional switchcontrainsModifierHint to a language, the compilers can easily understand range and sequence intention, in unsafe range check type language,
> which would allow it to further optimize this code much more easily, than a massive crazy analysis of the whole program to determine and ensure these contrains.
>
> This simple would allow everyone to communicate there intentional uses of the switch statement, based the large scope of the program they are writing, which would
> allow for it to further optimize the low level code generation and increase performance.
>
> I typically I feel that this would be a minor change, because I am not awhere of an additional parameter that can be supplied to Switch, the SwitchConstraints modified would
> naturally be backwards compatible with all languages and would be a progressive improvement. The reason for naturally backwards compatible, is
> that #define could define the sequence false, to be non-op, so in old compilers, SwitchConstraintsModiferHints, would be valid and compile, also due to
> the fact in C/C++ you can specify multiple commands separated by a comma. switch(switchValue, false) already compiles and the compiler
> will optimize away the false value I should hope.
>


`switch (x, y)` mean same as `(void)x; switch(y)`

This means that you cannot use it as is already valid code.

> Compilers can progressively take advantage of the hint and improve the low-level code generation, eventually leading to faster and more precise and consise code
> being written communicate its range behaviours more clearly.
>
> Look forward to hearing what one you guys think.
>
> Kind Regards,
>
> Wesley Oliver
>


And if this is only a hint, this should be an attribute as it does not
change behavior of a valid program if we ignore this attribute or use
it:

```
switch (x) [[SwitchConstraintModifiersHints]] //or before `switch`
depending with case is allowed by C++
{
//...
}
```

If you use this attribute incorrectly then you will get UB similar to
`[[noreturn]]`.

Received on 2021-02-05 06:46:24