llvm / llvm/llvm-project

Loop reduction optimization incorrectly propagates poison

Open
#177,729 7 comments 0 reactions 1 assignee Claimed by @kshitijvp View on GitHub
generated by fuzzer llvm:SCEV loopoptim miscompilation
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

**Fuzzer Generated Test**
**Reproducer**
https://alive2.llvm.org/ce/z/eCwTnN

**Description**
When a loop executes zero times, the source returns the initial phi value without using the loop-variant input, but the optimizer transforms this to compute `input * count` which propagates poison.

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

```llvm
define i8 @test(i32 %x, i32 %n) {
entry:
br label %for.cond

for.cond: ; preds = %for.cond, %entry
%load.r1 = phi i32 [ %ibinop2, %for.cond ], [ 0, %entry ]
%load = phi i32 [ %ibinop, %for.cond ], [ 0, %entry ]
%ibinop2 = add i32 %load.r1, %x
%ibinop = add i32 %load, 1
%icmp = icmp slt i32 %load, %n
br i1 %icmp, label %for.cond, label %for.end

for.end: ; preds = %for.cond
%t = trunc i32 %load.r1 to i8
ret i8 %t
}
```

**Output**

```llvm
----------------------------------------
define i8 @test(i32 %x, i32 %n) {
entry:
br label %for.cond

for.cond:
%load.r1 = phi i32 [ %ibinop2, %for.cond ], [ 0, %entry ]
%load = phi i32 [ %ibinop, %for.cond ], [ 0, %entry ]
%ibinop2 = add i32 %load.r1, %x
%ibinop = add i32 %load, 1
%icmp = icmp slt i32 %load, %n
br i1 %icmp, label %for.cond, label %for.end

for.end:
%t = trunc i32 %load.r1 to i8
ret i8 %t
}
=>
define i8 @test(i32 %x, i32 %n) nofree willreturn memory(none) {
entry:
%smax = smax i32 %n, 0
%#0 = mul i32 %x, %smax
%t = trunc i32 %#0 to i8
ret i8 %t
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i32 %x = poison
i32 %n = #x00000000 (0)

Source:
>> Jump to %for.cond
i32 %load.r1 = #x00000000 (0)
i32 %load = #x00000000 (0)
i32 %ibinop2 = poison
i32 %ibinop = #x00000001 (1)
i1 %icmp = #x0 (0)
>> Jump to %for.end
i8 %t = #x00 (0)

Target:
i32 %smax = #x00000000 (0)
i32 %#0 = poison
i8 %t = poison
Source value: #x00 (0)
Target value: poison

Summary:
0 correct transformations
1 incorrect transformations
0 failed-to-prove transformations
0 Alive2 errors
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.