arm-none-eabi-gcc miscompiles code sequence

Bug #1436058 reported by Guillermo Loyola
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
GNU Arm Embedded Toolchain
Invalid
Critical
Unassigned

Bug Description

* Release version:
    Problem seen in all of 4_8-2014q3-20140805, 4_9-2014q4-20141203 and 4_9-2015q1-20150306.

* Host
    Using binary releases for both MacOS and Linux, as downloaded directly from launchpad. The disassembly files attached were produced on MacOS with 2015q1

* Test case/symptom
    The simple code sequence in the lnat.c file attached is being miscompiled at any optimization level other than O0.

    Specifically the code generated for the while statement:

            li = 0;
            while ( ((b.A[id][li] & 0x80) == 0) && (li < 6) ) {
                    li++;
            }

    is completely missing the (li < 6) test. When linked together with test.c and run, the output is:

    lnat: id 0, li 12
    lnat: id 0, li 12

    showing that li is allowed to go past the limit of 6.

Revision history for this message
Guillermo Loyola (gmo-5) wrote :
Revision history for this message
Joey Ye (jinyun-ye) wrote :

Incredible to be wrong with such a simple case. Thanks reporting and will verify it tomorrow.

Revision history for this message
Guillermo Loyola (gmo-5) wrote :

The source file with main() is missing. Added here.

Changed in gcc-arm-embedded:
status: New → Confirmed
importance: Undecided → Critical
Revision history for this message
Thomas Preud'homme (thomas-preudhomme) wrote :

As my colleague Bin Cheng pointed out, this is because the code rely on undefined behavior. Indeed, b_struct is defined as:

struct b_struct
{
    uint8_t A[7][6];
};

So a given row of A has only 6 elements. Therefore the first check ((b.A[id][li] & 0x80) == 0) is undefined for li >= 6 and GCC assumes this code is never executed for such values of li. This is why the second condition is removed.

You can tell GCC not to optimize so aggressively by using -faggressive-loop-optimizations.

Best regards.

Changed in gcc-arm-embedded:
status: Confirmed → Invalid
Revision history for this message
Joey Ye (jinyun-ye) wrote : Re: [Bug 1436058] Re: arm-none-eabi-gcc miscompiles code sequence

My suggestion would be to put li<6 test before the other test, which should
avoid the undefined behavior.
On Mar 25, 2015 3:15 AM, "Thomas Preud'homme" <email address hidden>
wrote:

> As my colleague Bin Cheng pointed out, this is because the code rely on
> undefined behavior. Indeed, b_struct is defined as:
>
> struct b_struct
> {
> uint8_t A[7][6];
> };
>
> So a given row of A has only 6 elements. Therefore the first check
> ((b.A[id][li] & 0x80) == 0) is undefined for li >= 6 and GCC assumes
> this code is never executed for such values of li. This is why the
> second condition is removed.
>
> You can tell GCC not to optimize so aggressively by using -faggressive-
> loop-optimizations.
>
> Best regards.
>
> ** Changed in: gcc-arm-embedded
> Status: Confirmed => Invalid
>
> --
> You received this bug notification because you are a member of GCC ARM
> Embedded Maintainers, which is subscribed to GCC ARM Embedded.
> https://bugs.launchpad.net/bugs/1436058
>
> Title:
> arm-none-eabi-gcc miscompiles code sequence
>
> Status in GNU Tools for ARM Embedded Processors:
> Invalid
>
> Bug description:
> * Release version:
> Problem seen in all of 4_8-2014q3-20140805, 4_9-2014q4-20141203 and
> 4_9-2015q1-20150306.
>
> * Host
> Using binary releases for both MacOS and Linux, as downloaded
> directly from launchpad. The disassembly files attached were produced on
> MacOS with 2015q1
>
> * Test case/symptom
> The simple code sequence in the lnat.c file attached is being
> miscompiled at any optimization level other than O0.
>
> Specifically the code generated for the while statement:
>
> li = 0;
> while ( ((b.A[id][li] & 0x80) == 0) && (li < 6) ) {
> li++;
> }
>
> is completely missing the (li < 6) test. When linked together with
> test.c and run, the output is:
>
> lnat: id 0, li 12
> lnat: id 0, li 12
>
> showing that li is allowed to go past the limit of 6.
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/gcc-arm-embedded/+bug/1436058/+subscriptions
>

Revision history for this message
Guillermo Loyola (gmo-5) wrote :

Thanks you for your analysis, I certainly get the correct behavior if I change the order of the conditionals.

Could this case become a new warning from the compiler?

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.