[PATCH] D78439: [AVR] Fix miscompilation of zext + add

Ayke via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 19 07:29:11 PDT 2020


aykevl added a comment.

It took me much longer than it should to find a solid reproducer, but here is one:

  // in one file
  uint32_t add(uint32_t a, uint16_t b) {
      return a + b;
  }
  
  // in another file
  uint32_t add(uint32_t a, uint16_t b);
  
  
  // somewhere in the code of that file
  uart_printint("add", add(0x7ffff, 1));

Adding 0x7ffff and 1 should result in 0x80000. However, without this patch it results in 0x60000.

Assembly without this patch:

  d20:       64 0f           add     r22, r20
  d22:       75 1f           adc     r23, r21
  d24:       80 40           sbci    r24, 0x00       ; 0
  d26:       90 40           sbci    r25, 0x00       ; 0
  d28:       08 95           ret

With this patch:

  d1c:       20 e0           ldi     r18, 0x00       ; 0
  d1e:       30 e0           ldi     r19, 0x00       ; 0
  d20:       64 0f           add     r22, r20
  d22:       75 1f           adc     r23, r21
  d24:       82 1f           adc     r24, r18
  d26:       93 1f           adc     r25, r19
  d28:       08 95           ret



> A subtraction of zero is always redundant, therefore the two SBCIs from the first patch are completely redundant, and could be removed by the compiler in a future optimization.

The `sbci` not only subtracts an immediate (in this case zero), but it also subtracts the carry bit. Therefore it definitely does have an effect. This also is true for the last two `adc` instructions: they are needed to add the carry bit in case the previous add instruction caused a wraparound. However `sbci` and `adc` use the carry in the opposite direction (subtracting or adding it to their result).

Looking at AVRInstrInfo.td, I suspect there is a much larger number of these bugs around `sbci`.

I found this bug while trying to add AVR support to compiler-rt. One instance of the bug is here <https://github.com/llvm/llvm-project/blob/release/10.x/compiler-rt/lib/builtins/muldi3.c#L24> (the `+=`). I originally found it somewhere else, but had trouble finding the exact location again.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78439/new/

https://reviews.llvm.org/D78439





More information about the llvm-commits mailing list