This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CL430.... calls __mpyi when implemeting the CLIP macro

cl430 mangles a nested version of CLIP()

 

With....

#define MAX(a,b)  (((a)>(b))?(a):(b))

#define MIN(a,b)  (((a)<(b))?(a):(b))

#define CLIP(n, min, max) MIN((MAX((n),(min))), (max))

 

   n = CLIP(n, 0, 4095);   preprocesses to:

   n = ((((((((n))>((0)))?((n)):((0)))))<((4095)))?((((((n))>((0)))?((n)):((0))))):((4095)));

    which expands to:

n =
(
   (
      (
         (
            (
               (
                  ((n))>((0))
               )
               ?
               ((n))
               :
               ((0))
            )
         )
      )
      <
      ((4095))
   )
   ?
   (
      (
         ((((n))>((0)))
         ?
         ((n))
         :
         ((0)))
      )
   )
   :
   ((4095))
);


     and compiles to....

      77 000000 0CCB          MOVA      r12,r11               ; [] |40|
      79 000002 430F          MOV.W     #0,r15                ; [] |41|
      80 000004 930B          TST.W     r11                   ; [] |41|
      81 000006 3801          JL        $C$L1                 ; [] |41|
      84 000008 431F          MOV.W     #1,r15                ; [] |41|
      86 00000a       $C$L1:   
      87 00000a 0FCC          MOVA      r15,r12               ; [] |41|
      88 00000c 0BCD          MOVA      r11,r13               ; [] |41|
      93 00000e 13B0!         CALLA     #__mpyi               ; [] |41|
         000010 0000
      95 000012 903C          CMP.W     #4095,r12             ; [] |41|
      96 000016 3803          JL        $C$L2                 ; [] |41|
      99 000018 403B          MOV.W     #4095,r11             ; [] |41|
     100 00001c 3C05          JMP       $C$L3                 ; [] |41|
     103 00001e       $C$L2:   
     104 00001e 0BCC          MOVA      r11,r12               ; [] |41|
     105 000020 0FCD          MOVA      r15,r13               ; [] |41|
     110 000022 13B0!         CALLA     #__mpyi               ; [] |41|
     112 000026 0CCB          MOVA      r12,r11               ; [] |41|
     114 000028       $C$L3:   

which should actually work, despite the multiplies  The non-nested version of the macro elicits a sane behavior.

#define CLIP(n, min, max) (((n)<(min))?(min):(((n)>(max))?(max):(n)))

   .....   n = (((n)<(0))?(0):(((n)>(4095))?(4095):(n)));  ....

      77 000000 930C          TST.W     r12                   ; [] |41|
      78 000002 3806          JL        $C$L1                 ; [] |41|
      81 000004 903C          CMP.W     #4096,r12             ; [] |41|
      82 000008 3804          JL        $C$L2                 ; [] |41|
      85 00000a 403C          MOV.W     #4095,r12             ; [] |41|
      86 00000e 3C01          JMP       $C$L2                 ; [] |41|
      89 000010       $C$L1:   
      90 000010 430C          MOV.W     #0,r12                ; [] |41|
      92 000012       $C$L2:   

Lots of extra braces in the verbose expansion, but it looks legal. Compiler guys! What's up?

 

     regards Steven Pruzina

 

 

 

 

  • Sorry for the delay.

    The two CLIP macros are quite different actually.  The first one is similar to this C code ...

       // Assign clipped value to r
       if (n > 0)    temp = n;    // 1st MAX
       else          temp = 0;

       if (temp < 4095)
       {
          if (n > 0) r = n;       // 2nd MAX
          else       r = 0;
       }
       else
          r = 4095;

    Notice how MAX is invoked two times.  The 2nd implementation of CLIP is similar to this C code ...
       // Assign clipped value to r
       if (n < 0)         r = 0;
       else if (n > 4095) r = 4095;
       else               r = n;
    It is little surprise the 2nd implementation works better.  
    I don't know why the multiplies are being done.  I need a test case I can use to reproduce that output.
    Thanks and regards,
    -George

     

  • For each multiply, one of the operands is a boolean value.  The idea is undoubtedly to use a multiplication by 0 or 1 to avoid using a branch to implement a ternary operator.  George is correct, we need a compilable test case to pursue this further.

  • We managed to reproduce the inefficiency of using multiply to compute a boolean value.  SDSCM00035238 has been filed in our ClearQuest system.  Feel free to query status on this entry here.  Use the "Find Record ID" box.

    Thanks and regards,

    -George