diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -80,6 +80,16 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width, MachineIRBuilder &MIRBuilder, bool IsSigned) { + assert(Width <= 64 && "Unsupported integer width!"); + if (Width <= 8) + Width = 8; + else if (Width <= 16) + Width = 16; + else if (Width <= 32) + Width = 32; + else if (Width <= 64) + Width = 64; + auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt) .addDef(createTypeVReg(MIRBuilder)) .addImm(Width) diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp --- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp @@ -27,6 +27,8 @@ (VT.getVectorElementType() == MVT::i1 || VT.getVectorElementType() == MVT::i8)) return 1; + if (!VT.isVector() && VT.isInteger() && VT.getSizeInBits() <= 64) + return 1; return getNumRegisters(Context, VT); } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1189,6 +1189,7 @@ .addUse(GR.getSPIRVTypeID(ResType)) .constrainAllUses(TII, TRI, RBI); if (TyOpcode == SPIRV::OpTypeInt) { + assert(Imm.getBitWidth() <= 64 && "Unsupported integer width!"); Register Reg = GR.getOrCreateConstInt(Imm.getZExtValue(), I, ResType, TII); if (Reg == ResVReg) return true; diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -77,24 +77,19 @@ void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) { const auto Bitwidth = Imm.getBitWidth(); - switch (Bitwidth) { - case 1: - break; // Already handled. - case 8: - case 16: - case 32: + if (Bitwidth == 1) + return; // Already handled + else if (Bitwidth <= 32) { MIB.addImm(Imm.getZExtValue()); - break; - case 64: { + return; + } else if (Bitwidth <= 64) { uint64_t FullImm = Imm.getZExtValue(); uint32_t LowBits = FullImm & 0xffffffff; uint32_t HighBits = (FullImm >> 32) & 0xffffffff; MIB.addImm(LowBits).addImm(HighBits); - break; - } - default: - report_fatal_error("Unsupported constant bitwidth"); + return; } + report_fatal_error("Unsupported constant bitwidth"); } void buildOpName(Register Target, const StringRef &Name, diff --git a/llvm/test/CodeGen/SPIRV/constant/local-arbitrary-width-integers-constants-type-promotion.ll b/llvm/test/CodeGen/SPIRV/constant/local-arbitrary-width-integers-constants-type-promotion.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/constant/local-arbitrary-width-integers-constants-type-promotion.ll @@ -0,0 +1,58 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s + +define i4 @getConstantI4() { + ret i4 2 ; i4 => OpTypeInt 8 +} + +define i11 @getConstantI11() { + ret i11 7 ; i11 => OpTypeInt 16 +} + +define i24 @getConstantI24() { + ret i24 42 ; i24 => OpTypeInt 32 +} + +define i63 @getConstantI63() { + ret i63 5705 ; i63 => OpTypeInt 64 +} + +;; Capabilities: +; CHECK-DAG: OpCapability Int8 +; CHECK-DAG: OpCapability Int16 +; CHECK-DAG: OpCapability Int64 + +; CHECK-NOT: DAG-FENCE + +;; Names: +; CHECK-DAG: OpName %[[#GET_I4:]] "getConstantI4" +; CHECK-DAG: OpName %[[#GET_I11:]] "getConstantI11" +; CHECK-DAG: OpName %[[#GET_I24:]] "getConstantI24" +; CHECK-DAG: OpName %[[#GET_I63:]] "getConstantI63" + +; CHECK-NOT: DAG-FENCE + +;; Types and Constants: +; CHECK-DAG: %[[#I8:]] = OpTypeInt 8 0 +; CHECK-DAG: %[[#I16:]] = OpTypeInt 16 0 +; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#CST_I8:]] = OpConstant %[[#I8]] 2 +; CHECK-DAG: %[[#CST_I16:]] = OpConstant %[[#I16]] 7 +; CHECK-DAG: %[[#CST_I32:]] = OpConstant %[[#I32]] 42 +; CHECK-DAG: %[[#CST_I64:]] = OpConstant %[[#I64]] 5705 + +; CHECK: %[[#GET_I4]] = OpFunction %[[#I8]] +; CHECK: OpReturnValue %[[#CST_I8]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I11]] = OpFunction %[[#I16]] +; CHECK: OpReturnValue %[[#CST_I16]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I24]] = OpFunction %[[#I32]] +; CHECK: OpReturnValue %[[#CST_I32]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I63]] = OpFunction %[[#I64]] +; CHECK: OpReturnValue %[[#CST_I64]] +; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll b/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll --- a/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll +++ b/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll @@ -1,5 +1,9 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +define i8 @getConstantI8() { + ret i8 2 +} + define i16 @getConstantI16() { ret i16 -58 } @@ -17,12 +21,14 @@ } ;; Capabilities: +; CHECK-DAG: OpCapability Int8 ; CHECK-DAG: OpCapability Int16 ; CHECK-DAG: OpCapability Int64 ; CHECK-NOT: DAG-FENCE ;; Names: +; CHECK-DAG: OpName %[[#GET_I8:]] "getConstantI8" ; CHECK-DAG: OpName %[[#GET_I16:]] "getConstantI16" ; CHECK-DAG: OpName %[[#GET_I32:]] "getConstantI32" ; CHECK-DAG: OpName %[[#GET_I64:]] "getConstantI64" @@ -31,14 +37,20 @@ ; CHECK-NOT: DAG-FENCE ;; Types and Constants: +; CHECK-DAG: %[[#I8:]] = OpTypeInt 8 0 ; CHECK-DAG: %[[#I16:]] = OpTypeInt 16 0 ; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0 ; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#CST_I8:]] = OpConstant %[[#I8]] 2 ; CHECK-DAG: %[[#CST_I16:]] = OpConstant %[[#I16]] 65478 ; CHECK-DAG: %[[#CST_I32:]] = OpConstant %[[#I32]] 42 ; CHECK-DAG: %[[#CST_I64:]] = OpConstant %[[#I64]] 123456789 0 ; CHECK-DAG: %[[#CST_LARGE_I64:]] = OpConstant %[[#I64]] 0 8 +; CHECK: %[[#GET_I8]] = OpFunction %[[#I8]] +; CHECK: OpReturnValue %[[#CST_I8]] +; CHECK: OpFunctionEnd + ; CHECK: %[[#GET_I16]] = OpFunction %[[#I16]] ; CHECK: OpReturnValue %[[#CST_I16]] ; CHECK: OpFunctionEnd