-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NFC][HLSL] Move emitter out of AMDGPU.cpp #133251
Conversation
farzonl
commented
Mar 27, 2025
•
edited
Loading
edited
- Move all HLSL code out of AMDGPU.cpp to CGHLSLBuiltins.cpp
- Fixes accidental reorganization of HLSL code into AMDGPU caused by ([NFC][clang] Split clang/lib/CodeGen/CGBuiltin.cpp into target-specific files #132252, 7f920e2e5f70b)
- Create a home for LangBuiltins - Move all HLSL code out of AMDGPU.cpp to CGHLSLBuiltins.cpp
@llvm/pr-subscribers-clang @llvm/pr-subscribers-hlsl Author: Farzon Lotfi (farzonl) Changes
Patch is 63.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133251.diff 4 Files Affected:
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index c375fa5dc7516..50a01a8e2908f 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -637,6 +637,7 @@ hlsl:
- clang/lib/Sema/HLSLExternalSemaSource.cpp
- clang/lib/Sema/SemaHLSL.cpp
- clang/lib/CodeGen/CGHLSLRuntime.*
+ - clang/lib/CodeGen/LangBuiltins/CGHLSLBuiltins.cpp
- llvm/include/llvm/Frontend/HLSL/**
- llvm/lib/Frontend/HLSL/**
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 94a908197d795..10407a33932b1 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -115,6 +115,7 @@ add_clang_library(clangCodeGen
PatternInit.cpp
SanitizerMetadata.cpp
SwiftCallingConv.cpp
+ LangBuiltins/CGHLSLBuiltins.cpp
TargetBuiltins/ARM.cpp
TargetBuiltins/AMDGPU.cpp
TargetBuiltins/Hexagon.cpp
diff --git a/clang/lib/CodeGen/LangBuiltins/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/LangBuiltins/CGHLSLBuiltins.cpp
new file mode 100644
index 0000000000000..5709594a34826
--- /dev/null
+++ b/clang/lib/CodeGen/LangBuiltins/CGHLSLBuiltins.cpp
@@ -0,0 +1,740 @@
+//===------- CGHLSLBuiltins.cpp - Emit LLVM Code for HLSL builtins --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit HLSL Builtin calls as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGBuiltin.h"
+#include "CGHLSLRuntime.h"
+
+using namespace clang;
+using namespace CodeGen;
+using namespace llvm;
+
+static Value *handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E) {
+ assert((E->getArg(0)->getType()->hasUnsignedIntegerRepresentation() &&
+ E->getArg(1)->getType()->hasUnsignedIntegerRepresentation()) &&
+ "asdouble operands types mismatch");
+ Value *OpLowBits = CGF.EmitScalarExpr(E->getArg(0));
+ Value *OpHighBits = CGF.EmitScalarExpr(E->getArg(1));
+
+ llvm::Type *ResultType = CGF.DoubleTy;
+ int N = 1;
+ if (auto *VTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) {
+ N = VTy->getNumElements();
+ ResultType = llvm::FixedVectorType::get(CGF.DoubleTy, N);
+ }
+
+ if (CGF.CGM.getTarget().getTriple().isDXIL())
+ return CGF.Builder.CreateIntrinsic(
+ /*ReturnType=*/ResultType, Intrinsic::dx_asdouble,
+ {OpLowBits, OpHighBits}, nullptr, "hlsl.asdouble");
+
+ if (!E->getArg(0)->getType()->isVectorType()) {
+ OpLowBits = CGF.Builder.CreateVectorSplat(1, OpLowBits);
+ OpHighBits = CGF.Builder.CreateVectorSplat(1, OpHighBits);
+ }
+
+ llvm::SmallVector<int> Mask;
+ for (int i = 0; i < N; i++) {
+ Mask.push_back(i);
+ Mask.push_back(i + N);
+ }
+
+ Value *BitVec = CGF.Builder.CreateShuffleVector(OpLowBits, OpHighBits, Mask);
+
+ return CGF.Builder.CreateBitCast(BitVec, ResultType);
+}
+
+static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) {
+ Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
+
+ Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy);
+ Value *CMP;
+ Value *LastInstr;
+
+ if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) {
+ FZeroConst = ConstantVector::getSplat(
+ ElementCount::getFixed(VecTy->getNumElements()), FZeroConst);
+ auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
+ CMP = CGF->Builder.CreateIntrinsic(
+ CGF->Builder.getInt1Ty(), CGF->CGM.getHLSLRuntime().getAnyIntrinsic(),
+ {FCompInst});
+ } else
+ CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
+
+ if (CGF->CGM.getTarget().getTriple().isDXIL())
+ LastInstr =
+ CGF->Builder.CreateIntrinsic(CGF->VoidTy, Intrinsic::dx_discard, {CMP});
+ else if (CGF->CGM.getTarget().getTriple().isSPIRV()) {
+ BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn);
+ BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn);
+
+ CGF->Builder.CreateCondBr(CMP, LT0, End);
+
+ CGF->Builder.SetInsertPoint(LT0);
+
+ CGF->Builder.CreateIntrinsic(CGF->VoidTy, Intrinsic::spv_discard, {});
+
+ LastInstr = CGF->Builder.CreateBr(End);
+ CGF->Builder.SetInsertPoint(End);
+ } else {
+ llvm_unreachable("Backend Codegen not supported.");
+ }
+
+ return LastInstr;
+}
+
+static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
+ Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
+ const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
+ const auto *OutArg2 = dyn_cast<HLSLOutArgExpr>(E->getArg(2));
+
+ CallArgList Args;
+ LValue Op1TmpLValue =
+ CGF->EmitHLSLOutArgExpr(OutArg1, Args, OutArg1->getType());
+ LValue Op2TmpLValue =
+ CGF->EmitHLSLOutArgExpr(OutArg2, Args, OutArg2->getType());
+
+ if (CGF->getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee())
+ Args.reverseWritebacks();
+
+ Value *LowBits = nullptr;
+ Value *HighBits = nullptr;
+
+ if (CGF->CGM.getTarget().getTriple().isDXIL()) {
+
+ llvm::Type *RetElementTy = CGF->Int32Ty;
+ if (auto *Op0VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>())
+ RetElementTy = llvm::VectorType::get(
+ CGF->Int32Ty, ElementCount::getFixed(Op0VecTy->getNumElements()));
+ auto *RetTy = llvm::StructType::get(RetElementTy, RetElementTy);
+
+ CallInst *CI = CGF->Builder.CreateIntrinsic(
+ RetTy, Intrinsic::dx_splitdouble, {Op0}, nullptr, "hlsl.splitdouble");
+
+ LowBits = CGF->Builder.CreateExtractValue(CI, 0);
+ HighBits = CGF->Builder.CreateExtractValue(CI, 1);
+
+ } else {
+ // For Non DXIL targets we generate the instructions.
+
+ if (!Op0->getType()->isVectorTy()) {
+ FixedVectorType *DestTy = FixedVectorType::get(CGF->Int32Ty, 2);
+ Value *Bitcast = CGF->Builder.CreateBitCast(Op0, DestTy);
+
+ LowBits = CGF->Builder.CreateExtractElement(Bitcast, (uint64_t)0);
+ HighBits = CGF->Builder.CreateExtractElement(Bitcast, 1);
+ } else {
+ int NumElements = 1;
+ if (const auto *VecTy =
+ E->getArg(0)->getType()->getAs<clang::VectorType>())
+ NumElements = VecTy->getNumElements();
+
+ FixedVectorType *Uint32VecTy =
+ FixedVectorType::get(CGF->Int32Ty, NumElements * 2);
+ Value *Uint32Vec = CGF->Builder.CreateBitCast(Op0, Uint32VecTy);
+ if (NumElements == 1) {
+ LowBits = CGF->Builder.CreateExtractElement(Uint32Vec, (uint64_t)0);
+ HighBits = CGF->Builder.CreateExtractElement(Uint32Vec, 1);
+ } else {
+ SmallVector<int> EvenMask, OddMask;
+ for (int I = 0, E = NumElements; I != E; ++I) {
+ EvenMask.push_back(I * 2);
+ OddMask.push_back(I * 2 + 1);
+ }
+ LowBits = CGF->Builder.CreateShuffleVector(Uint32Vec, EvenMask);
+ HighBits = CGF->Builder.CreateShuffleVector(Uint32Vec, OddMask);
+ }
+ }
+ }
+ CGF->Builder.CreateStore(LowBits, Op1TmpLValue.getAddress());
+ auto *LastInst =
+ CGF->Builder.CreateStore(HighBits, Op2TmpLValue.getAddress());
+ CGF->EmitWritebacks(Args);
+ return LastInst;
+}
+
+// Return dot product intrinsic that corresponds to the QT scalar type
+static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) {
+ if (QT->isFloatingType())
+ return RT.getFDotIntrinsic();
+ if (QT->isSignedIntegerType())
+ return RT.getSDotIntrinsic();
+ assert(QT->isUnsignedIntegerType());
+ return RT.getUDotIntrinsic();
+}
+
+static Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) {
+ if (QT->hasSignedIntegerRepresentation()) {
+ return RT.getFirstBitSHighIntrinsic();
+ }
+
+ assert(QT->hasUnsignedIntegerRepresentation());
+ return RT.getFirstBitUHighIntrinsic();
+}
+
+// Return wave active sum that corresponds to the QT scalar type
+static Intrinsic::ID getWaveActiveSumIntrinsic(llvm::Triple::ArchType Arch,
+ CGHLSLRuntime &RT, QualType QT) {
+ switch (Arch) {
+ case llvm::Triple::spirv:
+ return Intrinsic::spv_wave_reduce_sum;
+ case llvm::Triple::dxil: {
+ if (QT->isUnsignedIntegerType())
+ return Intrinsic::dx_wave_reduce_usum;
+ return Intrinsic::dx_wave_reduce_sum;
+ }
+ default:
+ llvm_unreachable("Intrinsic WaveActiveSum"
+ " not supported by target architecture");
+ }
+}
+
+// Return wave active sum that corresponds to the QT scalar type
+static Intrinsic::ID getWaveActiveMaxIntrinsic(llvm::Triple::ArchType Arch,
+ CGHLSLRuntime &RT, QualType QT) {
+ switch (Arch) {
+ case llvm::Triple::spirv:
+ if (QT->isUnsignedIntegerType())
+ return Intrinsic::spv_wave_reduce_umax;
+ return Intrinsic::spv_wave_reduce_max;
+ case llvm::Triple::dxil: {
+ if (QT->isUnsignedIntegerType())
+ return Intrinsic::dx_wave_reduce_umax;
+ return Intrinsic::dx_wave_reduce_max;
+ }
+ default:
+ llvm_unreachable("Intrinsic WaveActiveMax"
+ " not supported by target architecture");
+ }
+}
+
+Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E,
+ ReturnValueSlot ReturnValue) {
+ if (!getLangOpts().HLSL)
+ return nullptr;
+
+ switch (BuiltinID) {
+ case Builtin::BI__builtin_hlsl_adduint64: {
+ Value *OpA = EmitScalarExpr(E->getArg(0));
+ Value *OpB = EmitScalarExpr(E->getArg(1));
+ QualType Arg0Ty = E->getArg(0)->getType();
+ uint64_t NumElements = Arg0Ty->castAs<VectorType>()->getNumElements();
+ assert(Arg0Ty == E->getArg(1)->getType() &&
+ "AddUint64 operand types must match");
+ assert(Arg0Ty->hasIntegerRepresentation() &&
+ "AddUint64 operands must have an integer representation");
+ assert((NumElements == 2 || NumElements == 4) &&
+ "AddUint64 operands must have 2 or 4 elements");
+
+ llvm::Value *LowA;
+ llvm::Value *HighA;
+ llvm::Value *LowB;
+ llvm::Value *HighB;
+
+ // Obtain low and high words of inputs A and B
+ if (NumElements == 2) {
+ LowA = Builder.CreateExtractElement(OpA, (uint64_t)0, "LowA");
+ HighA = Builder.CreateExtractElement(OpA, (uint64_t)1, "HighA");
+ LowB = Builder.CreateExtractElement(OpB, (uint64_t)0, "LowB");
+ HighB = Builder.CreateExtractElement(OpB, (uint64_t)1, "HighB");
+ } else {
+ LowA = Builder.CreateShuffleVector(OpA, {0, 2}, "LowA");
+ HighA = Builder.CreateShuffleVector(OpA, {1, 3}, "HighA");
+ LowB = Builder.CreateShuffleVector(OpB, {0, 2}, "LowB");
+ HighB = Builder.CreateShuffleVector(OpB, {1, 3}, "HighB");
+ }
+
+ // Use an uadd_with_overflow to compute the sum of low words and obtain a
+ // carry value
+ llvm::Value *Carry;
+ llvm::Value *LowSum = EmitOverflowIntrinsic(
+ *this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
+ llvm::Value *ZExtCarry =
+ Builder.CreateZExt(Carry, HighA->getType(), "CarryZExt");
+
+ // Sum the high words and the carry
+ llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB, "HighSum");
+ llvm::Value *HighSumPlusCarry =
+ Builder.CreateAdd(HighSum, ZExtCarry, "HighSumPlusCarry");
+
+ if (NumElements == 4) {
+ return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
+ "hlsl.AddUint64");
+ }
+
+ llvm::Value *Result = PoisonValue::get(OpA->getType());
+ Result = Builder.CreateInsertElement(Result, LowSum, (uint64_t)0,
+ "hlsl.AddUint64.upto0");
+ Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, (uint64_t)1,
+ "hlsl.AddUint64");
+ return Result;
+ }
+ case Builtin::BI__builtin_hlsl_resource_getpointer: {
+ Value *HandleOp = EmitScalarExpr(E->getArg(0));
+ Value *IndexOp = EmitScalarExpr(E->getArg(1));
+
+ // TODO: Map to an hlsl_device address space.
+ llvm::Type *RetTy = llvm::PointerType::getUnqual(getLLVMContext());
+
+ return Builder.CreateIntrinsic(
+ RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
+ ArrayRef<Value *>{HandleOp, IndexOp});
+ }
+ case Builtin::BI__builtin_hlsl_all: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+ CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.all");
+ }
+ case Builtin::BI__builtin_hlsl_and: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ return Builder.CreateAnd(Op0, Op1, "hlsl.and");
+ }
+ case Builtin::BI__builtin_hlsl_or: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ return Builder.CreateOr(Op0, Op1, "hlsl.or");
+ }
+ case Builtin::BI__builtin_hlsl_any: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+ CGM.getHLSLRuntime().getAnyIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.any");
+ }
+ case Builtin::BI__builtin_hlsl_asdouble:
+ return handleAsDoubleBuiltin(*this, E);
+ case Builtin::BI__builtin_hlsl_elementwise_clamp: {
+ Value *OpX = EmitScalarExpr(E->getArg(0));
+ Value *OpMin = EmitScalarExpr(E->getArg(1));
+ Value *OpMax = EmitScalarExpr(E->getArg(2));
+
+ QualType Ty = E->getArg(0)->getType();
+ if (auto *VecTy = Ty->getAs<VectorType>())
+ Ty = VecTy->getElementType();
+
+ Intrinsic::ID Intr;
+ if (Ty->isFloatingType()) {
+ Intr = CGM.getHLSLRuntime().getNClampIntrinsic();
+ } else if (Ty->isUnsignedIntegerType()) {
+ Intr = CGM.getHLSLRuntime().getUClampIntrinsic();
+ } else {
+ assert(Ty->isSignedIntegerType());
+ Intr = CGM.getHLSLRuntime().getSClampIntrinsic();
+ }
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/OpX->getType(), Intr,
+ ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "hlsl.clamp");
+ }
+ case Builtin::BI__builtin_hlsl_cross: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ E->getArg(1)->getType()->hasFloatingRepresentation() &&
+ "cross operands must have a float representation");
+ // make sure each vector has exactly 3 elements
+ assert(
+ E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() == 3 &&
+ E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() == 3 &&
+ "input vectors must have 3 elements each");
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getCrossIntrinsic(),
+ ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.cross");
+ }
+ case Builtin::BI__builtin_hlsl_dot: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ llvm::Type *T0 = Op0->getType();
+ llvm::Type *T1 = Op1->getType();
+
+ // If the arguments are scalars, just emit a multiply
+ if (!T0->isVectorTy() && !T1->isVectorTy()) {
+ if (T0->isFloatingPointTy())
+ return Builder.CreateFMul(Op0, Op1, "hlsl.dot");
+
+ if (T0->isIntegerTy())
+ return Builder.CreateMul(Op0, Op1, "hlsl.dot");
+
+ llvm_unreachable(
+ "Scalar dot product is only supported on ints and floats.");
+ }
+ // For vectors, validate types and emit the appropriate intrinsic
+
+ // A VectorSplat should have happened
+ assert(T0->isVectorTy() && T1->isVectorTy() &&
+ "Dot product of vector and scalar is not supported.");
+
+ auto *VecTy0 = E->getArg(0)->getType()->castAs<VectorType>();
+ [[maybe_unused]] auto *VecTy1 =
+ E->getArg(1)->getType()->castAs<VectorType>();
+
+ assert(VecTy0->getElementType() == VecTy1->getElementType() &&
+ "Dot product of vectors need the same element types.");
+
+ assert(VecTy0->getNumElements() == VecTy1->getNumElements() &&
+ "Dot product requires vectors to be of the same size.");
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/T0->getScalarType(),
+ getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
+ ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
+ }
+ case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
+ Value *A = EmitScalarExpr(E->getArg(0));
+ Value *B = EmitScalarExpr(E->getArg(1));
+ Value *C = EmitScalarExpr(E->getArg(2));
+
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
+ "hlsl.dot4add.i8packed");
+ }
+ case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
+ Value *A = EmitScalarExpr(E->getArg(0));
+ Value *B = EmitScalarExpr(E->getArg(1));
+ Value *C = EmitScalarExpr(E->getArg(2));
+
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
+ "hlsl.dot4add.u8packed");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/ConvertType(E->getType()),
+ getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), E->getArg(0)->getType()),
+ ArrayRef<Value *>{X}, nullptr, "hlsl.firstbithigh");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/ConvertType(E->getType()),
+ CGM.getHLSLRuntime().getFirstBitLowIntrinsic(), ArrayRef<Value *>{X},
+ nullptr, "hlsl.firstbitlow");
+ }
+ case Builtin::BI__builtin_hlsl_lerp: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Y = EmitScalarExpr(E->getArg(1));
+ Value *S = EmitScalarExpr(E->getArg(2));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("lerp operand must have a float representation");
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
+ ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
+ }
+ case Builtin::BI__builtin_hlsl_normalize: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ "normalize operand must have a float representation");
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/X->getType(),
+ CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X},
+ nullptr, "hlsl.normalize");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_degrees: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ "degree operand must have a float representation");
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(),
+ ArrayRef<Value *>{X}, nullptr, "hlsl.degrees");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_frac: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("frac operand must have a float representation");
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getFracIntrinsic(),
+ ArrayRef<Value *>{Op0}, nullptr, "hlsl.frac");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Xty = Op0->getType();
+ llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
+ if (Xty->isVectorTy()) {
+ auto *XVecTy = E->getArg(0)->getType()->castAs<VectorType>();
+ retType = llvm::VectorType::get(
+ retType, ElementCount::getFixed(XVecTy->getNumElements()));
+ }
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("isinf operand m...
[truncated]
|
clang/lib/CodeGen/CMakeLists.txt
Outdated
@@ -115,6 +115,7 @@ add_clang_library(clangCodeGen | |||
PatternInit.cpp | |||
SanitizerMetadata.cpp | |||
SwiftCallingConv.cpp | |||
LangBuiltins/CGHLSLBuiltins.cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't bother with the LangBuiltins subdirectory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for creating this PR, LGTM (I wasn't able to do it earlier as one of my kids was ill, so away from laptop)
No worries. Thanks for the approval! |