Skip to content

Commit 35135da

Browse files
committed
--Added lround and llround intrinsic
1 parent f5d3470 commit 35135da

File tree

4 files changed

+235
-1
lines changed

4 files changed

+235
-1
lines changed

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ class SPIRVInstructionSelector : public InstructionSelector {
273273
GL::GLSLExtInst GLInst) const;
274274
bool selectExtInst(Register ResVReg, const SPIRVType *ResType,
275275
MachineInstr &I, const ExtInstList &ExtInsts) const;
276+
bool selectExtInstForLRound(Register ResVReg, const SPIRVType *ResType,
277+
MachineInstr &I, CL::OpenCLExtInst CLInst,
278+
GL::GLSLExtInst GLInst) const;
279+
bool selectExtInstForLRound(Register ResVReg, const SPIRVType *ResType,
280+
MachineInstr &I,
281+
const ExtInstList &ExtInsts) const;
276282

277283
bool selectLog10(Register ResVReg, const SPIRVType *ResType,
278284
MachineInstr &I) const;
@@ -676,7 +682,22 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
676682
return selectSUCmp(ResVReg, ResType, I, true);
677683
case TargetOpcode::G_UCMP:
678684
return selectSUCmp(ResVReg, ResType, I, false);
679-
685+
case TargetOpcode::G_LROUND:
686+
case TargetOpcode::G_LLROUND: {
687+
Register regForLround =
688+
MRI->createVirtualRegister(MRI->getRegClass(ResVReg), "lround");
689+
MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
690+
GR.assignSPIRVTypeToVReg(GR.getSPIRVTypeForVReg(I.getOperand(1).getReg()),
691+
regForLround, *(I.getParent()->getParent()));
692+
selectExtInstForLRound(regForLround, GR.getSPIRVTypeForVReg(regForLround),
693+
I, CL::round, GL::Round);
694+
MachineBasicBlock &BB = *I.getParent();
695+
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConvertFToS))
696+
.addDef(ResVReg)
697+
.addUse(GR.getSPIRVTypeID(ResType))
698+
.addUse(regForLround);
699+
return MIB.constrainAllUses(TII, TRI, RBI);
700+
}
680701
case TargetOpcode::G_STRICT_FMA:
681702
case TargetOpcode::G_FMA:
682703
return selectExtInst(ResVReg, ResType, I, CL::fma, GL::Fma);
@@ -1015,6 +1036,41 @@ bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
10151036
}
10161037
return false;
10171038
}
1039+
bool SPIRVInstructionSelector::selectExtInstForLRound(
1040+
Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
1041+
CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst) const {
1042+
ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1043+
{SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1044+
return selectExtInstForLRound(ResVReg, ResType, I, ExtInsts);
1045+
}
1046+
1047+
bool SPIRVInstructionSelector::selectExtInstForLRound(
1048+
Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
1049+
const ExtInstList &Insts) const {
1050+
for (const auto &Ex : Insts) {
1051+
SPIRV::InstructionSet::InstructionSet Set = Ex.first;
1052+
uint32_t Opcode = Ex.second;
1053+
if (STI.canUseExtInstSet(Set)) {
1054+
MachineBasicBlock &BB = *I.getParent();
1055+
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
1056+
.addDef(ResVReg)
1057+
.addUse(GR.getSPIRVTypeID(ResType))
1058+
.addImm(static_cast<uint32_t>(Set))
1059+
.addImm(Opcode);
1060+
const unsigned NumOps = I.getNumOperands();
1061+
unsigned Index = 1;
1062+
if (Index < NumOps &&
1063+
I.getOperand(Index).getType() ==
1064+
MachineOperand::MachineOperandType::MO_IntrinsicID)
1065+
Index = 2;
1066+
for (; Index < NumOps; ++Index)
1067+
MIB.add(I.getOperand(Index));
1068+
MIB.constrainAllUses(TII, TRI, RBI);
1069+
return true;
1070+
}
1071+
}
1072+
return false;
1073+
}
10181074

10191075
bool SPIRVInstructionSelector::selectOpWithSrcs(Register ResVReg,
10201076
const SPIRVType *ResType,

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
272272
{G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO})
273273
.alwaysLegal();
274274

275+
getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
276+
.legalForCartesianProduct(allFloatScalarsAndVectors,
277+
allIntScalarsAndVectors);
278+
275279
// FP conversions.
276280
getActionDefinitionsBuilder({G_FPTRUNC, G_FPEXT})
277281
.legalForCartesianProduct(allFloatScalarsAndVectors);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: [[opencl:%[0-9]+]] = OpExtInstImport "OpenCL.std"
5+
; CHECK-DAG: [[f32:%[0-9]+]] = OpTypeFloat 32
6+
; CHECK-DAG: [[i32:%[0-9]+]] = OpTypeInt 32 0
7+
; CHECK-DAG: [[f64:%[0-9]+]] = OpTypeFloat 64
8+
; CHECK-DAG: [[i64:%[0-9]+]] = OpTypeInt 64 0
9+
; CHECK-DAG: [[vecf32:%[0-9]+]] = OpTypeVector [[f32]]
10+
; CHECK-DAG: [[veci32:%[0-9]+]] = OpTypeVector [[i32]]
11+
; CHECK-DAG: [[vecf64:%[0-9]+]] = OpTypeVector [[f64]]
12+
; CHECK-DAG: [[veci64:%[0-9]+]] = OpTypeVector [[i64]]
13+
14+
; CHECK: [[rounded_i32_f32:%[0-9]+]] = OpExtInst [[f32]] [[opencl]] round %[[#]]
15+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i32]] [[rounded_i32_f32]]
16+
; CHECK: [[rounded_i32_f64:%[0-9]+]] = OpExtInst [[f64]] [[opencl]] round %[[#]]
17+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i32]] [[rounded_i32_f64]]
18+
; CHECK: [[rounded_i64_f32:%[0-9]+]] = OpExtInst [[f32]] [[opencl]] round %[[#]]
19+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i64]] [[rounded_i64_f32]]
20+
; CHECK: [[rounded_i64_f64:%[0-9]+]] = OpExtInst [[f64]] [[opencl]] round %[[#]]
21+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i64]] [[rounded_i64_f64]]
22+
; CHECK: [[rounded_v4i32_f32:%[0-9]+]] = OpExtInst [[vecf32]] [[opencl]] round %[[#]]
23+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci32]] [[rounded_v4i32_f32]]
24+
; CHECK: [[rounded_v4i32_f64:%[0-9]+]] = OpExtInst [[vecf64]] [[opencl]] round %[[#]]
25+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci32]] [[rounded_v4i32_f64]]
26+
; CHECK: [[rounded_v4i64_f32:%[0-9]+]] = OpExtInst [[vecf32]] [[opencl]] round %[[#]]
27+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci64]] [[rounded_v4i64_f32]]
28+
; CHECK: [[rounded_v4i64_f64:%[0-9]+]] = OpExtInst [[vecf64]] [[opencl]] round %[[#]]
29+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci64]] [[rounded_v4i64_f64]]
30+
31+
define spir_func i32 @test_llround_i32_f32(float %arg0) {
32+
entry:
33+
%0 = call i32 @llvm.llround.i32.f32(float %arg0)
34+
ret i32 %0
35+
}
36+
37+
define spir_func i32 @test_llround_i32_f64(double %arg0) {
38+
entry:
39+
%0 = call i32 @llvm.llround.i32.f64(double %arg0)
40+
ret i32 %0
41+
}
42+
43+
define spir_func i64 @test_llround_i64_f32(float %arg0) {
44+
entry:
45+
%0 = call i64 @llvm.llround.i64.f32(float %arg0)
46+
ret i64 %0
47+
}
48+
49+
define spir_func i64 @test_llround_i64_f64(double %arg0) {
50+
entry:
51+
%0 = call i64 @llvm.llround.i64.f64(double %arg0)
52+
ret i64 %0
53+
}
54+
55+
define spir_func <4 x i32> @test_llround_v4i32_f32(<4 x float> %arg0) {
56+
entry:
57+
%0 = call <4 x i32> @llvm.llround.v4i32.f32(<4 x float> %arg0)
58+
ret <4 x i32> %0
59+
}
60+
61+
define spir_func <4 x i32> @test_llround_v4i32_f64(<4 x double> %arg0) {
62+
entry:
63+
%0 = call <4 x i32> @llvm.llround.v4i32.f64(<4 x double> %arg0)
64+
ret <4 x i32> %0
65+
}
66+
67+
define spir_func <4 x i64> @test_llround_v4i64_f32(<4 x float> %arg0) {
68+
entry:
69+
%0 = call <4 x i64> @llvm.llround.v4i64.f32(<4 x float> %arg0)
70+
ret <4 x i64> %0
71+
}
72+
73+
define spir_func <4 x i64> @test_llround_v4i64_f64(<4 x double> %arg0) {
74+
entry:
75+
%0 = call <4 x i64> @llvm.llround.v4i64.f64(<4 x double> %arg0)
76+
ret <4 x i64> %0
77+
}
78+
79+
declare i32 @llvm.llround.i32.f32(float)
80+
declare i32 @llvm.llround.i32.f64(double)
81+
declare i64 @llvm.llround.i64.f32(float)
82+
declare i64 @llvm.llround.i64.f64(double)
83+
84+
declare <4 x i32> @llvm.llround.v4i32.f32(<4 x float>)
85+
declare <4 x i32> @llvm.llround.v4i32.f64(<4 x double>)
86+
declare <4 x i64> @llvm.llround.v4i64.f32(<4 x float>)
87+
declare <4 x i64> @llvm.llround.v4i64.f64(<4 x double>)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: [[opencl:%[0-9]+]] = OpExtInstImport "OpenCL.std"
5+
; CHECK-DAG: [[f32:%[0-9]+]] = OpTypeFloat 32
6+
; CHECK-DAG: [[i32:%[0-9]+]] = OpTypeInt 32 0
7+
; CHECK-DAG: [[f64:%[0-9]+]] = OpTypeFloat 64
8+
; CHECK-DAG: [[i64:%[0-9]+]] = OpTypeInt 64 0
9+
; CHECK-DAG: [[vecf32:%[0-9]+]] = OpTypeVector [[f32]]
10+
; CHECK-DAG: [[veci32:%[0-9]+]] = OpTypeVector [[i32]]
11+
; CHECK-DAG: [[vecf64:%[0-9]+]] = OpTypeVector [[f64]]
12+
; CHECK-DAG: [[veci64:%[0-9]+]] = OpTypeVector [[i64]]
13+
14+
; CHECK: [[rounded_i32_f32:%[0-9]+]] = OpExtInst [[f32]] [[opencl]] round %[[#]]
15+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i32]] [[rounded_i32_f32]]
16+
; CHECK: [[rounded_i32_f64:%[0-9]+]] = OpExtInst [[f64]] [[opencl]] round %[[#]]
17+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i32]] [[rounded_i32_f64]]
18+
; CHECK: [[rounded_i64_f32:%[0-9]+]] = OpExtInst [[f32]] [[opencl]] round %[[#]]
19+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i64]] [[rounded_i64_f32]]
20+
; CHECK: [[rounded_i64_f64:%[0-9]+]] = OpExtInst [[f64]] [[opencl]] round %[[#]]
21+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[i64]] [[rounded_i64_f64]]
22+
; CHECK: [[rounded_v4i32_f32:%[0-9]+]] = OpExtInst [[vecf32]] [[opencl]] round %[[#]]
23+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci32]] [[rounded_v4i32_f32]]
24+
; CHECK: [[rounded_v4i32_f64:%[0-9]+]] = OpExtInst [[vecf64]] [[opencl]] round %[[#]]
25+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci32]] [[rounded_v4i32_f64]]
26+
; CHECK: [[rounded_v4i64_f32:%[0-9]+]] = OpExtInst [[vecf32]] [[opencl]] round %[[#]]
27+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci64]] [[rounded_v4i64_f32]]
28+
; CHECK: [[rounded_v4i64_f64:%[0-9]+]] = OpExtInst [[vecf64]] [[opencl]] round %[[#]]
29+
; CHECK-NEXT: %[[#]] = OpConvertFToS [[veci64]] [[rounded_v4i64_f64]]
30+
31+
define spir_func i32 @test_lround_i32_f32(float %arg0) {
32+
entry:
33+
%0 = call i32 @llvm.lround.i32.f32(float %arg0)
34+
ret i32 %0
35+
}
36+
37+
define spir_func i32 @test_lround_i32_f64(double %arg0) {
38+
entry:
39+
%0 = call i32 @llvm.lround.i32.f64(double %arg0)
40+
ret i32 %0
41+
}
42+
43+
define spir_func i64 @test_lround_i64_f32(float %arg0) {
44+
entry:
45+
%0 = call i64 @llvm.lround.i64.f32(float %arg0)
46+
ret i64 %0
47+
}
48+
49+
define spir_func i64 @test_lround_i64_f64(double %arg0) {
50+
entry:
51+
%0 = call i64 @llvm.lround.i64.f64(double %arg0)
52+
ret i64 %0
53+
}
54+
55+
define spir_func <4 x i32> @test_lround_v4i32_f32(<4 x float> %arg0) {
56+
entry:
57+
%0 = call <4 x i32> @llvm.lround.v4i32.f32(<4 x float> %arg0)
58+
ret <4 x i32> %0
59+
}
60+
61+
define spir_func <4 x i32> @test_lround_v4i32_f64(<4 x double> %arg0) {
62+
entry:
63+
%0 = call <4 x i32> @llvm.lround.v4i32.f64(<4 x double> %arg0)
64+
ret <4 x i32> %0
65+
}
66+
67+
define spir_func <4 x i64> @test_lround_v4i64_f32(<4 x float> %arg0) {
68+
entry:
69+
%0 = call <4 x i64> @llvm.lround.v4i64.f32(<4 x float> %arg0)
70+
ret <4 x i64> %0
71+
}
72+
73+
define spir_func <4 x i64> @test_lround_v4i64_f64(<4 x double> %arg0) {
74+
entry:
75+
%0 = call <4 x i64> @llvm.lround.v4i64.f64(<4 x double> %arg0)
76+
ret <4 x i64> %0
77+
}
78+
79+
declare i32 @llvm.lround.i32.f32(float)
80+
declare i32 @llvm.lround.i32.f64(double)
81+
declare i64 @llvm.lround.i64.f32(float)
82+
declare i64 @llvm.lround.i64.f64(double)
83+
84+
declare <4 x i32> @llvm.lround.v4i32.f32(<4 x float>)
85+
declare <4 x i32> @llvm.lround.v4i32.f64(<4 x double>)
86+
declare <4 x i64> @llvm.lround.v4i64.f32(<4 x float>)
87+
declare <4 x i64> @llvm.lround.v4i64.f64(<4 x double>)

0 commit comments

Comments
 (0)