[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits


@@ -19108,6 +19108,21 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+IntegerType *Int1Ty =
+llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty &&
+   "wave_active_any_true operand must be a bool");
+
+llvm::FunctionType *FT =

V-FEXrt wrote:

I originally had something like this

```hlsl
  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
Value *Op = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
Op->getType(), 
CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic(), 
Op, nullptr, "hlsl.wave.activeanytrue"
);
  }
```

but that was failing with a convergence error `Cannot mix controlled and 
uncontrolled convergence in the same function.`. I also though I tried 
`Intrinsic::getOrInsertDeclaration` but I can't remember what happened with 
that.  I'll give it another try

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt created 
https://github.com/llvm/llvm-project/pull/115902

Resolves https://github.com/llvm/llvm-project/issues/99160

- [x]  Implement `WaveActiveAnyTrue` clang builtin,
- [x]  Link `WaveActiveAnyTrue` clang builtin with `hlsl_intrinsics.h`
- [x]  Add sema checks for `WaveActiveAnyTrue` to 
`CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [x]  Add codegen for `WaveActiveAnyTrue` to `EmitHLSLBuiltinExpr` in 
`CGBuiltin.cpp`
- [x]  Add codegen tests to 
`clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl`
- [x]  Add sema tests to 
`clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl`
- [x]  Create the `int_dx_WaveActiveAnyTrue` intrinsic in `IntrinsicsDirectX.td`
- [x]  Create the `DXILOpMapping` of `int_dx_WaveActiveAnyTrue` to `113` in 
`DXIL.td`
- [x]  Create the `WaveActiveAnyTrue.ll` and `WaveActiveAnyTrue_errors.ll` 
tests in `llvm/test/CodeGen/DirectX/`
- [x]  Create the `int_spv_WaveActiveAnyTrue` intrinsic in `IntrinsicsSPIRV.td`
- [x]  In SPIRVInstructionSelector.cpp create the `WaveActiveAnyTrue` lowering 
and map it to `int_spv_WaveActiveAnyTrue` in 
`SPIRVInstructionSelector::selectIntrinsic`.
- [x]  Create SPIR-V backend test case in 
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll`

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/3] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRu

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/3] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,17 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32v1.3-vulkan-unknown %s -o 
- | FileCheck %s

V-FEXrt wrote:

do you mean `-mtriple=spirv32v1.5-unknown-unknown`? I couldn't get any other 
variant of the `spirv` part to work

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/4] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_wave_active_any_true();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 
0}}
+}
+
+bool test_too_many_arg(bool p0) {
+  return __builtin_hlsl_wave_active_any_true(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 
2}}
+}
+
+struct Foo
+{
+  int a;
+};
+
+bool test_type_check_2(Foo p0) {

V-FEXrt wrote:

Delete the `_2`  from the function name

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-12 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-13 Thread Ashley Coleman via cfe-commits


@@ -93,6 +93,7 @@ def int_dx_rsqrt  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], 
[LLVMMatchType<0>]
 def int_dx_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], 
[llvm_i1_ty], [IntrConvergent, IntrNoMem]>;
 def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], 
[IntrConvergent, IntrNoMem]>;
 def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], 
[IntrConvergent]>;
+def int_dx_wave_activeanytrue : DefaultAttrsIntrinsic<[llvm_i1_ty], 
[llvm_i1_ty], [IntrConvergent]>;

V-FEXrt wrote:

I don't feel strongly either way, and I'm happy to rename but doesn't 
`wave.anyactivetrue` match the proposal as much as `wave.any`  does while being 
more explicit?

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-13 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/5] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-13 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/6] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -17,12 +17,10 @@ double test_int_builtin(double p0) {
 
 double2 test_int_builtin_2(double2 p0) {
   return __builtin_hlsl_elementwise_firstbithigh(p0);
-  // expected-error@-1 {{1st argument must be a vector of integers
-  // (was 'double2' (aka 'vector'))}}
+  // expected-error@-1 {{1st argument must be a vector of integers (was 
'double2' (aka 'vector'))}}
 }
 
 float test_int_builtin_3(float p0) {
   return __builtin_hlsl_elementwise_firstbithigh(p0);
-  // expected-error@-1 {{1st argument must be a vector of integers
-  // (was 'float')}}
+  // expected-error@-1 {{1st argument must be a vector of integers (was 
'double')}}

V-FEXrt wrote:

The test framework doesn't actually assert these lines when split. I had to 
unsplit them which raised a test failure that was then fixed

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-21 Thread Ashley Coleman via cfe-commits


@@ -1949,24 +1949,36 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveOpInst(Register ResVReg,
+const SPIRVType *ResType,
+MachineInstr &I,
+unsigned Opcode) const {
+  MachineBasicBlock &BB = *I.getParent();
+  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+
+  auto BMI = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I,
+IntTy, TII));
+
+  for (unsigned j = 2; j < I.getNumOperands(); j++) {

V-FEXrt wrote:

I'm a die hard vim user >.< 

But I do already have clangd setup and I think I can set that up to do the same

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,17 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | 
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - 
-filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#bool:]] = OpTypeBool
+; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#scope:]] = OpConstant %[[#uint]] 3
+
+; CHECK-LABEL: Begin function test_wave_any
+define i1 @test_wave_any(i1 %p1) {
+entry:
+; CHECK: %[[#param:]] = OpFunctionParameter %[[#bool]]
+; CHECK: %{{.+}} = OpGroupNonUniformAny %[[#bool]] %[[#scope]] %[[#param]]
+  %ret = call i1 @llvm.spv.wave.any(i1 %p1)

V-FEXrt wrote:

This [similar 
commit](https://github.com/llvm/llvm-project/pull/111010/commits/484b2089ae9f0a0fae09b6d68b70171f1007bade#diff-bac84b1c33bc0aee1edd39550243c6e3c5606b6b8538b2f424a55ce3c9977244)
 (from which I was basing my changes) seems to have intentionally removed the 
convergence intrinsics generated by the frontend. Should we mirror that or 
should convergence be added back in to that test?

cc @inbelic 

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2848,7 +2819,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
   case Intrinsic::spv_wave_active_countbits:
 return selectWaveActiveCountBits(ResVReg, ResType, I);
   case Intrinsic::spv_wave_any:
-return selectWaveActiveAnyTrue(ResVReg, ResType, I);
+return selectWaveNOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny);
   case Intrinsic::spv_wave_is_first_lane: {
 SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);

V-FEXrt wrote:

Maybe, I'm reading the diff wrong, but I think I already did that?

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2848,7 +2819,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
   case Intrinsic::spv_wave_active_countbits:
 return selectWaveActiveCountBits(ResVReg, ResType, I);
   case Intrinsic::spv_wave_any:
-return selectWaveActiveAnyTrue(ResVReg, ResType, I);
+return selectWaveNOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny);
   case Intrinsic::spv_wave_is_first_lane: {
 SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);

V-FEXrt wrote:

ohhh I see. Certainly reading the diff wrong! Will fix it up :)

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,6 +1952,23 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveActiveAnyTrue(Register ResVReg,
+   const SPIRVType 
*ResType,
+   MachineInstr &I) const {
+  assert(I.getNumOperands() == 3);
+  assert(I.getOperand(2).isReg());
+
+  MachineBasicBlock &BB = *I.getParent();
+  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+
+  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpGroupNonUniformAny))

V-FEXrt wrote:

Okay, done! Please take a look!

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,6 +1952,23 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveActiveAnyTrue(Register ResVReg,
+   const SPIRVType 
*ResType,
+   MachineInstr &I) const {
+  assert(I.getNumOperands() == 3);
+  assert(I.getOperand(2).isReg());
+
+  MachineBasicBlock &BB = *I.getParent();
+  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+
+  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpGroupNonUniformAny))

V-FEXrt wrote:

https://github.com/llvm/llvm-project/pull/115902/commits/8733a1b619dff0c8bcf86316c02252f2c4f5a6b6

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2826,6 +2843,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
 return selectExtInst(ResVReg, ResType, I, CL::s_clamp, GL::SClamp);
   case Intrinsic::spv_wave_active_countbits:
 return selectWaveActiveCountBits(ResVReg, ResType, I);
+  case Intrinsic::spv_wave_any:
+return selectWaveActiveAnyTrue(ResVReg, ResType, I);

V-FEXrt wrote:

no reason. Its just left over from previous commits. Give me a sec

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -86,6 +86,7 @@ let TargetPrefix = "spv" in {
   def int_spv_dot4add_i8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], 
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
   def int_spv_dot4add_u8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], 
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
   def int_spv_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], 
[llvm_i1_ty], [IntrConvergent, IntrNoMem]>;
+  def int_spv_wave_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], 
[IntrConvergent, IntrNoMem]>;

V-FEXrt wrote:

@inbelic says its fine to keep here 
https://github.com/llvm/llvm-project/pull/115902#discussion_r1849054561

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/15] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,24 +1955,48 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveNOpInst(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ unsigned Opcode,
+ unsigned OperandCount) const {
+  assert(I.getNumOperands() == OperandCount);

V-FEXrt wrote:

I was just blindly refactoring, but one could argue that asserting the expected 
`OperandCount` is safer from a "is this doing what I expect" angle

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,24 +1955,48 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveNOpInst(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ unsigned Opcode,
+ unsigned OperandCount) const {
+  assert(I.getNumOperands() == OperandCount);

V-FEXrt wrote:

Especially since the value is statically known for each opcode

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/18] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2206,6 +2206,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)

V-FEXrt wrote:

I was just kind of following what others had done. But imo its worth keeping if 
for nothing else besides the documentation

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,6 +1952,23 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveActiveAnyTrue(Register ResVReg,
+   const SPIRVType 
*ResType,
+   MachineInstr &I) const {
+  assert(I.getNumOperands() == 3);
+  assert(I.getOperand(2).isReg());
+
+  MachineBasicBlock &BB = *I.getParent();
+  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+
+  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpGroupNonUniformAny))

V-FEXrt wrote:

> If it is easy to write a generic with a different number of operands then we 
> could also look at the other wave intriniscs

This should be farily reasonable to do. I'll take a look

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,24 +1955,48 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveNOpInst(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ unsigned Opcode,
+ unsigned OperandCount) const {
+  assert(I.getNumOperands() == OperandCount);
+  for (unsigned j = 2; j < OperandCount; j++) {
+assert(I.getOperand(j).isReg());
+  }
+
+  MachineBasicBlock &BB = *I.getParent();
+  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+
+  auto BMI = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I,
+IntTy, TII));
+
+  for (unsigned j = 2; j < OperandCount; j++) {
+BMI.addUse(I.getOperand(j).getReg());
+  }
+
+  return BMI.constrainAllUses(TII, TRI, RBI);
+}
+
+bool SPIRVInstructionSelector::selectWaveActiveAnyTrue(Register ResVReg,
+   const SPIRVType 
*ResType,
+   MachineInstr &I) const {
+  return selectWaveNOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny, 
3);

V-FEXrt wrote:

N/A  after removing `OperandCount`

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/16] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -1949,24 +1955,48 @@ bool SPIRVInstructionSelector::selectSign(Register 
ResVReg,
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectWaveNOpInst(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ unsigned Opcode,
+ unsigned OperandCount) const {
+  assert(I.getNumOperands() == OperandCount);

V-FEXrt wrote:

https://github.com/llvm/llvm-project/pull/115902/commits/42d24e47bfd0d635119bfa858bdf01b14238fe8c

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2826,6 +2843,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
 return selectExtInst(ResVReg, ResType, I, CL::s_clamp, GL::SClamp);
   case Intrinsic::spv_wave_active_countbits:
 return selectWaveActiveCountBits(ResVReg, ResType, I);
+  case Intrinsic::spv_wave_any:
+return selectWaveActiveAnyTrue(ResVReg, ResType, I);

V-FEXrt wrote:

https://github.com/llvm/llvm-project/pull/115902/commits/42d24e47bfd0d635119bfa858bdf01b14238fe8c

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-19 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt created 
https://github.com/llvm/llvm-project/pull/116858

Closes https://github.com/llvm/llvm-project/issues/99116

- [x]  Implement firstbitlow clang builtin,
- [x]  Link firstbitlow clang builtin with hlsl_intrinsics.h
- [x]  Add sema checks for firstbitlow to CheckHLSLBuiltinFunctionCall in 
SemaChecking.cpp
- [x]  Add codegen for firstbitlow to EmitHLSLBuiltinExpr in CGBuiltin.cpp
- [x]  Add codegen tests to clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
- [x]  Add sema tests to clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
- [x]  Create the int_dx_firstbitlow intrinsic in IntrinsicsDirectX.td
- [x]  Create the DXILOpMapping of int_dx_firstbitlow to 32 in DXIL.td
- [x]  Create the firstbitlow.ll and firstbitlow_errors.ll tests in 
llvm/test/CodeGen/DirectX/
- [x]  Create the int_spv_firstbitlow intrinsic in IntrinsicsSPIRV.td
- [x]  In SPIRVInstructionSelector.cpp create the firstbitlow lowering and map 
it to int_spv_firstbitlow in SPIRVInstructionSelector::selectIntrinsic.
- [x]  Create SPIR-V backend test case in 
llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

>From 49021b33222e0553a3ea52d9802bf133cfa97700 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 14 Nov 2024 11:53:39 -0700
Subject: [PATCH 1/3] [HLSL] Implement elementwise firstbitlow builtin

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |   9 +-
 clang/lib/CodeGen/CGHLSLRuntime.h |   1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  72 
 clang/lib/Sema/SemaHLSL.cpp   |   3 +-
 .../CodeGenHLSL/builtins/firstbitlow.hlsl | 153 
 .../BuiltIns/firstbithigh-errors.hlsl |   6 +-
 .../SemaHLSL/BuiltIns/firstbitlow-errors.hlsl |  26 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   2 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   1 +
 llvm/lib/Target/DirectX/DXIL.td   |  13 ++
 .../DirectX/DirectXTargetTransformInfo.cpp|   1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 169 ++
 llvm/test/CodeGen/DirectX/firstbitlow.ll  |  47 +
 .../test/CodeGen/DirectX/firstbitlow_error.ll |  10 ++
 .../SPIRV/hlsl-intrinsics/firstbitlow.ll  | 104 +++
 16 files changed, 617 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow.ll
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow_error.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index e866605ac05c09..afe0a311f236d8 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4810,6 +4810,12 @@ def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFirstBitLow : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_firstbitlow"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_frac"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9e0c0bff0125c0..a65b96684f18eb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18956,7 +18956,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 "hlsl.dot4add.u8packed");
   }
   case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
-
 Value *X = EmitScalarExpr(E->getArg(0));
 
 return Builder.CreateIntrinsic(
@@ -18964,6 +18963,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), 
E->getArg(0)->getType()),
 ArrayRef{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{X},
+nullptr, "hlsl.firstbitlow");
+  }
   case Builtin::BI__builtin_hlsl_lerp: {
 Value *X = EmitScalarExpr(E->getArg(0));
 Value *Y = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index 381a5959ec098e..c9eb1b08ff6ba6 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -96,6 +96,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
 

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o 
- | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN:   spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// Test basic lowering to runtime function call for int values.
+
+// CHECK-LABEL: test

V-FEXrt wrote:

ah yeah, good point

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-15 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/12] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/11] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/9] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/11] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/8] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 1/8] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which evalua

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-14 Thread Ashley Coleman via cfe-commits


@@ -93,6 +93,7 @@ def int_dx_rsqrt  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], 
[LLVMMatchType<0>]
 def int_dx_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], 
[llvm_i1_ty], [IntrConvergent, IntrNoMem]>;
 def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], 
[IntrConvergent, IntrNoMem]>;
 def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], 
[IntrConvergent]>;
+def int_dx_wave_activeanytrue : DefaultAttrsIntrinsic<[llvm_i1_ty], 
[llvm_i1_ty], [IntrConvergent]>;

V-FEXrt wrote:

Oh it does and I just fully missed that. Sounds good thanks!

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-20 Thread Ashley Coleman via cfe-commits


@@ -2848,7 +2819,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
   case Intrinsic::spv_wave_active_countbits:
 return selectWaveActiveCountBits(ResVReg, ResType, I);
   case Intrinsic::spv_wave_any:
-return selectWaveActiveAnyTrue(ResVReg, ResType, I);
+return selectWaveNOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny);
   case Intrinsic::spv_wave_is_first_lane: {
 SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);

V-FEXrt wrote:

https://github.com/llvm/llvm-project/pull/115902/commits/ee787874ed394763a7028182df4f1bfeb8cb37cb

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


[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-15 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/13] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement `WaveActiveAllTrue` Intrinsic (PR #117245)

2024-12-09 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/117245

>From 1156d98a0ba25a92b4edbacb7c17e5ad6bb2b522 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 21 Nov 2024 08:42:31 -0700
Subject: [PATCH 1/2] [HLSL] Implement WaveActiveAllTrue Intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 ++
 clang/lib/CodeGen/CGBuiltin.cpp   | 10 +
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 
 .../builtins/WaveActiveAllTrue.hlsl   | 17 +++
 .../BuiltIns/WaveActiveAllTrue-errors.hlsl| 21 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   |  8 +++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  2 ++
 .../test/CodeGen/DirectX/WaveActiveAllTrue.ll | 10 +
 .../hlsl-intrinsics/WaveActiveAllTrue.ll  | 21 +++
 12 files changed, 107 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 32a09e2ceb3857..d64a66fc9d9cf7 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_all_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_any_true"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c2e983eebebc10..06d7aaf9badc07 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19419,6 +19419,16 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_all_true: {
+Value *Op = EmitScalarExpr(E->getArg(0));
+llvm::Type *Ty = Op->getType();
+assert(Ty->isIntegerTy(1) &&
+   "Intrinsic WaveActiveAllTrue operand must be a bool");
+
+Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
+return EmitRuntimeCall(
+Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
+  }
   case Builtin::BI__builtin_hlsl_wave_active_any_true: {
 Value *Op = EmitScalarExpr(E->getArg(0));
 assert(Op->getType()->isIntegerTy(1) &&
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index bb120c8b5e9e60..1260bb4bc9001b 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -91,6 +91,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 1126e13600f8af..b745997f1d5a2b 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2241,6 +2241,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in all active lanes in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in all lanes.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_all_true)
+__attribute__((convergent)) bool WaveActiveAllTrue(bool Val);
+
 /// \brief Returns true if the expression is true in any active lane in the
 /// current wave.
 ///
diff --git a/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl 
b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
new file mode 100644
index 00..df530a9cee561a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN:   dxil-pc-shadermodel6.3-co

[clang] [llvm] [HLSL] Implement `WaveActiveAllTrue` Intrinsic (PR #117245)

2024-12-09 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,21 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | 
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - 
-filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#bool:]] = OpTypeBool
+; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#scope:]] = OpConstant %[[#uint]] 3
+; CHECK-DAG: OpCapability GroupNonUniformVote
+
+; CHECK-LABEL: Begin function test_wave_all
+define i1 @test_wave_all(i1 %p1) #0 {
+entry:
+; CHECK: %[[#param:]] = OpFunctionParameter %[[#bool]]
+; CHECK: %{{.+}} = OpGroupNonUniformAll %[[#bool]] %[[#scope]] %[[#param]]
+  %0 = call token @llvm.experimental.convergence.entry()

V-FEXrt wrote:

@Keenuts requested they be included here 
https://github.com/llvm/llvm-project/pull/115902#discussion_r1850647413

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-09 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,219 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | 
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - 
-filetype=obj | spirv-val %}
+
+; CHECK-DAG: [[glsl_450_ext:%.+]] = OpExtInstImport "GLSL.std.450"
+; CHECK-DAG: OpMemoryModel Logical GLSL450
+; CHECK-DAG: [[u32_t:%.+]] = OpTypeInt 32 0
+; CHECK-DAG: [[u32x2_t:%.+]] = OpTypeVector [[u32_t]] 2
+; CHECK-DAG: [[u32x3_t:%.+]] = OpTypeVector [[u32_t]] 3
+; CHECK-DAG: [[u32x4_t:%.+]] = OpTypeVector [[u32_t]] 4
+; CHECK-DAG: [[const_0:%.*]] = OpConstant [[u32_t]] 0
+; CHECK-DAG: [[const_0x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_0]] 
[[const_0]]
+; CHECK-DAG: [[const_1:%.*]] = OpConstant [[u32_t]] 1
+; CHECK-DAG: [[const_32:%.*]] = OpConstant [[u32_t]] 32
+; CHECK-DAG: [[const_32x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_32]] 
[[const_32]]
+; CHECK-DAG: [[const_neg1:%.*]] = OpConstant [[u32_t]] 4294967295
+; CHECK-DAG: [[const_neg1x2:%.*]] = OpConstantComposite [[u32x2_t]] 
[[const_neg1]] [[const_neg1]]
+; CHECK-DAG: [[u16_t:%.+]] = OpTypeInt 16 0
+; CHECK-DAG: [[u16x2_t:%.+]] = OpTypeVector [[u16_t]] 2
+; CHECK-DAG: [[u16x3_t:%.+]] = OpTypeVector [[u16_t]] 3
+; CHECK-DAG: [[u16x4_t:%.+]] = OpTypeVector [[u16_t]] 4
+; CHECK-DAG: [[u64_t:%.+]] = OpTypeInt 64 0
+; CHECK-DAG: [[u64x2_t:%.+]] = OpTypeVector [[u64_t]] 2
+; CHECK-DAG: [[u64x3_t:%.+]] = OpTypeVector [[u64_t]] 3
+; CHECK-DAG: [[u64x4_t:%.+]] = OpTypeVector [[u64_t]] 4
+; CHECK-DAG: [[bool_t:%.+]] = OpTypeBool
+; CHECK-DAG: [[boolx2_t:%.+]] = OpTypeVector [[bool_t]] 2
+
+; CHECK-LABEL: Begin function firstbitlow_i32
+define noundef i32 @firstbitlow_i32(i32 noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i32(i32 %a)
+  ret i32 %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v2xi32
+define noundef <2 x i32> @firstbitlow_v2xi32(<2 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x2_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i32(<2 x i32> %a)
+  ret <2 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v3xi32
+define noundef <3 x i32> @firstbitlow_v3xi32(<3 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x3_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i32(<3 x i32> %a)
+  ret <3 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v4xi32
+define noundef <4 x i32> @firstbitlow_v4xi32(<4 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x4_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i32(<4 x i32> %a)
+  ret <4 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_i16
+define noundef i32 @firstbitlow_i16(i16 noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i16(i16 %a)
+  ret i32 %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v2i16
+define noundef <2 x i32> @firstbitlow_v2i16(<2 x i16> noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x2_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32x2_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i16(<2 x i16> %a)
+  ret <2 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v3xi16
+define noundef <3 x i32> @firstbitlow_v3xi16(<3 x i16> noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x3_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32x3_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i16(<3 x i16> %a)
+  ret <3 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v4xi16
+define noundef <4 x i32> @firstbitlow_v4xi16(<4 x i16> noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x4_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32x4_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i16(<4 x i1

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits


@@ -3166,109 +3171,228 @@ bool 
SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  Register ConstIntOne =
+  GR.getOrCreateConstInt(1, I, BaseType, TII, ZeroAsNull);
+
+  // SPIRV doesn't support vectors with more than 4 components. Since the
+  // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
+  // operate on vectors with 2 or less components. When largers vectors are
+  // seen. Split them, recurse, then recombine them.
+  if (ComponentCount > 2) {
+unsigned LeftComponentCount = ComponentCount / 2;

V-FEXrt wrote:

Can you give an example? I'm pretty sure the splitting will never create a 
vector too large (but the merging back together certainly can)

Example:

Given `u64x12` the call stack becomes

```c++
selectFirstBitSet64(u64x12); // Top
selectFirstBitSet64Overflow(u64x12); // Top
  selectFirstBitSet64(u64x6); // Top.Left
  selectFirstBitSet64Overflow(u64x6);   // Top.Left
selectFirstBitSet64(u64x3);  // Top.Left.Left
selectFirstBitSet64Overflow(u64x3); // Top.Left.Left
  selectFirstBitSet64(u64);  // Top.Left.Left.Left
  selectFirstBitSet64(u64x2);  // Top.Left.Left.Right
selectFirstBitSet64Overflow(u64x3); // Top.Left.Right
  selectFirstBitSet64(u64);  // Top.Left.Right.Left
  selectFirstBitSet64(u64x2);  // Top.Left.Right.Right
  selectFirstBitSet64Overflow(u64x6);   // Top.Right
selectFirstBitSet64(u64x3);  // Top.Right.Left
selectFirstBitSet64Overflow(u64x3); // Top.Right.Left
  selectFirstBitSet64(u64);  // Top.Right.Left.Left
  selectFirstBitSet64(u64x2);  // Top.Right.Left.Right
selectFirstBitSet64Overflow(u64x3); // Top.Right.Right
  selectFirstBitSet64(u64);  // Top.Right.Right.Left
  selectFirstBitSet64(u64x2);  // Top.Right.Right.Right
```

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


[clang] [llvm] [HLSL] Implement `WaveActiveAllTrue` Intrinsic (PR #117245)

2024-12-16 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/117245

>From 1156d98a0ba25a92b4edbacb7c17e5ad6bb2b522 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 21 Nov 2024 08:42:31 -0700
Subject: [PATCH 1/2] [HLSL] Implement WaveActiveAllTrue Intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 ++
 clang/lib/CodeGen/CGBuiltin.cpp   | 10 +
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 
 .../builtins/WaveActiveAllTrue.hlsl   | 17 +++
 .../BuiltIns/WaveActiveAllTrue-errors.hlsl| 21 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   |  8 +++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  2 ++
 .../test/CodeGen/DirectX/WaveActiveAllTrue.ll | 10 +
 .../hlsl-intrinsics/WaveActiveAllTrue.ll  | 21 +++
 12 files changed, 107 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 32a09e2ceb3857..d64a66fc9d9cf7 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_all_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_any_true"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c2e983eebebc10..06d7aaf9badc07 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19419,6 +19419,16 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_all_true: {
+Value *Op = EmitScalarExpr(E->getArg(0));
+llvm::Type *Ty = Op->getType();
+assert(Ty->isIntegerTy(1) &&
+   "Intrinsic WaveActiveAllTrue operand must be a bool");
+
+Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
+return EmitRuntimeCall(
+Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
+  }
   case Builtin::BI__builtin_hlsl_wave_active_any_true: {
 Value *Op = EmitScalarExpr(E->getArg(0));
 assert(Op->getType()->isIntegerTy(1) &&
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index bb120c8b5e9e60..1260bb4bc9001b 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -91,6 +91,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 1126e13600f8af..b745997f1d5a2b 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2241,6 +2241,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in all active lanes in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in all lanes.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_all_true)
+__attribute__((convergent)) bool WaveActiveAllTrue(bool Val);
+
 /// \brief Returns true if the expression is true in any active lane in the
 /// current wave.
 ///
diff --git a/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl 
b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
new file mode 100644
index 00..df530a9cee561a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN:   dxil-pc-shadermodel6.3-co

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits


@@ -3166,109 +3171,228 @@ bool 
SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  Register ConstIntOne =
+  GR.getOrCreateConstInt(1, I, BaseType, TII, ZeroAsNull);
+
+  // SPIRV doesn't support vectors with more than 4 components. Since the
+  // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
+  // operate on vectors with 2 or less components. When largers vectors are
+  // seen. Split them, recurse, then recombine them.
+  if (ComponentCount > 2) {
+unsigned LeftComponentCount = ComponentCount / 2;

V-FEXrt wrote:

Actually one thing I was considering was to just explicitly handle the vec3 and 
vec4 cases then assert for anything higher  but they are equally as messy while 
being strictly less general

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits


@@ -3166,109 +3171,228 @@ bool 
SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  Register ConstIntOne =
+  GR.getOrCreateConstInt(1, I, BaseType, TII, ZeroAsNull);
+
+  // SPIRV doesn't support vectors with more than 4 components. Since the
+  // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
+  // operate on vectors with 2 or less components. When largers vectors are
+  // seen. Split them, recurse, then recombine them.
+  if (ComponentCount > 2) {
+unsigned LeftComponentCount = ComponentCount / 2;

V-FEXrt wrote:

I tried to write it to handle that case. It should just keep recursing and 
splitting the vectors in half until its under 2 components. 

I do think we are strictly limited by SPIRV here though. Say hlsl supported 
u64x8, we still have to accept the vec8 in as a parameter and return a vec8 
out. Both of which would require invalid SPIRV

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/116858

>From a63e05d2e090edf7834fb62296bccd071a8e38b8 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 14 Nov 2024 11:53:39 -0700
Subject: [PATCH 1/7] [HLSL] Implement elementwise firstbitlow builtin

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |   9 +-
 clang/lib/CodeGen/CGHLSLRuntime.h |   1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  72 
 clang/lib/Sema/SemaHLSL.cpp   |   3 +-
 .../CodeGenHLSL/builtins/firstbitlow.hlsl | 153 
 .../BuiltIns/firstbithigh-errors.hlsl |   6 +-
 .../SemaHLSL/BuiltIns/firstbitlow-errors.hlsl |  26 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   1 +
 llvm/lib/Target/DirectX/DXIL.td   |  13 ++
 .../DirectX/DirectXTargetTransformInfo.cpp|   1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 169 ++
 llvm/test/CodeGen/DirectX/firstbitlow.ll  |  47 +
 .../test/CodeGen/DirectX/firstbitlow_error.ll |  10 ++
 .../SPIRV/hlsl-intrinsics/firstbitlow.ll  | 104 +++
 16 files changed, 616 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow.ll
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow_error.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 32a09e2ceb3857..a4fb671e479307 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4834,6 +4834,12 @@ def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFirstBitLow : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_firstbitlow"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_frac"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c2e983eebebc10..cbd4c931b05b05 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19255,7 +19255,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 "hlsl.dot4add.u8packed");
   }
   case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
-
 Value *X = EmitScalarExpr(E->getArg(0));
 
 return Builder.CreateIntrinsic(
@@ -19263,6 +19262,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), 
E->getArg(0)->getType()),
 ArrayRef{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{X},
+nullptr, "hlsl.firstbitlow");
+  }
   case Builtin::BI__builtin_hlsl_lerp: {
 Value *X = EmitScalarExpr(E->getArg(0));
 Value *Y = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index bb120c8b5e9e60..df285e185173dc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -97,6 +97,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
   GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 1126e13600f8af..c132c300da27a4 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1121,6 +1121,78 @@ uint3 firstbithigh(uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
 uint4 firstbithigh(uint64_t4);
 
+//===--===//
+// firstbitlow builtins
+//===--===//
+
+/// \fn T firstbitlow(T Val)
+/// \brief Returns the location of the first set bit starting from the lowest
+/// order bit and working upward, per component.
+/// \param Val the input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fir

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-16 Thread Ashley Coleman via cfe-commits


@@ -3166,109 +3171,228 @@ bool 
SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  Register ConstIntOne =
+  GR.getOrCreateConstInt(1, I, BaseType, TII, ZeroAsNull);
+
+  // SPIRV doesn't support vectors with more than 4 components. Since the
+  // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
+  // operate on vectors with 2 or less components. When largers vectors are
+  // seen. Split them, recurse, then recombine them.
+  if (ComponentCount > 2) {
+unsigned LeftComponentCount = ComponentCount / 2;

V-FEXrt wrote:

Ah yep. :/

I was hoping it was clean and only  `SrcReg` `ResReg`  were "bad" but nope.

Probably just go with the assert that its never larger than `u64x4` for now. 

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-17 Thread Ashley Coleman via cfe-commits


@@ -3139,136 +3151,269 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  unsigned LeftComponentCount = ComponentCount / 2;
+  unsigned RightComponentCount = ComponentCount - LeftComponentCount;
+  bool LeftIsVector = LeftComponentCount > 1;
+
+  // Split the SrcReg in half into 2 smaller vec registers
+  // (ie i64x4 -> i64x2, i64x2)
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *postCastT =
-  GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder);
-  Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
+  SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *LeftOpType;
+  SPIRVType *LeftResType;
+  if (LeftIsVector) {
+LeftOpType =
+GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
+LeftResType =
+GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, 
MIRBuilder);
+  } else {
+LeftOpType = OpType;
+LeftResType = BaseType;
+  }
+
+  SPIRVType *RightOpType =
+  GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
+  SPIRVType *RightResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+
+  Register LeftSideIn = MRI->createVirtualRegister(GR.getRegClass(LeftOpType));
+  Register RightSideIn =
+  MRI->createVirtualRegister(GR.getRegClass(RightOpType));
+
+  bool Result;
+
+  // Extract the left half from the SrcReg into LeftSideIn
+  // accounting for the special case when it only has one element
+  if (LeftIsVector) {
+auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+   TII.get(SPIRV::OpVectorShuffle))
+   .addDef(LeftSideIn)
+   .addUse(GR.getSPIRVTypeID(LeftOpType))
+   .addUse(SrcReg)
+   // Per the spec, repeat the vector if only one vec is needed
+   .addUse(SrcReg);
+
+for (unsigned J = 0; J < LeftComponentCo

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-12-17 Thread Ashley Coleman via cfe-commits


@@ -3139,136 +3151,269 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  Register ConstIntZero =
+  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
+  unsigned LeftComponentCount = ComponentCount / 2;
+  unsigned RightComponentCount = ComponentCount - LeftComponentCount;
+  bool LeftIsVector = LeftComponentCount > 1;
+
+  // Split the SrcReg in half into 2 smaller vec registers
+  // (ie i64x4 -> i64x2, i64x2)
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *postCastT =
-  GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder);
-  Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
+  SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *LeftOpType;
+  SPIRVType *LeftResType;
+  if (LeftIsVector) {
+LeftOpType =
+GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
+LeftResType =
+GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, 
MIRBuilder);
+  } else {
+LeftOpType = OpType;
+LeftResType = BaseType;
+  }
+
+  SPIRVType *RightOpType =
+  GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
+  SPIRVType *RightResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+
+  Register LeftSideIn = MRI->createVirtualRegister(GR.getRegClass(LeftOpType));
+  Register RightSideIn =
+  MRI->createVirtualRegister(GR.getRegClass(RightOpType));
+
+  bool Result;
+
+  // Extract the left half from the SrcReg into LeftSideIn
+  // accounting for the special case when it only has one element
+  if (LeftIsVector) {
+auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+   TII.get(SPIRV::OpVectorShuffle))
+   .addDef(LeftSideIn)
+   .addUse(GR.getSPIRVTypeID(LeftOpType))
+   .addUse(SrcReg)
+   // Per the spec, repeat the vector if only one vec is needed
+   .addUse(SrcReg);
+
+for (unsigned J = 0; J < LeftComponentCo

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-21 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/18] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement WaveActiveAnyTrue intrinsic (PR #115902)

2024-11-21 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/115902

>From 845256b2ed971a4e42f7f871e8b51e711486261a Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Mon, 11 Nov 2024 16:34:23 -0700
Subject: [PATCH 01/19] [HLSL] Implement WaveActiveAnyTrue intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 +
 clang/lib/CodeGen/CGBuiltin.cpp   | 13 ++
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 +++
 clang/lib/Sema/SemaHLSL.cpp   |  6 +
 .../builtins/WaveActiveAnyTrue.hlsl   | 17 +
 .../BuiltIns/WaveActiveAnyTrue-errors.hlsl| 21 
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   | 10 
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++
 .../test/CodeGen/DirectX/WaveActiveAnyTrue.ll | 10 
 .../hlsl-intrinsics/WaveActiveAnyTrue.ll  | 17 +
 13 files changed, 136 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAnyTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAnyTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAnyTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 9bd67e0cefebc3..496b6739724295 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4744,6 +4744,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_any_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d7f5c54a1913..c4a6a9abee63cc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18960,6 +18960,19 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_any_true: {
+// Assert Op->getType() == Bool
+
+// FIXME: PR Question: Can this be simpler? Looks like Int1Ty isn't  
predefined
+IntegerType* Int1Ty = 
llvm::Type::getInt1Ty(CGM.getTypes().getLLVMContext());
+Value *Op = EmitScalarExpr(E->getArg(0));
+assert(Op->getType() == Int1Ty && "wave_active_any_true operand must be a 
bool");
+
+// FIXME: PR Question: Re Style SingleRef vs {SingleRef} vs 
ArrayRef{SingleRef}
+llvm::FunctionType *FT = llvm::FunctionType::get(Int1Ty, {Int1Ty}, 
/*isVarArg=*/false);
+llvm::StringRef Name = 
Intrinsic::getName(CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic());
+return EmitRuntimeCall(CGM.CreateRuntimeFunction(FT, Name, {}, 
/*Local=*/false, /*AssumeConvergent=*/true), {Op}, "hlsl.wave.activeanytrue");
+  }
   case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
 // defined in SPIRVBuiltins.td. So instead we manually get the matching 
name
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index cd533cad84e9fb..c3b689ea44fcb8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -89,6 +89,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_activeanytrue)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
 
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 8ade4b27f360fb..90991e95d6565a 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2096,6 +2096,15 @@ float4 trunc(float4);
 // Wave* builtins
 
//===--===//
 
+/// \brief Returns true if the expression is true in any active lane in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in any lane.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true)
+__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val);
+
 /// \brief Counts the number of boolean variables which eval

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-22 Thread Ashley Coleman via cfe-commits


@@ -3158,6 +3172,166 @@ bool 
SPIRVInstructionSelector::selectFirstBitHigh(Register ResVReg,
   }
 }
 
+bool SPIRVInstructionSelector::selectFirstBitLow16(Register ResVReg,
+   const SPIRVType *ResType,
+   MachineInstr &I) const {
+  // OpUConvert treats the operand bits as an unsigned i16 and zero extends it
+  // to an unsigned i32. As this leaves all the least significant bits 
unchanged
+  // the first set bit from the LSB side doesn't change.
+  Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
+  bool Result = selectNAryOpWithSrcs(
+  ExtReg, ResType, I, {I.getOperand(2).getReg()}, SPIRV::OpUConvert);
+  return Result && selectFirstBitLow32(ResVReg, ResType, I, ExtReg);
+}
+
+bool SPIRVInstructionSelector::selectFirstBitLow32(Register ResVReg,
+   const SPIRVType *ResType,
+   MachineInstr &I,
+   Register SrcReg) const {
+  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
+  .addDef(ResVReg)
+  .addUse(GR.getSPIRVTypeID(ResType))
+  .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
+  .addImm(GL::FindILsb)
+  .addUse(SrcReg)
+  .constrainAllUses(TII, TRI, RBI);
+}
+
+bool SPIRVInstructionSelector::selectFirstBitLow64(Register ResVReg,
+   const SPIRVType *ResType,
+   MachineInstr &I) const {
+  Register OpReg = I.getOperand(2).getReg();
+
+  // 1. Split int64 into 2 pieces using a bitcast
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  MachineIRBuilder MIRBuilder(I);
+  SPIRVType *PostCastType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2 * ComponentCount, MIRBuilder);
+  Register BitcastReg =
+  MRI->createVirtualRegister(GR.getRegClass(PostCastType));
+  bool Result =
+  selectUnOpWithSrc(BitcastReg, PostCastType, I, OpReg, SPIRV::OpBitcast);
+
+  // 2. Find the first set bit from the LSB side for all the pieces in #1
+  Register FBLReg = MRI->createVirtualRegister(GR.getRegClass(PostCastType));
+  Result = Result && selectFirstBitLow32(FBLReg, PostCastType, I, BitcastReg);
+
+  // 3. Split result vector into high bits and low bits
+  Register HighReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
+  Register LowReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
+
+  bool ZeroAsNull = STI.isOpenCLEnv();
+  bool IsScalarRes = ResType->getOpcode() != SPIRV::OpTypeVector;
+  if (IsScalarRes) {
+// if scalar do a vector extract
+Result =
+Result &&
+selectNAryOpWithSrcs(
+HighReg, ResType, I,
+{FBLReg, GR.getOrCreateConstInt(0, I, ResType, TII, ZeroAsNull)},
+SPIRV::OpVectorExtractDynamic);
+Result =
+Result &&
+selectNAryOpWithSrcs(
+LowReg, ResType, I,
+{FBLReg, GR.getOrCreateConstInt(1, I, ResType, TII, ZeroAsNull)},
+SPIRV::OpVectorExtractDynamic);
+  } else {
+// if vector do a shufflevector
+auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+   TII.get(SPIRV::OpVectorShuffle))
+   .addDef(HighReg)
+   .addUse(GR.getSPIRVTypeID(ResType))
+   .addUse(FBLReg)
+   // Per the spec, repeat the vector if only one vec is needed
+   .addUse(FBLReg);
+
+// high bits are stored in even indexes. Extract them from FBLReg
+for (unsigned j = 0; j < ComponentCount * 2; j += 2) {
+  MIB.addImm(j);
+}
+Result = Result && MIB.constrainAllUses(TII, TRI, RBI);
+
+MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+  TII.get(SPIRV::OpVectorShuffle))
+  .addDef(LowReg)
+  .addUse(GR.getSPIRVTypeID(ResType))
+  .addUse(FBLReg)
+  // Per the spec, repeat the vector if only one vec is needed
+  .addUse(FBLReg);
+
+// low bits are stored in odd indexes. Extract them from FBLReg
+for (unsigned j = 1; j < ComponentCount * 2; j += 2) {
+  MIB.addImm(j);
+}
+Result = Result && MIB.constrainAllUses(TII, TRI, RBI);
+  }
+
+  // 4. Check the result. When low bits == -1 use high, otherwise use low

V-FEXrt wrote:

I couldn't figure out how to make the swapping work since the shared function 
is actually what assigns High/Low, but I added a flag to the shared function to 
swap the regs. Lmk if that's good enough or if there is something I'm missing!

https://github.com/llvm/llvm-project/pull/116858
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.o

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-22 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/116858

>From eeb864972c48625fa56b96e6b018affe04d84e00 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 14 Nov 2024 11:53:39 -0700
Subject: [PATCH 1/4] [HLSL] Implement elementwise firstbitlow builtin

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |   9 +-
 clang/lib/CodeGen/CGHLSLRuntime.h |   1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  72 
 clang/lib/Sema/SemaHLSL.cpp   |   3 +-
 .../CodeGenHLSL/builtins/firstbitlow.hlsl | 153 
 .../BuiltIns/firstbithigh-errors.hlsl |   6 +-
 .../SemaHLSL/BuiltIns/firstbitlow-errors.hlsl |  26 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   2 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   1 +
 llvm/lib/Target/DirectX/DXIL.td   |  13 ++
 .../DirectX/DirectXTargetTransformInfo.cpp|   1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 169 ++
 llvm/test/CodeGen/DirectX/firstbitlow.ll  |  47 +
 .../test/CodeGen/DirectX/firstbitlow_error.ll |  10 ++
 .../SPIRV/hlsl-intrinsics/firstbitlow.ll  | 104 +++
 16 files changed, 617 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow.ll
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow_error.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 290feb58754adb..7132c8f816dbc0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4822,6 +4822,12 @@ def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFirstBitLow : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_firstbitlow"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_frac"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4b96bdb709c777..cca840f908cfec 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19119,7 +19119,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 "hlsl.dot4add.u8packed");
   }
   case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
-
 Value *X = EmitScalarExpr(E->getArg(0));
 
 return Builder.CreateIntrinsic(
@@ -19127,6 +19126,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), 
E->getArg(0)->getType()),
 ArrayRef{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{X},
+nullptr, "hlsl.firstbitlow");
+  }
   case Builtin::BI__builtin_hlsl_lerp: {
 Value *X = EmitScalarExpr(E->getArg(0));
 Value *Y = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8e0ed42b79a35..3c3841998938da 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -97,6 +97,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
   GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index a484d04155d6b2..e0df7cf71af1cc 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1103,6 +1103,78 @@ uint3 firstbithigh(uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
 uint4 firstbithigh(uint64_t4);
 
+//===--===//
+// firstbitlow builtins
+//===--===//
+
+/// \fn T firstbitlow(T Val)
+/// \brief Returns the location of the first set bit starting from the lowest
+/// order bit and working upward, per component.
+/// \param Val the input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fir

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-22 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/116858

>From eeb864972c48625fa56b96e6b018affe04d84e00 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 14 Nov 2024 11:53:39 -0700
Subject: [PATCH 1/5] [HLSL] Implement elementwise firstbitlow builtin

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |   9 +-
 clang/lib/CodeGen/CGHLSLRuntime.h |   1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  72 
 clang/lib/Sema/SemaHLSL.cpp   |   3 +-
 .../CodeGenHLSL/builtins/firstbitlow.hlsl | 153 
 .../BuiltIns/firstbithigh-errors.hlsl |   6 +-
 .../SemaHLSL/BuiltIns/firstbitlow-errors.hlsl |  26 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   2 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   1 +
 llvm/lib/Target/DirectX/DXIL.td   |  13 ++
 .../DirectX/DirectXTargetTransformInfo.cpp|   1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 169 ++
 llvm/test/CodeGen/DirectX/firstbitlow.ll  |  47 +
 .../test/CodeGen/DirectX/firstbitlow_error.ll |  10 ++
 .../SPIRV/hlsl-intrinsics/firstbitlow.ll  | 104 +++
 16 files changed, 617 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow.ll
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow_error.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 290feb58754adb..7132c8f816dbc0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4822,6 +4822,12 @@ def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFirstBitLow : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_firstbitlow"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_frac"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4b96bdb709c777..cca840f908cfec 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19119,7 +19119,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 "hlsl.dot4add.u8packed");
   }
   case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
-
 Value *X = EmitScalarExpr(E->getArg(0));
 
 return Builder.CreateIntrinsic(
@@ -19127,6 +19126,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), 
E->getArg(0)->getType()),
 ArrayRef{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{X},
+nullptr, "hlsl.firstbitlow");
+  }
   case Builtin::BI__builtin_hlsl_lerp: {
 Value *X = EmitScalarExpr(E->getArg(0));
 Value *Y = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8e0ed42b79a35..3c3841998938da 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -97,6 +97,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
   GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index a484d04155d6b2..e0df7cf71af1cc 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1103,6 +1103,78 @@ uint3 firstbithigh(uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
 uint4 firstbithigh(uint64_t4);
 
+//===--===//
+// firstbitlow builtins
+//===--===//
+
+/// \fn T firstbitlow(T Val)
+/// \brief Returns the location of the first set bit starting from the lowest
+/// order bit and working upward, per component.
+/// \param Val the input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fir

[clang] [llvm] [HLSL] Implement `WaveActiveAllTrue` Intrinsic (PR #117245)

2024-11-21 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt created 
https://github.com/llvm/llvm-project/pull/117245

Resolves https://github.com/llvm/llvm-project/issues/99161

- [x]  Implement `WaveActiveAllTrue` clang builtin,
- [x]  Link `WaveActiveAllTrue` clang builtin with `hlsl_intrinsics.h`
- [x]  Add sema checks for `WaveActiveAllTrue` to 
`CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [x]  Add codegen for `WaveActiveAllTrue` to `EmitHLSLBuiltinExpr` in 
`CGBuiltin.cpp`
- [x]  Add codegen tests to 
`clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl`
- [x]  Add sema tests to 
`clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl`
- [x]  Create the `int_dx_WaveActiveAllTrue` intrinsic in `IntrinsicsDirectX.td`
- [x]  Create the `DXILOpMapping` of `int_dx_WaveActiveAllTrue` to `114` in 
`DXIL.td`
- [x]  Create the `WaveActiveAllTrue.ll` and `WaveActiveAllTrue_errors.ll` 
tests in `llvm/test/CodeGen/DirectX/`
- [x]  Create the `int_spv_WaveActiveAllTrue` intrinsic in `IntrinsicsSPIRV.td`
- [x]  In SPIRVInstructionSelector.cpp create the `WaveActiveAllTrue` lowering 
and map it to `int_spv_WaveActiveAllTrue` in 
`SPIRVInstructionSelector::selectIntrinsic`.
- [x]  Create SPIR-V backend test case in 
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll`

>From 73afef24940e4d0978220063df87d3ebda8da615 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 21 Nov 2024 08:42:31 -0700
Subject: [PATCH] [HLSL] Implement WaveActiveAllTrue Intrinsic

---
 clang/include/clang/Basic/Builtins.td |  6 ++
 clang/lib/CodeGen/CGBuiltin.cpp   | 10 +
 clang/lib/CodeGen/CGHLSLRuntime.h |  1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  9 
 .../builtins/WaveActiveAllTrue.hlsl   | 17 +++
 .../BuiltIns/WaveActiveAllTrue-errors.hlsl| 21 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  1 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  1 +
 llvm/lib/Target/DirectX/DXIL.td   |  8 +++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  2 ++
 .../test/CodeGen/DirectX/WaveActiveAllTrue.ll | 10 +
 .../hlsl-intrinsics/WaveActiveAllTrue.ll  | 21 +++
 12 files changed, 107 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 290feb58754adb..8aa5719d736f94 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4750,6 +4750,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_wave_active_all_true"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(bool)";
+}
+
 def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_any_true"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index ff7132fd8bc1e7..522a6ce3b999e3 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19282,6 +19282,16 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
 ArrayRef{Op0, Op1}, nullptr, "hlsl.step");
   }
+  case Builtin::BI__builtin_hlsl_wave_active_all_true: {
+Value *Op = EmitScalarExpr(E->getArg(0));
+llvm::Type *Ty = Op->getType();
+assert(Ty->isIntegerTy(1) &&
+   "Intrinsic WaveActiveAllTrue operand must be a bool");
+
+Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
+return EmitRuntimeCall(
+Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
+  }
   case Builtin::BI__builtin_hlsl_wave_active_any_true: {
 Value *Op = EmitScalarExpr(E->getArg(0));
 assert(Op->getType()->isIntegerTy(1) &&
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8e0ed42b79a35..29c0fe1acabccc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -91,6 +91,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib

[clang] [llvm] [HLSL] Implement `WaveActiveAllTrue` Intrinsic (PR #117245)

2024-11-21 Thread Ashley Coleman via cfe-commits


@@ -861,6 +861,14 @@ def CreateHandleFromBinding : DXILOp<217, 
createHandleFromBinding> {
   let stages = [Stages];
 }
 
+def WaveActiveAllTrue : DXILOp<334, waveAllTrue> {

V-FEXrt wrote:

Crossed wires with SPIRV. This should be 114  not 334

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-22 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt updated 
https://github.com/llvm/llvm-project/pull/116858

>From eeb864972c48625fa56b96e6b018affe04d84e00 Mon Sep 17 00:00:00 2001
From: Ashley Coleman 
Date: Thu, 14 Nov 2024 11:53:39 -0700
Subject: [PATCH 1/6] [HLSL] Implement elementwise firstbitlow builtin

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |   9 +-
 clang/lib/CodeGen/CGHLSLRuntime.h |   1 +
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  |  72 
 clang/lib/Sema/SemaHLSL.cpp   |   3 +-
 .../CodeGenHLSL/builtins/firstbitlow.hlsl | 153 
 .../BuiltIns/firstbithigh-errors.hlsl |   6 +-
 .../SemaHLSL/BuiltIns/firstbitlow-errors.hlsl |  26 +++
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   2 +
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   1 +
 llvm/lib/Target/DirectX/DXIL.td   |  13 ++
 .../DirectX/DirectXTargetTransformInfo.cpp|   1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 169 ++
 llvm/test/CodeGen/DirectX/firstbitlow.ll  |  47 +
 .../test/CodeGen/DirectX/firstbitlow_error.ll |  10 ++
 .../SPIRV/hlsl-intrinsics/firstbitlow.ll  | 104 +++
 16 files changed, 617 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/firstbitlow.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/firstbitlow-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow.ll
 create mode 100644 llvm/test/CodeGen/DirectX/firstbitlow_error.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/firstbitlow.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 290feb58754adb..7132c8f816dbc0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4822,6 +4822,12 @@ def HLSLFirstBitHigh : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFirstBitLow : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_firstbitlow"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_frac"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4b96bdb709c777..cca840f908cfec 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19119,7 +19119,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 "hlsl.dot4add.u8packed");
   }
   case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
-
 Value *X = EmitScalarExpr(E->getArg(0));
 
 return Builder.CreateIntrinsic(
@@ -19127,6 +19126,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 getFirstBitHighIntrinsic(CGM.getHLSLRuntime(), 
E->getArg(0)->getType()),
 ArrayRef{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{X},
+nullptr, "hlsl.firstbitlow");
+  }
   case Builtin::BI__builtin_hlsl_lerp: {
 Value *X = EmitScalarExpr(E->getArg(0));
 Value *Y = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8e0ed42b79a35..3c3841998938da 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -97,6 +97,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)
   GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index a484d04155d6b2..e0df7cf71af1cc 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -1103,6 +1103,78 @@ uint3 firstbithigh(uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
 uint4 firstbithigh(uint64_t4);
 
+//===--===//
+// firstbitlow builtins
+//===--===//
+
+/// \fn T firstbitlow(T Val)
+/// \brief Returns the location of the first set bit starting from the lowest
+/// order bit and working upward, per component.
+/// \param Val the input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_fir

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2024-11-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,168 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | 
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - 
-filetype=obj | spirv-val %}
+
+; CHECK-DAG: [[glsl_450_ext:%.+]] = OpExtInstImport "GLSL.std.450"
+; CHECK-DAG: OpMemoryModel Logical GLSL450
+; CHECK-DAG: [[u32_t:%.+]] = OpTypeInt 32 0
+; CHECK-DAG: [[u32x2_t:%.+]] = OpTypeVector [[u32_t]] 2
+; CHECK-DAG: [[u32x3_t:%.+]] = OpTypeVector [[u32_t]] 3
+; CHECK-DAG: [[u32x4_t:%.+]] = OpTypeVector [[u32_t]] 4
+; CHECK-DAG: [[const_0:%.*]] = OpConstant [[u32_t]] 0
+; CHECK-DAG: [[const_0x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_0]] 
[[const_0]]
+; CHECK-DAG: [[const_0x3:%.*]] = OpConstantComposite [[u32x3_t]] [[const_0]] 
[[const_0]] [[const_0]]
+; CHECK-DAG: [[const_1:%.*]] = OpConstant [[u32_t]] 1
+; CHECK-DAG: [[const_32:%.*]] = OpConstant [[u32_t]] 32
+; CHECK-DAG: [[const_32x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_32]] 
[[const_32]]
+; CHECK-DAG: [[const_32x3:%.*]] = OpConstantComposite [[u32x3_t]] [[const_32]] 
[[const_32]] [[const_32]]
+; CHECK-DAG: [[const_neg1:%.*]] = OpConstant [[u32_t]] 4294967295
+; CHECK-DAG: [[const_neg1x2:%.*]] = OpConstantComposite [[u32x2_t]] 
[[const_neg1]] [[const_neg1]]
+; CHECK-DAG: [[const_neg1x3:%.*]] = OpConstantComposite [[u32x3_t]] 
[[const_neg1]] [[const_neg1]] [[const_neg1]]
+; CHECK-DAG: [[u16_t:%.+]] = OpTypeInt 16 0
+; CHECK-DAG: [[u16x2_t:%.+]] = OpTypeVector [[u16_t]] 2
+; CHECK-DAG: [[u16x3_t:%.+]] = OpTypeVector [[u16_t]] 3
+; CHECK-DAG: [[u16x4_t:%.+]] = OpTypeVector [[u16_t]] 4
+; CHECK-DAG: [[u64_t:%.+]] = OpTypeInt 64 0
+; CHECK-DAG: [[u64x2_t:%.+]] = OpTypeVector [[u64_t]] 2
+; CHECK-DAG: [[u64x3_t:%.+]] = OpTypeVector [[u64_t]] 3
+; CHECK-DAG: [[bool_t:%.+]] = OpTypeBool
+; CHECK-DAG: [[boolx2_t:%.+]] = OpTypeVector [[bool_t]] 2
+; CHECK-DAG: [[boolx3_t:%.+]] = OpTypeVector [[bool_t]] 3
+
+; CHECK-LABEL: Begin function firstbitlow_i32
+define noundef i32 @firstbitlow_i32(i32 noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i32(i32 %a)
+  ret i32 %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v2xi32
+define noundef <2 x i32> @firstbitlow_v2xi32(<2 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x2_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i32(<2 x i32> %a)
+  ret <2 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v3xi32
+define noundef <3 x i32> @firstbitlow_v3xi32(<3 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x3_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i32(<3 x i32> %a)
+  ret <3 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v4xi32
+define noundef <4 x i32> @firstbitlow_v4xi32(<4 x i32> noundef %a) {
+entry:
+; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x4_t]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i32(<4 x i32> %a)
+  ret <4 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_i16
+define noundef i32 @firstbitlow_i16(i16 noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i16(i16 %a)
+  ret i32 %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v2i16
+define noundef <2 x i32> @firstbitlow_v2i16(<2 x i16> noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x2_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32x2_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i16(<2 x i16> %a)
+  ret <2 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v3xi16
+define noundef <3 x i32> @firstbitlow_v3xi16(<3 x i16> noundef %a) {
+entry:
+; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x3_t]]
+; CHECK: [[a32:%.+]] = OpUConvert [[u32x3_t]] [[a16]]
+; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a32]]
+; CHECK: OpReturnValue [[ret]]
+  %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i16(<3 x i16> %a)
+  ret <3 x i32> %elt.firstbitlow
+}
+
+; CHECK-LABEL: Begin function firstbitlow_v4xi16
+define noundef <4 x i32> @firstbitlow_v4xi16(

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-08 Thread Ashley Coleman via cfe-commits


@@ -3178,98 +3178,74 @@ bool 
SPIRVInstructionSelector::selectFirstBitSet64Overflow(
 Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
 Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
 
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
   unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
-  bool ZeroAsNull = STI.isOpenCLEnv();
-  Register ConstIntZero =
-  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
-  unsigned LeftComponentCount = ComponentCount / 2;
-  unsigned RightComponentCount = ComponentCount - LeftComponentCount;
-  bool LeftIsVector = LeftComponentCount > 1;
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
 
-  // Split the SrcReg in half into 2 smaller vec registers
-  // (ie i64x4 -> i64x2, i64x2)
+  bool ZeroAsNull = STI.isOpenCLEnv();
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
-  SPIRVType *LeftVecOpType;
-  SPIRVType *LeftVecResType;
-  if (LeftIsVector) {
-LeftVecOpType =
-GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
-LeftVecResType =
-GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, 
MIRBuilder);
-  } else {
-LeftVecOpType = OpType;
-LeftVecResType = BaseType;
-  }
-
-  SPIRVType *RightVecOpType =
-  GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
-  SPIRVType *RightVecResType =
-  GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+  SPIRVType *Vec2ResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
 
-  Register LeftSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(LeftVecOpType));
-  Register RightSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(RightVecOpType));
+  std::vector PartialRegs;
 
-  bool Result;
+  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+  unsigned CurrentComponent = 0;
+  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
+Register SubVecReg = MRI->createVirtualRegister(GR.getRegClass(I64x2Type));
 
-  // Extract the left half from the SrcReg into LeftSideIn
-  // accounting for the special case when it only has one element
-  if (LeftIsVector) {
 auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
-   .addDef(LeftSideIn)
-   .addUse(GR.getSPIRVTypeID(LeftVecOpType))
+   .addDef(SubVecReg)
+   .addUse(GR.getSPIRVTypeID(I64x2Type))
.addUse(SrcReg)
// Per the spec, repeat the vector if only one vec is needed
.addUse(SrcReg);
 
-for (unsigned J = 0; J < LeftComponentCount; J++) {
-  MIB.addImm(J);
-}
+MIB.addImm(CurrentComponent);
+MIB.addImm(CurrentComponent + 1);
 
-Result = MIB.constrainAllUses(TII, TRI, RBI);
-  } else {
-Result =
-selectOpWithSrcs(LeftSideIn, LeftVecOpType, I, {SrcReg, ConstIntZero},
- SPIRV::OpVectorExtractDynamic);
-  }
+if (!MIB.constrainAllUses(TII, TRI, RBI))
+  return false;
 
-  // Extract the right half from the SrcReg into RightSideIn.
-  // Right will always be a vector since the only time one element is left is
-  // when Component == 3, and in that case Left is one element.
-  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
- TII.get(SPIRV::OpVectorShuffle))
- .addDef(RightSideIn)
- .addUse(GR.getSPIRVTypeID(RightVecOpType))
- .addUse(SrcReg)
- // Per the spec, repeat the vector if only one vec is needed
- .addUse(SrcReg);
+Register SubVecBitSetReg =

V-FEXrt wrote:

uhh I think so? Its hard to give this thing a precise name.

This is the register that holds the firstbitlow/high result for each of the 
sub/split vectors extracted from the input vector

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-08 Thread Ashley Coleman via cfe-commits


@@ -3178,98 +3178,74 @@ bool 
SPIRVInstructionSelector::selectFirstBitSet64Overflow(
 Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
 Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
 
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
   unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
-  bool ZeroAsNull = STI.isOpenCLEnv();
-  Register ConstIntZero =
-  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
-  unsigned LeftComponentCount = ComponentCount / 2;
-  unsigned RightComponentCount = ComponentCount - LeftComponentCount;
-  bool LeftIsVector = LeftComponentCount > 1;
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
 
-  // Split the SrcReg in half into 2 smaller vec registers
-  // (ie i64x4 -> i64x2, i64x2)
+  bool ZeroAsNull = STI.isOpenCLEnv();
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
-  SPIRVType *LeftVecOpType;
-  SPIRVType *LeftVecResType;
-  if (LeftIsVector) {
-LeftVecOpType =
-GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
-LeftVecResType =
-GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, 
MIRBuilder);
-  } else {
-LeftVecOpType = OpType;
-LeftVecResType = BaseType;
-  }
-
-  SPIRVType *RightVecOpType =
-  GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
-  SPIRVType *RightVecResType =
-  GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+  SPIRVType *Vec2ResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
 
-  Register LeftSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(LeftVecOpType));
-  Register RightSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(RightVecOpType));
+  std::vector PartialRegs;
 
-  bool Result;
+  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+  unsigned CurrentComponent = 0;
+  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
+Register SubVecReg = MRI->createVirtualRegister(GR.getRegClass(I64x2Type));
 
-  // Extract the left half from the SrcReg into LeftSideIn
-  // accounting for the special case when it only has one element
-  if (LeftIsVector) {
 auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
-   .addDef(LeftSideIn)
-   .addUse(GR.getSPIRVTypeID(LeftVecOpType))
+   .addDef(SubVecReg)
+   .addUse(GR.getSPIRVTypeID(I64x2Type))
.addUse(SrcReg)
// Per the spec, repeat the vector if only one vec is needed
.addUse(SrcReg);
 
-for (unsigned J = 0; J < LeftComponentCount; J++) {
-  MIB.addImm(J);
-}
+MIB.addImm(CurrentComponent);
+MIB.addImm(CurrentComponent + 1);
 
-Result = MIB.constrainAllUses(TII, TRI, RBI);
-  } else {
-Result =
-selectOpWithSrcs(LeftSideIn, LeftVecOpType, I, {SrcReg, ConstIntZero},
- SPIRV::OpVectorExtractDynamic);
-  }
+if (!MIB.constrainAllUses(TII, TRI, RBI))
+  return false;
 
-  // Extract the right half from the SrcReg into RightSideIn.
-  // Right will always be a vector since the only time one element is left is
-  // when Component == 3, and in that case Left is one element.
-  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
- TII.get(SPIRV::OpVectorShuffle))
- .addDef(RightSideIn)
- .addUse(GR.getSPIRVTypeID(RightVecOpType))
- .addUse(SrcReg)
- // Per the spec, repeat the vector if only one vec is needed
- .addUse(SrcReg);
+Register SubVecBitSetReg =

V-FEXrt wrote:

Do you have a name in mind? Would love to have something better. If not I can 
basically just add the above as a comment

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-08 Thread Ashley Coleman via cfe-commits


@@ -3178,98 +3178,74 @@ bool 
SPIRVInstructionSelector::selectFirstBitSet64Overflow(
 Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
 Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
 
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
   unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
-  bool ZeroAsNull = STI.isOpenCLEnv();
-  Register ConstIntZero =
-  GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
-  unsigned LeftComponentCount = ComponentCount / 2;
-  unsigned RightComponentCount = ComponentCount - LeftComponentCount;
-  bool LeftIsVector = LeftComponentCount > 1;
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
 
-  // Split the SrcReg in half into 2 smaller vec registers
-  // (ie i64x4 -> i64x2, i64x2)
+  bool ZeroAsNull = STI.isOpenCLEnv();
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
-  SPIRVType *LeftVecOpType;
-  SPIRVType *LeftVecResType;
-  if (LeftIsVector) {
-LeftVecOpType =
-GR.getOrCreateSPIRVVectorType(OpType, LeftComponentCount, MIRBuilder);
-LeftVecResType =
-GR.getOrCreateSPIRVVectorType(BaseType, LeftComponentCount, 
MIRBuilder);
-  } else {
-LeftVecOpType = OpType;
-LeftVecResType = BaseType;
-  }
-
-  SPIRVType *RightVecOpType =
-  GR.getOrCreateSPIRVVectorType(OpType, RightComponentCount, MIRBuilder);
-  SPIRVType *RightVecResType =
-  GR.getOrCreateSPIRVVectorType(BaseType, RightComponentCount, MIRBuilder);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+  SPIRVType *Vec2ResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
 
-  Register LeftSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(LeftVecOpType));
-  Register RightSideIn =
-  MRI->createVirtualRegister(GR.getRegClass(RightVecOpType));
+  std::vector PartialRegs;
 
-  bool Result;
+  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+  unsigned CurrentComponent = 0;
+  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {

V-FEXrt wrote:

The 2 case is avoided in `selectFirstBitSet64`

```c++
  if (ComponentCount > 2) {
return selectFirstBitSet64Overflow(ResVReg, ResType, I, SrcReg,
   BitSetOpcode, SwapPrimarySide);
  }
```

I didn't want to artificially not support/special case size 2 since it makes 
the code more complicated and it's already handled by the caller

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL][SPIRV][DXIL] Implement `WaveActiveMax` intrinsic (PR #123428)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o 
- | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \
+// RUN:   spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// Test basic lowering to runtime function call.
+
+// CHECK-LABEL: test_int
+int test_int(int expr) {
+  // CHECK-SPIRV:  %[[RET:.*]] = call spir_func [[TY:.*]] 
@llvm.spv.wave.reduce.max.i32([[TY]] %[[#]])
+  // CHECK-DXIL:  %[[RET:.*]] = call [[TY:.*]] 
@llvm.dx.wave.reduce.max.i32([[TY]] %[[#]])
+  // CHECK:  ret [[TY]] %[[RET]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY]] @llvm.dx.wave.reduce.max.i32([[TY]]) #[[#attr:]]
+// CHECK-SPIRV: declare spir_func [[TY]] @llvm.spv.wave.reduce.max.i32([[TY]]) 
#[[#attr:]]
+
+// CHECK-LABEL: test_uint64_t
+uint64_t test_uint64_t(uint64_t expr) {
+  // CHECK-SPIRV:  %[[RET:.*]] = call spir_func [[TY:.*]] 
@llvm.spv.wave.reduce.umax.i64([[TY]] %[[#]])
+  // CHECK-DXIL:  %[[RET:.*]] = call [[TY:.*]] 
@llvm.dx.wave.reduce.umax.i64([[TY]] %[[#]])
+  // CHECK:  ret [[TY]] %[[RET]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY]] @llvm.dx.wave.reduce.umax.i64([[TY]]) #[[#attr:]]
+// CHECK-SPIRV: declare spir_func [[TY]] 
@llvm.spv.wave.reduce.umax.i64([[TY]]) #[[#attr:]]
+
+// Test basic lowering to runtime function call with array and float value.
+
+// CHECK-LABEL: test_floatv4
+float4 test_floatv4(float4 expr) {
+  // CHECK-SPIRV:  %[[RET1:.*]] = call reassoc nnan ninf nsz arcp afn 
spir_func [[TY1:.*]] @llvm.spv.wave.reduce.max.v4f32([[TY1]] %[[#]]
+  // CHECK-DXIL:  %[[RET1:.*]] = call reassoc nnan ninf nsz arcp afn 
[[TY1:.*]] @llvm.dx.wave.reduce.max.v4f32([[TY1]] %[[#]])
+  // CHECK:  ret [[TY1]] %[[RET1]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY1]] @llvm.dx.wave.reduce.max.v4f32([[TY1]]) 
#[[#attr]]
+// CHECK-SPIRV: declare spir_func [[TY1]] 
@llvm.spv.wave.reduce.max.v4f32([[TY1]]) #[[#attr]]
+
+// CHECK: attributes #[[#attr]] = {{{.*}} convergent {{.*}}}
+

V-FEXrt wrote:

oh wait nvm, I got confused. This is the post function stuff I think

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


[clang] [llvm] [HLSL][SPIRV][DXIL] Implement `WaveActiveMax` intrinsic (PR #123428)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \
+// RUN:   dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o 
- | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \
+// RUN:   spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
+// RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// Test basic lowering to runtime function call.
+
+// CHECK-LABEL: test_int
+int test_int(int expr) {
+  // CHECK-SPIRV:  %[[RET:.*]] = call spir_func [[TY:.*]] 
@llvm.spv.wave.reduce.max.i32([[TY]] %[[#]])
+  // CHECK-DXIL:  %[[RET:.*]] = call [[TY:.*]] 
@llvm.dx.wave.reduce.max.i32([[TY]] %[[#]])
+  // CHECK:  ret [[TY]] %[[RET]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY]] @llvm.dx.wave.reduce.max.i32([[TY]]) #[[#attr:]]
+// CHECK-SPIRV: declare spir_func [[TY]] @llvm.spv.wave.reduce.max.i32([[TY]]) 
#[[#attr:]]
+
+// CHECK-LABEL: test_uint64_t
+uint64_t test_uint64_t(uint64_t expr) {
+  // CHECK-SPIRV:  %[[RET:.*]] = call spir_func [[TY:.*]] 
@llvm.spv.wave.reduce.umax.i64([[TY]] %[[#]])
+  // CHECK-DXIL:  %[[RET:.*]] = call [[TY:.*]] 
@llvm.dx.wave.reduce.umax.i64([[TY]] %[[#]])
+  // CHECK:  ret [[TY]] %[[RET]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY]] @llvm.dx.wave.reduce.umax.i64([[TY]]) #[[#attr:]]
+// CHECK-SPIRV: declare spir_func [[TY]] 
@llvm.spv.wave.reduce.umax.i64([[TY]]) #[[#attr:]]
+
+// Test basic lowering to runtime function call with array and float value.
+
+// CHECK-LABEL: test_floatv4
+float4 test_floatv4(float4 expr) {
+  // CHECK-SPIRV:  %[[RET1:.*]] = call reassoc nnan ninf nsz arcp afn 
spir_func [[TY1:.*]] @llvm.spv.wave.reduce.max.v4f32([[TY1]] %[[#]]
+  // CHECK-DXIL:  %[[RET1:.*]] = call reassoc nnan ninf nsz arcp afn 
[[TY1:.*]] @llvm.dx.wave.reduce.max.v4f32([[TY1]] %[[#]])
+  // CHECK:  ret [[TY1]] %[[RET1]]
+  return WaveActiveMax(expr);
+}
+
+// CHECK-DXIL: declare [[TY1]] @llvm.dx.wave.reduce.max.v4f32([[TY1]]) 
#[[#attr]]
+// CHECK-SPIRV: declare spir_func [[TY1]] 
@llvm.spv.wave.reduce.max.v4f32([[TY1]]) #[[#attr]]
+
+// CHECK: attributes #[[#attr]] = {{{.*}} convergent {{.*}}}
+

V-FEXrt wrote:

Is this leftover cruft?

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,133 @@
+//=== ParseHLSLRootSignatureTest.cpp - Parse Root Signature tests 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Parse/ParseHLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::root_signature;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class ParseHLSLRootSignatureTest : public ::testing::Test {
+protected:
+  ParseHLSLRootSignatureTest()
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
+TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  std::unique_ptr CreatePP(StringRef Source,
+ TrivialModuleLoader &ModLoader) {
+std::unique_ptr Buf =
+llvm::MemoryBuffer::getMemBuffer(Source);
+SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+HeaderSearch HeaderInfo(std::make_shared(), SourceMgr,
+Diags, LangOpts, Target.get());
+std::unique_ptr PP = std::make_unique(
+std::make_shared(), Diags, LangOpts, SourceMgr,
+HeaderInfo, ModLoader,
+/*IILookup =*/nullptr,
+/*OwnsHeaderSearch =*/false);
+PP->Initialize(*Target);
+PP->EnterMainSourceFile();
+return PP;
+  }
+
+  void CheckTokens(SmallVector &Computed,
+   SmallVector &Expected) {
+ASSERT_EQ(Computed.size(), Expected.size());
+for (unsigned I = 0, E = Expected.size(); I != E; ++I) {
+  ASSERT_EQ(Computed[I].Kind, Expected[I]);
+}
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  std::shared_ptr TargetOpts;
+  IntrusiveRefCntPtr Target;
+};
+
+TEST_F(ParseHLSLRootSignatureTest, LexValidTokensTest) {
+  const llvm::StringLiteral Source = R"cc(
+-42
+
+b0 t43 u987 s234
+
+(),|=
+
+DescriptorTable
+
+CBV SRV UAV Sampler
+space visibility flags
+numDescriptors offset
+
+DESCRIPTOR_RANGE_OFFSET_APPEND
+
+DATA_VOLATILE
+DATA_STATIC_WHILE_SET_AT_EXECUTE
+DATA_STATIC
+DESCRIPTORS_VOLATILE
+DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS
+
+shader_visibility_all
+shader_visibility_vertex
+shader_visibility_hull
+shader_visibility_domain
+shader_visibility_geometry
+shader_visibility_pixel
+shader_visibility_amplification
+shader_visibility_mesh
+
+42 +42
+  )cc";
+
+  TrivialModuleLoader ModLoader;
+  auto PP = CreatePP(Source, ModLoader);
+  auto TokLoc = SourceLocation();
+
+  RootSignatureLexer Lexer(Source, TokLoc, *PP);
+
+  SmallVector Tokens = {
+  RootSignatureToken() // invalid token for completeness
+  };
+  ASSERT_FALSE(Lexer.Lex(Tokens));

V-FEXrt wrote:

No, I'm happy to punt it

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,153 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent

V-FEXrt wrote:

Yep that would be great!

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,133 @@
+//=== ParseHLSLRootSignatureTest.cpp - Parse Root Signature tests 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Parse/ParseHLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::root_signature;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class ParseHLSLRootSignatureTest : public ::testing::Test {
+protected:
+  ParseHLSLRootSignatureTest()
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
+TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  std::unique_ptr CreatePP(StringRef Source,
+ TrivialModuleLoader &ModLoader) {
+std::unique_ptr Buf =
+llvm::MemoryBuffer::getMemBuffer(Source);
+SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+HeaderSearch HeaderInfo(std::make_shared(), SourceMgr,
+Diags, LangOpts, Target.get());
+std::unique_ptr PP = std::make_unique(
+std::make_shared(), Diags, LangOpts, SourceMgr,
+HeaderInfo, ModLoader,
+/*IILookup =*/nullptr,
+/*OwnsHeaderSearch =*/false);
+PP->Initialize(*Target);
+PP->EnterMainSourceFile();
+return PP;
+  }
+
+  void CheckTokens(SmallVector &Computed,
+   SmallVector &Expected) {
+ASSERT_EQ(Computed.size(), Expected.size());
+for (unsigned I = 0, E = Expected.size(); I != E; ++I) {
+  ASSERT_EQ(Computed[I].Kind, Expected[I]);
+}
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  std::shared_ptr TargetOpts;
+  IntrusiveRefCntPtr Target;
+};
+
+TEST_F(ParseHLSLRootSignatureTest, LexValidTokensTest) {
+  const llvm::StringLiteral Source = R"cc(
+-42
+
+b0 t43 u987 s234
+
+(),|=
+
+DescriptorTable
+
+CBV SRV UAV Sampler
+space visibility flags
+numDescriptors offset
+
+DESCRIPTOR_RANGE_OFFSET_APPEND
+
+DATA_VOLATILE
+DATA_STATIC_WHILE_SET_AT_EXECUTE
+DATA_STATIC
+DESCRIPTORS_VOLATILE
+DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS
+
+shader_visibility_all
+shader_visibility_vertex
+shader_visibility_hull
+shader_visibility_domain
+shader_visibility_geometry
+shader_visibility_pixel
+shader_visibility_amplification
+shader_visibility_mesh
+
+42 +42
+  )cc";
+
+  TrivialModuleLoader ModLoader;
+  auto PP = CreatePP(Source, ModLoader);
+  auto TokLoc = SourceLocation();
+
+  RootSignatureLexer Lexer(Source, TokLoc, *PP);
+
+  SmallVector Tokens = {
+  RootSignatureToken() // invalid token for completeness
+  };
+  ASSERT_FALSE(Lexer.Lex(Tokens));

V-FEXrt wrote:

Would be nice to see a more robust set of failure tests

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,133 @@
+//=== ParseHLSLRootSignatureTest.cpp - Parse Root Signature tests 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Parse/ParseHLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::root_signature;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class ParseHLSLRootSignatureTest : public ::testing::Test {
+protected:
+  ParseHLSLRootSignatureTest()
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
+TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  std::unique_ptr CreatePP(StringRef Source,
+ TrivialModuleLoader &ModLoader) {
+std::unique_ptr Buf =
+llvm::MemoryBuffer::getMemBuffer(Source);
+SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+HeaderSearch HeaderInfo(std::make_shared(), SourceMgr,
+Diags, LangOpts, Target.get());
+std::unique_ptr PP = std::make_unique(
+std::make_shared(), Diags, LangOpts, SourceMgr,
+HeaderInfo, ModLoader,
+/*IILookup =*/nullptr,
+/*OwnsHeaderSearch =*/false);
+PP->Initialize(*Target);
+PP->EnterMainSourceFile();
+return PP;
+  }
+
+  void CheckTokens(SmallVector &Computed,
+   SmallVector &Expected) {
+ASSERT_EQ(Computed.size(), Expected.size());
+for (unsigned I = 0, E = Expected.size(); I != E; ++I) {
+  ASSERT_EQ(Computed[I].Kind, Expected[I]);
+}
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  std::shared_ptr TargetOpts;
+  IntrusiveRefCntPtr Target;
+};
+
+TEST_F(ParseHLSLRootSignatureTest, LexValidTokensTest) {
+  const llvm::StringLiteral Source = R"cc(
+-42
+
+b0 t43 u987 s234
+
+(),|=
+
+DescriptorTable
+
+CBV SRV UAV Sampler
+space visibility flags
+numDescriptors offset
+
+DESCRIPTOR_RANGE_OFFSET_APPEND
+
+DATA_VOLATILE
+DATA_STATIC_WHILE_SET_AT_EXECUTE
+DATA_STATIC
+DESCRIPTORS_VOLATILE
+DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS
+
+shader_visibility_all
+shader_visibility_vertex
+shader_visibility_hull
+shader_visibility_domain
+shader_visibility_geometry
+shader_visibility_pixel
+shader_visibility_amplification
+shader_visibility_mesh
+
+42 +42
+  )cc";
+
+  TrivialModuleLoader ModLoader;
+  auto PP = CreatePP(Source, ModLoader);
+  auto TokLoc = SourceLocation();
+
+  RootSignatureLexer Lexer(Source, TokLoc, *PP);
+
+  SmallVector Tokens = {
+  RootSignatureToken() // invalid token for completeness
+  };
+  ASSERT_FALSE(Lexer.Lex(Tokens));
+
+  SmallVector Expected = {

V-FEXrt wrote:

Its probably my unfamiliarity with the code but I can't see how this is 
actually building up the list of expected tokens. Importing the `.def` file 
here _seems_ strange

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt approved this pull request.

Personally happy with the code at a high level, though it would be best to have 
someone with domain knowledge also approve

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-22 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,153 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent

V-FEXrt wrote:

I'm personally not a big fan of untracked TODOs in code. They quickly fall out 
of context and never get resolved. Would be good to make sure this is tracked 
as part of an issue if it isn't resolved before merge

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-13 Thread Ashley Coleman via cfe-commits


@@ -3181,136 +3193,250 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
+
+  bool ZeroAsNull = STI.isOpenCLEnv();

V-FEXrt wrote:

I see, yeah I don't know. Maybe @spall has context here? A lot of this code was 
originally pulled from her PR

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,130 @@
+//=== ParseHLSLRootSignatureTest.cpp - Parse Root Signature tests 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Parse/ParseHLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::root_signature;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class ParseHLSLRootSignatureTest : public ::testing::Test {
+protected:
+  ParseHLSLRootSignatureTest()
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
+TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  Preprocessor *CreatePP(StringRef Source, TrivialModuleLoader &ModLoader) {
+std::unique_ptr Buf =
+llvm::MemoryBuffer::getMemBuffer(Source);
+SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+HeaderSearch HeaderInfo(std::make_shared(), SourceMgr,
+Diags, LangOpts, Target.get());
+Preprocessor *PP =
+new Preprocessor(std::make_shared(), Diags,

V-FEXrt wrote:

imo unless you have a strong reason for it, you should _really_ avoid 
new/delete and instead use C++ smart pointers for allocating/freeing heap 
memory. It takes care of the memory management for you and prevents accidental 
memory leaks.

In this case, `std::unique_ptr` would work perfectly 
https://en.cppreference.com/w/cpp/memory/unique_ptr


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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,152 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent
+  return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+  // NumericLiteralParser does not handle the sign so we will manually apply it
+  Result.Signed = Buffer.front() == '-';
+  if (Result.Signed)
+AdvanceBuffer();
+
+  // Retrieve the possible number
+  StringRef NumSpelling = Buffer.take_while(IsPreprocessorNumberChar);
+
+  // Parse the numeric value and so semantic checks on its specification
+  clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
+  PP.getSourceManager(), PP.getLangOpts(),
+  PP.getTargetInfo(), PP.getDiagnostics());
+  if (Literal.hadError)
+return true; // Error has already been reported so just return
+
+  // Retrieve the number value to store into the token
+  if (Literal.isIntegerLiteral()) {
+Result.Kind = TokenKind::int_literal;
+
+APSInt X = APSInt(32, Result.Signed);
+if (Literal.GetIntegerValue(X))
+  return true; // TODO: Report overflow error
+
+X = Result.Signed ? -X : X;
+Result.IntLiteral = (uint32_t)X.getZExtValue();
+  } else {
+return true; // TODO: report unsupported number literal specification
+  }
+
+  AdvanceBuffer(NumSpelling.size());
+  return false;
+}
+
+bool RootSignatureLexer::Lex(SmallVector &Tokens) {
+  // Discard any leading whitespace
+  AdvanceBuffer(Buffer.take_while(isspace).size());
+
+  while (!Buffer.empty()) {
+RootSignatureToken Result;
+if (LexToken(Result))
+  return true;
+
+// Successfully Lexed the token so we can store it
+Tokens.push_back(Result);
+
+// Discard any trailing whitespace
+AdvanceBuffer(Buffer.take_while(isspace).size());
+  }
+
+  return false;
+}
+
+bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
+  // Record where this token is in the text for usage in parser diagnostics
+  Result.TokLoc = SourceLoc;
+
+  char C = Buffer.front();
+
+  // Punctuators
+  switch (C) {
+#define PUNCTUATOR(X, Y)   
\
+  case Y: {
\
+Result.Kind = TokenKind::pu_##X;   
\
+AdvanceBuffer();   
\
+return false;  
\
+  }
+#include "clang/Parse/HLSLRootSignatureTokenKinds.def"

V-FEXrt wrote:

Is there a particular reason you define `PUNCTUATOR` both here and in the 
`.def` file? It makes the `.def` file harder to follow since the `#define 
PUNCTUATOR` there isn't actually used

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,152 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent
+  return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+  // NumericLiteralParser does not handle the sign so we will manually apply it
+  Result.Signed = Buffer.front() == '-';
+  if (Result.Signed)
+AdvanceBuffer();
+
+  // Retrieve the possible number
+  StringRef NumSpelling = Buffer.take_while(IsPreprocessorNumberChar);
+
+  // Parse the numeric value and so semantic checks on its specification
+  clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
+  PP.getSourceManager(), PP.getLangOpts(),
+  PP.getTargetInfo(), PP.getDiagnostics());
+  if (Literal.hadError)
+return true; // Error has already been reported so just return
+
+  // Retrieve the number value to store into the token
+  if (Literal.isIntegerLiteral()) {
+Result.Kind = TokenKind::int_literal;
+
+APSInt X = APSInt(32, Result.Signed);
+if (Literal.GetIntegerValue(X))
+  return true; // TODO: Report overflow error
+
+X = Result.Signed ? -X : X;
+Result.IntLiteral = (uint32_t)X.getZExtValue();
+  } else {
+return true; // TODO: report unsupported number literal specification
+  }
+
+  AdvanceBuffer(NumSpelling.size());
+  return false;
+}
+
+bool RootSignatureLexer::Lex(SmallVector &Tokens) {
+  // Discard any leading whitespace
+  AdvanceBuffer(Buffer.take_while(isspace).size());
+
+  while (!Buffer.empty()) {
+RootSignatureToken Result;
+if (LexToken(Result))
+  return true;
+
+// Successfully Lexed the token so we can store it
+Tokens.push_back(Result);
+
+// Discard any trailing whitespace
+AdvanceBuffer(Buffer.take_while(isspace).size());
+  }
+
+  return false;
+}
+
+bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
+  // Record where this token is in the text for usage in parser diagnostics
+  Result.TokLoc = SourceLoc;
+
+  char C = Buffer.front();
+
+  // Punctuators
+  switch (C) {
+#define PUNCTUATOR(X, Y)   
\
+  case Y: {
\
+Result.Kind = TokenKind::pu_##X;   
\
+AdvanceBuffer();   
\
+return false;  
\
+  }
+#include "clang/Parse/HLSLRootSignatureTokenKinds.def"

V-FEXrt wrote:

if it must always be defined before inclusion you could do

```
#ifndef PUNCTUATOR 
#error some message
#endif
```

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,152 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent
+  return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+  // NumericLiteralParser does not handle the sign so we will manually apply it
+  Result.Signed = Buffer.front() == '-';

V-FEXrt wrote:

I'm assuming no, but is unary `+` allowed here?

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,152 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent
+  return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+  // NumericLiteralParser does not handle the sign so we will manually apply it
+  Result.Signed = Buffer.front() == '-';
+  if (Result.Signed)
+AdvanceBuffer();
+
+  // Retrieve the possible number
+  StringRef NumSpelling = Buffer.take_while(IsPreprocessorNumberChar);
+
+  // Parse the numeric value and so semantic checks on its specification
+  clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
+  PP.getSourceManager(), PP.getLangOpts(),
+  PP.getTargetInfo(), PP.getDiagnostics());
+  if (Literal.hadError)
+return true; // Error has already been reported so just return
+
+  // Retrieve the number value to store into the token
+  if (Literal.isIntegerLiteral()) {
+Result.Kind = TokenKind::int_literal;
+
+APSInt X = APSInt(32, Result.Signed);
+if (Literal.GetIntegerValue(X))
+  return true; // TODO: Report overflow error
+
+X = Result.Signed ? -X : X;
+Result.IntLiteral = (uint32_t)X.getZExtValue();
+  } else {
+return true; // TODO: report unsupported number literal specification
+  }

V-FEXrt wrote:

nit: invert the condition and early exit

```suggestion
  if (!Literal.isIntegerLiteral()) {
return true; // TODO: report unsupported number literal specification
  }
  
  Result.Kind = TokenKind::int_literal;

  APSInt X = APSInt(32, Result.Signed);
  if (Literal.GetIntegerValue(X))
return true; // TODO: Report overflow error

  X = Result.Signed ? -X : X;
  Result.IntLiteral = (uint32_t)X.getZExtValue();
```

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-15 Thread Ashley Coleman via cfe-commits

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,152 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+  // TODO: extend for float support with or without hexadecimal/exponent
+  return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+  // NumericLiteralParser does not handle the sign so we will manually apply it
+  Result.Signed = Buffer.front() == '-';
+  if (Result.Signed)
+AdvanceBuffer();
+
+  // Retrieve the possible number
+  StringRef NumSpelling = Buffer.take_while(IsPreprocessorNumberChar);
+
+  // Parse the numeric value and so semantic checks on its specification

V-FEXrt wrote:

typo?
```suggestion
  // Parse the numeric value and do semantic checks on its specification
```

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-16 Thread Ashley Coleman via cfe-commits


@@ -0,0 +1,130 @@
+//=== ParseHLSLRootSignatureTest.cpp - Parse Root Signature tests 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Parse/ParseHLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::root_signature;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class ParseHLSLRootSignatureTest : public ::testing::Test {
+protected:
+  ParseHLSLRootSignatureTest()
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
+TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  Preprocessor *CreatePP(StringRef Source, TrivialModuleLoader &ModLoader) {
+std::unique_ptr Buf =
+llvm::MemoryBuffer::getMemBuffer(Source);
+SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+
+HeaderSearch HeaderInfo(std::make_shared(), SourceMgr,
+Diags, LangOpts, Target.get());
+Preprocessor *PP =
+new Preprocessor(std::make_shared(), Diags,

V-FEXrt wrote:

I think you can just derefence the `unique_ptr`. Something like `*ptr->get()`

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-16 Thread Ashley Coleman via cfe-commits

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


[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)

2025-01-16 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits


@@ -3181,136 +3193,250 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
+
+  bool ZeroAsNull = STI.isOpenCLEnv();
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *postCastT =
-  GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder);
-  Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
-  bool Result =
-  selectOpWithSrcs(bitcastReg, postCastT, I, {OpReg}, SPIRV::OpBitcast);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+  SPIRVType *Vec2ResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
+
+  std::vector PartialRegs;
+
+  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+  unsigned CurrentComponent = 0;
+  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
+// This register holds the firstbitX result for each of the i64x2 vectors
+// extracted from SrcReg
+Register BitSetResult =
+MRI->createVirtualRegister(GR.getRegClass(I64x2Type));
+
+auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+   TII.get(SPIRV::OpVectorShuffle))
+   .addDef(BitSetResult)
+   .addUse(GR.getSPIRVTypeID(I64x2Type))
+   .addUse(SrcReg)
+   // Per the spec, repeat the vector if only one vec is needed
+   .addUse(SrcReg);
+
+MIB.addImm(CurrentComponent);
+MIB.addImm(CurrentComponent + 1);

V-FEXrt wrote:

Is it not true? The generated op code does list the src vector reg twice

```
; CHECK: [[high_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[lsb_bits]] 
[[lsb_bits]] 0 2
; CHECK: [[low_bits:%.+]] = OpVecto

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits


@@ -3181,136 +3193,250 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
+
+  bool ZeroAsNull = STI.isOpenCLEnv();
   MachineIRBuilder MIRBuilder(I);
-  SPIRVType *postCastT =
-  GR.getOrCreateSPIRVVectorType(baseType, 2 * count, MIRBuilder);
-  Register bitcastReg = MRI->createVirtualRegister(GR.getRegClass(postCastT));
-  bool Result =
-  selectOpWithSrcs(bitcastReg, postCastT, I, {OpReg}, SPIRV::OpBitcast);
+  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
+  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
+  SPIRVType *I64x2Type = GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder);
+  SPIRVType *Vec2ResType =
+  GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder);
+
+  std::vector PartialRegs;
+
+  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
+  unsigned CurrentComponent = 0;
+  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
+// This register holds the firstbitX result for each of the i64x2 vectors
+// extracted from SrcReg
+Register BitSetResult =
+MRI->createVirtualRegister(GR.getRegClass(I64x2Type));
+
+auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+   TII.get(SPIRV::OpVectorShuffle))
+   .addDef(BitSetResult)
+   .addUse(GR.getSPIRVTypeID(I64x2Type))
+   .addUse(SrcReg)
+   // Per the spec, repeat the vector if only one vec is needed
+   .addUse(SrcReg);
+
+MIB.addImm(CurrentComponent);
+MIB.addImm(CurrentComponent + 1);

V-FEXrt wrote:

Well, I suppose its not true that you _have_ to set the second vector to the 
first but you have to set _something_ and setting the same thing works because 
you always have the first. But that causes 

[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits


@@ -3181,136 +3193,250 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
+
+  bool ZeroAsNull = STI.isOpenCLEnv();

V-FEXrt wrote:

> If this is only used in 1 place, we should move it closer to the use.
Yeah sorry, it got moved during the loop refactor 

>  why can't we use OpConstantNull in Vulkan
looking into it

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits

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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-10 Thread Ashley Coleman via cfe-commits


@@ -3181,136 +3193,250 @@ Register 
SPIRVInstructionSelector::buildPointerToResource(
   return AcReg;
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh16(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
-  // zero or sign extend
+bool SPIRVInstructionSelector::selectFirstBitSet16(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+unsigned ExtendOpcode, unsigned BitSetOpcode) const {
   Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
-  bool Result =
-  selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()}, Opcode);
-  return Result && selectFirstBitHigh32(ResVReg, ResType, I, ExtReg, IsSigned);
+  bool Result = selectOpWithSrcs(ExtReg, ResType, I, 
{I.getOperand(2).getReg()},
+ ExtendOpcode);
+
+  return Result &&
+ selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh32(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-Register SrcReg,
-bool IsSigned) const {
-  unsigned Opcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
+bool SPIRVInstructionSelector::selectFirstBitSet32(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode) const {
   return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
   .addDef(ResVReg)
   .addUse(GR.getSPIRVTypeID(ResType))
   .addImm(static_cast(SPIRV::InstructionSet::GLSL_std_450))
-  .addImm(Opcode)
+  .addImm(BitSetOpcode)
   .addUse(SrcReg)
   .constrainAllUses(TII, TRI, RBI);
 }
 
-bool SPIRVInstructionSelector::selectFirstBitHigh64(Register ResVReg,
-const SPIRVType *ResType,
-MachineInstr &I,
-bool IsSigned) const {
-  Register OpReg = I.getOperand(2).getReg();
-  // 1. split our int64 into 2 pieces using a bitcast
-  unsigned count = GR.getScalarOrVectorComponentCount(ResType);
-  SPIRVType *baseType = GR.retrieveScalarOrVectorIntType(ResType);
+bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
+Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
+Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
+
+  // SPIR-V only allow vecs of size 2,3,4. Calling with a larger vec requires
+  // creating a param reg and return reg with an invalid vec size. If that is
+  // resolved then this function is valid for vectors of any component size.
+  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");
+
+  bool ZeroAsNull = STI.isOpenCLEnv();

V-FEXrt wrote:

Looks like it does bottom out in `OpConstantNull`

https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp#L347

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


[clang] [HLSL] Implement HLSL Flat casting (excluding splat cases) (PR #118842)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -6358,3 +6359,89 @@ RValue CodeGenFunction::EmitPseudoObjectRValue(const 
PseudoObjectExpr *E,
 LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) {
   return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV;
 }
+
+void CodeGenFunction::FlattenAccessAndType(
+Address Addr, QualType AddrType,
+SmallVectorImpl> &AccessList,
+SmallVectorImpl &FlatTypes) {
+  // WorkList is list of type we are processing + the Index List to access
+  // the field of that type in Addr for use in a GEP
+  llvm::SmallVector>,
+16>
+  WorkList;
+  llvm::IntegerType *IdxTy = llvm::IntegerType::get(getLLVMContext(), 32);
+  WorkList.push_back(
+  {AddrType,
+   {llvm::ConstantInt::get(
+   IdxTy,
+   0)}}); // Addr should be a pointer so we need to 'dereference' it
+
+  while (!WorkList.empty()) {
+std::pair> P =
+WorkList.pop_back_val();
+QualType T = P.first;
+llvm::SmallVector IdxList = P.second;
+T = T.getCanonicalType().getUnqualifiedType();
+assert(!isa(T) && "Matrix types not yet supported in HLSL");
+if (const auto *CAT = dyn_cast(T)) {
+  uint64_t Size = CAT->getZExtSize();
+  for (int64_t i = Size - 1; i > -1; i--) {

V-FEXrt wrote:

nit: `i` should be `I` 
https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly

aside: At least for my setup, using a lower case, even in loops, raises a 
warning

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


[clang] [HLSL] Implement HLSL Flat casting (excluding splat cases) (PR #118842)

2025-01-15 Thread Ashley Coleman via cfe-commits


@@ -2412,6 +2412,102 @@ bool SemaHLSL::CheckCompatibleParameterABI(FunctionDecl 
*New,
   return HadError;
 }
 
+// Generally follows PerformScalarCast, with cases reordered for
+// clarity of what types are supported
+bool SemaHLSL::CanPerformScalarCast(QualType SrcTy, QualType DestTy) {
+
+  if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))
+return true;
+
+  switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) {
+  case Type::STK_Bool: // casting from bool is like casting from an integer
+  case Type::STK_Integral:
+switch (DestTy->getScalarTypeKind()) {
+case Type::STK_Bool:
+case Type::STK_Integral:
+case Type::STK_Floating:
+  return true;
+case Type::STK_CPointer:
+case Type::STK_ObjCObjectPointer:
+case Type::STK_BlockPointer:
+case Type::STK_MemberPointer:
+  llvm_unreachable("HLSL doesn't support pointers.");
+case Type::STK_IntegralComplex:
+case Type::STK_FloatingComplex:
+  llvm_unreachable("HLSL doesn't support complex types.");
+case Type::STK_FixedPoint:
+  llvm_unreachable("HLSL doesn't support fixed point types.");
+}
+llvm_unreachable("Should have returned before this");
+
+  case Type::STK_Floating:
+switch (DestTy->getScalarTypeKind()) {
+case Type::STK_Floating:
+case Type::STK_Bool:
+case Type::STK_Integral:
+  return true;
+case Type::STK_FloatingComplex:
+case Type::STK_IntegralComplex:
+  llvm_unreachable("HLSL doesn't support complex types.");
+case Type::STK_FixedPoint:
+  llvm_unreachable("HLSL doesn't support fixed point types.");
+case Type::STK_CPointer:
+case Type::STK_ObjCObjectPointer:
+case Type::STK_BlockPointer:
+case Type::STK_MemberPointer:
+  llvm_unreachable("HLSL doesn't support pointers.");
+}
+llvm_unreachable("Should have returned before this");
+
+  case Type::STK_MemberPointer:
+  case Type::STK_CPointer:
+  case Type::STK_BlockPointer:
+  case Type::STK_ObjCObjectPointer:
+llvm_unreachable("HLSL doesn't support pointers.");
+
+  case Type::STK_FixedPoint:
+llvm_unreachable("HLSL doesn't support fixed point types.");
+
+  case Type::STK_FloatingComplex:
+  case Type::STK_IntegralComplex:
+llvm_unreachable("HLSL doesn't support complex types.");
+  }
+
+  llvm_unreachable("Unhandled scalar cast");
+}
+
+// Can we perform an HLSL Flattened cast?
+// TODO: update this code when matrices are added

V-FEXrt wrote:

idk if this is something llvm has, but other projects I've worked on will tie 
"future todos" like this to an issue somewhere so they are easier to find later.

If that's something llvm does then this todo would be good to associate with an 
issue

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


[clang] [HLSL] Make bool in hlsl i32 (PR #122977)

2025-01-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt approved this pull request.


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


[clang] [llvm] [HLSL] Implement elementwise firstbitlow builtin (PR #116858)

2025-01-15 Thread Ashley Coleman via cfe-commits

V-FEXrt wrote:

Yeah I figured they weren't broken by me but I had assumed I needed all green 
before merging so was waiting for the fix to make it into main but happy to 
merge as is if that's acceptable

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


[clang] [HLSL] Implement HLSL intialization list support (PR #123141)

2025-02-14 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt approved this pull request.


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


[clang] [HLSL] Implement HLSL intialization list support (PR #123141)

2025-02-14 Thread Ashley Coleman via cfe-commits


@@ -1730,6 +1731,16 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
   }
 #endif
 
+  // HLSL initialization lists in the AST are an expansion which can contain
+  // side-effecting expressions wrapped in opaque value expressions. To 
properly
+  // emit these we need to emit the opaque values before we emit the argument
+  // expressions themselves. This is a little hacky, but it prevents us needing
+  // to do a bigger AST-level change for a language feature that we need
+  // deprecate in the near future.

V-FEXrt wrote:

Can you/should you reference an issue here to link this to the "future 
deprecation"?

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


[clang] [HLSL] Implement HLSL intialization list support (PR #123141)

2025-02-14 Thread Ashley Coleman via cfe-commits


@@ -3173,9 +3173,18 @@ bool SemaHLSL::TransformInitList(const InitializedEntity 
&Entity,
   BuildFlattenedTypeList(InitTy, DestTypes);
 
   llvm::SmallVector ArgExprs;
-  for (Expr *Arg : Init->inits())
-if (!BuildInitializerList(SemaRef, Ctx, Arg, ArgExprs, DestTypes))
+  for (unsigned I = 0; I < Init->getNumInits(); ++I) {
+Expr *E = Init->getInit(I);
+if (E->HasSideEffects(Ctx)) {
+  QualType Ty = E->getType();
+  if (auto *RTy = Ty->getAs())
+E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());

V-FEXrt wrote:

Unless there is some magic I'm missing, this is memory leak right? 3182 
reassigns `E` without freeing? 
Does `OpaqueValueExpr` take ownership of the old `E`?

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


[clang] [HLSL] Implement HLSL splatting (PR #118992)

2025-02-13 Thread Ashley Coleman via cfe-commits

https://github.com/V-FEXrt approved this pull request.


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


  1   2   >