This PR continues https://github.com/llvm/llvm-project/pull/101732 changes in virtual register processing aimed to improve correctness of emitted MIR between passes from the perspective of MachineVerifier. Namely, the following changes are introduced: * register classes (lib/Target/SPIRV/SPIRVRegisterInfo.td) and instruction patterns (lib/Target/SPIRV/SPIRVInstrInfo.td) are corrected and simplified (by removing unnecessary sophisticated options) -- e.g., this PR gets rid of duplicating 32/64 bits patterns, removes ANYID register class and simplifies definition of the rest of register classes, * hardcoded LLT scalar types in passes before instruction selection are corrected -- the goal is to have correct bit width before instruction selection, and use 64 bits registers for pattern matching in the instruction selection pass; 32-bit registers remain where they are described in such terms by SPIR-V specification (like, for example, creation of virtual registers for scope/mem semantics operands), * rework virtual register type/class assignment for calls/builtins lowering, * a series of minor changes to fix validity of emitted code between passes: - ensure that that bitcast changes the type, - fix the pattern for instruction selection for OpExtInst, - simplify inline asm operands usage, - account for arbitrary integer sizes / update legalizer rules; * add '-verify-machineinstrs' to existed test cases. See also https://github.com/llvm/llvm-project/issues/88129 that this PR may resolve. This PR fixes a great number of issues reported by MachineVerifier and, as a result, reduces a number of failed test cases for the mode with expensive checks set on from ~200 to ~57.
212 lines
6.7 KiB
LLVM
212 lines
6.7 KiB
LLVM
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
|
|
|
|
; CHECK-DAG: OpName [[TRUNC32_16:%.*]] "f32tof16"
|
|
; CHECK-DAG: OpName [[EXT16_32:%.*]] "f16tof32"
|
|
|
|
; CHECK-DAG: OpName [[TRUNC32_16v3:%.*]] "f32tof16v3"
|
|
; CHECK-DAG: OpName [[EXT16_32v3:%.*]] "f16tof32v3"
|
|
|
|
; CHECK-DAG: OpName [[F32toS32:%.*]] "f32tos32"
|
|
; CHECK-DAG: OpName [[F32toS16:%.*]] "f32tos16"
|
|
; CHECK-DAG: OpName [[F32toS8:%.*]] "f32tos8"
|
|
; CHECK-DAG: OpName [[F16toS32:%.*]] "f16tos32"
|
|
; CHECK-DAG: OpName [[F16toS16:%.*]] "f16tos16"
|
|
; CHECK-DAG: OpName [[F16toS8:%.*]] "f16tos8"
|
|
|
|
; CHECK-DAG: OpName [[F32toU32v2:%.*]] "f32tou32v2"
|
|
; CHECK-DAG: OpName [[F32toU16v2:%.*]] "f32tou16v2"
|
|
; CHECK-DAG: OpName [[F32toU8v2:%.*]] "f32tou8v2"
|
|
; CHECK-DAG: OpName [[F16toU32v2:%.*]] "f16tou32v2"
|
|
; CHECK-DAG: OpName [[F16toU16v2:%.*]] "f16tou16v2"
|
|
; CHECK-DAG: OpName [[F16toU8v2:%.*]] "f16tou8v2"
|
|
|
|
; CHECK-DAG: [[F32:%.*]] = OpTypeFloat 32
|
|
; CHECK-DAG: [[F16:%.*]] = OpTypeFloat 16
|
|
; CHECK-DAG: [[F32v2:%.*]] = OpTypeVector [[F32]] 2
|
|
; CHECK-DAG: [[F16v2:%.*]] = OpTypeVector [[F16]] 2
|
|
; CHECK-DAG: [[F32v3:%.*]] = OpTypeVector [[F32]] 3
|
|
; CHECK-DAG: [[F16v3:%.*]] = OpTypeVector [[F16]] 3
|
|
; CHECK-DAG: [[U32:%.*]] = OpTypeInt 32 0
|
|
; CHECK-DAG: [[U16:%.*]] = OpTypeInt 16 0
|
|
; CHECK-DAG: [[U8:%.*]] = OpTypeInt 8 0
|
|
; CHECK-DAG: [[U32v2:%.*]] = OpTypeVector [[U32]] 2
|
|
; CHECK-DAG: [[U16v2:%.*]] = OpTypeVector [[U16]] 2
|
|
; CHECK-DAG: [[U8v2:%.*]] = OpTypeVector [[U8]] 2
|
|
|
|
|
|
; CHECK: [[TRUNC32_16]] = OpFunction [[F16]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpFConvert [[F16]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define half @f32tof16(float %a) {
|
|
%r = fptrunc float %a to half
|
|
ret half %r
|
|
}
|
|
|
|
; CHECK: [[EXT16_32]] = OpFunction [[F32]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpFConvert [[F32]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define float @f16tof32(half %a) {
|
|
%r = fpext half %a to float
|
|
ret float %r
|
|
}
|
|
|
|
; CHECK: [[TRUNC32_16v3]] = OpFunction [[F16v3]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32v3]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpFConvert [[F16v3]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <3 x half> @f32tof16v3(<3 x float> %a) {
|
|
%r = fptrunc <3 x float> %a to <3 x half>
|
|
ret <3 x half> %r
|
|
}
|
|
|
|
; CHECK: [[EXT16_32v3]] = OpFunction [[F32v3]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16v3]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpFConvert [[F32v3]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <3 x float> @f16tof32v3(<3 x half> %a) {
|
|
%r = fpext <3 x half> %a to <3 x float>
|
|
ret <3 x float> %r
|
|
}
|
|
|
|
; CHECK: [[F32toS32]] = OpFunction [[U32]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U32]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i32 @f32tos32(float %a) {
|
|
%r = fptosi float %a to i32
|
|
ret i32 %r
|
|
}
|
|
|
|
; CHECK: [[F32toS16]] = OpFunction [[U16]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U16]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i16 @f32tos16(float %a) {
|
|
%r = fptosi float %a to i16
|
|
ret i16 %r
|
|
}
|
|
|
|
; CHECK: [[F32toS8]] = OpFunction [[U8]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U8]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i8 @f32tos8(float %a) {
|
|
%r = fptosi float %a to i8
|
|
ret i8 %r
|
|
}
|
|
|
|
; CHECK: [[F16toS32]] = OpFunction [[U32]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U32]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i32 @f16tos32(half %a) {
|
|
%r = fptosi half %a to i32
|
|
ret i32 %r
|
|
}
|
|
|
|
; CHECK: [[F16toS16]] = OpFunction [[U16]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U16]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i16 @f16tos16(half %a) {
|
|
%r = fptosi half %a to i16
|
|
ret i16 %r
|
|
}
|
|
|
|
; CHECK: [[F16toS8]] = OpFunction [[U8]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToS [[U8]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define i8 @f16tos8(half %a) {
|
|
%r = fptosi half %a to i8
|
|
ret i8 %r
|
|
}
|
|
|
|
; CHECK: [[F32toU32v2]] = OpFunction [[U32v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U32v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i32> @f32tou32v2(<2 x float> %a) {
|
|
%r = fptoui <2 x float> %a to <2 x i32>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
; CHECK: [[F32toU16v2]] = OpFunction [[U16v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U16v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i16> @f32tou16v2(<2 x float> %a) {
|
|
%r = fptoui <2 x float> %a to <2 x i16>
|
|
ret <2 x i16> %r
|
|
}
|
|
|
|
; CHECK: [[F32toU8v2]] = OpFunction [[U8v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F32v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U8v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i8> @f32tou8v2(<2 x float> %a) {
|
|
%r = fptoui <2 x float> %a to <2 x i8>
|
|
ret <2 x i8> %r
|
|
}
|
|
|
|
; CHECK: [[F16toU32v2]] = OpFunction [[U32v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U32v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i32> @f16tou32v2(<2 x half> %a) {
|
|
%r = fptoui <2 x half> %a to <2 x i32>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
; CHECK: [[F16toU16v2]] = OpFunction [[U16v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U16v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i16> @f16tou16v2(<2 x half> %a) {
|
|
%r = fptoui <2 x half> %a to <2 x i16>
|
|
ret <2 x i16> %r
|
|
}
|
|
|
|
; CHECK: [[F16toU8v2]] = OpFunction [[U8v2]]
|
|
; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[F16v2]]
|
|
; CHECK: OpLabel
|
|
; CHECK: [[R:%.*]] = OpConvertFToU [[U8v2]] [[A]]
|
|
; CHECK: OpReturnValue [[R]]
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
define <2 x i8> @f16tou8v2(<2 x half> %a) {
|
|
%r = fptoui <2 x half> %a to <2 x i8>
|
|
ret <2 x i8> %r
|
|
}
|