• AVR Freaks

AnsweredHot![SOLVED](PEBKAC)Is this a known bug in the XC8 v2.20 compiler?

Author
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
2020/06/14 11:34:21 (permalink)
0

[SOLVED](PEBKAC)Is this a known bug in the XC8 v2.20 compiler?

Using: MPLABX v5.40, XC8 v2.20, Windows7 pro 64-bit.
The C code:
volatile unsigned char pData[240];
 
unsigned char I;
void LinearMemory(volatile unsigned char *pRam)
{
    I = sizeof(pData);
    do
    {
        *pRam-- = I;
    } while(--I);
}
void LinearMemoryValidate(volatile unsigned char *pRam)
{
    I = sizeof(pData);
    do
    {
        if (*pRam-- == I)
        {
            NOP();
            NOP();
            NOP();
        }
        else
        {
            NOP();
            NOP();
            NOP();
        }
    } while(--I);
}
/*
 * Application
 */
void main(void)
{
    PIC_Init();
    /*
     * Process loop
     */
    for(;;)
    {
        LinearMemory(&pData[sizeof(pData)-1]);
        LinearMemoryValidate(&pData[sizeof(pData)-1]);
    }
    return;
}

 
Disassembly:
!void LinearMemoryValidate(volatile unsigned char *pRam)
!{
!    I = sizeof(pData);
0x7E0: MOVLW 0xF0
0x7E1: MOVWF 0x72
0x7E2: MOVF 0x72, W
0x7E3: MOVWF I
!    do
!    {
!        if (*pRam-- == I)
0x7E4: MOVF __pcstackCOMMON, W
0x7E5: MOVWF FSR1
0x7E6: MOVF 0x71, W
0x7E7: MOVWF FSR1H
0x7E8: MOVF INDF1, W     <=== here pPram is de-referenced in to WREG so where is the compare to I?
0x7E9: MOVLW 0x1
0x7EA: SUBWF __pcstackCOMMON, F
0x7EB: MOVLW 0x0
0x7EC: SUBWFB 0x71, F
!        {
!            NOP();
0x7ED: NOP
!            NOP();
0x7EE: NOP
!            NOP();
0x7EF: NOP
!        }
!        else
!        {
!            NOP();
!            NOP();
!            NOP();
!        }
!    } while(--I);
0x7F0: MOVLW 0x1
0x7F1: SUBWF I, F
0x7F2: BTFSC STATUS, 0x2
0x7F3: RETURN
0x7F4: GOTO 0x7E4

post edited by dan1138 - 2020/06/14 20:24:19
#1
du00000001
Just Some Member
  • Total Posts : 3787
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 11:52:53 (permalink)
+2 (2)
Why do you expect the compiler to reproduce your source nonsense. This is an optimizing compiler!
It has found out that both branches are identical. So there is no need to branch at all.
Make one of the branches execute 4 NOPs and re-evaluate the "bug"!
 

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#2
du00000001
Just Some Member
  • Total Posts : 3787
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 11:55:52 (permalink) ☼ Best Answerby dan1138 2020/06/14 20:24:38
+2 (2)
It's not a bug - it's a feature.
 
PEBKAC

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#3
al_bin
Super Member
  • Total Posts : 201
  • Reward points : 0
  • Joined: 2011/02/11 06:28:47
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 11:59:56 (permalink)
0
Why do you think this is an error and not code optimization?
 
Albert
#4
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 12:42:42 (permalink)
0
al_bin
Why do you think this is an error and not code optimization?

Because I was building with optimizations set to zero.
 
It would seem that optimization for this code elimination in the 'if' statement cannot be turned off.
 
 
#5
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 13:14:04 (permalink)
0
@du00000001,
 
Yes this is definitely a PEBKAC. I am so embarrassed. :)
 
So in a desperate ubernerd attempt at face saving I did find a completely inconsequential nit-picky issue with the code generation when the 'if' statement get optimized.
 
Source code:
volatile unsigned char pData[240];
volatile unsigned char I;   <=== note changed to volatile storage class ===>
void LinearMemory(volatile unsigned char *pRam)
{
    I = sizeof(pData);
    do
    {
        *pRam-- = I;
    } while(--I);
}
void LinearMemoryValidate(volatile unsigned char *pRam)
{
    I = sizeof(pData);
    do
    {
        if (*pRam-- == I)
        {
            NOP();
            NOP();
        }
        else
        {
            NOP();
            NOP();
        }

    } while(--I);
}
/*
 * Application
 */
void main(void)
{
    PIC_Init();
    /*
     * Process loop
     */
    LinearMemory(&pData[sizeof(pData)-1]);
    for(;;)
    {
        LinearMemoryValidate(&pData[sizeof(pData)-1]);
    }
    return;
}

 
Generated code:
!void LinearMemoryValidate(volatile unsigned char *pRam)
!{
!    I = sizeof(pData);
0x7DD: MOVLW 0xF0
0x7DE: MOVWF 0x72
0x7DF: MOVF 0x72, W
0x7E0: MOVWF I
!    do
!    {
!        if (*pRam-- == I)
0x7E1: MOVF __pcstackCOMMON, W
0x7E2: MOVWF FSR1
0x7E3: MOVF 0x71, W
0x7E4: MOVWF FSR1H
0x7E5: MOVF INDF1, W   <==== pRam is a pointer to a volatile object so is read here
0x7E6: MOVLW 0x1        ==== but I is also volatile so should be read as well.
0x7E7: SUBWF __pcstackCOMMON, F
0x7E8: MOVLW 0x0
0x7E9: SUBWFB 0x71, F
!        {
!            NOP();
0x7EA: NOP
!            NOP();
0x7EB: NOP
!        }
!        else
!        {
!            NOP();
!            NOP();
!        }
!    } while(--I);
0x7EC: MOVLW 0x1
0x7ED: SUBWF I, F
0x7EE: BTFSS STATUS, 0x2
0x7EF: GOTO 0x7F1
0x7F0: GOTO 0x7F2
0x7F1: GOTO 0x7E1
!}
0x7F2: RETURN

Now I fully admit this is a non-issue with this code but I told the compiler that 'I' was volatile so it's not 'suppose' to optimize out the reads and writes.
 
Pointing this out is a small and petty thing to do and fixing this in the XC8 compiler would be a pointless waste of effort.
#6
du00000001
Just Some Member
  • Total Posts : 3787
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 14:27:03 (permalink)
0
dan1138
@du00000001,
 
Yes this is definitely a PEBKAC. I am so embarrassed. :)
 
So in a desperate ubernerd attempt at face saving I did find a completely inconsequential nit-picky issue with the code generation when the 'if' statement get optimized.
 
<...snipped...>
 
Now I fully admit this is a non-issue with this code but I told the compiler that 'I' was volatile so it's not 'suppose' to optimize out the reads and writes.
 
Pointing this out is a small and petty thing to do and fixing this in the XC8 compiler would be a pointless waste of effort.



And what's this one:
0x7ED: SUBWF I, F

 
Not your day today ?
 

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#7
1and0
Access is Denied
  • Total Posts : 10906
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 18:31:55 (permalink)
0
du00000001
 
And what's this one:
0x7ED: SUBWF I, F

 
Not your day today ?

 
That is for
while(--I);

not for
if (*pRam-- == I)

which is Dan's inquiry.
 
 
#8
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 18:35:02 (permalink)
+1 (1)
du00000001
And what's this one:
0x7ED: SUBWF I, F

Not your day today ?

That is the one that does the
} while(--I);

 
The one I am on about is a completely trivial utterly useless read of the volatile object 'I' in the statement:
if (*pRam-- == I)
 
 
For an ISO compliant compiler this is suppose to result in one read of each volatile object because, correct me if I have this wrong, this expression creates a sequence point where the left and right expressions must be evaluated even when either choice causes the same code to execute.
 
This is a minor and trivial notion, not worth the time I have so far wasted on it. But I don't have anything better to do today.
post edited by dan1138 - 2020/06/14 18:36:32
#9
du00000001
Just Some Member
  • Total Posts : 3787
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 19:07:42 (permalink)
0
As we already learned,
*pRam--

is compiled (has to be executed), but the remainder (if ... == I) is dropped as both execution alternatives are identical.
Whether I is volatile or not is irrelevant if the decision doesn't have to be made at all.
Why not create non-identical branches (e.g. 2 vs. 3 NOPs) ?

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#10
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/14 20:13:53 (permalink)
+3 (3)
du00000001
As we already learned,
*pRam--

is compiled (has to be executed), but the remainder (if ... == I) is dropped as both execution alternatives are identical.
Whether I is volatile or not is irrelevant if the decision doesn't have to be made at all.
Why not create non-identical branches (e.g. 2 vs. 3 NOPs) ?

My point, and it is trivial, is that the XC8 optimization behavior is inconsistent with the treatment of volatile elements of an 'if expression'. For this specific case where both are volatile. That the generated code reads one object and not the other when the expression evaluation is removed by the optimizer is inconsistent.
 
Consider this contrived example where the optimized code will fail:
  if (*pRam-- == RCREG) while(RCIF); else while(RCIF);

 
All in all a discussion full of sound and furry signifing nothing. (Apologies to Mr. W. Shakespeare)
post edited by dan1138 - 2020/06/17 08:54:54
#11
mad_c
Super Member
  • Total Posts : 1243
  • Reward points : 0
  • Joined: 2010/12/12 17:48:27
  • Location: Brisbane, Australia
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/16 14:15:17 (permalink)
+5 (5)
dan1138
 
My point, and it is trivial, is that the XC8 optimization behavior is inconsistent with the treatment of volatile elements of an 'if expression'. 

Thanks for pointing this out. It's unlikely to affect many projects, but the volatile object should be read. I have created a report to track this.
 
Jeff.
#12
visenri
Starting Member
  • Total Posts : 9
  • Reward points : 0
  • Joined: 2017/10/25 15:30:29
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/21 11:42:07 (permalink)
0
mad_c
dan1138
 
My point, and it is trivial, is that the XC8 optimization behavior is inconsistent with the treatment of volatile elements of an 'if expression'. 

Thanks for pointing this out. It's unlikely to affect many projects, but the volatile object should be read. I have created a report to track this.
 
Jeff.




I've also seen volatile variables "reads" being optimized out.
 
Has microchip been able to reproduce your reported cases?
#13
dan1138
Super Member
  • Total Posts : 3631
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Is this a known bug in the XC8 v2.20 compiler? 2020/06/21 12:26:13 (permalink)
+2 (2)
visenri
Has microchip been able to reproduce your reported cases?

At a guess that would be a yes, as Jeff(mad_c) has commented in this topic that he had ".. created a report to track this."
 
That said there is almost no practical implementation where a failure to perform a redundant read of a volatile object can actually matter with an XC8 application. There are only a few cases where reading a Special Function Register will change the state of another bit.
 
I was able to contrive code that exploits the condition in XC8. The actual code does nothing useful. No sane person would create this code for any other reason than to show the compiler doesn't conform to the ISO C standard.
 
This is a technical bug in the compiler that cannot have a significant consequence in a real world application.
 
visenri
I've also seen volatile variables "reads" being optimized out.

It would be import if you have examples of the optimizer removing essential reads of volatile objects. You should submit a support case and get a response from Microchip.
post edited by dan1138 - 2020/06/21 12:42:37
#14
Jump to:
© 2020 APG vNext Commercial Version 4.5