| Issue |
185099
|
| Summary |
[VectorCombine] Incorrect pointer offset when shrinking `shufflevector` loads of `<N x i1>`
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
cardigan1008
|
This is a miscompilation case when reviewing https://github.com/llvm/llvm-project/pull/179001:
```llvm
@g = global [2 x i8] [i8 170, i8 0], align 32
define i32 @shuffle_v8_v8i1_cond_r1_2(ptr nocapture readonly %arg0, i1 %cond) local_unnamed_addr {
entry:
%val0 = load <8 x i1>, ptr %arg0, align 1
br i1 %cond, label %then, label %else
then: ; preds = %entry
%val1 = shufflevector <8 x i1> %val0, <8 x i1> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
br label %finally
else: ; preds = %entry
%val2 = shufflevector <8 x i1> %val0, <8 x i1> poison, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
br label %finally
finally: ; preds = %else, %then
%val3 = phi <8 x i1> [ %val1, %then ], [ %val2, %else ]
%res = bitcast <8 x i1> %val3 to i8
%res32 = zext i8 %res to i32
ret i32 %res32
}
define i32 @main(i32 %argc, ptr %argv) {
entry:
%r = call i32 @shuffle_v8_v8i1_cond_r1_2(ptr @g, i1 true)
ret i32 %r
}
```
**Transformed LLVM IR:**
```llvm
; ModuleID = '/data/tmp/tmpqj2ym6tl/orig.ll'
source_filename = "/data/tmp/tmpqj2ym6tl/orig.ll"
@g = global [2 x i8] c"\AA\00", align 32
define i32 @shuffle_v8_v8i1_cond_r1_2(ptr readonly captures(none) %arg0, i1 %cond) local_unnamed_addr {
entry:
%0 = getelementptr inbounds i8, ptr %arg0, i64 1
%1 = load <2 x i1>, ptr %0, align 1
br i1 %cond, label %then, label %else
then: ; preds = %entry
%val1 = shufflevector <2 x i1> %1, <2 x i1> poison, <8 x i32> zeroinitializer
br label %finally
else: ; preds = %entry
%val2 = shufflevector <2 x i1> %1, <2 x i1> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
br label %finally
finally: ; preds = %else, %then
%val3 = phi <8 x i1> [ %val1, %then ], [ %val2, %else ]
%res = bitcast <8 x i1> %val3 to i8
%res32 = zext i8 %res to i32
ret i32 %res32
}
define i32 @main(i32 %argc, ptr %argv) {
entry:
%r = call i32 @shuffle_v8_v8i1_cond_r1_2(ptr @g, i1 true)
ret i32 %r
}
```
Ran lli on them, we got different results:
```sh
$ lli src.ll
$ echo $?
255
$ lli tgt.ll
$ echo $?
0
```
Alive2 also proved this: https://alive2.llvm.org/ce/z/sNXJtP
> Note: This is a review assisted with a self-built agent. The reproducer was validated manually. Please let me know if anything is wrong.
**Bug Triggering Analysis:**
The provided test case loads an `<8 x i1>` vector from a global variable `@g` which is initialized to `[i8 170, i8 0]`. The first byte is `10101010` in binary. The `shufflevector` extracts the element at index 1, which is `1` (`true`). The result is a vector of all `true`s, which is bitcasted to `i8` resulting in `255`.
The `VectorCombine` pass shrinks the load to `<2 x i1>` starting at index 1. It calculates the pointer offset as `1 * getTypeAllocSize(i1) = 1 * 1 = 1` byte. It adds 1 byte to the pointer, reading from the second byte of `@g`, which is `0`. The result is a vector of all `false`s, which is bitcasted to `i8` resulting in `0`.
This causes a difference in execution, confirming the bug.
**Fix Weakness Analysis:**
The fix uses `DL->getTypeAllocSize(ElemTy)` to compute the element size in bytes. This is incorrect for non-byte-sized elements like `i1` or `i4`, because `getTypeAllocSize` rounds up to the nearest byte. For `i1`, it returns 1 byte. Multiplying `LowOffset` by this rounded-up size results in an incorrect byte offset for the pointer addition. The fix should either check if the element type is byte-sized (`DL->typeSizeEqualsStoreSize(ElemTy)`) or calculate the offset in bits and check if it's a multiple of 8.
cc @Icohedron
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs