llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.3k stars 11.68k forks source link

[SPIR-V] Bad OpSwitch generation with i64 immediates #94964

Open Keenuts opened 3 months ago

Keenuts commented 3 months ago

When a 64-bit immediate value is used in a switch construct, the SPIR-V emitter splits the 64bit int into 2 32-bit integers, causing a bad instruction to be generated:

OpSwitch %5 %8 4294967295 4294967295 %9
instead of
OpSwitch %5 %8 -1 %9

Test case to reproduce:

; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-SPIRV:        %[[#cond:]] = OpFunctionParameter %[[#]]
; CHECK-SPIRV:                      OpSwitch %[[#cond]] %[[#default:]] -1 %[[#case_one:]]
; CHECK-SPIRV-DAG:  %[[#default]] = OpLabel
; CHECK-SPIRV-DAG: %[[#case_one]] = OpLabel

define spir_kernel void @bar(i64 %cond) {
entry:
  switch i64 %cond, label %default [ i64 -1, label %case_one ]
case_one:
  ret void
default:
  ret void
}
llvmbot commented 3 months ago

@llvm/issue-subscribers-bug

Author: Nathan Gauër (Keenuts)

When a 64-bit immediate value is used in a switch construct, the SPIR-V emitter splits the 64bit int into 2 32-bit integers, causing a bad instruction to be generated: ``` OpSwitch %5 %8 4294967295 4294967295 %9 instead of OpSwitch %5 %8 -1 %9 ``` Test case to reproduce: ```cpp ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#cond:]] = OpFunctionParameter %[[#]] ; CHECK-SPIRV: OpSwitch %[[#cond]] %[[#default:]] -1 %[[#case_one:]] ; CHECK-SPIRV-DAG: %[[#default]] = OpLabel ; CHECK-SPIRV-DAG: %[[#case_one]] = OpLabel define spir_kernel void @bar(i64 %cond) { entry: switch i64 %cond, label %default [ i64 -1, label %case_one ] case_one: ret void default: ret void } ```