Skip to content

Commit 4f5eaa1

Browse files
authored
merge main into amd-staging (#635)
2 parents 913ae1c + 16790ef commit 4f5eaa1

File tree

102 files changed

+3126
-1390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+3126
-1390
lines changed

.git-blame-ignore-revs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,12 @@ a3a007ad5fa20abc90ead4e1030b481bf109b4cf
143143
b7e332d3f59f567b1999fbcc660d7837cba8e406
144144
6056f942abe83b05406df8b04e95ec37a3d160b5
145145
906295b8a31c8dac5aa845864c0bca9f02f86184
146+
147+
# [clang-tidy][NFC] Remove trailing whitespaces in documentation
148+
8f2b167de4a1268160c06512d08863a9e8f43290
149+
150+
# [clang-tidy][NFC] Enforce 80 characters limit in docs
151+
5edf70c41c5d69f3751b4199f642f4585599dade
152+
c73870dbe89a8219130e21a0b3f13df76d299352
153+
74c40293c309dbd142bf1f0ebfbfde6be8d30655
154+
a7ba8dcad76476478100c228a31d9c48391b1e03

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,10 @@ Improvements to Clang's diagnostics
684684
- Clang no longer emits ``-Wmissing-noreturn`` for virtual methods where
685685
the function body consists of a `throw` expression (#GH167247).
686686

687+
- A new warning ``-Wenum-compare-typo`` has been added to detect potential erroneous
688+
comparison operators when mixed with bitwise operators in enum value initializers.
689+
This can be locally disabled by explicitly casting the initializer value.
690+
687691
Improvements to Clang's time-trace
688692
----------------------------------
689693

clang/include/clang/Basic/BuiltinsSPIRVVK.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ include "clang/Basic/BuiltinsSPIRVBase.td"
1212
def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
1313
def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
1414
def refract : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
15+
def fwidth : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13760,4 +13760,12 @@ def note_amdgcn_protected_by_predicate : Note<"jump enters statement controlled"
1376013760
" by AMDGPU feature predicate">;
1376113761

1376213762
def err_amdgcn_coop_atomic_invalid_as : Error<"cooperative atomic requires a global or generic pointer">;
13763+
13764+
def warn_comparison_in_enum_initializer : Warning<
13765+
"comparison operator '%0' is potentially a typo for a shift operator '%1'">,
13766+
InGroup<DiagGroup<"enum-compare-typo">>;
13767+
13768+
def note_enum_compare_typo_suggest : Note<
13769+
"use '%0' to perform a bitwise shift">;
13770+
1376313771
} // end of sema component.

clang/lib/CodeGen/TargetBuiltins/SPIR.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
151151
Intrinsic::spv_global_offset,
152152
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
153153
"spv.global.offset");
154+
case SPIRV::BI__builtin_spirv_fwidth:
155+
return Builder.CreateIntrinsic(
156+
/*ReturnType=*/getTypes().ConvertType(E->getType()),
157+
Intrinsic::spv_fwidth, ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))},
158+
nullptr, "spv.fwidth");
154159
}
155160
return nullptr;
156161
}

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ constexpr K firstbithigh_impl(T X) {
160160
return FBH;
161161
}
162162

163+
template <typename T> constexpr T fwidth_impl(T input) {
164+
#if (__has_builtin(__builtin_spirv_fwidth))
165+
return __builtin_spirv_fwidth(input);
166+
#else
167+
T derivCoarseX = ddx_coarse(input);
168+
derivCoarseX = abs(derivCoarseX);
169+
T derivCoarseY = ddy_coarse(input);
170+
derivCoarseY = abs(derivCoarseY);
171+
return derivCoarseX + derivCoarseY;
172+
#endif
173+
}
174+
163175
} // namespace __detail
164176
} // namespace hlsl
165177

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,5 +666,45 @@ smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
666666
return __detail::smoothstep_vec_impl(Min, Max, X);
667667
}
668668

669+
//===----------------------------------------------------------------------===//
670+
// fwidth builtin
671+
//===----------------------------------------------------------------------===//
672+
673+
/// \fn T fwidth(T x)
674+
/// \brief Computes the sum of the absolute values of the partial derivatives
675+
/// with regard to the x and y screen space coordinates.
676+
/// \param x [in] The floating-point scalar or vector to process.
677+
///
678+
/// The return value is a floating-point scalar or vector where each element
679+
/// holds the computation of the matching element in the input.
680+
681+
template <typename T>
682+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
683+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
684+
__detail::is_same<half, T>::value,
685+
T> fwidth(T input) {
686+
return __detail::fwidth_impl(input);
687+
}
688+
689+
template <typename T>
690+
const inline __detail::enable_if_t<
691+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
692+
fwidth(T input) {
693+
return __detail::fwidth_impl(input);
694+
}
695+
696+
template <int N>
697+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
698+
const inline __detail::HLSL_FIXED_VECTOR<half, N> fwidth(
699+
__detail::HLSL_FIXED_VECTOR<half, N> input) {
700+
return __detail::fwidth_impl(input);
701+
}
702+
703+
template <int N>
704+
const inline __detail::HLSL_FIXED_VECTOR<float, N>
705+
fwidth(__detail::HLSL_FIXED_VECTOR<float, N> input) {
706+
return __detail::fwidth_impl(input);
707+
}
708+
669709
} // namespace hlsl
670710
#endif //_HLSL_HLSL_INTRINSICS_H_

clang/lib/Sema/SemaDecl.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "llvm/ADT/SmallPtrSet.h"
6464
#include "llvm/ADT/SmallString.h"
6565
#include "llvm/ADT/StringExtras.h"
66+
#include "llvm/ADT/StringRef.h"
6667
#include "llvm/Support/SaveAndRestore.h"
6768
#include "llvm/TargetParser/Triple.h"
6869
#include <algorithm>
@@ -20637,6 +20638,59 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
2063720638
return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
2063820639
}
2063920640

20641+
// Emits a warning when a suspicious comparison operator is used along side
20642+
// binary operators in enum initializers.
20643+
static void CheckForComparisonInEnumInitializer(SemaBase &Sema,
20644+
const EnumDecl *Enum) {
20645+
bool HasBitwiseOp = false;
20646+
SmallVector<const BinaryOperator *, 4> SuspiciousCompares;
20647+
20648+
// Iterate over all the enum values, gather suspisious comparison ops and
20649+
// whether any enum initialisers contain a binary operator.
20650+
for (const auto *ECD : Enum->enumerators()) {
20651+
const Expr *InitExpr = ECD->getInitExpr();
20652+
if (!InitExpr)
20653+
continue;
20654+
20655+
const Expr *E = InitExpr->IgnoreParenImpCasts();
20656+
20657+
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
20658+
BinaryOperatorKind Op = BinOp->getOpcode();
20659+
20660+
// Check for bitwise ops (<<, >>, &, |)
20661+
if (BinOp->isBitwiseOp() || BinOp->isShiftOp()) {
20662+
HasBitwiseOp = true;
20663+
} else if (Op == BO_LT || Op == BO_GT) {
20664+
// Check for the typo pattern (Comparison < or >)
20665+
const Expr *LHS = BinOp->getLHS()->IgnoreParenImpCasts();
20666+
if (const auto *IntLiteral = dyn_cast<IntegerLiteral>(LHS)) {
20667+
// Specifically looking for accidental bitshifts "1 < X" or "1 > X"
20668+
if (IntLiteral->getValue() == 1)
20669+
SuspiciousCompares.push_back(BinOp);
20670+
}
20671+
}
20672+
}
20673+
}
20674+
20675+
// If we found a bitwise op and some sus compares, iterate over the compares
20676+
// and warn.
20677+
if (HasBitwiseOp) {
20678+
for (const auto *BinOp : SuspiciousCompares) {
20679+
StringRef SuggestedOp = (BinOp->getOpcode() == BO_LT)
20680+
? BinaryOperator::getOpcodeStr(BO_Shl)
20681+
: BinaryOperator::getOpcodeStr(BO_Shr);
20682+
SourceLocation OperatorLoc = BinOp->getOperatorLoc();
20683+
20684+
Sema.Diag(OperatorLoc, diag::warn_comparison_in_enum_initializer)
20685+
<< BinOp->getOpcodeStr() << SuggestedOp;
20686+
20687+
Sema.Diag(OperatorLoc, diag::note_enum_compare_typo_suggest)
20688+
<< SuggestedOp
20689+
<< FixItHint::CreateReplacement(OperatorLoc, SuggestedOp);
20690+
}
20691+
}
20692+
}
20693+
2064020694
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2064120695
Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
2064220696
const ParsedAttributesView &Attrs) {
@@ -20774,6 +20828,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2077420828
NumPositiveBits, NumNegativeBits);
2077520829

2077620830
CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
20831+
CheckForComparisonInEnumInitializer(*this, Enum);
2077720832

2077820833
if (Enum->isClosedFlag()) {
2077920834
for (Decl *D : Elements) {

clang/lib/Sema/SemaSPIRV.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,24 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI,
360360
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
361361
return checkGenericCastToPtr(SemaRef, TheCall);
362362
}
363+
case SPIRV::BI__builtin_spirv_fwidth: {
364+
if (SemaRef.checkArgCount(TheCall, 1))
365+
return true;
366+
367+
// Check if first argument has floating representation
368+
ExprResult A = TheCall->getArg(0);
369+
QualType ArgTyA = A.get()->getType();
370+
if (!ArgTyA->hasFloatingRepresentation()) {
371+
SemaRef.Diag(A.get()->getBeginLoc(), diag::err_builtin_invalid_arg_type)
372+
<< /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
373+
<< /* fp */ 1 << ArgTyA;
374+
return true;
375+
}
376+
377+
QualType RetTy = ArgTyA;
378+
TheCall->setType(RetTy);
379+
break;
380+
}
363381
}
364382
return false;
365383
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
2+
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
3+
// RUN: FileCheck %s --check-prefixes=CHECK
4+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-unknown-vulkan1.3-library %s \
5+
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
6+
// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
7+
8+
// CHECK-LABEL: define {{.*}} half @_ZN4hlsl8__detail11fwidth_implIDhEET_S2_
9+
// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
10+
// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
11+
// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
12+
// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
13+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
14+
// CHECK: ret half %{{.*}}
15+
// CHECK-LABEL-SPIRV: half @_Z15test_f16_fwidthDh
16+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} half @llvm.spv.fwidth.f16(half %{{.*}})
17+
// CHECK-SPIRV: ret half %spv.fwidth
18+
half test_f16_fwidth(half val) {
19+
return fwidth(val);
20+
}
21+
22+
// CHECK-LABEL: define {{.*}} <2 x half> @_ZN4hlsl8__detail11fwidth_implIDv2_DhEET_S3_
23+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
24+
// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
25+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
26+
// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
27+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
28+
// CHECK: ret <2 x half> %{{.*}}
29+
// CHECK-LABEL-SPIRV: <2 x half> @_Z16test_f16_fwidth2Dv2_Dh
30+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x half> @llvm.spv.fwidth.v2f16(<2 x half> %{{.*}})
31+
// CHECK-SPIRV: ret <2 x half> %spv.fwidth
32+
half2 test_f16_fwidth2(half2 val) {
33+
return fwidth(val);
34+
}
35+
36+
// CHECK-LABEL: define {{.*}} <3 x half> @_ZN4hlsl8__detail11fwidth_implIDv3_DhEET_S3_
37+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
38+
// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
39+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
40+
// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
41+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
42+
// CHECK: ret <3 x half> %{{.*}}
43+
// CHECK-LABEL-SPIRV: <3 x half> @_Z16test_f16_fwidth3Dv3_Dh
44+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x half> @llvm.spv.fwidth.v3f16(<3 x half> %{{.*}})
45+
// CHECK-SPIRV: ret <3 x half> %spv.fwidth
46+
half3 test_f16_fwidth3(half3 val) {
47+
return fwidth(val);
48+
}
49+
50+
// CHECK-LABEL: define {{.*}} <4 x half> @_ZN4hlsl8__detail11fwidth_implIDv4_DhEET_S3_
51+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
52+
// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
53+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
54+
// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
55+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
56+
// CHECK: ret <4 x half> %{{.*}}
57+
// CHECK-LABEL-SPIRV: <4 x half> @_Z16test_f16_fwidth4Dv4_Dh
58+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x half> @llvm.spv.fwidth.v4f16(<4 x half> %{{.*}})
59+
// CHECK-SPIRV: ret <4 x half> %spv.fwidth
60+
half4 test_f16_fwidth4(half4 val) {
61+
return fwidth(val);
62+
}
63+
64+
// CHECK-LABEL: define {{.*}} float @_ZN4hlsl8__detail11fwidth_implIfEET_S2_
65+
// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
66+
// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
67+
// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
68+
// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
69+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
70+
// CHECK: ret float %{{.*}}
71+
// CHECK-LABEL-SPIRV: float @_Z15test_f32_fwidthf
72+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} float @llvm.spv.fwidth.f32(float %{{.*}})
73+
// CHECK-SPIRV: ret float %spv.fwidth
74+
float test_f32_fwidth(float val) {
75+
return fwidth(val);
76+
}
77+
78+
// CHECK-LABEL: define {{.*}} <2 x float> @_ZN4hlsl8__detail11fwidth_implIDv2_fEET_S3_
79+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
80+
// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
81+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
82+
// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
83+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
84+
// CHECK: ret <2 x float> %{{.*}}
85+
// CHECK-LABEL-SPIRV: <2 x float> @_Z16test_f32_fwidth2Dv2_f
86+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x float> @llvm.spv.fwidth.v2f32(<2 x float> %{{.*}})
87+
// CHECK-SPIRV: ret <2 x float> %spv.fwidth
88+
float2 test_f32_fwidth2(float2 val) {
89+
return fwidth(val);
90+
}
91+
92+
// CHECK-LABEL: define {{.*}} <3 x float> @_ZN4hlsl8__detail11fwidth_implIDv3_fEET_S3_
93+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
94+
// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
95+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
96+
// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
97+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
98+
// CHECK: ret <3 x float> %{{.*}}
99+
// CHECK-LABEL-SPIRV: <3 x float> @_Z16test_f32_fwidth3Dv3_f
100+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x float> @llvm.spv.fwidth.v3f32(<3 x float> %{{.*}})
101+
// CHECK-SPIRV: ret <3 x float> %spv.fwidth
102+
float3 test_f32_fwidth3(float3 val) {
103+
return fwidth(val);
104+
}
105+
106+
// CHECK-LABEL: define {{.*}} <4 x float> @_ZN4hlsl8__detail11fwidth_implIDv4_fEET_S3_
107+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
108+
// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
109+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
110+
// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
111+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
112+
// CHECK: ret <4 x float> %{{.*}}
113+
// CHECK-LABEL-SPIRV: <4 x float> @_Z16test_f32_fwidth4Dv4_f
114+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x float> @llvm.spv.fwidth.v4f32(<4 x float> %{{.*}})
115+
// CHECK-SPIRV: ret <4 x float> %spv.fwidth
116+
float4 test_f32_fwidth4(float4 val) {
117+
return fwidth(val);
118+
}

0 commit comments

Comments
 (0)