| Issue |
203586
|
| Summary |
SPIRV backend asserts on addl/subc intrinsics used in switch
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
sarnex
|
Given the following example
```
unsigned long f(unsigned long a, unsigned long b, int sel) {
unsigned long v;
int of;
switch (sel) {
case 0:
of = __builtin_uaddl_overflow(a, b, &v);
break;
case 1:
of = __builtin_usubl_overflow(a, b, &v);
break;
default:
of = __builtin_uaddl_overflow(a, a, &v);
break;
}
return of ? v : v + 1;
}
```
We see the below asserting when compiling for `spirv64` with `O2`:
```
nsarnie:/llvm/build$ bin/clang -target spirv64 -O2 repro.c
PHI node operands are not the same type as the result!
%.pn = phi i32 [ %2, %sw.default ], [ %1, %sw.bb ], [ %0, %sw.bb1 ]
in function f
fatal error: error in backend: Broken function found, compilation aborted!
```
The IR before `spirv-emit-intrinsics` looks like
```
define spir_func i64 @f(i64 noundef %a, i64 noundef %b, i32 noundef %sel) local_unnamed_addr #0 {
entry:
switch i32 %sel, label %sw.default [
i32 0, label %sw.bb
i32 1, label %sw.bb1
]
sw.bb1: ; preds = %entry
%0 = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
br label %sw.epilog
sw.bb: ; preds = %entry
%1 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
br label %sw.epilog
sw.default: ; preds = %entry
%2 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %a)
br label %sw.epilog
sw.epilog: ; preds = %sw.default, %sw.bb1, %sw.bb
%.pn = phi { i64, i1 } [ %2, %sw.default ], [ %1, %sw.bb ], [ %0, %sw.bb1 ]
%of.0.in = extractvalue { i64, i1 } %.pn, 1
%v.0 = extractvalue { i64, i1 } %.pn, 0
%not.of.0.in = xor i1 %of.0.in, true
%add = zext i1 %not.of.0.in to i64
%cond = add i64 %v.0, %add
ret i64 %cond
}
```
The problem is that in `spirv-emit-intrinsics`, we mutate the type of the PHI node to be i32 to prevent the IRTranslator from seeing a multi-register type (added [here](https://github.com/llvm/llvm-project/pull/186086)), but nothing mutates the incoming blocks to the PHI, so there is a type mismatch(`i32` vs `{ i64, i1 }`), causing the problem.
I'm not totally sure what the fix would be. It seems like we have to mutate the PHI to `i32` to prevent other issues, but then we need to deal with the `CallInst` somehow. Maybe we need a new `spv_usub_with_overflow`? Not sure.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs