Uploaded image for project: 'Embedded Software & Tools'
  1. Embedded Software & Tools
  2. EXT_EP-11783

Compiler may optimize incorrectly when assigning boolean vector result of a vector compare to a non-variable left hand side (e.g. a dereferenced pointer, or struct field)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Medium Medium
    • Code Generation Tools
    • CODEGEN-12527
    • Hide
      C7000_3.1.0.LTS
      C7000_4.1.0.LTS
      Show
      C7000_3.1.0.LTS C7000_4.1.0.LTS
    • Hide
      C7000_3.1.2.LTS
      C7000_5.0.0.LTS*
      C7000_4.1.1.LTS*
      Show
      C7000_3.1.2.LTS C7000_5.0.0.LTS* C7000_4.1.1.LTS*
    • default
    • Hide
      Introduce a volatile temp variable before assignment of the boolean vector.

      for example, the following code can be converted as such:

      Original version:
      {noformat}
         // Run test
         for (uint16_t i = 0; i < USED_SIZE; i += 16)
         {
            __float16 vecZero = (__float16)(0);
            __float16 vec = *(__float16 *)(array + i);
            __bool16 cmp_res = __cmp_lt_bool(vec, vecZero);

            //SimdVectorTest is a class which holds a boolean vector
            SimdVectorTest cmp_res_v = SimdVectorTest::fromNative(cmp_res);
            cmp_res = cmp_res_v.toNative(); //this returns a reference to the
                                            //stored boolean vector

            __float16 res = __select(cmp_res, vec, vecZero);
            *(__float16 *)(array + i) = res;
         }

         // Verify Results
         for (uint16_t i = 45; i < 60; ++i)
            printf("array[%d]: %g\n", i, array[i]);
      {noformat}

      Workaround version:
      {noformat}
         // Run test
         for (uint16_t i = 0; i < USED_SIZE; i += 16)
         {
            __float16 vecZero = (__float16)(0);
            __float16 vec = *(__float16 *)(array + i);
            __bool16 cmp_res = __cmp_lt_bool(vec, vecZero);

            volatile __bool16 temp = cmp_res;

            //SimdVectorTest is a class which holds a boolean vector
            SimdVectorTest cmp_res_v = SimdVectorTest::fromNative(temp);
            cmp_res = cmp_res_v.toNative(); //this returns a reference to the
                                            //stored boolean vector

            __float16 res = __select(cmp_res, vec, vecZero);
            *(__float16 *)(array + i) = res;
         }

         // Verify Results
         for (uint16_t i = 45; i < 60; ++i)
            printf("array[%d]: %g\n", i, array[i]);
      {noformat}

      Show
      Introduce a volatile temp variable before assignment of the boolean vector. for example, the following code can be converted as such: Original version: {noformat}    // Run test    for (uint16_t i = 0; i < USED_SIZE; i += 16)    {       __float16 vecZero = (__float16)(0);       __float16 vec = *(__float16 *)(array + i);       __bool16 cmp_res = __cmp_lt_bool(vec, vecZero);       //SimdVectorTest is a class which holds a boolean vector       SimdVectorTest cmp_res_v = SimdVectorTest::fromNative(cmp_res);       cmp_res = cmp_res_v.toNative(); //this returns a reference to the                                       //stored boolean vector       __float16 res = __select(cmp_res, vec, vecZero);       *(__float16 *)(array + i) = res;    }    // Verify Results    for (uint16_t i = 45; i < 60; ++i)       printf("array[%d]: %g\n", i, array[i]); {noformat} Workaround version: {noformat}    // Run test    for (uint16_t i = 0; i < USED_SIZE; i += 16)    {       __float16 vecZero = (__float16)(0);       __float16 vec = *(__float16 *)(array + i);       __bool16 cmp_res = __cmp_lt_bool(vec, vecZero);       volatile __bool16 temp = cmp_res;       //SimdVectorTest is a class which holds a boolean vector       SimdVectorTest cmp_res_v = SimdVectorTest::fromNative(temp);       cmp_res = cmp_res_v.toNative(); //this returns a reference to the                                       //stored boolean vector       __float16 res = __select(cmp_res, vec, vecZero);       *(__float16 *)(array + i) = res;    }    // Verify Results    for (uint16_t i = 45; i < 60; ++i)       printf("array[%d]: %g\n", i, array[i]); {noformat}

      The attached file has this code ...

         // Run test
         for (uint16_t i = 0; i < USED_SIZE; i += 16)
         {
            __float16 vecZero = (__float16)(0);
            __float16 vec = *(__float16 *)(array + i);
            __bool16 cmp_res = __cmp_lt_bool(vec, vecZero);
      
            SimdVectorTest cmp_res_v = SimdVectorTest::fromNative(cmp_res);
            cmp_res = cmp_res_v.toNative();
      
            __float16 res = __select(cmp_res, vec, vecZero);
            *(__float16 *)(array + i) = res;
         }
      
         // Verify Results
         for (uint16_t i = 45; i < 60; ++i)
            printf("array[%d]: %g\n", i, array[i]);
      

      SimdVectorTest is a class that wraps the vector type __bool16. When built with no optimization, the expected result is produced.

      array[45]: -5
      array[46]: -4
      array[47]: -3
      array[48]: -2
      array[49]: -1
      array[50]: 0
      array[51]: 0
      array[52]: 0
      array[53]: 0
      array[54]: 0
      array[55]: 0
      array[56]: 0
      array[57]: 0
      array[58]: 0
      array[59]: 0
      

      When built with --opt_level=3, incorrect output is produced.

      array[45]: -5
      array[46]: -4
      array[47]: -3
      array[48]: -2
      array[49]: -1
      array[50]: 0
      array[51]: 1
      array[52]: 2
      array[53]: 3
      array[54]: 4
      array[55]: 5
      array[56]: 0
      array[57]: 0
      array[58]: 0
      array[59]: 0
      

            syncuser TI User
            syncuser TI User
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: