Skip to content

Commit 16d1a64

Browse files
cooppCooper Partin
andauthored
[DirectX] Fix HLSL bitshifts to leverage the OpenCL pipeline for bitshifting (#81030)
Fixes #55106 In HLSL bit shifts are defined to shift by shift size % type size. This contains the following changes: HLSL codegen bit shifts will be emitted as x << (y & (sizeof(x) - 1) and bitshift masking leverages the OpenCL pipeline for this. Tests were also added to validate this behavior. Before this change the following was being emitted: ; Function Attrs: noinline nounwind optnone define noundef i32 @"?shl32@@yahhh@Z"(i32 noundef %V, i32 noundef %S) #0 { entry: %S.addr = alloca i32, align 4 %V.addr = alloca i32, align 4 store i32 %S, ptr %S.addr, align 4 store i32 %V, ptr %V.addr, align 4 %0 = load i32, ptr %V.addr, align 4 %1 = load i32, ptr %S.addr, align 4 %shl = shl i32 %0, %1 ret i32 %shl } After this change: ; Function Attrs: noinline nounwind optnone define noundef i32 @"?shl32@@yahhh@Z"(i32 noundef %V, i32 noundef %S) #0 { entry: %S.addr = alloca i32, align 4 %V.addr = alloca i32, align 4 store i32 %S, ptr %S.addr, align 4 store i32 %V, ptr %V.addr, align 4 %0 = load i32, ptr %V.addr, align 4 %1 = load i32, ptr %S.addr, align 4 %shl.mask = and i32 %1, 31 %shl = shl i32 %0, %shl.mask ret i32 %shl } --------- Co-authored-by: Cooper Partin <[email protected]>
1 parent c8d431e commit 16d1a64

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4168,7 +4168,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
41684168
bool SanitizeBase = SanitizeSignedBase || SanitizeUnsignedBase;
41694169
bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent);
41704170
// OpenCL 6.3j: shift values are effectively % word size of LHS.
4171-
if (CGF.getLangOpts().OpenCL)
4171+
if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL)
41724172
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask");
41734173
else if ((SanitizeBase || SanitizeExponent) &&
41744174
isa<llvm::IntegerType>(Ops.LHS->getType())) {
@@ -4237,7 +4237,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
42374237
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
42384238

42394239
// OpenCL 6.3j: shift values are effectively % word size of LHS.
4240-
if (CGF.getLangOpts().OpenCL)
4240+
if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL)
42414241
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shr.mask");
42424242
else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
42434243
isa<llvm::IntegerType>(Ops.LHS->getType())) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
4+
5+
int shl32(int V, int S) {
6+
return V << S;
7+
}
8+
9+
// CHECK: define noundef i32 @"?shl32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 {
10+
// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31
11+
// CHECK-DAG: %{{.*}} = shl i32 %{{.*}}, %[[Masked]]
12+
13+
int shr32(int V, int S) {
14+
return V >> S;
15+
}
16+
17+
// CHECK: define noundef i32 @"?shr32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 {
18+
// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31
19+
// CHECK-DAG: %{{.*}} = ashr i32 %{{.*}}, %[[Masked]]
20+
21+
int64_t shl64(int64_t V, int64_t S) {
22+
return V << S;
23+
}
24+
25+
// CHECK: define noundef i64 @"?shl64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 {
26+
// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63
27+
// CHECK-DAG: %{{.*}} = shl i64 %{{.*}}, %[[Masked]]
28+
29+
int64_t shr64(int64_t V, int64_t S) {
30+
return V >> S;
31+
}
32+
33+
// CHECK: define noundef i64 @"?shr64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 {
34+
// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63
35+
// CHECK-DAG: %{{.*}} = ashr i64 %{{.*}}, %[[Masked]]

0 commit comments

Comments
 (0)