Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: Evaluation - 05.12

>
>
>
About optimizations

About optimizations

Feb 15 2017

Verifying the recommendation "Don't do the compilers job" from the book "The Ultimate Question of Programming, Refactoring, and Everything".

Note. The article was first published in Russian on livejournal.com. The article and is translation are posted on our website with the author's permission.

In the blog of PVS-Studio team you can find many examples of errors made by programmers and the recommendations of how you can avoid these mistakes (http://www.viva64.com/en/b/0391/).

The first piece of advice: don't do the compilers job. Do not optimize manually those fragments that will be optimized anyway. As an example we see a code fragment taken from MySQL project where a programmer deployed a loop manually and made a mistake. Further on, the author says if we write this function with a loop, the compiler will most likely deploy it itself.

Let's check it with the help of the online compiler. I copied the source code of function from the article and edited them a little bit so that they would compile without any additional files.

The compilation was done with the help of clang 3.9 compiler for the arm target with the optimization level -O2 (with these settings the compiler deploys the loops).

So, here is the original source code:

int rr_cmp(unsigned char *a, unsigned char *b)
{
  if (a[0] != b[0])
    return (int) a[0] - (int) b[0];
  if (a[1] != b[1])
    return (int) a[1] - (int) b[1];
  if (a[2] != b[2])
    return (int) a[2] - (int) b[2];
  if (a[3] != b[3])
    return (int) a[3] - (int) b[3];
  if (a[4] != b[4])
    return (int) a[4] - (int) b[4];
  if (a[5] != b[5])
    return (int) a[5] - (int) b[5];
  if (a[6] != b[6])
    return (int) a[6] - (int) b[6];
  return (int) a[7] - (int) b[7];
}

The result for arm:

rr_cmp(unsigned char*, unsigned char*):
@ @rr_cmp(unsigned char*, unsigned char*)
        ldrb    r2, [r1]
        ldrb    r3, [r0]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #1]
        ldrb    r3, [r0, #1]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #2]
        ldrb    r3, [r0, #2]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #3]
        ldrb    r3, [r0, #3]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #4]
        ldrb    r3, [r0, #4]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #5]
        ldrb    r3, [r0, #5]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #6]
        ldrb    r3, [r0, #6]
        cmp     r3, r2
        ldrbeq  r1, [r1, #7]
        ldrbeq  r0, [r0, #7]
        subeq   r0, r0, r1
        bxeq    lr
.LBB0_7:
        sub     r0, r3, r2
        bx      lr

The source code, suggested by the author from PVS-Studio:

int rr_cmp(unsigned char *a,unsigned char *b)
{
  for (int i = 0; i < 7; ++i)
  {
    if (a[i] != b[i])
      return a[i] - b[i]; 
  }
  return a[7] - b[7];
}

Result:

rr_cmp(unsigned char*, unsigned char*):
@ @rr_cmp(unsigned char*, unsigned char*)
        ldrb    r2, [r1]
        ldrb    r3, [r0]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #1]
        ldrb    r3, [r0, #1]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #2]
        ldrb    r3, [r0, #2]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #3]
        ldrb    r3, [r0, #3]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #4]
        ldrb    r3, [r0, #4]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #5]
        ldrb    r3, [r0, #5]
        cmp     r3, r2
        bne     .LBB0_7
        ldrb    r2, [r1, #6]
        ldrb    r3, [r0, #6]
        cmp     r3, r2
        ldrbeq  r1, [r1, #7]
        ldrbeq  r0, [r0, #7]
        subeq   r0, r0, r1
        bxeq    lr
.LBB0_7:
        sub     r0, r3, r2
        bx      lr

Well... "Find 10 differences".

It's all the same.

However, oddly enough, the result for x86-64 will be slightly different. But this is another story.



Comments (0)

Next comments next comments
close comment form