xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--------- SPIR.cpp - Emit LLVM Code for builtins ---------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Builtin calls as LLVM code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CGHLSLRuntime.h"
14*700637cbSDimitry Andric #include "CodeGenFunction.h"
15*700637cbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
16*700637cbSDimitry Andric #include "llvm/IR/Intrinsics.h"
17*700637cbSDimitry Andric 
18*700637cbSDimitry Andric using namespace clang;
19*700637cbSDimitry Andric using namespace CodeGen;
20*700637cbSDimitry Andric using namespace llvm;
21*700637cbSDimitry Andric 
EmitSPIRVBuiltinExpr(unsigned BuiltinID,const CallExpr * E)22*700637cbSDimitry Andric Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
23*700637cbSDimitry Andric                                              const CallExpr *E) {
24*700637cbSDimitry Andric   switch (BuiltinID) {
25*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_distance: {
26*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
27*700637cbSDimitry Andric     Value *Y = EmitScalarExpr(E->getArg(1));
28*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
29*700637cbSDimitry Andric            E->getArg(1)->getType()->hasFloatingRepresentation() &&
30*700637cbSDimitry Andric            "Distance operands must have a float representation");
31*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->isVectorType() &&
32*700637cbSDimitry Andric            E->getArg(1)->getType()->isVectorType() &&
33*700637cbSDimitry Andric            "Distance operands must be a vector");
34*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
35*700637cbSDimitry Andric         /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance,
36*700637cbSDimitry Andric         ArrayRef<Value *>{X, Y}, nullptr, "spv.distance");
37*700637cbSDimitry Andric   }
38*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_length: {
39*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(0));
40*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
41*700637cbSDimitry Andric            "length operand must have a float representation");
42*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->isVectorType() &&
43*700637cbSDimitry Andric            "length operand must be a vector");
44*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
45*700637cbSDimitry Andric         /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_length,
46*700637cbSDimitry Andric         ArrayRef<Value *>{X}, nullptr, "spv.length");
47*700637cbSDimitry Andric   }
48*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_reflect: {
49*700637cbSDimitry Andric     Value *I = EmitScalarExpr(E->getArg(0));
50*700637cbSDimitry Andric     Value *N = EmitScalarExpr(E->getArg(1));
51*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
52*700637cbSDimitry Andric            E->getArg(1)->getType()->hasFloatingRepresentation() &&
53*700637cbSDimitry Andric            "Reflect operands must have a float representation");
54*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->isVectorType() &&
55*700637cbSDimitry Andric            E->getArg(1)->getType()->isVectorType() &&
56*700637cbSDimitry Andric            "Reflect operands must be a vector");
57*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
58*700637cbSDimitry Andric         /*ReturnType=*/I->getType(), Intrinsic::spv_reflect,
59*700637cbSDimitry Andric         ArrayRef<Value *>{I, N}, nullptr, "spv.reflect");
60*700637cbSDimitry Andric   }
61*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_smoothstep: {
62*700637cbSDimitry Andric     Value *Min = EmitScalarExpr(E->getArg(0));
63*700637cbSDimitry Andric     Value *Max = EmitScalarExpr(E->getArg(1));
64*700637cbSDimitry Andric     Value *X = EmitScalarExpr(E->getArg(2));
65*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
66*700637cbSDimitry Andric            E->getArg(1)->getType()->hasFloatingRepresentation() &&
67*700637cbSDimitry Andric            E->getArg(2)->getType()->hasFloatingRepresentation() &&
68*700637cbSDimitry Andric            "SmoothStep operands must have a float representation");
69*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
70*700637cbSDimitry Andric         /*ReturnType=*/Min->getType(), Intrinsic::spv_smoothstep,
71*700637cbSDimitry Andric         ArrayRef<Value *>{Min, Max, X}, /*FMFSource=*/nullptr,
72*700637cbSDimitry Andric         "spv.smoothstep");
73*700637cbSDimitry Andric   }
74*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_faceforward: {
75*700637cbSDimitry Andric     Value *N = EmitScalarExpr(E->getArg(0));
76*700637cbSDimitry Andric     Value *I = EmitScalarExpr(E->getArg(1));
77*700637cbSDimitry Andric     Value *Ng = EmitScalarExpr(E->getArg(2));
78*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
79*700637cbSDimitry Andric            E->getArg(1)->getType()->hasFloatingRepresentation() &&
80*700637cbSDimitry Andric            E->getArg(2)->getType()->hasFloatingRepresentation() &&
81*700637cbSDimitry Andric            "FaceForward operands must have a float representation");
82*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
83*700637cbSDimitry Andric         /*ReturnType=*/N->getType(), Intrinsic::spv_faceforward,
84*700637cbSDimitry Andric         ArrayRef<Value *>{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
85*700637cbSDimitry Andric   }
86*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
87*700637cbSDimitry Andric     Value *Ptr = EmitScalarExpr(E->getArg(0));
88*700637cbSDimitry Andric     assert(E->getArg(0)->getType()->hasPointerRepresentation() &&
89*700637cbSDimitry Andric            E->getArg(1)->getType()->hasIntegerRepresentation() &&
90*700637cbSDimitry Andric            "GenericCastToPtrExplicit takes a pointer and an int");
91*700637cbSDimitry Andric     llvm::Type *Res = getTypes().ConvertType(E->getType());
92*700637cbSDimitry Andric     assert(Res->isPointerTy() &&
93*700637cbSDimitry Andric            "GenericCastToPtrExplicit doesn't return a pointer");
94*700637cbSDimitry Andric     llvm::CallInst *Call = Builder.CreateIntrinsic(
95*700637cbSDimitry Andric         /*ReturnType=*/Res, Intrinsic::spv_generic_cast_to_ptr_explicit,
96*700637cbSDimitry Andric         ArrayRef<Value *>{Ptr}, nullptr, "spv.generic_cast");
97*700637cbSDimitry Andric     Call->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
98*700637cbSDimitry Andric     return Call;
99*700637cbSDimitry Andric   }
100*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_num_workgroups:
101*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
102*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
103*700637cbSDimitry Andric         Intrinsic::spv_num_workgroups,
104*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
105*700637cbSDimitry Andric         "spv.num.workgroups");
106*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_workgroup_size:
107*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
108*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
109*700637cbSDimitry Andric         Intrinsic::spv_workgroup_size,
110*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
111*700637cbSDimitry Andric         "spv.workgroup.size");
112*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_workgroup_id:
113*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
114*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
115*700637cbSDimitry Andric         Intrinsic::spv_group_id,
116*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
117*700637cbSDimitry Andric         "spv.group.id");
118*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_local_invocation_id:
119*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
120*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
121*700637cbSDimitry Andric         Intrinsic::spv_thread_id_in_group,
122*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
123*700637cbSDimitry Andric         "spv.thread.id.in.group");
124*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_global_invocation_id:
125*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
126*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
127*700637cbSDimitry Andric         Intrinsic::spv_thread_id,
128*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
129*700637cbSDimitry Andric         "spv.thread.id");
130*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_global_size:
131*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
132*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
133*700637cbSDimitry Andric         Intrinsic::spv_global_size,
134*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
135*700637cbSDimitry Andric         "spv.num.workgroups");
136*700637cbSDimitry Andric   case SPIRV::BI__builtin_spirv_global_offset:
137*700637cbSDimitry Andric     return Builder.CreateIntrinsic(
138*700637cbSDimitry Andric         /*ReturnType=*/getTypes().ConvertType(E->getType()),
139*700637cbSDimitry Andric         Intrinsic::spv_global_offset,
140*700637cbSDimitry Andric         ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
141*700637cbSDimitry Andric         "spv.global.offset");
142*700637cbSDimitry Andric   }
143*700637cbSDimitry Andric   return nullptr;
144*700637cbSDimitry Andric }
145