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@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 <co...@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]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits