https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/109180
>From 3c58861f3e8c2f1333d0b36c6f5b7ba7f3d9e187 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Wed, 18 Sep 2024 12:20:19 -0700 Subject: [PATCH 1/9] add cross hlsl function --- clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 15 +++++ clang/lib/CodeGen/CGHLSLRuntime.h | 1 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 22 +++++++ clang/lib/Sema/SemaHLSL.cpp | 14 +++++ clang/test/CodeGenHLSL/builtins/cross.hlsl | 36 ++++++++++++ .../test/SemaHLSL/BuiltIns/cross-errors.hlsl | 31 ++++++++++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/DirectX/DXILIntrinsicExpansion.cpp | 40 +++++++++++++ .../Target/SPIRV/SPIRVInstructionSelector.cpp | 24 +++++++- llvm/test/CodeGen/DirectX/cross.ll | 57 +++++++++++++++++++ .../CodeGen/SPIRV/hlsl-intrinsics/cross.ll | 33 +++++++++++ 13 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenHLSL/builtins/cross.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/cross.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cross.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 8c5d7ad763bf97..c4735b59dfb0be 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4709,6 +4709,12 @@ def HLSLCreateHandle : LangBuiltin<"HLSL_LANG"> { let Prototype = "void*(unsigned char)"; } +def HLSLCross: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_cross"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_dot"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7e18aafcdd4b8a..0883ad17ce0ffd 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18639,6 +18639,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, IsUnsigned ? Intrinsic::dx_uclamp : Intrinsic::dx_clamp, ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "dx.clamp"); } + case Builtin::BI__builtin_hlsl_cross: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + Value *Op1 = EmitScalarExpr(E->getArg(1)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "step operands must have a float representation"); + // make sure each vector has exactly 3 elements + auto *XVecTy1 = E->getArg(0)->getType()->getAs<VectorType>(); + auto *XVecTy2 = E->getArg(1)->getType()->getAs<VectorType>(); + assert(XVecTy1->getNumElements() == 3 && XVecTy2->getNumElements() == 3 && + "input vectors must have 3 elements each"); + return Builder.CreateIntrinsic( + /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getCrossIntrinsic(), + ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.cross"); + } case Builtin::BI__builtin_hlsl_dot: { Value *Op0 = EmitScalarExpr(E->getArg(0)); Value *Op1 = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index a8aabca7348ffb..6722d2c7c50a2b 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -74,6 +74,7 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(All, all) GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any) + GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross) GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac) GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length) GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 6cd6a2caf19994..e4b40978dea6b9 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1563,6 +1563,28 @@ uint64_t3 reversebits(uint64_t3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint64_t4 reversebits(uint64_t4); +//===----------------------------------------------------------------------===// +// cross builtins +//===----------------------------------------------------------------------===// + +/// \fn T cross(T x, T y) +/// \brief Returns the cross product of two floating-point, 3D vectors. +/// \param x [in] The first floating-point, 3D vector. +/// \param y [in] The second floating-point, 3D vector. +/// +/// Result is the cross product of x and y, i.e., the resulting +/// components are, in order : +/// x[1] * y[2] - y[1] * x[2] +/// x[2] * y[0] - y[2] * x[0] +/// x[0] * y[1] - y[0] * x[1] + +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) +half3 cross(half3, half3); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross) +float3 cross(float3, float3); + //===----------------------------------------------------------------------===// // rcp builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index a303f211501348..e7e7a3c259e27a 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1704,6 +1704,20 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_cross: { + if (SemaRef.checkArgCount(TheCall, 2)) + return true; + if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; + if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + // return type is the same as the input type + TheCall->setType(ArgTyA); + break; + } case Builtin::BI__builtin_hlsl_dot: { if (SemaRef.checkArgCount(TheCall, 2)) return true; diff --git a/clang/test/CodeGenHLSL/builtins/cross.hlsl b/clang/test/CodeGenHLSL/builtins/cross.hlsl new file mode 100644 index 00000000000000..047e7fef7136fe --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/cross.hlsl @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv + +// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half> +// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float> +// NATIVE_HALF: ret <3 x half> %hlsl.cross +// NO_HALF: ret <3 x float> %hlsl.cross +half3 test_cross_half3(half3 p0, half3 p1) +{ + return cross(p0, p1); +} + +// CHECK: define [[FNATTRS]] <3 x float> @ +// CHECK: %hlsl.cross = call <3 x float> @llvm.[[TARGET]].cross.v3f32( +// CHECK: ret <3 x float> %hlsl.cross +float3 test_cross_float3(float3 p0, float3 p1) +{ + return cross(p0, p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl new file mode 100644 index 00000000000000..40ab4b533a495e --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected + +void test_too_few_arg() +{ + return __builtin_hlsl_cross(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} +} + +void test_too_many_arg(float3 p0) +{ + return __builtin_hlsl_cross(p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_cross_int_to_float_promotion(int p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_cross_int2_to_float2_promotion(int2 p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 3ce7b8b987ef86..f4242772bab20c 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -44,6 +44,7 @@ def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; +def int_dx_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_dx_saturate : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index a4c01952927175..480b391bd54fdf 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -60,6 +60,7 @@ let TargetPrefix = "spv" in { Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>; def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; + def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>; def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>], [IntrNoMem, IntrWillReturn] >; diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index dd73b895b14d37..e921dffede38f8 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -43,6 +43,7 @@ static bool isIntrinsicExpansion(Function &F) { case Intrinsic::dx_all: case Intrinsic::dx_any: case Intrinsic::dx_clamp: + case Intrinsic::dx_cross: case Intrinsic::dx_uclamp: case Intrinsic::dx_lerp: case Intrinsic::dx_length: @@ -73,6 +74,42 @@ static Value *expandAbs(CallInst *Orig) { "dx.max"); } +static Value *expandCrossIntrinsic(CallInst *Orig) { + + VectorType *VT = cast<VectorType>(Orig->getType()); + if (cast<FixedVectorType>(VT)->getNumElements() != 3) + report_fatal_error(Twine("return vector must have exactly 3 elements"), + /* gen_crash_diag=*/false); + + Value *op0 = Orig->getOperand(0); + Value *op1 = Orig->getOperand(1); + IRBuilder<> Builder(Orig); + + Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0); + Value *op0_y = Builder.CreateExtractElement(op0, 1); + Value *op0_z = Builder.CreateExtractElement(op0, 2); + + Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0); + Value *op1_y = Builder.CreateExtractElement(op1, 1); + Value *op1_z = Builder.CreateExtractElement(op1, 2); + + auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * { + Value *xy = Builder.CreateFMul(x0, y1); + Value *yx = Builder.CreateFMul(y0, x1); + return Builder.CreateFSub(xy, yx); + }; + + Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z); + Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x); + Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y); + + Value *cross = UndefValue::get(VT); + cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0); + cross = Builder.CreateInsertElement(cross, zx_xz, 1); + cross = Builder.CreateInsertElement(cross, xy_yx, 2); + return cross; +} + // Create appropriate DXIL float dot intrinsic for the given A and B operands // The appropriate opcode will be determined by the size of the operands // The dot product is placed in the position indicated by Orig @@ -434,6 +471,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { case Intrinsic::dx_any: Result = expandAnyOrAllIntrinsic(Orig, IntrinsicId); break; + case Intrinsic::dx_cross: + Result = expandCrossIntrinsic(Orig); + break; case Intrinsic::dx_uclamp: case Intrinsic::dx_clamp: Result = expandClampIntrinsic(Orig, IntrinsicId); diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index b526c9f29f1e6a..677119840709aa 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -167,7 +167,8 @@ class SPIRVInstructionSelector : public InstructionSelector { bool selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned comparisonOpcode, MachineInstr &I) const; - + bool selectCross(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; bool selectICmp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; bool selectFCmp(Register ResVReg, const SPIRVType *ResType, @@ -1465,6 +1466,25 @@ bool SPIRVInstructionSelector::selectAny(Register ResVReg, return selectAnyOrAll(ResVReg, ResType, I, SPIRV::OpAny); } +bool SPIRVInstructionSelector::selectCross(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + + assert(I.getNumOperands() == 4); + assert(I.getOperand(2).isReg()); + assert(I.getOperand(3).isReg()); + MachineBasicBlock &BB = *I.getParent(); + + return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450)) + .addImm(GL::Cross) + .addUse(I.getOperand(2).getReg()) + .addUse(I.getOperand(3).getReg()) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectFmix(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { @@ -2458,6 +2478,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectAll(ResVReg, ResType, I); case Intrinsic::spv_any: return selectAny(ResVReg, ResType, I); + case Intrinsic::spv_cross: + return selectCross(ResVReg, ResType, I); case Intrinsic::spv_lerp: return selectFmix(ResVReg, ResType, I); case Intrinsic::spv_length: diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll new file mode 100644 index 00000000000000..90847ac635dbba --- /dev/null +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -0,0 +1,57 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefix=CHECK +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefix=CHECK + +; Make sure dxil operation function calls for cross are generated for half/float. + +declare <3 x half> @llvm.dx.cross.v3f16(<3 x half>, <3 x half>) +declare <3 x float> @llvm.dx.cross.v3f32(<3 x float>, <3 x float>) + +define noundef <3 x half> @test_cross_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) { +entry: + ; CHECK: %0 = extractelement <3 x half> %p0, i64 0 + ; CHECK: %1 = extractelement <3 x half> %p0, i64 1 + ; CHECK: %2 = extractelement <3 x half> %p0, i64 2 + ; CHECK: %3 = extractelement <3 x half> %p1, i64 0 + ; CHECK: %4 = extractelement <3 x half> %p1, i64 1 + ; CHECK: %5 = extractelement <3 x half> %p1, i64 2 + ; CHECK: %6 = fmul half %1, %5 + ; CHECK: %7 = fmul half %2, %4 + ; CHECK: %8 = fsub half %6, %7 + ; CHECK: %9 = fmul half %2, %3 + ; CHECK: %10 = fmul half %0, %5 + ; CHECK: %11 = fsub half %9, %10 + ; CHECK: %12 = fmul half %0, %4 + ; CHECK: %13 = fmul half %1, %3 + ; CHECK: %14 = fsub half %12, %13 + ; CHECK: %15 = insertelement <3 x half> undef, half %8, i64 0 + ; CHECK: %16 = insertelement <3 x half> %15, half %11, i64 1 + ; CHECK: %17 = insertelement <3 x half> %16, half %14, i64 2 + ; CHECK: ret <3 x half> %17 + %hlsl.cross = call <3 x half> @llvm.dx.cross.v3f16(<3 x half> %p0, <3 x half> %p1) + ret <3 x half> %hlsl.cross +} + +define noundef <3 x float> @test_cross_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) { +entry: + ; CHECK: %0 = extractelement <3 x float> %p0, i64 0 + ; CHECK: %1 = extractelement <3 x float> %p0, i64 1 + ; CHECK: %2 = extractelement <3 x float> %p0, i64 2 + ; CHECK: %3 = extractelement <3 x float> %p1, i64 0 + ; CHECK: %4 = extractelement <3 x float> %p1, i64 1 + ; CHECK: %5 = extractelement <3 x float> %p1, i64 2 + ; CHECK: %6 = fmul float %1, %5 + ; CHECK: %7 = fmul float %2, %4 + ; CHECK: %8 = fsub float %6, %7 + ; CHECK: %9 = fmul float %2, %3 + ; CHECK: %10 = fmul float %0, %5 + ; CHECK: %11 = fsub float %9, %10 + ; CHECK: %12 = fmul float %0, %4 + ; CHECK: %13 = fmul float %1, %3 + ; CHECK: %14 = fsub float %12, %13 + ; CHECK: %15 = insertelement <3 x float> undef, float %8, i64 0 + ; CHECK: %16 = insertelement <3 x float> %15, float %11, i64 1 + ; CHECK: %17 = insertelement <3 x float> %16, float %14, i64 2 + ; CHECK: ret <3 x float> %17 + %hlsl.cross = call <3 x float> @llvm.dx.cross.v3f32(<3 x float> %p0, <3 x float> %p1) + ret <3 x float> %hlsl.cross +} diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cross.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cross.ll new file mode 100644 index 00000000000000..2e0eb8c429ac27 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cross.ll @@ -0,0 +1,33 @@ +; RUN: llc -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 %} + +; Make sure SPIRV operation function calls for cross are lowered correctly. + +; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450" +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec3_float_16:]] = OpTypeVector %[[#float_16]] 3 +; CHECK-DAG: %[[#vec3_float_32:]] = OpTypeVector %[[#float_32]] 3 + +define noundef <3 x half> @cross_half4(<3 x half> noundef %a, <3 x half> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec3_float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_16]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec3_float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#vec3_float_16]] %[[#op_ext_glsl]] Cross %[[#arg0]] %[[#arg1]] + %hlsl.cross = call <3 x half> @llvm.spv.cross.v4f16(<3 x half> %a, <3 x half> %b) + ret <3 x half> %hlsl.cross +} + +define noundef <3 x float> @cross_float4(<3 x float> noundef %a, <3 x float> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec3_float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec3_float_32]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec3_float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#vec3_float_32]] %[[#op_ext_glsl]] Cross %[[#arg0]] %[[#arg1]] + %hlsl.cross = call <3 x float> @llvm.spv.cross.v4f32(<3 x float> %a, <3 x float> %b) + ret <3 x float> %hlsl.cross +} + +declare <3 x half> @llvm.spv.cross.v4f16(<3 x half>, <3 x half>) +declare <3 x float> @llvm.spv.cross.v4f32(<3 x float>, <3 x float>) >From 9109b48786888ffc708e163441d5f6c7fb8977c3 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Fri, 20 Sep 2024 15:08:16 -0700 Subject: [PATCH 2/9] address Farzon --- clang/lib/CodeGen/CGBuiltin.cpp | 2 +- llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +- .../Target/DirectX/DXILIntrinsicExpansion.cpp | 12 ++-- llvm/test/CodeGen/DirectX/cross.ll | 72 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 0883ad17ce0ffd..47fff98e99a4ba 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18644,7 +18644,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, Value *Op1 = EmitScalarExpr(E->getArg(1)); assert(E->getArg(0)->getType()->hasFloatingRepresentation() && E->getArg(1)->getType()->hasFloatingRepresentation() && - "step operands must have a float representation"); + "cross operands must have a float representation"); // make sure each vector has exactly 3 elements auto *XVecTy1 = E->getArg(0)->getType()->getAs<VectorType>(); auto *XVecTy2 = E->getArg(1)->getType()->getAs<VectorType>(); diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index f4242772bab20c..c3ae6c9168ef4c 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -44,8 +44,8 @@ def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; -def int_dx_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; +def int_dx_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_dx_saturate : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; def int_dx_dot2 : diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index e921dffede38f8..445da7b30139f1 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -85,13 +85,13 @@ static Value *expandCrossIntrinsic(CallInst *Orig) { Value *op1 = Orig->getOperand(1); IRBuilder<> Builder(Orig); - Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0); - Value *op0_y = Builder.CreateExtractElement(op0, 1); - Value *op0_z = Builder.CreateExtractElement(op0, 2); + Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0"); + Value *op0_y = Builder.CreateExtractElement(op0, 1, "y0"); + Value *op0_z = Builder.CreateExtractElement(op0, 2, "z0"); - Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0); - Value *op1_y = Builder.CreateExtractElement(op1, 1); - Value *op1_z = Builder.CreateExtractElement(op1, 2); + Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "x1"); + Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1"); + Value *op1_z = Builder.CreateExtractElement(op1, 2, "z1"); auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * { Value *xy = Builder.CreateFMul(x0, y1); diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll index 90847ac635dbba..bc665244ed20c6 100644 --- a/llvm/test/CodeGen/DirectX/cross.ll +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -8,50 +8,50 @@ declare <3 x float> @llvm.dx.cross.v3f32(<3 x float>, <3 x float>) define noundef <3 x half> @test_cross_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) { entry: - ; CHECK: %0 = extractelement <3 x half> %p0, i64 0 - ; CHECK: %1 = extractelement <3 x half> %p0, i64 1 - ; CHECK: %2 = extractelement <3 x half> %p0, i64 2 - ; CHECK: %3 = extractelement <3 x half> %p1, i64 0 - ; CHECK: %4 = extractelement <3 x half> %p1, i64 1 - ; CHECK: %5 = extractelement <3 x half> %p1, i64 2 - ; CHECK: %6 = fmul half %1, %5 - ; CHECK: %7 = fmul half %2, %4 + ; CHECK: %x0 = extractelement <3 x half> %p0, i64 0 + ; CHECK: %y0 = extractelement <3 x half> %p0, i64 1 + ; CHECK: %z0 = extractelement <3 x half> %p0, i64 2 + ; CHECK: %x1 = extractelement <3 x half> %p1, i64 0 + ; CHECK: %y1 = extractelement <3 x half> %p1, i64 1 + ; CHECK: %z1 = extractelement <3 x half> %p1, i64 2 + ; CHECK: %0 = fmul half %y0, %z1 + ; CHECK: %1 = fmul half %z0, %y1 + ; CHECK: %2 = fsub half %0, %1 + ; CHECK: %3 = fmul half %z0, %x1 + ; CHECK: %4 = fmul half %x0, %z1 + ; CHECK: %5 = fsub half %3, %4 + ; CHECK: %6 = fmul half %x0, %y1 + ; CHECK: %7 = fmul half %y0, %x1 ; CHECK: %8 = fsub half %6, %7 - ; CHECK: %9 = fmul half %2, %3 - ; CHECK: %10 = fmul half %0, %5 - ; CHECK: %11 = fsub half %9, %10 - ; CHECK: %12 = fmul half %0, %4 - ; CHECK: %13 = fmul half %1, %3 - ; CHECK: %14 = fsub half %12, %13 - ; CHECK: %15 = insertelement <3 x half> undef, half %8, i64 0 - ; CHECK: %16 = insertelement <3 x half> %15, half %11, i64 1 - ; CHECK: %17 = insertelement <3 x half> %16, half %14, i64 2 - ; CHECK: ret <3 x half> %17 + ; CHECK: %9 = insertelement <3 x half> undef, half %2, i64 0 + ; CHECK: %10 = insertelement <3 x half> %9, half %5, i64 1 + ; CHECK: %11 = insertelement <3 x half> %10, half %8, i64 2 + ; CHECK: ret <3 x half> %11 %hlsl.cross = call <3 x half> @llvm.dx.cross.v3f16(<3 x half> %p0, <3 x half> %p1) ret <3 x half> %hlsl.cross } define noundef <3 x float> @test_cross_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) { entry: - ; CHECK: %0 = extractelement <3 x float> %p0, i64 0 - ; CHECK: %1 = extractelement <3 x float> %p0, i64 1 - ; CHECK: %2 = extractelement <3 x float> %p0, i64 2 - ; CHECK: %3 = extractelement <3 x float> %p1, i64 0 - ; CHECK: %4 = extractelement <3 x float> %p1, i64 1 - ; CHECK: %5 = extractelement <3 x float> %p1, i64 2 - ; CHECK: %6 = fmul float %1, %5 - ; CHECK: %7 = fmul float %2, %4 + ; CHECK: %x0 = extractelement <3 x float> %p0, i64 0 + ; CHECK: %y0 = extractelement <3 x float> %p0, i64 1 + ; CHECK: %z0 = extractelement <3 x float> %p0, i64 2 + ; CHECK: %x1 = extractelement <3 x float> %p1, i64 0 + ; CHECK: %y1 = extractelement <3 x float> %p1, i64 1 + ; CHECK: %z1 = extractelement <3 x float> %p1, i64 2 + ; CHECK: %0 = fmul float %y0, %z1 + ; CHECK: %1 = fmul float %z0, %y1 + ; CHECK: %2 = fsub float %0, %1 + ; CHECK: %3 = fmul float %z0, %x1 + ; CHECK: %4 = fmul float %x0, %z1 + ; CHECK: %5 = fsub float %3, %4 + ; CHECK: %6 = fmul float %x0, %y1 + ; CHECK: %7 = fmul float %y0, %x1 ; CHECK: %8 = fsub float %6, %7 - ; CHECK: %9 = fmul float %2, %3 - ; CHECK: %10 = fmul float %0, %5 - ; CHECK: %11 = fsub float %9, %10 - ; CHECK: %12 = fmul float %0, %4 - ; CHECK: %13 = fmul float %1, %3 - ; CHECK: %14 = fsub float %12, %13 - ; CHECK: %15 = insertelement <3 x float> undef, float %8, i64 0 - ; CHECK: %16 = insertelement <3 x float> %15, float %11, i64 1 - ; CHECK: %17 = insertelement <3 x float> %16, float %14, i64 2 - ; CHECK: ret <3 x float> %17 + ; CHECK: %9 = insertelement <3 x float> undef, float %2, i64 0 + ; CHECK: %10 = insertelement <3 x float> %9, float %5, i64 1 + ; CHECK: %11 = insertelement <3 x float> %10, float %8, i64 2 + ; CHECK: ret <3 x float> %11 %hlsl.cross = call <3 x float> @llvm.dx.cross.v3f32(<3 x float> %p0, <3 x float> %p1) ret <3 x float> %hlsl.cross } >From b5dc3e74bb9e2a347eb637f89b5c850af3d0ece4 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Fri, 20 Sep 2024 15:31:53 -0700 Subject: [PATCH 3/9] use correct naming convention for vec elements --- .../Target/DirectX/DXILIntrinsicExpansion.cpp | 8 ++--- llvm/test/CodeGen/DirectX/cross.ll | 36 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index 445da7b30139f1..c6b5e8ddb13bc2 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -86,12 +86,12 @@ static Value *expandCrossIntrinsic(CallInst *Orig) { IRBuilder<> Builder(Orig); Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0"); - Value *op0_y = Builder.CreateExtractElement(op0, 1, "y0"); - Value *op0_z = Builder.CreateExtractElement(op0, 2, "z0"); + Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1"); + Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2"); - Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "x1"); + Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0"); Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1"); - Value *op1_z = Builder.CreateExtractElement(op1, 2, "z1"); + Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2"); auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * { Value *xy = Builder.CreateFMul(x0, y1); diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll index bc665244ed20c6..74934a628988c3 100644 --- a/llvm/test/CodeGen/DirectX/cross.ll +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -9,19 +9,19 @@ declare <3 x float> @llvm.dx.cross.v3f32(<3 x float>, <3 x float>) define noundef <3 x half> @test_cross_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) { entry: ; CHECK: %x0 = extractelement <3 x half> %p0, i64 0 - ; CHECK: %y0 = extractelement <3 x half> %p0, i64 1 - ; CHECK: %z0 = extractelement <3 x half> %p0, i64 2 - ; CHECK: %x1 = extractelement <3 x half> %p1, i64 0 + ; CHECK: %x1 = extractelement <3 x half> %p0, i64 1 + ; CHECK: %x2 = extractelement <3 x half> %p0, i64 2 + ; CHECK: %y0 = extractelement <3 x half> %p1, i64 0 ; CHECK: %y1 = extractelement <3 x half> %p1, i64 1 - ; CHECK: %z1 = extractelement <3 x half> %p1, i64 2 - ; CHECK: %0 = fmul half %y0, %z1 - ; CHECK: %1 = fmul half %z0, %y1 + ; CHECK: %y2 = extractelement <3 x half> %p1, i64 2 + ; CHECK: %0 = fmul half %x1, %y2 + ; CHECK: %1 = fmul half %x2, %y1 ; CHECK: %2 = fsub half %0, %1 - ; CHECK: %3 = fmul half %z0, %x1 - ; CHECK: %4 = fmul half %x0, %z1 + ; CHECK: %3 = fmul half %x2, %y0 + ; CHECK: %4 = fmul half %x0, %y2 ; CHECK: %5 = fsub half %3, %4 ; CHECK: %6 = fmul half %x0, %y1 - ; CHECK: %7 = fmul half %y0, %x1 + ; CHECK: %7 = fmul half %x1, %y0 ; CHECK: %8 = fsub half %6, %7 ; CHECK: %9 = insertelement <3 x half> undef, half %2, i64 0 ; CHECK: %10 = insertelement <3 x half> %9, half %5, i64 1 @@ -34,19 +34,19 @@ entry: define noundef <3 x float> @test_cross_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) { entry: ; CHECK: %x0 = extractelement <3 x float> %p0, i64 0 - ; CHECK: %y0 = extractelement <3 x float> %p0, i64 1 - ; CHECK: %z0 = extractelement <3 x float> %p0, i64 2 - ; CHECK: %x1 = extractelement <3 x float> %p1, i64 0 + ; CHECK: %x1 = extractelement <3 x float> %p0, i64 1 + ; CHECK: %x2 = extractelement <3 x float> %p0, i64 2 + ; CHECK: %y0 = extractelement <3 x float> %p1, i64 0 ; CHECK: %y1 = extractelement <3 x float> %p1, i64 1 - ; CHECK: %z1 = extractelement <3 x float> %p1, i64 2 - ; CHECK: %0 = fmul float %y0, %z1 - ; CHECK: %1 = fmul float %z0, %y1 + ; CHECK: %y2 = extractelement <3 x float> %p1, i64 2 + ; CHECK: %0 = fmul float %x1, %y2 + ; CHECK: %1 = fmul float %x2, %y1 ; CHECK: %2 = fsub float %0, %1 - ; CHECK: %3 = fmul float %z0, %x1 - ; CHECK: %4 = fmul float %x0, %z1 + ; CHECK: %3 = fmul float %x2, %y0 + ; CHECK: %4 = fmul float %x0, %y2 ; CHECK: %5 = fsub float %3, %4 ; CHECK: %6 = fmul float %x0, %y1 - ; CHECK: %7 = fmul float %y0, %x1 + ; CHECK: %7 = fmul float %x1, %y0 ; CHECK: %8 = fsub float %6, %7 ; CHECK: %9 = insertelement <3 x float> undef, float %2, i64 0 ; CHECK: %10 = insertelement <3 x float> %9, float %5, i64 1 >From a8f8faf343e5b21a74b7aa2fdc599a6aab2be28b Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 23 Sep 2024 14:34:07 -0700 Subject: [PATCH 4/9] add more test cases to cross-errors --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaHLSL.cpp | 15 +++++++++++++++ clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl | 12 ++++++++++++ 3 files changed, 29 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ba813af960af6f..55533402b8b8c8 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -312,6 +312,8 @@ def err_invalid_vector_long_double_decl_spec : Error< "cannot use 'long double' with '__vector'">; def err_invalid_vector_complex_decl_spec : Error< "cannot use '_Complex' with '__vector'">; +def err_invalid_vector_size : Error< + "expected vector size of '%0', but vector size is '%1'">; def warn_vector_long_decl_spec_combination : Warning< "use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e7e7a3c259e27a..7c04645700036b 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1711,6 +1711,21 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall)) return true; + // ensure both args have 3 elements + int NumElementsArg1 = + TheCall->getArg(0)->getType()->getAs<VectorType>()->getNumElements(); + int NumElementsArg2 = + TheCall->getArg(1)->getType()->getAs<VectorType>()->getNumElements(); + if (NumElementsArg1 != 3) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_invalid_vector_size) + << NumElementsArg1 << 3; + return true; + } + if (NumElementsArg2 != 3) { + SemaRef.Diag(TheCall->getBeginLoc(), diag::err_invalid_vector_size) + << NumElementsArg2 << 3; + return true; + } ExprResult A = TheCall->getArg(0); QualType ArgTyA = A.get()->getType(); diff --git a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl index 40ab4b533a495e..1bc4f11af70474 100644 --- a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl @@ -29,3 +29,15 @@ bool2 builtin_cross_int2_to_float2_promotion(int2 p1) return __builtin_hlsl_cross(p1, p1); // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} } + +float2 builtin_cross_float2(float2 p1, float2 p2) +{ + return __builtin_hlsl_cross(p1, p2); + // expected-error@-1 {{expected vector size of '2', but vector size is '3'}} +} + +float3 builtin_cross_float3_int3(float3 p1, int3 p2) +{ + return __builtin_hlsl_cross(p1, p2); + // expected-error@-1 {{all arguments to '__builtin_hlsl_cross' must have the same type}} +} >From 32d6add7b32535e5b1ba8fa428faf1cabde94b56 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 23 Sep 2024 16:10:18 -0700 Subject: [PATCH 5/9] drop unneeded check-prefix --- llvm/test/CodeGen/DirectX/cross.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll index 74934a628988c3..3869e5b382713d 100644 --- a/llvm/test/CodeGen/DirectX/cross.ll +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefix=CHECK -; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefix=CHECK +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s ; Make sure dxil operation function calls for cross are generated for half/float. >From c13d2b1218044f01cc6dbc5d92da3335ecbc5fcf Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Tue, 24 Sep 2024 10:03:39 -0700 Subject: [PATCH 6/9] remove an unneeded run --- llvm/test/CodeGen/DirectX/cross.ll | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll index 3869e5b382713d..37fb33e4a9f848 100644 --- a/llvm/test/CodeGen/DirectX/cross.ll +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -1,5 +1,4 @@ ; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s -; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s ; Make sure dxil operation function calls for cross are generated for half/float. >From 81aa399533fa8d71b4f1508b27d03318981794ff Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 30 Sep 2024 13:57:31 -0700 Subject: [PATCH 7/9] update diag message --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++--- clang/lib/Sema/SemaHLSL.cpp | 14 ++++++++++---- clang/lib/Sema/SemaInit.cpp | 2 +- clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1eea8b0ca8f3c2..deabb72ff75396 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -312,8 +312,6 @@ def err_invalid_vector_long_double_decl_spec : Error< "cannot use 'long double' with '__vector'">; def err_invalid_vector_complex_decl_spec : Error< "cannot use '_Complex' with '__vector'">; -def err_invalid_vector_size : Error< - "expected vector size of '%0', but vector size is '%1'">; def warn_vector_long_decl_spec_combination : Warning< "use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; @@ -10508,7 +10506,9 @@ def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_initializers : Error< - "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; + "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; +def err_incorrect_vector_element_count : Error< + err_vector_incorrect_num_initializers.Summary>; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index b867057013bf5f..50bbd6cf680bcf 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1840,14 +1840,20 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall->getArg(0)->getType()->getAs<VectorType>()->getNumElements(); int NumElementsArg2 = TheCall->getArg(1)->getType()->getAs<VectorType>()->getNumElements(); + if (NumElementsArg1 != 3) { - SemaRef.Diag(TheCall->getBeginLoc(), diag::err_invalid_vector_size) - << NumElementsArg1 << 3; + int LessOrMore = NumElementsArg1 > 3 ? 1 : 0; + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_vector_incorrect_num_initializers) + << LessOrMore << 3 << NumElementsArg1 << 1; return true; } if (NumElementsArg2 != 3) { - SemaRef.Diag(TheCall->getBeginLoc(), diag::err_invalid_vector_size) - << NumElementsArg2 << 3; + int LessOrMore = NumElementsArg1 > 3 ? 1 : 0; + + SemaRef.Diag(TheCall->getBeginLoc(), + diag::err_vector_incorrect_num_initializers) + << LessOrMore << 3 << NumElementsArg2 << 1; return true; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 4d11f2a43fcc6b..1d16fe89ab3971 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1977,7 +1977,7 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, if (!VerifyOnly) SemaRef.Diag(IList->getBeginLoc(), diag::err_vector_incorrect_num_initializers) - << (numEltsInit < maxElements) << maxElements << numEltsInit; + << (numEltsInit < maxElements) << maxElements << numEltsInit << 0; hadError = true; } } diff --git a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl index 1bc4f11af70474..d448a964b2f8a9 100644 --- a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl @@ -33,7 +33,7 @@ bool2 builtin_cross_int2_to_float2_promotion(int2 p1) float2 builtin_cross_float2(float2 p1, float2 p2) { return __builtin_hlsl_cross(p1, p2); - // expected-error@-1 {{expected vector size of '2', but vector size is '3'}} + // expected-error@-1 {{too many elements in vector operand (expected 3 elements, have 2)}} } float3 builtin_cross_float3_int3(float3 p1, int3 p2) >From 15defe2cc5a084e5600963fb803f9475b69263ec Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Tue, 1 Oct 2024 13:44:54 -0700 Subject: [PATCH 8/9] use orig name, adjust tests, address feedback --- clang/include/clang/Basic/Builtins.td | 6 --- .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/Sema/SemaHLSL.cpp | 10 ++--- clang/lib/Sema/SemaInit.cpp | 5 ++- clang/test/CodeGenHLSL/builtins/cross.hlsl | 3 +- .../Target/DirectX/DXILIntrinsicExpansion.cpp | 2 +- llvm/test/CodeGen/DirectX/cross.ll | 44 +++++++++---------- 7 files changed, 34 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index d65c450d38a988..f004406a0c51b9 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4709,12 +4709,6 @@ def HLSLClamp : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } -def HLSLCreateHandle : LangBuiltin<"HLSL_LANG"> { - let Spellings = ["__builtin_hlsl_create_handle"]; - let Attributes = [NoThrow, Const]; - let Prototype = "void*(unsigned char)"; -} - def HLSLCross: LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_cross"]; let Attributes = [NoThrow, Const]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index deabb72ff75396..2a10184c5f2552 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10505,10 +10505,8 @@ def err_first_argument_to_cwsc_pdtor_call : Error< def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; -def err_vector_incorrect_num_initializers : Error< +def err_vector_incorrect_num_elements : Error< "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">; -def err_incorrect_vector_element_count : Error< - err_vector_incorrect_num_initializers.Summary>; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 50bbd6cf680bcf..a43cafd9a54911 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1844,16 +1844,16 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (NumElementsArg1 != 3) { int LessOrMore = NumElementsArg1 > 3 ? 1 : 0; SemaRef.Diag(TheCall->getBeginLoc(), - diag::err_vector_incorrect_num_initializers) - << LessOrMore << 3 << NumElementsArg1 << 1; + diag::err_vector_incorrect_num_elements) + << LessOrMore << 3 << NumElementsArg1 << /*operand*/ 1; return true; } if (NumElementsArg2 != 3) { - int LessOrMore = NumElementsArg1 > 3 ? 1 : 0; + int LessOrMore = NumElementsArg2 > 3 ? 1 : 0; SemaRef.Diag(TheCall->getBeginLoc(), - diag::err_vector_incorrect_num_initializers) - << LessOrMore << 3 << NumElementsArg2 << 1; + diag::err_vector_incorrect_num_elements) + << LessOrMore << 3 << NumElementsArg2 << /*operand*/ 1; return true; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1d16fe89ab3971..edd1fe40fdf278 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1976,8 +1976,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, if (numEltsInit != maxElements) { if (!VerifyOnly) SemaRef.Diag(IList->getBeginLoc(), - diag::err_vector_incorrect_num_initializers) - << (numEltsInit < maxElements) << maxElements << numEltsInit << 0; + diag::err_vector_incorrect_num_elements) + << (numEltsInit < maxElements) << maxElements << numEltsInit + << /*initialization*/ 0; hadError = true; } } diff --git a/clang/test/CodeGenHLSL/builtins/cross.hlsl b/clang/test/CodeGenHLSL/builtins/cross.hlsl index 047e7fef7136fe..514e57d36b2016 100644 --- a/clang/test/CodeGenHLSL/builtins/cross.hlsl +++ b/clang/test/CodeGenHLSL/builtins/cross.hlsl @@ -19,8 +19,9 @@ // NATIVE_HALF: define [[FNATTRS]] <3 x half> @ // NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half> -// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float> // NATIVE_HALF: ret <3 x half> %hlsl.cross +// NO_HALF: define [[FNATTRS]] <3 x float> @ +// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float> // NO_HALF: ret <3 x float> %hlsl.cross half3 test_cross_half3(half3 p0, half3 p1) { diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index b0f9aade24cf65..fcfc8cb4faa2f9 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -97,7 +97,7 @@ static Value *expandCrossIntrinsic(CallInst *Orig) { auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * { Value *xy = Builder.CreateFMul(x0, y1); Value *yx = Builder.CreateFMul(y0, x1); - return Builder.CreateFSub(xy, yx); + return Builder.CreateFSub(xy, yx, Orig->getName()); }; Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z); diff --git a/llvm/test/CodeGen/DirectX/cross.ll b/llvm/test/CodeGen/DirectX/cross.ll index 37fb33e4a9f848..6ec3ec4d3594af 100644 --- a/llvm/test/CodeGen/DirectX/cross.ll +++ b/llvm/test/CodeGen/DirectX/cross.ll @@ -15,17 +15,17 @@ entry: ; CHECK: %y2 = extractelement <3 x half> %p1, i64 2 ; CHECK: %0 = fmul half %x1, %y2 ; CHECK: %1 = fmul half %x2, %y1 - ; CHECK: %2 = fsub half %0, %1 - ; CHECK: %3 = fmul half %x2, %y0 - ; CHECK: %4 = fmul half %x0, %y2 - ; CHECK: %5 = fsub half %3, %4 - ; CHECK: %6 = fmul half %x0, %y1 - ; CHECK: %7 = fmul half %x1, %y0 - ; CHECK: %8 = fsub half %6, %7 - ; CHECK: %9 = insertelement <3 x half> undef, half %2, i64 0 - ; CHECK: %10 = insertelement <3 x half> %9, half %5, i64 1 - ; CHECK: %11 = insertelement <3 x half> %10, half %8, i64 2 - ; CHECK: ret <3 x half> %11 + ; CHECK: %hlsl.cross1 = fsub half %0, %1 + ; CHECK: %2 = fmul half %x2, %y0 + ; CHECK: %3 = fmul half %x0, %y2 + ; CHECK: %hlsl.cross2 = fsub half %2, %3 + ; CHECK: %4 = fmul half %x0, %y1 + ; CHECK: %5 = fmul half %x1, %y0 + ; CHECK: %hlsl.cross3 = fsub half %4, %5 + ; CHECK: %6 = insertelement <3 x half> undef, half %hlsl.cross1, i64 0 + ; CHECK: %7 = insertelement <3 x half> %6, half %hlsl.cross2, i64 1 + ; CHECK: %8 = insertelement <3 x half> %7, half %hlsl.cross3, i64 2 + ; CHECK: ret <3 x half> %8 %hlsl.cross = call <3 x half> @llvm.dx.cross.v3f16(<3 x half> %p0, <3 x half> %p1) ret <3 x half> %hlsl.cross } @@ -40,17 +40,17 @@ entry: ; CHECK: %y2 = extractelement <3 x float> %p1, i64 2 ; CHECK: %0 = fmul float %x1, %y2 ; CHECK: %1 = fmul float %x2, %y1 - ; CHECK: %2 = fsub float %0, %1 - ; CHECK: %3 = fmul float %x2, %y0 - ; CHECK: %4 = fmul float %x0, %y2 - ; CHECK: %5 = fsub float %3, %4 - ; CHECK: %6 = fmul float %x0, %y1 - ; CHECK: %7 = fmul float %x1, %y0 - ; CHECK: %8 = fsub float %6, %7 - ; CHECK: %9 = insertelement <3 x float> undef, float %2, i64 0 - ; CHECK: %10 = insertelement <3 x float> %9, float %5, i64 1 - ; CHECK: %11 = insertelement <3 x float> %10, float %8, i64 2 - ; CHECK: ret <3 x float> %11 + ; CHECK: %hlsl.cross1 = fsub float %0, %1 + ; CHECK: %2 = fmul float %x2, %y0 + ; CHECK: %3 = fmul float %x0, %y2 + ; CHECK: %hlsl.cross2 = fsub float %2, %3 + ; CHECK: %4 = fmul float %x0, %y1 + ; CHECK: %5 = fmul float %x1, %y0 + ; CHECK: %hlsl.cross3 = fsub float %4, %5 + ; CHECK: %6 = insertelement <3 x float> undef, float %hlsl.cross1, i64 0 + ; CHECK: %7 = insertelement <3 x float> %6, float %hlsl.cross2, i64 1 + ; CHECK: %8 = insertelement <3 x float> %7, float %hlsl.cross3, i64 2 + ; CHECK: ret <3 x float> %8 %hlsl.cross = call <3 x float> @llvm.dx.cross.v3f32(<3 x float> %p0, <3 x float> %p1) ret <3 x float> %hlsl.cross } >From 514c40bdffe65b1a153090da02cd2e90a981a3cf Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Wed, 2 Oct 2024 14:44:03 -0700 Subject: [PATCH 9/9] remove unneeded flag, update code with latest main --- clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl | 4 ++-- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl index d448a964b2f8a9..423f5bac9471f4 100644 --- a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify void test_too_few_arg() { @@ -15,7 +15,7 @@ void test_too_many_arg(float3 p0) bool builtin_bool_to_float_type_promotion(bool p1) { return __builtin_hlsl_cross(p1, p1); - // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} + // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}} } bool builtin_cross_int_to_float_promotion(int p1) diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index efe19f5a8370e5..0567efd8a5d7af 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -61,6 +61,7 @@ let TargetPrefix = "spv" in { def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; + def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>], [IntrNoMem] >; diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index a6f85ca3a5ce2f..3917ad180b87fc 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -2502,7 +2502,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, case Intrinsic::spv_any: return selectAny(ResVReg, ResType, I); case Intrinsic::spv_cross: - return selectCross(ResVReg, ResType, I); + return selectExtInst(ResVReg, ResType, I, CL::cross, GL::Cross); case Intrinsic::spv_lerp: return selectExtInst(ResVReg, ResType, I, CL::mix, GL::FMix); case Intrinsic::spv_length: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits