llvm / llvm/llvm-project

[RISC-V][GlobalISel] Miscompilation where a bitwise-and of a value with its own negation is dropped, returning only the negation

Open
#203,972 5 comments 0 reactions 0 assignees View on GitHub
backend:RISC-V llvm:globalisel miscompilation
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

**Fuzzer Generated Test**
**Reproducer**
1. SelectionDAG - https://godbolt.org/z/jTTfefPr3
2. GlobalISel - https://godbolt.org/z/14Y9Y73zn

**Test Commit**
[efb038f38f23ee201ac872ae98668c2ef922f0fa](https://github.com/llvm/llvm-project/commit/efb038f38f23ee201ac872ae98668c2ef922f0fa)

**Description**
Since `mul nuw i32 x, -1` equals `-x`, the function is the lowest-set-bit idiom `x & -x`, but GlobalISel drops the `and` and returns just `-x`

**Steps to reproduce**
- Minimized test case, `input.ll`

```llvm
define i32 @f(i32 %x) {
%neg = mul nuw i32 %x, -1
%r = and i32 %x, %neg
ret i32 %r
}
```

```
llc -mtriple=riscv64 -mattr=+m,+b input.ll # SelectionDAG
llc -mtriple=riscv64 -mattr=+m,+b -global-isel input.ll # GlobalISel
```

**Output**

; SelectionDAG (x & -x)

```asm
f:
negw a1, a0
and a0, a0, a1
ret
```

; GlobalISel (drops the `and`, returns -x)

```asm
f:
negw a0, a0
ret
```

With `x = 1` (`mul nuw 1, -1` = `0xFFFFFFFF`, poison-free): source `1 & -1 = 1`, GlobalISel returns `0xFFFFFFFF` (`-1`)

**CC**: @regehr

Contributor guide

Open the contributing guide

Research direction

Start with the minimized test case in input.ll and run both llc commands shown for riscv64, with and without -global-isel. Compare the generated assembly: GlobalISel should preserve the x & -x operation rather than returning only -x, matching the SelectionDAG result.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.