llvm / llvm/llvm-project

[ARM] __builtin_subc() does not generate SBC instruction

Open
#204,270 1 comment 0 reactions 0 assignees View on GitHub
backend:ARM
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

On 32-bit ARM, `__builtin_addc()` works to generate ADC, but `__builtin_subc()` appears to always perform two integer subtractions. I found an open PR that seems to address a similar optimization issue, though I'm not sure if it directly fixes this: https://github.com/llvm/llvm-project/pull/184021

https://godbolt.org/z/MYdMY85TK

```c
unsigned long long add64(unsigned x0, unsigned x1, unsigned y0, unsigned y1)
{
unsigned carry = 0;
x0 = __builtin_addc(x0, y0, carry, &carry);
x1 = __builtin_addc(x1, y1, carry, &carry);
return (unsigned long long)x1 << 32 | x0;
}

unsigned long long sub64(unsigned x0, unsigned x1, unsigned y0, unsigned y1)
{
unsigned carry = 0;
x0 = __builtin_subc(x0, y0, carry, &carry);
x1 = __builtin_subc(x1, y1, carry, &carry);
return (unsigned long long)x1 << 32 | x0;
}
```

```gas
add64:
adds r0, r0, r2
adc r1, r3, r1
bx lr

sub64:
sub r1, r1, r3
mov r3, #0
subs r0, r0, r2
adc r2, r3, #0
eor r2, r2, #1
sub r1, r1, r2
bx lr
```

Contributor guide

Open the contributing guide

Research direction

Start with the Godbolt reproducer and compare the ARM assembly for __builtin_addc() and __builtin_subc(), then inspect the LLVM lowering and instruction-selection paths for these builtins. The related PR #184021 may provide context; done means the subtraction sequence produces the expected SBC instruction without regressing the existing addc behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.