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

Multiplication assignment operation, int32 *= (uint16_t)int16, incorrectly loses the cast to uint16_t during optimization

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Medium Medium
    • Code Generation Tools
    • CODEGEN-12778
    • Hide
      C2000_22.6.0.LTS
      C2000_18.1.7.LTS
      C2000_21.6.0.LTS
      C2000_18.12.3.LTS
      C2000_20.2.0.LTS
      Show
      C2000_22.6.0.LTS C2000_18.1.7.LTS C2000_21.6.0.LTS C2000_18.12.3.LTS C2000_20.2.0.LTS
    • Hide
      C2000_25.3.0.LTS*
      C2000_22.6.3.LTS
      C2000_21.6.2.LTS*
      Show
      C2000_25.3.0.LTS* C2000_22.6.3.LTS C2000_21.6.2.LTS*
    • default
    • Use --opt_level=off or 0

      Multiplication assignment operation like below that assigns to a int32_t/uint32_t variable from either a int16_t variable which is then cast to uint16_t (or an uint16_t variable which is then cast to int16_t) will receive an invalid optimization that incorrectly eliminates the cast:

      This C code:
      var_int32_t/var_uint32_t *= (uint16_t)var_int16_t
      is incorrectly converted to below:
      var_int32_t/var_uint32_t *= var_int16_t

      And this C code:
      var_int32_t/var_uint32_t *= (int16_t)var_uint16_t
      is incorrectly converted to below:
      var_int32_t/var_uint32_t *= var_uint16_t

      NOTE: below may also have the issue:
      var_int32 = var_int32 * (uint16_t)var_int16_t

      To see the issue in the generated assembly, use option --src_interlist and below C code:
      vint32 *= (uint16_t)vint16;
      Will have assembly with below optimizer comments showing the lack of cast to uint16_t:
      ;*** 10 -------------- vint32 *= vint16;

      Original description:
      The attached file has these lines ...

      int16_t gv1_i16 = 0xC0;
      int16_t gv2_i16 = 0xC000;
      
      int32_t multiply_with_global()
      {
          int32_t lv1_i32;
      
          lv1_i32 = gv1_i16;
          lv1_i32 *= (uint16_t)gv2_i16;
          return lv1_i32; // incorrect: -3145728
      }
      

      Build it ...

      % cl2000 -@options.txt file.c
      

      Inspect the resulting assembly file. Ignore the debug directives. The key lines of assembly are:

      _multiply_with_global:
      ;* AL    assigned to _lv1_i32
      ;*** 10	-----------------------    _lv1_i32 = gv1_i16;
      ;*** 11	-----------------------    _lv1_i32 *= gv2_i16;
      ;*** 12	-----------------------    return _lv1_i32;
              MOVW      DP,#_gv1_i16          ; [CPU_ARAU] 
              SETC      SXM                   ; [CPU_ALU] 
              MOVX      TL,@_gv2_i16          ; [CPU_ALU] |11| 
              MOV       ACC,@_gv1_i16         ; [CPU_ALU] |10| 
              IMPYL     ACC,XT,ACC            ; [CPU_ALU] |11| 
              LRETR     ; [CPU_FPU]
      

      Note how a signed instruction is used to load gv1_i16. Because of the cast to uint16_t, that should be an unsigned load.

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

              Created:
              Updated: