Skip to content

Commit 589e1c7

Browse files
authored
[HLSL] Add support for modulo of floating point scalar and vectors (llvm#135125)
fixes llvm#135122 SemaExpr.cpp - Make all doubles fail. Add sema support for float scalars and vectors when language mode is HLSL. CGExprScalar.cpp - Allow emit frem when language mode is HLSL.
1 parent 755016a commit 589e1c7

File tree

4 files changed

+181
-5
lines changed

4 files changed

+181
-5
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,8 +3964,11 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
39643964

39653965
if (Ops.Ty->hasUnsignedIntegerRepresentation())
39663966
return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem");
3967-
else
3968-
return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem");
3967+
3968+
if (CGF.getLangOpts().HLSL && Ops.Ty->hasFloatingRepresentation())
3969+
return Builder.CreateFRem(Ops.LHS, Ops.RHS, "rem");
3970+
3971+
return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem");
39693972
}
39703973

39713974
Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {

clang/lib/Sema/SemaExpr.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10695,10 +10695,30 @@ QualType Sema::CheckRemainderOperands(
1069510695
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
1069610696
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
1069710697

10698+
// Note: This check is here to simplify the double exclusions of
10699+
// scalar and vector HLSL checks. No getLangOpts().HLSL
10700+
// is needed since all languages exlcude doubles.
10701+
if (LHS.get()->getType()->isDoubleType() ||
10702+
RHS.get()->getType()->isDoubleType() ||
10703+
(LHS.get()->getType()->isVectorType() && LHS.get()
10704+
->getType()
10705+
->getAs<VectorType>()
10706+
->getElementType()
10707+
->isDoubleType()) ||
10708+
(RHS.get()->getType()->isVectorType() && RHS.get()
10709+
->getType()
10710+
->getAs<VectorType>()
10711+
->getElementType()
10712+
->isDoubleType()))
10713+
return InvalidOperands(Loc, LHS, RHS);
10714+
1069810715
if (LHS.get()->getType()->isVectorType() ||
1069910716
RHS.get()->getType()->isVectorType()) {
10700-
if (LHS.get()->getType()->hasIntegerRepresentation() &&
10701-
RHS.get()->getType()->hasIntegerRepresentation())
10717+
if ((LHS.get()->getType()->hasIntegerRepresentation() &&
10718+
RHS.get()->getType()->hasIntegerRepresentation()) ||
10719+
(getLangOpts().HLSL &&
10720+
(LHS.get()->getType()->hasFloatingRepresentation() ||
10721+
RHS.get()->getType()->hasFloatingRepresentation())))
1070210722
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
1070310723
/*AllowBothBool*/ getLangOpts().AltiVec,
1070410724
/*AllowBoolConversions*/ false,
@@ -10722,7 +10742,9 @@ QualType Sema::CheckRemainderOperands(
1072210742
if (LHS.isInvalid() || RHS.isInvalid())
1072310743
return QualType();
1072410744

10725-
if (compType.isNull() || !compType->isIntegerType())
10745+
if (compType.isNull() ||
10746+
(!compType->isIntegerType() &&
10747+
!(getLangOpts().HLSL && compType->isFloatingType())))
1072610748
return InvalidOperands(Loc, LHS, RHS);
1072710749
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
1072810750
return compType;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \
2+
// RUN: -fnative-half-type -emit-llvm -disable-llvm-passes -o - | \
3+
// RUN: FileCheck %s
4+
// RUN: %clang_cc1 -finclude-default-header -triple spirv-unknown-vulkan-compute %s \
5+
// RUN: -fnative-half-type -emit-llvm -disable-llvm-passes -o - | \
6+
// RUN: FileCheck %s
7+
8+
half2 half_vec_mod_by_int(half2 p1) {
9+
// CHECK-LABEL: half_vec_mod_by_int
10+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, splat (half 0xH4000)
11+
return p1 % 2;
12+
}
13+
14+
half2 half_vec_mod_by_float(half2 p1) {
15+
// CHECK-LABEL: half_vec_mod_by_float
16+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, splat (half 0xH4000)
17+
return p1 % (half)2.0;
18+
}
19+
20+
half2 half_vec_mod_by_half(half2 p1, half p2 ) {
21+
// CHECK-LABEL: half_vec_mod_by_half
22+
// CHECK: %splat.splatinsert = insertelement <2 x half> poison, half %{{.*}}, i64 0
23+
// CHECK: %splat.splat = shufflevector <2 x half> %splat.splatinsert, <2 x half> poison, <2 x i32> zeroinitializer
24+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, %splat.splat
25+
return p1 % p2;
26+
}
27+
28+
half2 half_vec_mod_by_half_vec(half2 p1, half2 p2 ) {
29+
// CHECK-LABEL: half_vec_mod_by_half_vec
30+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}, %{{.*}}
31+
return p1 % p2;
32+
}
33+
34+
half half_vec_mod_by_int(half p1) {
35+
// CHECK-LABEL: half_vec_mod_by_int
36+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn half %{{.*}}, 0xH4000
37+
return p1 % 2;
38+
}
39+
40+
half half_mod_by_float(half p1) {
41+
// CHECK-LABEL: half_mod_by_float
42+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn half %{{.*}}, 0xH4000
43+
return p1 % (half)2.0;
44+
}
45+
46+
half half_mod_by_half(half p1, half p2 ) {
47+
// CHECK-LABEL: half_mod_by_half
48+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}}
49+
return p1 % p2;
50+
}
51+
52+
half half_mod_by_half_vec(half p1, half2 p2 ) {
53+
// CHECK-LABEL: half_mod_by_half_vec
54+
// CHECK: %splat.splatinsert = insertelement <2 x half> poison, half %{{.*}}, i64 0
55+
// CHECK: %splat.splat = shufflevector <2 x half> %splat.splatinsert, <2 x half> poison, <2 x i32> zeroinitializer
56+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x half> %splat.splat, %{{.*}}
57+
return p1 % p2;
58+
}
59+
60+
float2 float_vec_mod_by_int(float2 p1) {
61+
// CHECK-LABEL: float_vec_mod_by_int
62+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, splat (float 2.000000e+00)
63+
return p1 % 2;
64+
}
65+
66+
float2 float_vec_mod_by_float_const(float2 p1) {
67+
// CHECK-LABEL: float_vec_mod_by_float_const
68+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, splat (float 2.000000e+00)
69+
return p1 % 2.0;
70+
}
71+
72+
float2 float_vec_mod_by_float(float2 p1, float p2 ) {
73+
// CHECK-LABEL: float_vec_mod_by_float
74+
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %{{.*}}, i64 0
75+
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
76+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, %splat.splat
77+
return p1 % p2;
78+
}
79+
80+
float2 float_vec_mod_by_float_vec(float2 p1, float2 p2 ) {
81+
// CHECK-LABEL: float_vec_mod_by_float_vec
82+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}, %{{.*}}
83+
return p1 % p2;
84+
}
85+
86+
float float_mod_by_int(float p1) {
87+
// CHECK-LABEL: float_mod_by_int
88+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn float %{{.*}}, 2.000000e+00
89+
return p1 % 2;
90+
}
91+
92+
float float_mod_by_float_const(float p1) {
93+
// CHECK-LABEL: float_mod_by_float_const
94+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn float %{{.*}}, 2.000000e+00
95+
return p1 % 2.0;
96+
}
97+
98+
float float_mod_by_float(float p1, float p2 ) {
99+
// CHECK-LABEL: float_mod_by_float
100+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}}
101+
return p1 % p2;
102+
}
103+
104+
float float_mod_by_float_vec(float p1, float2 p2 ) {
105+
// CHECK-LABEL: float_mod_by_float_vec
106+
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %{{.*}}, i64 0
107+
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
108+
// CHECK: %rem = frem reassoc nnan ninf nsz arcp afn <2 x float> %splat.splat, %{{.*}}
109+
return p1 % p2;
110+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify
2+
3+
export double2 double_vec_mod_by_int(double2 p1) {
4+
return p1 % 2;
5+
// expected-error@-1 {{invalid operands to binary expression ('double2' (aka 'vector<double, 2>') and 'int')}}
6+
}
7+
8+
export double2 double_vec_mod_by_float(double2 p1) {
9+
return p1 % 2.0;
10+
// expected-error@-1 {{invalid operands to binary expression ('double2' (aka 'vector<double, 2>') and 'float')}}
11+
}
12+
13+
export double2 double_vec_mod_by_double(double2 p1, double p2 ) {
14+
return p1 % p2;
15+
// expected-error@-1 {{invalid operands to binary expression ('double2' (aka 'vector<double, 2>') and 'double')}}
16+
}
17+
18+
export double2 double_vec_mod_by_double_vec(double2 p1, double2 p2 ) {
19+
return p1 % p2;
20+
// expected-error@-1 {{invalid operands to binary expression ('double2' (aka 'vector<double, 2>') and 'double2')}}
21+
}
22+
23+
export double double_mod_by_int(double p1) {
24+
return p1 % 2;
25+
// expected-error@-1 {{invalid operands to binary expression ('double' and 'int')}}
26+
}
27+
28+
export double double_mod_by_float(double p1) {
29+
return p1 % 2.0;
30+
// expected-error@-1 {{invalid operands to binary expression ('double' and 'float')}}
31+
}
32+
33+
export double double_mod_by_double(double p1, double p2 ) {
34+
return p1 % p2;
35+
// expected-error@-1 {{invalid operands to binary expression ('double' and 'double')}}
36+
}
37+
38+
export double double_mod_by_double_vec(double p1, double2 p2 ) {
39+
return p1 % p2;
40+
// expected-error@-1 {{invalid operands to binary expression ('double' and 'double2' (aka 'vector<double, 2>'))}}
41+
}

0 commit comments

Comments
 (0)