diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp index 62f5e47c5ea3b..42de884840dc9 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp @@ -50,6 +50,14 @@ void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI, unsigned IsBitwidth16 = MI->getFlags() & SPIRV::INST_PRINTER_WIDTH16; const unsigned NumVarOps = MI->getNumOperands() - StartIndex; + if (MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) { + // SPV_ALTERA_arbitrary_precision_integers allows for integer widths greater + // than 64, which will be encoded via multiple operands. + for (unsigned I = StartIndex; I != MI->getNumOperands(); ++I) + O << ' ' << MI->getOperand(I).getImm(); + return; + } + assert((NumVarOps == 1 || NumVarOps == 2) && "Unsupported number of bits for literal variable"); diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index d2a8fddc5d8e4..42edad255ce82 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -13,9 +13,14 @@ #include "SPIRVCommandLine.h" #include "MCTargetDesc/SPIRVBaseInfo.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/TargetParser/Triple.h" -#include + +#include #include +#include +#include +#include #define DEBUG_TYPE "spirv-commandline" @@ -176,7 +181,17 @@ bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, std::set &Vals) { SmallVector Tokens; ArgValue.split(Tokens, ",", -1, false); - std::sort(Tokens.begin(), Tokens.end()); + llvm::sort(Tokens, [](auto &&LHS, auto &&RHS) { + // We want to ensure that we handle "all" first, to ensure that any + // subsequent disablement actually behaves as expected i.e. given + // --spv-ext=all,-foo, we first enable all and then disable foo; this should + // be revisited and simplified. + if (LHS == "all") + return true; + if (RHS == "all") + return false; + return !(RHS < LHS); + }); std::set EnabledExtensions; diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index 0fb44052527f0..5d96a67500dff 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -151,22 +151,22 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) { } unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const { - if (Width > 64) - report_fatal_error("Unsupported integer width!"); const SPIRVSubtarget &ST = cast(CurMF->getSubtarget()); if (ST.canUseExtension( SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) || - ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) + (Width == 4 && ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4))) return Width; if (Width <= 8) - Width = 8; + return 8; else if (Width <= 16) - Width = 16; + return 16; else if (Width <= 32) - Width = 32; - else - Width = 64; - return Width; + return 32; + else if (Width <= 64) + return 64; + else if (Width <= 128) + return 128; + reportFatalUsageError("Unsupported Integer width!"); } SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width, @@ -413,7 +413,7 @@ Register SPIRVGlobalRegistry::createConstInt(const ConstantInt *CI, MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI) .addDef(Res) .addUse(getSPIRVTypeID(SpvType)); - addNumImm(APInt(BitWidth, CI->getZExtValue()), MIB); + addNumImm(CI->getValue(), MIB); } else { MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull) .addDef(Res) diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index 71df4cced434e..2078bfee2e767 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -48,6 +48,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { const LLT s16 = LLT::scalar(16); const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); + const LLT s128 = LLT::scalar(128); const LLT v16s64 = LLT::fixed_vector(16, 64); const LLT v16s32 = LLT::fixed_vector(16, 32); @@ -307,7 +308,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { typeInSet(1, allPtrsScalarsAndVectors))); getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE}) - .legalFor({s1}) + .legalFor({s1, s128}) .legalFor(allFloatAndIntScalarsAndPtrs) .legalFor(allowedVectorTypes) .moreElementsToNextPow2(0) diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 73432279c3306..7717f18d14a34 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1436,6 +1436,21 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability(SPIRV::Capability::Int16); else if (BitWidth == 8) Reqs.addCapability(SPIRV::Capability::Int8); + else if (BitWidth == 4 && + ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) { + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_int4); + Reqs.addCapability(SPIRV::Capability::Int4TypeINTEL); + } else if (BitWidth != 32) { + if (!ST.canUseExtension( + SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers)) + reportFatalUsageError( + "OpTypeInt type with a width other than 8, 16, 32 or 64 bits " + "requires the following SPIR-V extension: " + "SPV_ALTERA_arbitrary_precision_integers"); + Reqs.addExtension( + SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers); + Reqs.addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA); + } break; } case SPIRV::OpDot: { diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index 7fdb0fafa3719..6feae31c8370f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -108,6 +108,13 @@ void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) { // Asm Printer needs this info to print 64-bit operands correctly MIB.getInstr()->setAsmPrinterFlag(SPIRV::ASM_PRINTER_WIDTH64); return; + } else if (Bitwidth <= 128) { + uint32_t LowBits = Imm.getRawData()[0] & 0xffffffff; + uint32_t MidBits0 = (Imm.getRawData()[0] >> 32) & 0xffffffff; + uint32_t MidBits1 = Imm.getRawData()[1] & 0xffffffff; + uint32_t HighBits = (Imm.getRawData()[1] >> 32) & 0xffffffff; + MIB.addImm(LowBits).addImm(MidBits0).addImm(MidBits1).addImm(HighBits); + return; } report_fatal_error("Unsupported constant bitwidth"); } diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll new file mode 100644 index 0000000000000..c90ffdd17996c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-addsub.ll @@ -0,0 +1,67 @@ +; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %} + +; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers + +; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA +; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers" +; CHECK: OpName %[[#TestAdd:]] "test_add" +; CHECK: OpName %[[#TestSub:]] "test_sub" +; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0 +; CHECK: %[[#Const64Int128:]] = OpConstant %[[#Int128Ty]] 64 0 0 0 + +; CHECK: %[[#TestAdd]] = OpFunction +define spir_func void @test_add(i64 %AL, i64 %AH, i64 %BL, i64 %BH, ptr %RL, ptr %RH) { +entry: +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpShiftLeftLogical %[[#Int128Ty]] {{%[0-9]+}} %[[#Const64Int128]] +; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]] +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpIAdd %[[#Int128Ty]] + %tmp1 = zext i64 %AL to i128 + %tmp23 = zext i64 %AH to i128 + %tmp4 = shl i128 %tmp23, 64 + %tmp5 = or i128 %tmp4, %tmp1 + %tmp67 = zext i64 %BL to i128 + %tmp89 = zext i64 %BH to i128 + %tmp11 = shl i128 %tmp89, 64 + %tmp12 = or i128 %tmp11, %tmp67 + %tmp15 = add i128 %tmp12, %tmp5 + %tmp1617 = trunc i128 %tmp15 to i64 + store i64 %tmp1617, ptr %RL + %tmp21 = lshr i128 %tmp15, 64 + %tmp2122 = trunc i128 %tmp21 to i64 + store i64 %tmp2122, ptr %RH + ret void +; CHECK: OpFunctionEnd +} + +; CHECK: %[[#TestSub]] = OpFunction +define spir_func void @test_sub(i64 %AL, i64 %AH, i64 %BL, i64 %BH, ptr %RL, ptr %RH) { +entry: +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpShiftLeftLogical %[[#Int128Ty]] {{%[0-9]+}} %[[#Const64Int128]] +; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]] +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpISub %[[#Int128Ty]] + %tmp1 = zext i64 %AL to i128 + %tmp23 = zext i64 %AH to i128 + %tmp4 = shl i128 %tmp23, 64 + %tmp5 = or i128 %tmp4, %tmp1 + %tmp67 = zext i64 %BL to i128 + %tmp89 = zext i64 %BH to i128 + %tmp11 = shl i128 %tmp89, 64 + %tmp12 = or i128 %tmp11, %tmp67 + %tmp15 = sub i128 %tmp5, %tmp12 + %tmp1617 = trunc i128 %tmp15 to i64 + store i64 %tmp1617, ptr %RL + %tmp21 = lshr i128 %tmp15, 64 + %tmp2122 = trunc i128 %tmp21 to i64 + store i64 %tmp2122, ptr %RH + ret void +; CHECK: OpFunctionEnd +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll new file mode 100644 index 0000000000000..d1de5df499566 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-arith.ll @@ -0,0 +1,27 @@ +; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %} + +; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers + +; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA +; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers" +; CHECK: OpName %[[#Foo:]] "foo" +; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0 + +; CHECK: %[[#Foo]] = OpFunction +define i64 @foo(i64 %x, i64 %y, i32 %amt) { +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpSConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpBitwiseOr %[[#Int128Ty]] +; CHECK: {{.*}} = OpUConvert %[[#Int128Ty]] +; CHECK: {{.*}} = OpShiftRightLogical %[[#Int128Ty]] + %tmp0 = zext i64 %x to i128 + %tmp1 = sext i64 %y to i128 + %tmp2 = or i128 %tmp0, %tmp1 + %tmp7 = zext i32 13 to i128 + %tmp3 = lshr i128 %tmp2, %tmp7 + %tmp4 = trunc i128 %tmp3 to i64 + ret i64 %tmp4 +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll new file mode 100644 index 0000000000000..669e9362605a5 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_ALTERA_arbitrary_precision_integers/i128-switch-lower.ll @@ -0,0 +1,27 @@ +; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %} + +; CHECK-ERROR: LLVM ERROR: OpTypeInt type with a width other than 8, 16, 32 or 64 bits requires the following SPIR-V extension: SPV_ALTERA_arbitrary_precision_integers + +; CHECK: OpCapability ArbitraryPrecisionIntegersALTERA +; CHECK: OpExtension "SPV_ALTERA_arbitrary_precision_integers" +; CHECK: OpName %[[#Test:]] "test" +; CHECK: OpName %[[#Exit:]] "exit" +; CHECK: %[[#Int128Ty:]] = OpTypeInt 128 0 +; CHECK: %[[#UndefInt128:]] = OpUndef %[[#Int128Ty]] + +; CHECK: %[[#Test]] = OpFunction +define void @test() { +entry: +; CHECK: OpSwitch %[[#UndefInt128]] %[[#Exit]] 0 0 3 0 %[[#Exit]] 0 0 5 0 %[[#Exit]] 0 0 4 0 %[[#Exit]] 0 0 8 0 %[[#Exit]] + switch i128 poison, label %exit [ + i128 55340232221128654848, label %exit + i128 92233720368547758080, label %exit + i128 73786976294838206464, label %exit + i128 147573952589676412928, label %exit + ] +exit: + unreachable +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll index 5ddfc85702540..ecf4807a1d5fc 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=all,-SPV_ALTERA_arbitrary_precision_integers %s -o - | FileCheck %s +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=-SPV_ALTERA_arbitrary_precision_integers,all %s -o - | FileCheck %s ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=KHR %s -o - | FileCheck %s ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=khr %s -o - | FileCheck %s