diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 28988129fa91..aee3a29c6e42 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1707,29 +1707,29 @@ bool SPIRVInstructionSelector::selectPopCount64(Register ResVReg, SPIRVTypeInst VecI32Type = GR.getOrCreateSPIRVVectorType( I32Type, 2 * ComponentCount, MIRBuilder, /*IsSigned=*/false); - // ---- Stage 1: 64-bit → 2x32-bit ---- + // Converts 64 bit into and array of 32 bit, containing 2 elements. Register Vec32 = MRI->createVirtualRegister(GR.getRegClass(VecI32Type)); if (!selectOpWithSrcs(Vec32, VecI32Type, I, {SrcReg}, SPIRV::OpBitcast)) return false; - // ---- Stage 2: popcount per 32-bit lane ---- + // Apply popcount on each 32 bit lane Register Pop32 = MRI->createVirtualRegister(GR.getRegClass(VecI32Type)); if (!selectPopCount32(Pop32, VecI32Type, I, Vec32, Opcode)) return false; - // ---- Stage 3: split even (low) / odd (high) lanes ---- + // Splits result into highbit lane and lowbit lane auto MaybeParts = splitEvenOddLanes(Pop32, ComponentCount, I, I32Type); if (!MaybeParts) return false; SplitParts &Parts = *MaybeParts; - // ---- Stage 4: sum high + low ---- + // Sum high part and low part unsigned OpAdd = Parts.IsScalar ? SPIRV::OpIAddS : SPIRV::OpIAddV; Register Sum = MRI->createVirtualRegister(GR.getRegClass(Parts.Type)); if (!selectOpWithSrcs(Sum, Parts.Type, I, {Parts.High, Parts.Low}, OpAdd)) return false; - // ---- Stage 5: convert i32 sum to the final result type ---- + // Convert 32 bit sum into 64 bit scalar bool IsSigned = GR.isScalarOrVectorSigned(ResType); unsigned ConvOp = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert; return selectOpWithSrcs(ResVReg, ResType, I, {Sum}, ConvOp); @@ -3667,28 +3667,26 @@ bool SPIRVInstructionSelector::selectBitreverse64(Register ResVReg, MachineIRBuilder MIRBuilder(I); - // ---- Types ---- SPIRVTypeInst I32Type = GR.getOrCreateSPIRVIntegerType(32, MIRBuilder); SPIRVTypeInst VecI32Type = GR.getOrCreateSPIRVVectorType( I32Type, 2 * ComponentCount, MIRBuilder, /*IsSigned=*/false); - // ---- Stage 1: 64-bit -> 2x32-bit (High, Low) ---- + // Converts 64 bit into and array of 32 bit, containing 2 elements. Register Vec32 = MRI->createVirtualRegister(GR.getRegClass(VecI32Type)); if (!selectOpWithSrcs(Vec32, VecI32Type, I, {SrcReg}, SPIRV::OpBitcast)) return false; - // ---- Stage 2: bitreverse per 32-bit lane ---- + // Apply bitreverse on each 32 bit lane Register Reverse32 = MRI->createVirtualRegister(GR.getRegClass(VecI32Type)); if (!selectBitreverseNative(Reverse32, VecI32Type, I, Vec32)) return false; - // ---- Stage 3: split even (low) / odd (high) lanes ---- + // Splits result into highbit lane and lowbit lane auto MaybeParts = splitEvenOddLanes(Reverse32, ComponentCount, I, I32Type); if (!MaybeParts) return false; SplitParts &Parts = *MaybeParts; - // ---- Stage 4: swap halves and reconstruct v2i32 ---- // Reversing a 64-bit value = reverse each 32-bit half AND swap them, // so the old High word becomes lane 0 (low) and old Low becomes lane 1 // (high). @@ -3697,7 +3695,7 @@ bool SPIRVInstructionSelector::selectBitreverse64(Register ResVReg, SPIRV::OpCompositeConstruct)) return false; - // ---- Stage 5: v2i32 -> 64-bit ---- + // Groups 32 bit vector back to 64 bit scalar. return selectOpWithSrcs(ResVReg, ResType, I, {SwappedVec}, SPIRV::OpBitcast); } @@ -3730,9 +3728,9 @@ bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg, return selectBitreverseNative(ResVReg, ResType, I, OpReg); case 64: return selectBitreverse64(ResVReg, ResType, I, OpReg); - default: - report_fatal_error("G_BITREVERSE only support 16,32,64 bits."); } + return SPIRVInstructionSelector::diagnoseUnsupported( + I, "G_BITREVERSE only support 16,32,64 bits."); } if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll index 14c97e1d8f70..c1731bcdd2ec 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll @@ -3,6 +3,7 @@ ; CHECK: OpMemoryModel Logical GLSL450 +;CHECK-DAG: %[[#int_8:]] = OpTypeInt 8 ;CHECK-DAG: %[[#int_16:]] = OpTypeInt 16 ;CHECK-DAG: %[[#int_32:]] = OpTypeInt 32 ;CHECK-DAG: %[[#int_64:]] = OpTypeInt 64 @@ -29,6 +30,17 @@ entry: ret i32 %elt.bitreverse } +define noundef i8 @reversebits_i8(i8 noundef %a) { +entry: +; CHECK: %[[#param:]] = OpFunctionParameter %[[#int_8]] +; CHECK: %[[#conversion:]] = OpUConvert %[[#int_32]] %[[#param]] +; CHECK-NEXT: %[[#bitrev:]] = OpBitReverse %[[#int_32]] %[[#conversion]] +; CHECK-NEXT: %[[#shift:]] = OpShiftRightLogical %[[#int_32]] %[[#bitrev]] %[[#const_16]] +; CHECK-NEXT: %[[#]] = OpUConvert %[[#int_8]] %[[#shift]] + %elt.bitreverse = call i8 @llvm.bitreverse.i8(i8 %a) + ret i8 %elt.bitreverse +} + define noundef i16 @reversebits_i16(i16 noundef %a) { entry: ; CHECK: %[[#param:]] = OpFunctionParameter %[[#int_16]]