[clang] 16d1a64 - [DirectX] Fix HLSL bitshifts to leverage the OpenCL pipeline for bitshifting (#81030)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 8 09:50:25 PST 2024
Author: Cooper Partin
Date: 2024-02-08T11:50:21-06:00
New Revision: 16d1a6486c25769d264a6ddb70a48bbb1c23c077
URL: https://github.com/llvm/llvm-project/commit/16d1a6486c25769d264a6ddb70a48bbb1c23c077
DIFF: https://github.com/llvm/llvm-project/commit/16d1a6486c25769d264a6ddb70a48bbb1c23c077.diff
LOG: [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 at 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 at 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 <coopp at ntdev.microsoft.com>
Added:
clang/test/CodeGenHLSL/shift-mask.hlsl
Modified:
clang/lib/CodeGen/CGExprScalar.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index df8f71cf1d9008..fa03163bbde577 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4168,7 +4168,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
bool SanitizeBase = SanitizeSignedBase || SanitizeUnsignedBase;
bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent);
// OpenCL 6.3j: shift values are effectively % word size of LHS.
- if (CGF.getLangOpts().OpenCL)
+ if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL)
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask");
else if ((SanitizeBase || SanitizeExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
@@ -4237,7 +4237,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
// OpenCL 6.3j: shift values are effectively % word size of LHS.
- if (CGF.getLangOpts().OpenCL)
+ if (CGF.getLangOpts().OpenCL || CGF.getLangOpts().HLSL)
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shr.mask");
else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
diff --git a/clang/test/CodeGenHLSL/shift-mask.hlsl b/clang/test/CodeGenHLSL/shift-mask.hlsl
new file mode 100644
index 00000000000000..d046efaf9c1f9c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/shift-mask.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+int shl32(int V, int S) {
+ return V << S;
+}
+
+// CHECK: define noundef i32 @"?shl32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 {
+// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31
+// CHECK-DAG: %{{.*}} = shl i32 %{{.*}}, %[[Masked]]
+
+int shr32(int V, int S) {
+ return V >> S;
+}
+
+// CHECK: define noundef i32 @"?shr32{{[@$?.A-Za-z0-9_]+}}"(i32 noundef %V, i32 noundef %S) #0 {
+// CHECK-DAG: %[[Masked:.*]] = and i32 %{{.*}}, 31
+// CHECK-DAG: %{{.*}} = ashr i32 %{{.*}}, %[[Masked]]
+
+int64_t shl64(int64_t V, int64_t S) {
+ return V << S;
+}
+
+// CHECK: define noundef i64 @"?shl64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 {
+// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63
+// CHECK-DAG: %{{.*}} = shl i64 %{{.*}}, %[[Masked]]
+
+int64_t shr64(int64_t V, int64_t S) {
+ return V >> S;
+}
+
+// CHECK: define noundef i64 @"?shr64{{[@$?.A-Za-z0-9_]+}}"(i64 noundef %V, i64 noundef %S) #0 {
+// CHECK-DAG: %[[Masked:.*]] = and i64 %{{.*}}, 63
+// CHECK-DAG: %{{.*}} = ashr i64 %{{.*}}, %[[Masked]]
More information about the cfe-commits
mailing list