[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-03-01 Thread Farzon Lotfi via cfe-commits


@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;

farzonl wrote:

https://github.com/llvm/llvm-project/pull/83609

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-29 Thread Chris B via cfe-commits


@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;

llvm-beanz wrote:

I disagree here. I think we should collapse these down. You can use a 
`%select{...}` block in the error format string to support the old message and 
the new message from the same diagnostic entry.

These diagnostic strings end up becoming some pretty large constant data tables 
in the final clang executable so we've generally tried to reuse errors where it 
makes sense.

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-29 Thread Farzon Lotfi via cfe-commits

farzonl wrote:

@python3kgae  I wanted to hold off on merging this one because I was 
investigating why 
[56240f0](https://github.com/llvm/llvm-project/commit/56240f07c39deb4c48bf7370dc72b3c67299eee1)
   wiped out my changes on 
[d4384c5](https://github.com/llvm/llvm-project/commit/d4384c5ac52596eeab512574111e499f230b7db7).
 In any case I put fixes up on the frac intrinsic pr.

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-29 Thread Xiang Li via cfe-commits

https://github.com/python3kgae closed 
https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-29 Thread Xiang Li via cfe-commits

https://github.com/python3kgae updated 
https://github.com/llvm/llvm-project/pull/83077

>From 56240f07c39deb4c48bf7370dc72b3c67299eee1 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Sun, 25 Feb 2024 20:08:09 -0500
Subject: [PATCH] start of lerp intrinsic

---
 clang/include/clang/Basic/Builtins.td |   6 +
 .../clang/Basic/DiagnosticSemaKinds.td|   5 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  40 +++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  36 ++
 clang/lib/Sema/SemaChecking.cpp   |  69 +++-
 .../CodeGenHLSL/builtins/lerp-builtin.hlsl|  37 ++
 clang/test/CodeGenHLSL/builtins/lerp.hlsl | 105 ++
 clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl  |  28 ++---
 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl |  91 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   5 +
 10 files changed, 381 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 3bc35c5bb38ecf..b593cd4f4ede4d 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4536,6 +4536,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c8141fefb8edba..91ce10279f10d2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+  
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2d16e7cdc06053..74ca96117793c4 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18007,6 +18007,46 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  // DXC does this via casting to float should we do the same thing?
+  if (Xty->isIntegerTy()) {
+auto V = Builder.CreateSub(Y, X);
+V = Builder.CreateMul(S, V);
+return Builder.CreateAdd(X, V, "dx.lerp");
+  }
+  // Bools should have been promoted
+  llvm_unreachable("Scalar Lerp is only supported on ints and floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+   SVecTy->getNumElements() &&
+   "Lerp requires vectors to be of the same size.");
+return Builder.CreateIntrinsic(
+/*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
+nullptr, "dx.lerp");
+  }
   }
   return nullptr;
 }
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 08e5d981a4a4ca..1314bdefa37e7b 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -317,6 +317,42 @@ double3 floor(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor)
 double4 floor(double4);
 
+//===-

[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Xiang Li via cfe-commits

https://github.com/python3kgae approved this pull request.


https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl updated 
https://github.com/llvm/llvm-project/pull/83077

>From 56240f07c39deb4c48bf7370dc72b3c67299eee1 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Sun, 25 Feb 2024 20:08:09 -0500
Subject: [PATCH] start of lerp intrinsic

---
 clang/include/clang/Basic/Builtins.td |   6 +
 .../clang/Basic/DiagnosticSemaKinds.td|   5 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  40 +++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  36 ++
 clang/lib/Sema/SemaChecking.cpp   |  69 +++-
 .../CodeGenHLSL/builtins/lerp-builtin.hlsl|  37 ++
 clang/test/CodeGenHLSL/builtins/lerp.hlsl | 105 ++
 clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl  |  28 ++---
 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl |  91 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   5 +
 10 files changed, 381 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 3bc35c5bb38ecf2..b593cd4f4ede4d6 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4536,6 +4536,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c8141fefb8edba3..91ce10279f10d2b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+  
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2d16e7cdc060530..74ca96117793c4d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18007,6 +18007,46 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  // DXC does this via casting to float should we do the same thing?
+  if (Xty->isIntegerTy()) {
+auto V = Builder.CreateSub(Y, X);
+V = Builder.CreateMul(S, V);
+return Builder.CreateAdd(X, V, "dx.lerp");
+  }
+  // Bools should have been promoted
+  llvm_unreachable("Scalar Lerp is only supported on ints and floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+   SVecTy->getNumElements() &&
+   "Lerp requires vectors to be of the same size.");
+return Builder.CreateIntrinsic(
+/*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
+nullptr, "dx.lerp");
+  }
   }
   return nullptr;
 }
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 08e5d981a4a4ca9..1314bdefa37e7bb 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -317,6 +317,42 @@ double3 floor(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor)
 double4 floor(double4);
 
+//===-

[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Farzon Lotfi via cfe-commits


@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;

farzonl wrote:

I did it this way because the amount of test cases I would need to update to 
not be tied to two args was very large.

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Justin Bogner via cfe-commits


@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;

bogner wrote:

It wouldn't make sense to change it as part of this commit, but with this in 
place "err_vec_builtin_non_vector" has a bit of an ambiguous name now. Might be 
worth following up at some point

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Justin Bogner via cfe-commits


@@ -5169,49 +5169,63 @@ bool Sema::CheckPPCMMAType(QualType Type, 
SourceLocation TypeLoc) {
 bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
   assert(TheCall->getNumArgs() > 1);
   ExprResult A = TheCall->getArg(0);
-  ExprResult B = TheCall->getArg(1);
+
   QualType ArgTyA = A.get()->getType();
-  QualType ArgTyB = B.get()->getType();
+
   auto *VecTyA = ArgTyA->getAs();
-  auto *VecTyB = ArgTyB->getAs();
   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
-  if (VecTyA == nullptr && VecTyB == nullptr)
-return false;
 
-  if (VecTyA && VecTyB) {
-bool retValue = false;
-if (VecTyA->getElementType() != VecTyB->getElementType()) {
-  // Note: type promotion is intended to be handeled via the intrinsics
-  //  and not the builtin itself.
-  S->Diag(TheCall->getBeginLoc(), 
diag::err_vec_builtin_incompatible_vector)
-  << TheCall->getDirectCallee()
-  << SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
-  retValue = true;
-}
-if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
-  // if we get here a HLSLVectorTruncation is needed.
-  S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
-  << TheCall->getDirectCallee()
-  << SourceRange(TheCall->getArg(0)->getBeginLoc(),
- TheCall->getArg(1)->getEndLoc());
-  retValue = true;
-}
+  for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
+ExprResult B = TheCall->getArg(i);
+QualType ArgTyB = B.get()->getType();
+auto *VecTyB = ArgTyB->getAs();
+if (VecTyA == nullptr && VecTyB == nullptr)
+  return false;
 
-if (retValue)
-  TheCall->setType(VecTyA->getElementType());
+if (VecTyA && VecTyB) {
+  bool retValue = false;
+  if (VecTyA->getElementType() != VecTyB->getElementType()) {
+// Note: type promotion is intended to be handeled via the intrinsics
+//  and not the builtin itself.
+S->Diag(TheCall->getBeginLoc(),
+diag::err_vec_builtin_incompatible_vector_all)
+<< TheCall->getDirectCallee()
+<< SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
+retValue = true;
+  }
+  if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
+// if we get here a HLSLVectorTruncation is needed.
+S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector_all)
+<< TheCall->getDirectCallee()
+<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
+   TheCall->getArg(1)->getEndLoc());
+retValue = true;
+  }
+
+  if (!retValue)
+TheCall->setType(VecTyA->getElementType());
 
-return retValue;
+  return retValue;
+}
   }
 
   // Note: if we get here one of the args is a scalar which
   // requires a VectorSplat on Arg0 or Arg1
-  S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
+  S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector_all)
   << TheCall->getDirectCallee()
   << SourceRange(TheCall->getArg(0)->getBeginLoc(),
  TheCall->getArg(1)->getEndLoc());
   return true;
 }
 
+bool checkAllArgsAreFloatRepresnations(CallExpr *TheCall) {

bogner wrote:

typo "Represnations"

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Justin Bogner via cfe-commits

https://github.com/bogner approved this pull request.

LGTM, but see my comments in #83315 about test case formatting.

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Justin Bogner via cfe-commits

https://github.com/bogner edited https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-x86

Author: Farzon Lotfi (farzonl)


Changes

This is the start of implementing the lerp intrinsic 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
 Builtins.td - defines the builtin
hlsl_intrinsics.h - defines the lerp api
DiagnosticSemaKinds.td - needed a new error to be inclusive for more than two 
operands.
CGBuiltin.cpp - add the lerp intrinsic lowering
SemaChecking.cpp - type checks for lerp builtin
IntrinsicsDirectX.td - define the lerp intrinsic

this change implements the first half of #70102

---

Patch is 25.56 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/83077.diff


10 Files Affected:

- (modified) clang/include/clang/Basic/Builtins.td (+6) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+37) 
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+36) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+52-27) 
- (added) clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl (+37) 
- (added) clang/test/CodeGenHLSL/builtins/lerp.hlsl (+105) 
- (modified) clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl (+14-14) 
- (added) clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl (+91) 
- (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+5) 


``diff
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index e3432f7925ba14..755ef3631b2856 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4530,6 +4530,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 57784a4ba2e388..63115d4bd49091 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 54d7451a9d6221..17b7af924e5ff0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18006,6 +18006,43 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  llvm_unreachable("Scalar Lerp is only supported on floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+   XVecTy->getNumElements() == SVecTy->getNumElements() &&
+   "Lerp requires vectors to be of the same size.");
+assert(XVecTy->getElementType()->isRealFloatingType() &&
+   XVecTy->getElementType() == YVecTy->getElementType() &&
+   XVecTy->getElementType() == SVecTy->getElementType() &&
+   "Lerp requires float vectors to be of the same type.");
+return Builder.CreateIntrinsic(
+/*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
+nullptr, "dx.lerp");
+  }
   }
   return nullptr;
 }
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 08e5d981a4a4ca..1314bdefa37e7b 100644
---

[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-hlsl

Author: Farzon Lotfi (farzonl)


Changes

This is the start of implementing the lerp intrinsic 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
 Builtins.td - defines the builtin
hlsl_intrinsics.h - defines the lerp api
DiagnosticSemaKinds.td - needed a new error to be inclusive for more than two 
operands.
CGBuiltin.cpp - add the lerp intrinsic lowering
SemaChecking.cpp - type checks for lerp builtin
IntrinsicsDirectX.td - define the lerp intrinsic

this change implements the first half of #70102

---

Patch is 25.56 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/83077.diff


10 Files Affected:

- (modified) clang/include/clang/Basic/Builtins.td (+6) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+37) 
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+36) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+52-27) 
- (added) clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl (+37) 
- (added) clang/test/CodeGenHLSL/builtins/lerp.hlsl (+105) 
- (modified) clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl (+14-14) 
- (added) clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl (+91) 
- (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+5) 


``diff
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index e3432f7925ba14..755ef3631b2856 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4530,6 +4530,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 57784a4ba2e388..63115d4bd49091 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 54d7451a9d6221..17b7af924e5ff0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18006,6 +18006,43 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  llvm_unreachable("Scalar Lerp is only supported on floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+   XVecTy->getNumElements() == SVecTy->getNumElements() &&
+   "Lerp requires vectors to be of the same size.");
+assert(XVecTy->getElementType()->isRealFloatingType() &&
+   XVecTy->getElementType() == YVecTy->getElementType() &&
+   XVecTy->getElementType() == SVecTy->getElementType() &&
+   "Lerp requires float vectors to be of the same type.");
+return Builder.CreateIntrinsic(
+/*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
+nullptr, "dx.lerp");
+  }
   }
   return nullptr;
 }
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 08e5d981a4a4ca..1314bdefa37e7b 100644
--- a/clan

[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-28 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl ready_for_review 
https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-27 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl updated 
https://github.com/llvm/llvm-project/pull/83077

>From d4384c5ac52596eeab512574111e499f230b7db7 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Sun, 25 Feb 2024 20:08:09 -0500
Subject: [PATCH] [HLSL] Implementation  lerp intrinsic This is the start of
 implementing the lerp intrinsic
 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
 Builtins.td - defines the builtin hlsl_intrinsics.h - defines the lerp api
 DiagnosticSemaKinds.td - needed a new error to be inclusive for more than two
 operands. CGBuiltin.cpp - add the lerp intrinsic lowering SemaChecking.cpp -
 type checks for lerp builtin IntrinsicsDirectX.td - define the lerp intrinsic

this change implements the first half of #70102
---
 clang/include/clang/Basic/Builtins.td |   6 +
 .../clang/Basic/DiagnosticSemaKinds.td|   5 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  37 ++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  36 ++
 clang/lib/Sema/SemaChecking.cpp   |  79 -
 .../CodeGenHLSL/builtins/lerp-builtin.hlsl|  37 ++
 clang/test/CodeGenHLSL/builtins/lerp.hlsl | 105 ++
 clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl  |  28 ++---
 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl |  91 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   5 +
 10 files changed, 388 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index e3432f7925ba14..755ef3631b2856 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4530,6 +4530,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 57784a4ba2e388..63115d4bd49091 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 54d7451a9d6221..17b7af924e5ff0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18006,6 +18006,43 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  llvm_unreachable("Scalar Lerp is only supported on floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+   XVecTy->getNumElements() == SVecTy->getNumElements() &&
+   "Lerp requires vectors to be of the same size.");
+assert(XVecTy->getElementType()->isRealFloatingType() &&
+   XVecTy->getElementType() == YVecTy->getElementType() &&
+   XVecTy->getElementType() == SVecTy->getElementType() &&
+   "Lerp requires float vectors to be of the same type.");
+return Builder.CreateIntrinsic(
+ 

[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-27 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-27 Thread Farzon Lotfi via cfe-commits


@@ -24,4 +24,9 @@ def int_dx_dot :
 Intrinsic<[LLVMVectorElementType<0>], 
 [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, 
LLVMVectorElementType<0>>],
 [IntrNoMem, IntrWillReturn, Commutative] >;
+
+def int_dx_lerp :
+Intrinsic<[LLVMMatchType<0>], 
+[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>],

farzonl wrote:

I think you are right.  here is my understanding of the Tablegen. if you diff a 
`LLVMMatchType` vs `LLVMScalarOrSameVectorWidth`
The thing that will pop out as different are the type signatures:
https://github.com/llvm/llvm-project/assets/1802579/a6bad9a5-88b8-4316-aaea-f7fb7808c45b";>
For `anonymous_78` 
1. [15, 512] means
2. 512 maps to `EncMatchType`
3. 15 maps to `LLVMType`

we compare that to `anonymous_6913` `31, 768, 42, 512`

1. 31 is `LLVMScalarOrSameVectorWidth`
2. 768 is `EncSameWidth`
3. 42 is `LLVMVectorElementType`
4. 512 maps to `EncMatchType`

so when we match on anonymous_6913 we match on width and element type as well.

so then if we look at just `int_dx_lerp`  the type sig differences are [15, 7]  
vs  [31, 3, 42, 7] with [15, 3] being the same for both.

```
def ArgKind {
  int Any = 0;
  int AnyInteger = 1;
  int AnyFloat = 2;
  int AnyVector = 3;
  int AnyPointer = 4;
  int MatchType = 7;
}
```
The  7 just means match
The  3 means any vector

So with just LLVMMatchType we are matching on anyvector but any vector doesn't 
get encoded into the  return or argument types. Further we don't get 42  the 
`LLVMVectorElementType` or  31 the `LLVMScalarOrSameVectorWidth`.

Legend to determine signatures:
![image](https://github.com/llvm/llvm-project/assets/1802579/27b86f6d-14a2-4543-a8eb-3f887cdbea85)



https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-26 Thread Xiang Li via cfe-commits


@@ -24,4 +24,9 @@ def int_dx_dot :
 Intrinsic<[LLVMVectorElementType<0>], 
 [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, 
LLVMVectorElementType<0>>],
 [IntrNoMem, IntrWillReturn, Commutative] >;
+
+def int_dx_lerp :
+Intrinsic<[LLVMMatchType<0>], 
+[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>],

python3kgae wrote:

Should it be LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>> like dot?

https://github.com/llvm/llvm-project/pull/83077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL] implementation of lerp intrinsic (PR #83077)

2024-02-26 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl created 
https://github.com/llvm/llvm-project/pull/83077

This is the start of implementing the lerp intrinsic 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
 Builtins.td - defines the builtin
hlsl_intrinsics.h - defines the lerp api
DiagnosticSemaKinds.td - needed a new error to be inclusive for more than two 
operands.
CGBuiltin.cpp - add the lerp intrinsic lowering
SemaChecking.cpp - type checks for lerp builtin
IntrinsicsDirectX.td - define the lerp intrinsic

this change implements the first half of #70102

>From c6f533e226efbf38bfb1dc9df382342ec813cc37 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Sun, 25 Feb 2024 20:08:09 -0500
Subject: [PATCH] [HLSL] Implementation  lerp intrinsic This is the start of
 implementing the lerp intrinsic
 
https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-lerp
 Builtins.td - defines the builtin hlsl_intrinsics.h - defines the lerp api
 DiagnosticSemaKinds.td - needed a new error to be inclusive for more than two
 operands. CGBuiltin.cpp - add the lerp intrinsic lowering SemaChecking.cpp -
 type checks for lerp builtin IntrinsicsDirectX.td - define the lerp intrinsic

this change implements the first half of #70102
---
 clang/include/clang/Basic/Builtins.td |   6 +
 .../clang/Basic/DiagnosticSemaKinds.td|   5 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  37 ++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  36 ++
 clang/lib/Sema/SemaChecking.cpp   |  79 -
 .../CodeGenHLSL/builtins/lerp-builtin.hlsl|  37 ++
 clang/test/CodeGenHLSL/builtins/lerp.hlsl | 105 ++
 clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl  |  28 ++---
 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl |  91 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   5 +
 10 files changed, 388 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/lerp.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index e3432f7925ba14..755ef3631b2856 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4530,6 +4530,12 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 57784a4ba2e388..f1a5d30858f829 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10266,6 +10266,11 @@ def err_block_on_vm : Error<
 def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
+def err_vec_builtin_non_vector_all : Error<
+ "all arguments to %0 must be vectors">;
+def err_vec_builtin_incompatible_vector_all : Error<
+  "all arguments to %0 must have vectors of the same type">;
+  
 def err_vec_builtin_non_vector : Error<
  "first two arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 54d7451a9d6221..17b7af924e5ff0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18006,6 +18006,43 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
 ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
+  case Builtin::BI__builtin_hlsl_lerp: {
+Value *X = EmitScalarExpr(E->getArg(0));
+Value *Y = EmitScalarExpr(E->getArg(1));
+Value *S = EmitScalarExpr(E->getArg(2));
+llvm::Type *Xty = X->getType();
+llvm::Type *Yty = Y->getType();
+llvm::Type *Sty = S->getType();
+if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+  if (Xty->isFloatingPointTy()) {
+auto V = Builder.CreateFSub(Y, X);
+V = Builder.CreateFMul(S, V);
+return Builder.CreateFAdd(X, V, "dx.lerp");
+  }
+  llvm_unreachable("Scalar Lerp is only supported on floats.");
+}
+// A VectorSplat should have happened
+assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+   "Lerp of vector and scalar is not supported.");
+
+[[maybe_unused]] auto *XVecTy =
+E->getArg(0)->getType()->getAs();
+[[maybe_unused]] auto *YVecTy =
+E->getArg(1)->getType()->getAs();
+[[maybe_unused]] auto *SVecTy =
+E->getArg(2)->getType()->getAs();
+// A HLSLVectorTruncation should have happend
+