0

I am using the COSMIC compiler in the STVD ide and even though optimization is turned of with -no (documentation says "-no: do not use optimizer") some lines of code get removed and cannot have a breakpoint placed upon them, nor are they to be found in the disassembly.

I tried to set -oc (leave removed instructions as comments) which resulted in not even showing the removed lines as comment.

bool foo(void)
{
   uint8_t val;

   if (globalvar > 5)
      val = 0;

   for (val = 0; val < 8; val++)
   {
      some code...
   }

   return true;
}

I do know it seems idiotic to set val to 0 prior to the for loop but lets just assume it is for some reason necessary. When I set no optimization I expect it to be not optimized but insted the val = 0; gets removed without any traces.

I am not looking for a workaround like declaring val volatile whitch solves the problem. I am rather looking for a way to prevent the optimization or at least understand/know what changes are made to my code when compiling.

EN20
  • 51
  • 11
  • Seems like the purpose with this is just to create a spot to place a breakpoint? If so the work-around might be to change `val = 0` with `asm("NOP")` or whatever inline asm syntax you've got for NOP. Alternatively do `if (globalvar > 5) { volatile bool dummy = 0; }`. – Lundin Aug 13 '19 at 14:58
  • Unfortunately this is just one place where I noticed this behavior but I have got other problems which seam to be related to optimization of some kind. The point is that I want absolutely no optimization when I ask for it. The example is ment as a minimal example where I thought I could explain the unwanted behavior the best. But ``asm("NOP") `` is a pretty good suggestion for a breakpoint spot. Thanks for that. – EN20 Aug 13 '19 at 16:23
  • I appreciate that this is not real code, but at least it should be valid. val in this case should not be a bool. – Clifford Aug 13 '19 at 19:35

2 Answers2

0

It is not clear from the manual, but it seems that the -no option prevents assembly level optimisation. It seems possible that the code generator stage that runs before assembly optimisation may perform higher level optimisation such as redundant code removal.

From the manual:

-cp

disable the constant propagation optimization. By default, when a variable is assigned with a constant, any subsequent access to that variable is replaced by the constant itself until the variable is modified or a flow break is encountered (function call, loop, label ...).

It seems that it is this constant propagation feature that you must explicitly disable.

It is unusual perhaps, but it appears that this compiler optimises by default, and distinguishes between compiler optimisations and assembler optimisations (performed as the compilation stage), and them makes you switch off each individual optimisation separately.

To avoid this in the code, rather than switching it off globally, you could initialise val to a non-zero value in this case:

int val = -1 ;

Then the later assignment to zero will require explicit code. This has the advantage over volatile perhaps in that it will not block optimisations when you do enable them.

Community
  • 1
  • 1
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Unfortunately this does not solve my problem the way I would like it to do but it clarifies a lot. I tried your suggested and other parser options (**-cp must be -pcp** so the compiler knows it is a parser option) but they seem to be ignored or useless. Nevertheless I can at least now be quite sure that my other bug is based on something else than unintended optimization. – EN20 Aug 14 '19 at 06:21
  • @EN20 Sounds like a question for the vendor then - being commercial software one would imagine that they provide support. Otherwise you may as well use the free SDCC tool chain. – Clifford Aug 14 '19 at 06:53
  • I am with you on this one and the vendor told me kindly to ask **"the forum"** since I am using a free license. Since they do not have one themself I came here. I will definitely give the SDCC a try. – EN20 Aug 15 '19 at 04:51
0

I believe that this behaviour is allowed by the C language specification.

You are effectively writing the same value either once or twice to the same variable on successive lines of code. The compiler could assign this value to either a processor register or a memory location as it sees fit and knows that the value following the initial assignment in the for loop is the same as the value assigned when the if clause is actioned. As a result the language spec allows the compiler to throw the redundant code away.

The way to force the compiler to perform all read and write accesses to the variable is to use the volatile keyword. That is what it is for.

uɐɪ
  • 2,540
  • 1
  • 20
  • 23
  • No one is doubting that it is allowed; equally a compiler is allowed not to optimise it, and most tool chains do not apply it without explicit optimisation in order to improve the debug experience. While volatile would work, it would prevent optimisation, and in this case it is only required not to optimise for debug purposes. That is really _not_ what volatile is for. It is reasonable perhaps to expect this compiler to behave conventionally. That is it is useful for the developer to have control over such things. Moreover, this is a _long_ comment, not an answer. – Clifford Aug 15 '19 at 07:21