Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/new-prs-labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,11 @@ backend:DirectX:

backend:SPIR-V:
- clang/lib/Driver/ToolChains/SPIRV.*
- clang/lib/Sema/SemaSPIRV.cpp
- clang/include/clang/Sema/SemaSPIRV.h
- clang/include/clang/Basic/BuiltinsSPIRV.td
- clang/test/CodeGenSPIRV/**
- clang/test/SemaSPIRV/**
- llvm/lib/Target/SPIRV/**
- llvm/test/CodeGen/SPIRV/**
- llvm/test/Frontend/HLSL/**
Expand Down
15 changes: 15 additions & 0 deletions clang/include/clang/Basic/BuiltinsSPIRV.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//===--- BuiltinsSPIRV.td - SPIRV Builtin function database ---------*- C++ -*-===//
//
// 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/BuiltinsBase.td"

def HLSLDistance : Builtin {
let Spellings = ["__builtin_spirv_distance"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins
SOURCE BuiltinsRISCV.td
TARGET ClangBuiltinsRISCV)

clang_tablegen(BuiltinsSPIRV.inc -gen-clang-builtins
SOURCE BuiltinsSPIRV.td
TARGET ClangBuiltinsSPIRV)

clang_tablegen(BuiltinsX86.inc -gen-clang-builtins
SOURCE BuiltinsX86.td
TARGET ClangBuiltinsX86)
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/TargetBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ namespace clang {
};
}

/// SPIRV builtins
namespace SPIRV {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsSPIRV.inc"
LastTSBuiltin
};
} // namespace SPIRV

/// X86 builtins
namespace X86 {
enum {
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class SemaOpenMP;
class SemaPPC;
class SemaPseudoObject;
class SemaRISCV;
class SemaSPIRV;
class SemaSYCL;
class SemaSwift;
class SemaSystemZ;
Expand Down Expand Up @@ -1142,6 +1143,11 @@ class Sema final : public SemaBase {
return *RISCVPtr;
}

SemaSPIRV &SPIRV() {
assert(SPIRVPtr);
return *SPIRVPtr;
}

SemaSYCL &SYCL() {
assert(SYCLPtr);
return *SYCLPtr;
Expand Down Expand Up @@ -1219,6 +1225,7 @@ class Sema final : public SemaBase {
std::unique_ptr<SemaPPC> PPCPtr;
std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
std::unique_ptr<SemaRISCV> RISCVPtr;
std::unique_ptr<SemaSPIRV> SPIRVPtr;
std::unique_ptr<SemaSYCL> SYCLPtr;
std::unique_ptr<SemaSwift> SwiftPtr;
std::unique_ptr<SemaSystemZ> SystemZPtr;
Expand Down
29 changes: 29 additions & 0 deletions clang/include/clang/Sema/SemaSPIRV.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----- SemaSPIRV.h ----- Semantic Analysis for SPIRV constructs
//---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file declares semantic analysis for SPIRV constructs.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_SEMASPIRV_H
#define LLVM_CLANG_SEMA_SEMASPIRV_H

#include "clang/AST/ASTFwd.h"
#include "clang/Sema/SemaBase.h"

namespace clang {
class SemaSPIRV : public SemaBase {
public:
SemaSPIRV(Sema &S);

bool CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang

#endif // LLVM_CLANG_SEMA_SEMASPIRV_H
13 changes: 13 additions & 0 deletions clang/lib/Basic/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,24 @@
#include "SPIR.h"
#include "AMDGPU.h"
#include "Targets.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/TargetParser/TargetParser.h"

using namespace clang;
using namespace clang::targets;

static constexpr Builtin::Info BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
#include "clang/Basic/BuiltinsSPIRV.inc"
};

ArrayRef<Builtin::Info> SPIRVTargetInfo::getTargetBuiltins() const {
return llvm::ArrayRef(BuiltinInfo,
clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin);
}

void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
DefineStd(Builder, "SPIR", Opts);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

ArrayRef<Builtin::Info> getTargetBuiltins() const override;
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
};
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6757,6 +6757,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
case llvm::Triple::spirv:
return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@farzonl @michalpaszkowski I wonder should we extend this new approach to OpenCL as well?

case llvm::Triple::spirv64:
if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
return nullptr;
Expand Down Expand Up @@ -20440,6 +20442,26 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
}
}

Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
switch (BuiltinID) {
case SPIRV::BI__builtin_spirv_distance: {
Value *X = EmitScalarExpr(E->getArg(0));
Value *Y = EmitScalarExpr(E->getArg(1));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
E->getArg(1)->getType()->hasFloatingRepresentation() &&
"Distance operands must have a float representation");
assert(E->getArg(0)->getType()->isVectorType() &&
E->getArg(1)->getType()->isVectorType() &&
"Distance operands must be a vector");
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance,
ArrayRef<Value *>{X, Y}, nullptr, "spv.distance");
}
}
return nullptr;
}

/// Handle a SystemZ function in which the final argument is a pointer
/// to an int that receives the post-instruction CC value. At the LLVM level
/// this is represented as a function that returns a {result, cc} pair.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4756,6 +4756,7 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue);
llvm::Value *EmitSPIRVBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitScalarOrConstFoldImmArg(unsigned ICEArguments, unsigned Idx,
const CallExpr *E);
llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ add_clang_library(clangSema
SemaStmt.cpp
SemaStmtAsm.cpp
SemaStmtAttr.cpp
SemaSPIRV.cpp
SemaSYCL.cpp
SemaSwift.cpp
SemaSystemZ.cpp
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaSystemZ.h"
Expand Down Expand Up @@ -239,6 +240,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
PPCPtr(std::make_unique<SemaPPC>(*this)),
PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)),
RISCVPtr(std::make_unique<SemaRISCV>(*this)),
SPIRVPtr(std::make_unique<SemaSPIRV>(*this)),
SYCLPtr(std::make_unique<SemaSYCL>(*this)),
SwiftPtr(std::make_unique<SemaSwift>(*this)),
SystemZPtr(std::make_unique<SemaSystemZ>(*this)),
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
Expand Down Expand Up @@ -1934,6 +1935,8 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::spirv:
return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::systemz:
return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::x86:
Expand Down
59 changes: 59 additions & 0 deletions clang/lib/Sema/SemaSPIRV.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===- SemaSPIRV.cpp - Semantic Analysis for SPIRV constructs
//---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This implements Semantic Analysis for SPIRV constructs.
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaSPIRV.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Sema/Sema.h"

namespace clang {

SemaSPIRV::SemaSPIRV(Sema &S) : SemaBase(S) {}

bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
// position of memory order and scope arguments in the builtin
switch (BuiltinID) {
case SPIRV::BI__builtin_spirv_distance: {
if (SemaRef.checkArgCount(TheCall, 2))
return true;

ExprResult A = TheCall->getArg(0);
QualType ArgTyA = A.get()->getType();
auto *VTyA = ArgTyA->getAs<VectorType>();
if (VTyA == nullptr) {
SemaRef.Diag(A.get()->getBeginLoc(),
diag::err_typecheck_convert_incompatible)
<< ArgTyA
<< SemaRef.Context.getVectorType(ArgTyA, 2, VectorKind::Generic) << 1
<< 0 << 0;
return true;
}

ExprResult B = TheCall->getArg(1);
QualType ArgTyB = B.get()->getType();
auto *VTyB = ArgTyB->getAs<VectorType>();
if (VTyB == nullptr) {
SemaRef.Diag(A.get()->getBeginLoc(),
diag::err_typecheck_convert_incompatible)
<< ArgTyB
<< SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1
<< 0 << 0;
return true;
}

QualType RetTy = VTyA->getElementType();
TheCall->setType(RetTy);
break;
}
}
return false;
}
} // namespace clang
31 changes: 31 additions & 0 deletions clang/test/CodeGenSPIRV/Builtins/distance.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5

// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s

typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));

// CHECK-LABEL: define spir_func float @test_distance_float2(
// CHECK-SAME: <2 x float> noundef [[X:%.*]], <2 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
// CHECK-NEXT: ret float [[SPV_DISTANCE]]
//
float test_distance_float2(float2 X, float2 Y) { return __builtin_spirv_distance(X, Y); }

// CHECK-LABEL: define spir_func float @test_distance_float3(
// CHECK-SAME: <3 x float> noundef [[X:%.*]], <3 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v3f32(<3 x float> [[X]], <3 x float> [[Y]])
// CHECK-NEXT: ret float [[SPV_DISTANCE]]
//
float test_distance_float3(float3 X, float3 Y) { return __builtin_spirv_distance(X, Y); }

// CHECK-LABEL: define spir_func float @test_distance_float4(
// CHECK-SAME: <4 x float> noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v4f32(<4 x float> [[X]], <4 x float> [[Y]])
// CHECK-NEXT: ret float [[SPV_DISTANCE]]
//
float test_distance_float4(float4 X, float4 Y) { return __builtin_spirv_distance(X, Y); }
23 changes: 23 additions & 0 deletions clang/test/SemaSPIRV/BuiltIns/distance-errors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify

typedef float float2 __attribute__((ext_vector_type(2)));

float test_no_second_arg(float2 p0) {
return __builtin_spirv_distance(p0);
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
}

float test_too_many_arg(float2 p0) {
return __builtin_spirv_distance(p0, p0, p0);
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
}

float test_double_scalar_inputs(double p0, double p1) {
return __builtin_spirv_distance(p0, p1);
// expected-error@-1 {{passing 'double' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(double)))) double' (vector of 2 'double' values)}}
}

float test_int_scalar_inputs(int p0, int p1) {
return __builtin_spirv_distance(p0, p1);
// expected-error@-1 {{passing 'int' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}}
}
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/IntrinsicsSPIRV.td
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ let TargetPrefix = "spv" in {
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_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty, 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] >;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2906,6 +2906,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
return selectAny(ResVReg, ResType, I);
case Intrinsic::spv_cross:
return selectExtInst(ResVReg, ResType, I, CL::cross, GL::Cross);
case Intrinsic::spv_distance:
return selectExtInst(ResVReg, ResType, I, CL::distance, GL::Distance);
case Intrinsic::spv_lerp:
return selectExtInst(ResVReg, ResType, I, CL::mix, GL::FMix);
case Intrinsic::spv_length:
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/distance.ll
Original file line number Diff line number Diff line change
@@ -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 distance are lowered correctly.

; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4

define noundef half @distance_half4(<4 x half> noundef %a, <4 x half> noundef %b) {
entry:
; CHECK: %[[#]] = OpFunction %[[#float_16]] None %[[#]]
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Distance %[[#arg0]] %[[#arg1]]
%spv.distance = call half @llvm.spv.distance.f16(<4 x half> %a, <4 x half> %b)
ret half %spv.distance
}

define noundef float @distance_float4(<4 x float> noundef %a, <4 x float> noundef %b) {
entry:
; CHECK: %[[#]] = OpFunction %[[#float_32]] None %[[#]]
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Distance %[[#arg0]] %[[#arg1]]
%spv.distance = call float @llvm.spv.distance.f32(<4 x float> %a, <4 x float> %b)
ret float %spv.distance
}

declare half @llvm.spv.distance.f16(<4 x half>, <4 x half>)
declare float @llvm.spv.distance.f32(<4 x float>, <4 x float>)
Loading
Loading