IBM Support

IZ94727: INCORRECT 'IF' BRANCH WITH -O2

Subscribe

You can track all active APARs for this component.

 

APAR status

  • Closed as program error.

Error description

  • When compiling at -O2, the test case takes the incorrect branch
    and results in an incorrect output at runtime.
    
    ===== TESTCASE:
    $cat tc.c
    $ cat tc.c
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define FALSE 0
    #define TRUE  1
    
    typedef struct
    {
    #define SAPUP_OPTFLAGS_TMASK            7
    #define SAPUP_OPTFLAGS_TAND             1
    #define SAPUP_OPTFLAGS_TOR              2
    #define SAPUP_OPTFLAGS_TNOT             3
    
    #define SAPUP_OPTFLAGS_FFALSEFOUND      16 /*  If set, false
    subconditions were found  */
    #define SAPUP_OPTFLAGS_FTRUEFOUND       32 /*  If set, true
    subconditions were found  */
    #define SAPUP_OPTFLAGS_FNEGATED        256 /*  If set, we are in
    a negated (i. e. "not" branch)  */
        int Flags;
    
        const char *Node;
    }
    auxstackopteval_t;
    
    #define MAXOPTSDEPTH     200
    
    static int
    testroutine(const char *input, int mode)
    {
        auxstackopteval_t stack[MAXOPTSDEPTH];
        int istack, skipit;
    
        stack[0].Flags = SAPUP_OPTFLAGS_TAND; /*  top level node
    "<options>" is treated as "and"  */
        stack[0].Node = input;
        istack = 0;
    
        for(;;)
        {
            const char *xnode, *next;
            int type;
    
            /*printf("STACK #%d FL %d ND '%s'\n", istack,
    stack[istack].Flags, stack[istack].Node ?
              stack[istack].Node : "<NULL>");*/
    
            xnode = stack[istack].Node;
            if(xnode == NULL || *xnode == '\0' || *xnode == ':') /*
    pop  */
            {
                int oflags;
    
                if(istack == 0)
                    break;
    
                printf("stack[0].Flags = %d, stack[1].Flags = %d\n",
    stack[0].Flags, stack[1].Flags);
    
                /*  Here is where the problems starts: The new two
    lines seem to be executed in
                 *   the wrong order!
                 */
                oflags = stack[istack].Flags;
                --istack;
    
                /*  Merge result  */
                if((oflags & SAPUP_OPTFLAGS_TMASK) ==
    SAPUP_OPTFLAGS_TAND) /*  "and" - one failure sufficient  */
                {
                    stack[istack].Flags |= !(oflags &
    SAPUP_OPTFLAGS_FFALSEFOUND) ?
                        SAPUP_OPTFLAGS_FTRUEFOUND :
    SAPUP_OPTFLAGS_FFALSEFOUND;
                }
                else if((oflags & SAPUP_OPTFLAGS_TMASK) ==
    SAPUP_OPTFLAGS_TOR) /*  "or"  - one success is enough  */
                {
                    stack[istack].Flags |= (oflags &
    SAPUP_OPTFLAGS_FTRUEFOUND) ?
                        SAPUP_OPTFLAGS_FTRUEFOUND :
    SAPUP_OPTFLAGS_FFALSEFOUND;
                }
                else
                {
                    stack[istack].Flags |= (oflags &
    SAPUP_OPTFLAGS_FFALSEFOUND) ?
                        SAPUP_OPTFLAGS_FTRUEFOUND :
    SAPUP_OPTFLAGS_FFALSEFOUND; /*  "not" - negate  */
                }
    
                if(oflags != stack[istack + 1].Flags)
                    printf("*** BUG!!! Should have read
    stack[%d].Flags = %d, but have %d\n", istack + 1,
                           stack[istack + 1].Flags, oflags);
                else
                    printf("*** OK Read stack[%d].Flags = %d.\n",
    istack + 1, stack[istack + 1].Flags);
    
                continue;
            }
    
            next = strchr(xnode, ':') + 1;
    
            if(*xnode == 'a')
            {
                type = SAPUP_OPTFLAGS_TAND;
            }
            else if(*xnode == 'o')
            {
                type = SAPUP_OPTFLAGS_TOR;
            }
            else if(*xnode == '!')
            {
                type = SAPUP_OPTFLAGS_TNOT;
            }
            else if(*xnode == '+' || *xnode == '-')
            {
                int flags, emode, condition;
    
                type = 0;
                flags = stack[istack].Flags;
    
                condition = *xnode == '+' ? 2 : 1;
    
                /*  Check if condition applies at all  */
                if(condition != 0)
                {
                    condition = condition == 2; /*  map to proper
    TRUE/FALSE  */
    
                    stack[istack].Flags |= condition ?
    SAPUP_OPTFLAGS_FTRUEFOUND : SAPUP_OPTFLAGS_FFALSEFOUND;
    
                    /*  Short circuit for "and" and "or"  */
                    if(!(mode & 8) &&
                       (flags & SAPUP_OPTFLAGS_TMASK) == (condition
    ? SAPUP_OPTFLAGS_TOR : SAPUP_OPTFLAGS_TAND))
                    {
                        /*  We can finish the loop since at least
    one is true (for "or")
                         *   or at least one is false (for "and").
                         */
                        next = NULL;
                    }
                }
            }
            else
            {
                fprintf(stderr, "Internal error: Invalid condition
    node '%s' - expect and/or/not/option", input);
                goto error;
            }
    
            /*  Advance on same level  */
            stack[istack].Node = next;
    
            if(type != 0)
            {
                int isneg;
    
                /* ***  push  *** */
                isneg = stack[istack].Flags &
    SAPUP_OPTFLAGS_FNEGATED;
                if(type == SAPUP_OPTFLAGS_TNOT)
                    isneg ^= SAPUP_OPTFLAGS_FNEGATED;
    
                ++istack;
                stack[istack].Flags = isneg | type;
                stack[istack].Node  = input + 1;
                continue;
            }
        }
    
        /*  Top level is "and" condition, so one false is enough to
    fail completely  */
        skipit = (stack[0].Flags & SAPUP_OPTFLAGS_FFALSEFOUND) ?
    TRUE : FALSE;
    
        return skipit;
    error:
        return -1;
    }
    
    int main(int argc, char *argv[])
    {
        int rc;
    
        rc = testroutine("o+-:", 0);
    
        printf("RC %d\n", rc);
        return 0;
    }
    
    $
    
    
    
    ===== ACTUAL OUTPUT:
    $ ./tc
    stack[0].Flags = 1, stack[1].Flags = 34
    *** BUG!!! Should have read stack[1].Flags = 34, but have 1
    RC 1
    
    ===== EXPECTED OUTPUT:
    $ ./tc
    stack[0].Flags = 1, stack[1].Flags = 34
    *** OK Read stack[1].Flags = 34.
    RC 0
    

Local fix

  • N/A
    

Problem summary

  • USERS AFFECTED:
    This is a pattern sensitive optimization defect. Some users
    that compile with optimization may encounter this problem.
    
    PROBLEM DESCRIPTION:
    A specific optimization function failed to invalidate an
    internal optimizer cache after a state change.
    

Problem conclusion

  • The optimization function has been fixed to validate the
    internal optimizer cache after a state change.
    

Temporary fix

Comments

APAR Information

  • APAR number

    IZ94727

  • Reported component name

    XLC C++ AIX

  • Reported component ID

    5724M1200

  • Reported release

    800

  • Status

    CLOSED PER

  • PE

    NoPE

  • HIPER

    NoHIPER

  • Special Attention

    NoSpecatt

  • Submitted date

    2011-02-08

  • Closed date

    2011-05-11

  • Last modified date

    2011-05-12

Fix information

  • Fixed component name

    XLC AIX

  • Fixed component ID

    5724M1100

Applicable component levels

[{"Line of Business":{"code":"LOB08","label":"Cognitive Systems"},"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SSJT9L","label":"XL C\/C++"},"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"8.0"}]

Document Information

Modified date:
07 October 2021