bob80905 updated this revision to Diff 461739.
bob80905 added a comment.
Herald added subscribers: llvm-commits, bzcheeseman, sdasgup3, wenzhicui,
wrengr, cota, mravishankar, teijeong, rdzhabarov, tatianashp, ThomasRaoux,
msifontes, jurahul, Kayjukh, grosul1, Joonsoo, stephenneuendorffer, liufengdb,
aartbik, mgester, arpith-jacob, nicolasvasilache, antiagainst, shauheen,
rriddle, mehdi_amini, MaskRay.
Herald added a reviewer: antiagainst.
Herald added a reviewer: nicolasvasilache.
Herald added a reviewer: aartbik.
Herald added a reviewer: sscalpone.
Herald added a reviewer: dcaballe.
Herald added projects: MLIR, LLVM, Flang.
- add elementwise function tests
- remove int attribute links in hlsl_intrinsics.h
- rebase
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D134319/new/
https://reviews.llvm.org/D134319
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/HLSLExternalSemaSource.h
clang/lib/Driver/ToolChains/PS4CPU.cpp
clang/lib/Frontend/FrontendAction.cpp
clang/lib/Headers/hlsl/hlsl_intrinsics.h
clang/lib/Sema/HLSLExternalSemaSource.cpp
clang/lib/Sema/SemaExprMember.cpp
clang/test/AST/HLSL/Inputs/pch.hlsl
clang/test/AST/HLSL/Inputs/pch_with_buf.hlsl
clang/test/AST/HLSL/pch.hlsl
clang/test/AST/HLSL/pch_with_buf.hlsl
clang/test/CodeGenHLSL/builtins/ceil.hlsl
clang/test/Driver/debug-options.c
clang/test/Driver/ps4-ps5-linker-jmc.c
clang/test/SemaCXX/cxx1z-ast-print.cpp
clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
flang/test/Semantics/atomic01.f90
lld/COFF/Config.h
lld/COFF/Driver.cpp
lld/COFF/MapFile.cpp
lld/COFF/Options.td
lld/test/COFF/map.test
llvm/runtimes/CMakeLists.txt
mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp
mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp
mlir/lib/Dialect/Linalg/Transforms/CMakeLists.txt
mlir/lib/Dialect/Linalg/Transforms/SwapExtractSliceWithFillPatterns.cpp
mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
mlir/test/Conversion/MemRefToSPIRV/map-storage-class.mlir
mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir
mlir/test/Dialect/Linalg/swap-extract-slice-with-fill.mlir
mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
mlir/test/Target/SPIRV/cast-ops.mlir
mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
Index: mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
===================================================================
--- mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
+++ mlir/test/lib/Dialect/Linalg/TestLinalgTransforms.cpp
@@ -123,6 +123,11 @@
llvm::cl::desc("Test rewrite of linalgOp + extract_slice into "
"extract_slice + linalgOp"),
llvm::cl::init(false)};
+ Option<bool> testSwapExtractSliceWithFill{
+ *this, "test-swap-extract-slice-with-fill-pattern",
+ llvm::cl::desc(
+ "Test patterns to swap tensor.extract_slice(linalg.fill())"),
+ llvm::cl::init(false)};
};
} // namespace
@@ -508,6 +513,12 @@
(void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
}
+static void applySwapExtractSliceWithFillPattern(func::FuncOp funcOp) {
+ RewritePatternSet patterns(funcOp.getContext());
+ populateSwapExtractSliceWithFillPatterns(patterns);
+ (void)applyPatternsAndFoldGreedily(funcOp, std::move(patterns));
+}
+
/// Apply transformations specified as patterns.
void TestLinalgTransforms::runOnOperation() {
auto lambda = [&](void *) {
@@ -551,6 +562,8 @@
return applySplitReduction(getOperation());
if (testBubbleUpExtractSliceOpPattern)
return applyBubbleUpExtractSliceOpPattern(getOperation());
+ if (testSwapExtractSliceWithFill)
+ return applySwapExtractSliceWithFillPattern(getOperation());
}
namespace mlir {
Index: mlir/test/Target/SPIRV/cast-ops.mlir
===================================================================
--- mlir/test/Target/SPIRV/cast-ops.mlir
+++ mlir/test/Target/SPIRV/cast-ops.mlir
@@ -71,3 +71,23 @@
spv.ReturnValue %0 : i64
}
}
+
+// -----
+
+spv.module Logical GLSL450 requires #spv.vce<v1.0, [Kernel], []> {
+ spv.func @ptr_cast_to_generic(%arg0 : !spv.ptr<f32, CrossWorkgroup>) "None" {
+ // CHECK: {{%.*}} = spv.PtrCastToGeneric {{%.*}} : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<f32, Generic>
+ %0 = spv.PtrCastToGeneric %arg0 : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<f32, Generic>
+ spv.Return
+ }
+ spv.func @generic_cast_to_ptr(%arg0 : !spv.ptr<vector<2xi32>, Generic>) "None" {
+ // CHECK: {{%.*}} = spv.GenericCastToPtr {{%.*}} : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ %0 = spv.GenericCastToPtr %arg0 : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ spv.Return
+ }
+ spv.func @generic_cast_to_ptr_explicit(%arg0 : !spv.ptr<vector<2xi32>, Generic>) "None" {
+ // CHECK: {{%.*}} = spv.GenericCastToPtrExplicit {{%.*}} : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ %0 = spv.GenericCastToPtrExplicit %arg0 : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ spv.Return
+ }
+}
Index: mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
===================================================================
--- mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
+++ mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
@@ -260,3 +260,106 @@
spv.ReturnValue %0 : i64
}
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.PtrCastToGeneric
+//===----------------------------------------------------------------------===//
+
+func.func @ptrcasttogeneric1(%arg0 : !spv.ptr<f32, CrossWorkgroup>) {
+ // CHECK: {{%.*}} = spv.PtrCastToGeneric {{%.*}} : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<f32, Generic>
+ %0 = spv.PtrCastToGeneric %arg0 : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<f32, Generic>
+ return
+}
+// -----
+
+func.func @ptrcasttogeneric2(%arg0 : !spv.ptr<f32, StorageBuffer>) {
+ // expected-error @+1 {{pointer must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
+ %0 = spv.PtrCastToGeneric %arg0 : !spv.ptr<f32, StorageBuffer> to !spv.ptr<f32, Generic>
+ return
+}
+
+// -----
+
+func.func @ptrcasttogeneric3(%arg0 : !spv.ptr<f32, CrossWorkgroup>) {
+ // expected-error @+1 {{result type must be of storage class Generic}}
+ %0 = spv.PtrCastToGeneric %arg0 : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<f32, Uniform>
+ return
+}
+
+// -----
+
+func.func @ptrcasttogeneric4(%arg0 : !spv.ptr<f32, CrossWorkgroup>) {
+ // expected-error @+1 {{pointee type must have the same as the op result type}}
+ %0 = spv.PtrCastToGeneric %arg0 : !spv.ptr<f32, CrossWorkgroup> to !spv.ptr<vector<2xi32>, Generic>
+ return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.GenericCastToPtr
+//===----------------------------------------------------------------------===//
+
+func.func @genericcasttoptr1(%arg0 : !spv.ptr<vector<2xi32>, Generic>) {
+ // CHECK: {{%.*}} = spv.GenericCastToPtr {{%.*}} : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ %0 = spv.GenericCastToPtr %arg0 : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ return
+}
+// -----
+
+func.func @genericcasttoptr2(%arg0 : !spv.ptr<f32, Uniform>) {
+ // expected-error @+1 {{pointer type must be of storage class Generic}}
+ %0 = spv.GenericCastToPtr %arg0 : !spv.ptr<f32, Uniform> to !spv.ptr<f32, Workgroup>
+ return
+}
+
+// -----
+
+func.func @genericcasttoptr3(%arg0 : !spv.ptr<f32, Generic>) {
+ // expected-error @+1 {{result must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
+ %0 = spv.GenericCastToPtr %arg0 : !spv.ptr<f32, Generic> to !spv.ptr<f32, Uniform>
+ return
+}
+
+// -----
+
+func.func @genericcasttoptr4(%arg0 : !spv.ptr<f32, Generic>) {
+ // expected-error @+1 {{pointee type must have the same as the op result type}}
+ %0 = spv.GenericCastToPtr %arg0 : !spv.ptr<f32, Generic> to !spv.ptr<vector<2xi32>, Workgroup>
+ return
+}
+// -----
+
+//===----------------------------------------------------------------------===//
+// spv.GenericCastToPtrExplicit
+//===----------------------------------------------------------------------===//
+
+func.func @genericcasttoptrexplicit1(%arg0 : !spv.ptr<vector<2xi32>, Generic>) {
+ // CHECK: {{%.*}} = spv.GenericCastToPtrExplicit {{%.*}} : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ %0 = spv.GenericCastToPtrExplicit %arg0 : !spv.ptr<vector<2xi32>, Generic> to !spv.ptr<vector<2xi32>, CrossWorkgroup>
+ return
+}
+// -----
+
+func.func @genericcasttoptrexplicit2(%arg0 : !spv.ptr<f32, Uniform>) {
+ // expected-error @+1 {{pointer type must be of storage class Generic}}
+ %0 = spv.GenericCastToPtrExplicit %arg0 : !spv.ptr<f32, Uniform> to !spv.ptr<f32, Workgroup>
+ return
+}
+
+// -----
+
+func.func @genericcasttoptrexplicit3(%arg0 : !spv.ptr<f32, Generic>) {
+ // expected-error @+1 {{result must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
+ %0 = spv.GenericCastToPtrExplicit %arg0 : !spv.ptr<f32, Generic> to !spv.ptr<f32, Uniform>
+ return
+}
+
+// -----
+
+func.func @genericcasttoptrexplicit4(%arg0 : !spv.ptr<f32, Generic>) {
+ // expected-error @+1 {{pointee type must have the same as the op result type}}
+ %0 = spv.GenericCastToPtrExplicit %arg0 : !spv.ptr<f32, Generic> to !spv.ptr<vector<2xi32>, Workgroup>
+ return
+}
Index: mlir/test/Dialect/Linalg/swap-extract-slice-with-fill.mlir
===================================================================
--- /dev/null
+++ mlir/test/Dialect/Linalg/swap-extract-slice-with-fill.mlir
@@ -0,0 +1,28 @@
+//RUN: mlir-opt -split-input-file -test-linalg-transform-patterns=test-swap-extract-slice-with-fill-pattern %s | FileCheck %s
+
+// CHECK-LABEL: func.func @swap_fill_insert_slice
+// CHECK-SAME: (%[[INIT:.+]]: tensor<?x?x?xf32>, %[[OFFSET0:.+]]: index, %[[SIZE1:.+]]: index)
+// CHECK: %[[F0:.+]] = arith.constant 0.000000e+00 : f32
+// CHECK: %[[EXT:.+]] = tensor.extract_slice %[[INIT]][%[[OFFSET0]], 8, 4] [1, %[[SIZE1]], 6] [1, 3, 1]
+// CHECK: %[[FILL:.+]] = linalg.fill ins(%[[F0]] : f32) outs(%[[EXT]] : tensor<?x6xf32>) -> tensor<?x6xf32>
+// CHECK: return %[[FILL]]
+func.func @swap_fill_insert_slice(%init : tensor<?x?x?xf32>, %offset0: index, %size1: index) -> tensor<?x6xf32> {
+ %f0 = arith.constant 0.000000e+00 : f32
+ %0 = linalg.fill ins(%f0 : f32) outs(%init : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
+ %1 = tensor.extract_slice %0[%offset0, 8, 4] [1, %size1, 6] [1, 3, 1]
+ : tensor<?x?x?xf32> to tensor<?x6xf32>
+ return %1: tensor<?x6xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func.func @dont_swap_fill_insert_slice_multi_user
+// CHECK: linalg.fill
+// CHECK: tensor.extract_slice
+func.func @dont_swap_fill_insert_slice_multi_user(%init : tensor<?x?x?xf32>, %offset0: index, %size1: index) -> (tensor<?x?x?xf32>, tensor<2x?x6xf32>) {
+ %f0 = arith.constant 0.000000e+00 : f32
+ %0 = linalg.fill ins(%f0 : f32) outs(%init : tensor<?x?x?xf32>) -> tensor<?x?x?xf32>
+ %1 = tensor.extract_slice %0[%offset0, 8, 4] [2, %size1, 6] [1, 3, 1]
+ : tensor<?x?x?xf32> to tensor<2x?x6xf32>
+ return %0, %1: tensor<?x?x?xf32>, tensor<2x?x6xf32>
+}
Index: mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir
===================================================================
--- mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir
+++ mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir
@@ -33,6 +33,90 @@
return %0 : vector<1xf32>
}
+// CHECK-LABEL: func @cl_reduction_maxf
+// CHECK-SAME: (%[[V:.+]]: vector<3xf32>, %[[S:.+]]: f32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xf32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xf32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xf32>
+// CHECK: %[[MAX0:.+]] = spv.CL.fmax %[[S0]], %[[S1]]
+// CHECK: %[[MAX1:.+]] = spv.CL.fmax %[[MAX0]], %[[S2]]
+// CHECK: %[[MAX2:.+]] = spv.CL.fmax %[[MAX1]], %[[S]]
+// CHECK: return %[[MAX2]]
+func.func @cl_reduction_maxf(%v : vector<3xf32>, %s: f32) -> f32 {
+ %reduce = vector.reduction <maxf>, %v, %s : vector<3xf32> into f32
+ return %reduce : f32
+}
+
+// CHECK-LABEL: func @cl_reduction_minf
+// CHECK-SAME: (%[[V:.+]]: vector<3xf32>, %[[S:.+]]: f32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xf32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xf32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xf32>
+// CHECK: %[[MIN0:.+]] = spv.CL.fmin %[[S0]], %[[S1]]
+// CHECK: %[[MIN1:.+]] = spv.CL.fmin %[[MIN0]], %[[S2]]
+// CHECK: %[[MIN2:.+]] = spv.CL.fmin %[[MIN1]], %[[S]]
+// CHECK: return %[[MIN2]]
+func.func @cl_reduction_minf(%v : vector<3xf32>, %s: f32) -> f32 {
+ %reduce = vector.reduction <minf>, %v, %s : vector<3xf32> into f32
+ return %reduce : f32
+}
+
+// CHECK-LABEL: func @cl_reduction_maxsi
+// CHECK-SAME: (%[[V:.+]]: vector<3xi32>, %[[S:.+]]: i32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xi32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xi32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xi32>
+// CHECK: %[[MAX0:.+]] = spv.CL.s_max %[[S0]], %[[S1]]
+// CHECK: %[[MAX1:.+]] = spv.CL.s_max %[[MAX0]], %[[S2]]
+// CHECK: %[[MAX2:.+]] = spv.CL.s_max %[[MAX1]], %[[S]]
+// CHECK: return %[[MAX2]]
+func.func @cl_reduction_maxsi(%v : vector<3xi32>, %s: i32) -> i32 {
+ %reduce = vector.reduction <maxsi>, %v, %s : vector<3xi32> into i32
+ return %reduce : i32
+}
+
+// CHECK-LABEL: func @cl_reduction_minsi
+// CHECK-SAME: (%[[V:.+]]: vector<3xi32>, %[[S:.+]]: i32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xi32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xi32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xi32>
+// CHECK: %[[MIN0:.+]] = spv.CL.s_min %[[S0]], %[[S1]]
+// CHECK: %[[MIN1:.+]] = spv.CL.s_min %[[MIN0]], %[[S2]]
+// CHECK: %[[MIN2:.+]] = spv.CL.s_min %[[MIN1]], %[[S]]
+// CHECK: return %[[MIN2]]
+func.func @cl_reduction_minsi(%v : vector<3xi32>, %s: i32) -> i32 {
+ %reduce = vector.reduction <minsi>, %v, %s : vector<3xi32> into i32
+ return %reduce : i32
+}
+
+// CHECK-LABEL: func @cl_reduction_maxui
+// CHECK-SAME: (%[[V:.+]]: vector<3xi32>, %[[S:.+]]: i32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xi32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xi32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xi32>
+// CHECK: %[[MAX0:.+]] = spv.CL.u_max %[[S0]], %[[S1]]
+// CHECK: %[[MAX1:.+]] = spv.CL.u_max %[[MAX0]], %[[S2]]
+// CHECK: %[[MAX2:.+]] = spv.CL.u_max %[[MAX1]], %[[S]]
+// CHECK: return %[[MAX2]]
+func.func @cl_reduction_maxui(%v : vector<3xi32>, %s: i32) -> i32 {
+ %reduce = vector.reduction <maxui>, %v, %s : vector<3xi32> into i32
+ return %reduce : i32
+}
+
+// CHECK-LABEL: func @cl_reduction_minui
+// CHECK-SAME: (%[[V:.+]]: vector<3xi32>, %[[S:.+]]: i32)
+// CHECK: %[[S0:.+]] = spv.CompositeExtract %[[V]][0 : i32] : vector<3xi32>
+// CHECK: %[[S1:.+]] = spv.CompositeExtract %[[V]][1 : i32] : vector<3xi32>
+// CHECK: %[[S2:.+]] = spv.CompositeExtract %[[V]][2 : i32] : vector<3xi32>
+// CHECK: %[[MIN0:.+]] = spv.CL.u_min %[[S0]], %[[S1]]
+// CHECK: %[[MIN1:.+]] = spv.CL.u_min %[[MIN0]], %[[S2]]
+// CHECK: %[[MIN2:.+]] = spv.CL.u_min %[[MIN1]], %[[S]]
+// CHECK: return %[[MIN2]]
+func.func @cl_reduction_minui(%v : vector<3xi32>, %s: i32) -> i32 {
+ %reduce = vector.reduction <minui>, %v, %s : vector<3xi32> into i32
+ return %reduce : i32
+}
+
} // end module
// -----
Index: mlir/test/Conversion/MemRefToSPIRV/map-storage-class.mlir
===================================================================
--- mlir/test/Conversion/MemRefToSPIRV/map-storage-class.mlir
+++ mlir/test/Conversion/MemRefToSPIRV/map-storage-class.mlir
@@ -114,3 +114,56 @@
%0 = "dialect.memref_producer"() : () -> (memref<f32, 2>)
return
}
+
+// -----
+
+/// Checks memory maps to OpenCL mapping if Kernel capability is enabled.
+module attributes { spv.target_env = #spv.target_env<#spv.vce<v1.0, [Kernel], []>, #spv.resource_limits<>> } {
+func.func @operand_result() {
+ // CHECK: memref<f32, #spv.storage_class<CrossWorkgroup>>
+ %0 = "dialect.memref_producer"() : () -> (memref<f32>)
+ // CHECK: memref<4xi32, #spv.storage_class<Generic>>
+ %1 = "dialect.memref_producer"() : () -> (memref<4xi32, 1>)
+ // CHECK: memref<?x4xf16, #spv.storage_class<Workgroup>>
+ %2 = "dialect.memref_producer"() : () -> (memref<?x4xf16, 3>)
+ // CHECK: memref<*xf16, #spv.storage_class<UniformConstant>>
+ %3 = "dialect.memref_producer"() : () -> (memref<*xf16, 4>)
+
+
+ "dialect.memref_consumer"(%0) : (memref<f32>) -> ()
+ // CHECK: memref<4xi32, #spv.storage_class<Generic>>
+ "dialect.memref_consumer"(%1) : (memref<4xi32, 1>) -> ()
+ // CHECK: memref<?x4xf16, #spv.storage_class<Workgroup>>
+ "dialect.memref_consumer"(%2) : (memref<?x4xf16, 3>) -> ()
+ // CHECK: memref<*xf16, #spv.storage_class<UniformConstant>>
+ "dialect.memref_consumer"(%3) : (memref<*xf16, 4>) -> ()
+
+ return
+}
+}
+
+// -----
+
+/// Checks memory maps to Vulkan mapping if Shader capability is enabled.
+module attributes { spv.target_env = #spv.target_env<#spv.vce<v1.0, [Shader], []>, #spv.resource_limits<>> } {
+func.func @operand_result() {
+ // CHECK: memref<f32, #spv.storage_class<StorageBuffer>>
+ %0 = "dialect.memref_producer"() : () -> (memref<f32>)
+ // CHECK: memref<4xi32, #spv.storage_class<Generic>>
+ %1 = "dialect.memref_producer"() : () -> (memref<4xi32, 1>)
+ // CHECK: memref<?x4xf16, #spv.storage_class<Workgroup>>
+ %2 = "dialect.memref_producer"() : () -> (memref<?x4xf16, 3>)
+ // CHECK: memref<*xf16, #spv.storage_class<Uniform>>
+ %3 = "dialect.memref_producer"() : () -> (memref<*xf16, 4>)
+
+
+ "dialect.memref_consumer"(%0) : (memref<f32>) -> ()
+ // CHECK: memref<4xi32, #spv.storage_class<Generic>>
+ "dialect.memref_consumer"(%1) : (memref<4xi32, 1>) -> ()
+ // CHECK: memref<?x4xf16, #spv.storage_class<Workgroup>>
+ "dialect.memref_consumer"(%2) : (memref<?x4xf16, 3>) -> ()
+ // CHECK: memref<*xf16, #spv.storage_class<Uniform>>
+ "dialect.memref_consumer"(%3) : (memref<*xf16, 4>) -> ()
+ return
+}
+}
\ No newline at end of file
Index: mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
===================================================================
--- mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
+++ mlir/lib/Target/SPIRV/Serialization/SerializeOps.cpp
@@ -667,6 +667,32 @@
return success();
}
+template <>
+LogicalResult Serializer::processOp<spirv::GenericCastToPtrExplicitOp>(
+ spirv::GenericCastToPtrExplicitOp op) {
+ SmallVector<uint32_t, 4> operands;
+ Type resultTy;
+ Location loc = op->getLoc();
+ uint32_t resultTypeID = 0;
+ uint32_t resultID = 0;
+ resultTy = op->getResult(0).getType();
+ if (failed(processType(loc, resultTy, resultTypeID)))
+ return failure();
+ operands.push_back(resultTypeID);
+
+ resultID = getNextID();
+ operands.push_back(resultID);
+ valueIDMap[op->getResult(0)] = resultID;
+
+ for (Value operand : op->getOperands())
+ operands.push_back(getValueID(operand));
+ spirv::StorageClass resultStorage =
+ resultTy.cast<spirv::PointerType>().getStorageClass();
+ operands.push_back(static_cast<uint32_t>(resultStorage));
+ encodeInstructionInto(functionBody, spirv::Opcode::OpGenericCastToPtrExplicit,
+ operands);
+ return success();
+}
// Pull in auto-generated Serializer::dispatchToAutogenSerialization() and
// various Serializer::processOp<...>() specializations.
Index: mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
===================================================================
--- mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
+++ mlir/lib/Target/SPIRV/Deserialization/DeserializeOps.cpp
@@ -523,6 +523,38 @@
return success();
}
+template <>
+LogicalResult Deserializer::processOp<spirv::GenericCastToPtrExplicitOp>(
+ ArrayRef<uint32_t> words) {
+ if (words.size() != 4) {
+ return emitError(unknownLoc,
+ "expected 4 words in GenericCastToPtrExplicitOp"
+ " but got : ")
+ << words.size();
+ }
+ SmallVector<Type, 1> resultTypes;
+ SmallVector<Value, 4> operands;
+ uint32_t valueID = 0;
+ auto type = getType(words[0]);
+
+ if (!type)
+ return emitError(unknownLoc, "unknown type result <id> : ") << words[0];
+ resultTypes.push_back(type);
+
+ valueID = words[1];
+
+ auto arg = getValue(words[2]);
+ if (!arg)
+ return emitError(unknownLoc, "unknown result <id> : ") << words[2];
+ operands.push_back(arg);
+
+ Location loc = createFileLineColLoc(opBuilder);
+ Operation *op = opBuilder.create<spirv::GenericCastToPtrExplicitOp>(
+ loc, resultTypes, operands);
+ valueMap[valueID] = op->getResult(0);
+ return success();
+}
+
// Pull in auto-generated Deserializer::dispatchToAutogenDeserialization() and
// various Deserializer::processOp<...>() specializations.
#define GET_DESERIALIZATION_FNS
Index: mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
===================================================================
--- mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -1525,6 +1525,90 @@
return success();
}
+//===----------------------------------------------------------------------===//
+// spv.PtrCastToGenericOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::PtrCastToGenericOp::verify() {
+ auto operandType = pointer().getType().cast<spirv::PointerType>();
+ auto resultType = result().getType().cast<spirv::PointerType>();
+
+ spirv::StorageClass operandStorage = operandType.getStorageClass();
+ if (operandStorage != spirv::StorageClass::Workgroup &&
+ operandStorage != spirv::StorageClass::CrossWorkgroup &&
+ operandStorage != spirv::StorageClass::Function)
+ return emitError("pointer must point to the Workgroup, CrossWorkgroup"
+ ", or Function Storage Class");
+
+ spirv::StorageClass resultStorage = resultType.getStorageClass();
+ if (resultStorage != spirv::StorageClass::Generic)
+ return emitError("result type must be of storage class Generic");
+
+ Type operandPointeeType = operandType.getPointeeType();
+ Type resultPointeeType = resultType.getPointeeType();
+ if (operandPointeeType != resultPointeeType)
+ return emitOpError("pointer operand's pointee type must have the same "
+ "as the op result type, but found ")
+ << operandPointeeType << " vs " << resultPointeeType;
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// spv.GenericCastToPtrOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::GenericCastToPtrOp::verify() {
+ auto operandType = pointer().getType().cast<spirv::PointerType>();
+ auto resultType = result().getType().cast<spirv::PointerType>();
+
+ spirv::StorageClass operandStorage = operandType.getStorageClass();
+ if (operandStorage != spirv::StorageClass::Generic)
+ return emitError("pointer type must be of storage class Generic");
+
+ spirv::StorageClass resultStorage = resultType.getStorageClass();
+ if (resultStorage != spirv::StorageClass::Workgroup &&
+ resultStorage != spirv::StorageClass::CrossWorkgroup &&
+ resultStorage != spirv::StorageClass::Function)
+ return emitError("result must point to the Workgroup, CrossWorkgroup, "
+ "or Function Storage Class");
+
+ Type operandPointeeType = operandType.getPointeeType();
+ Type resultPointeeType = resultType.getPointeeType();
+ if (operandPointeeType != resultPointeeType)
+ return emitOpError("pointer operand's pointee type must have the same "
+ "as the op result type, but found ")
+ << operandPointeeType << " vs " << resultPointeeType;
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// spv.GenericCastToPtrExplicitOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::GenericCastToPtrExplicitOp::verify() {
+ auto operandType = pointer().getType().cast<spirv::PointerType>();
+ auto resultType = result().getType().cast<spirv::PointerType>();
+
+ spirv::StorageClass operandStorage = operandType.getStorageClass();
+ if (operandStorage != spirv::StorageClass::Generic)
+ return emitError("pointer type must be of storage class Generic");
+
+ spirv::StorageClass resultStorage = resultType.getStorageClass();
+ if (resultStorage != spirv::StorageClass::Workgroup &&
+ resultStorage != spirv::StorageClass::CrossWorkgroup &&
+ resultStorage != spirv::StorageClass::Function)
+ return emitError("result must point to the Workgroup, CrossWorkgroup, "
+ "or Function Storage Class");
+
+ Type operandPointeeType = operandType.getPointeeType();
+ Type resultPointeeType = resultType.getPointeeType();
+ if (operandPointeeType != resultPointeeType)
+ return emitOpError("pointer operand's pointee type must have the same "
+ "as the op result type, but found ")
+ << operandPointeeType << " vs " << resultPointeeType;
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// spv.BranchOp
//===----------------------------------------------------------------------===//
Index: mlir/lib/Dialect/Linalg/Transforms/SwapExtractSliceWithFillPatterns.cpp
===================================================================
--- /dev/null
+++ mlir/lib/Dialect/Linalg/Transforms/SwapExtractSliceWithFillPatterns.cpp
@@ -0,0 +1,41 @@
+//===- SwapExtractSliceWithFillPatterns.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
+#include "mlir/IR/PatternMatch.h"
+
+using namespace mlir;
+using namespace mlir::linalg;
+
+/// Swaps tensor.extract_slice(linalg.fill(%cst, %init)) into linalg.fill(%cst,
+/// tensor.extract_slice(%init)) when the linalg.fill op have no other users.
+/// This helps to reduce the fill footprint.
+struct SwapExtractSliceOfFill final
+ : public OpRewritePattern<tensor::ExtractSliceOp> {
+ using OpRewritePattern::OpRewritePattern;
+
+ LogicalResult matchAndRewrite(tensor::ExtractSliceOp extractOp,
+ PatternRewriter &rewriter) const override {
+ auto fillOp = extractOp.getSource().getDefiningOp<FillOp>();
+ if (!fillOp || !fillOp->hasOneUse())
+ return failure();
+
+ auto newExtractOp = rewriter.create<tensor::ExtractSliceOp>(
+ extractOp.getLoc(), extractOp.getType(), fillOp.getOutputs()[0],
+ extractOp.getMixedOffsets(), extractOp.getMixedSizes(),
+ extractOp.getMixedStrides());
+ rewriter.replaceOpWithNewOp<FillOp>(extractOp, fillOp.getInputs(),
+ ValueRange{newExtractOp.getResult()});
+ return success();
+ }
+};
+
+void mlir::linalg::populateSwapExtractSliceWithFillPatterns(
+ RewritePatternSet &patterns) {
+ patterns.add<SwapExtractSliceOfFill>(patterns.getContext());
+}
Index: mlir/lib/Dialect/Linalg/Transforms/CMakeLists.txt
===================================================================
--- mlir/lib/Dialect/Linalg/Transforms/CMakeLists.txt
+++ mlir/lib/Dialect/Linalg/Transforms/CMakeLists.txt
@@ -24,6 +24,7 @@
Promotion.cpp
Split.cpp
SplitReduction.cpp
+ SwapExtractSliceWithFillPatterns.cpp
Tiling.cpp
TilingInterfaceImpl.cpp
Transforms.cpp
Index: mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp
===================================================================
--- mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp
+++ mlir/lib/Conversion/VectorToSPIRV/VectorToSPIRV.cpp
@@ -272,6 +272,8 @@
}
};
+template <class SPVFMaxOp, class SPVFMinOp, class SPVUMaxOp, class SPVUMinOp,
+ class SPVSMaxOp, class SPVSMinOp>
struct VectorReductionPattern final
: public OpConversionPattern<vector::ReductionOp> {
using OpConversionPattern::OpConversionPattern;
@@ -317,18 +319,18 @@
#define INT_OR_FLOAT_CASE(kind, fop) \
case vector::CombiningKind::kind: \
- result = rewriter.create<spirv::fop>(loc, resultType, result, next); \
+ result = rewriter.create<fop>(loc, resultType, result, next); \
break
INT_AND_FLOAT_CASE(ADD, IAddOp, FAddOp);
INT_AND_FLOAT_CASE(MUL, IMulOp, FMulOp);
- INT_OR_FLOAT_CASE(MAXF, GLFMaxOp);
- INT_OR_FLOAT_CASE(MINF, GLFMinOp);
- INT_OR_FLOAT_CASE(MINUI, GLUMinOp);
- INT_OR_FLOAT_CASE(MINSI, GLSMinOp);
- INT_OR_FLOAT_CASE(MAXUI, GLUMaxOp);
- INT_OR_FLOAT_CASE(MAXSI, GLSMaxOp);
+ INT_OR_FLOAT_CASE(MAXF, SPVFMaxOp);
+ INT_OR_FLOAT_CASE(MINF, SPVFMinOp);
+ INT_OR_FLOAT_CASE(MINUI, SPVUMinOp);
+ INT_OR_FLOAT_CASE(MINSI, SPVSMinOp);
+ INT_OR_FLOAT_CASE(MAXUI, SPVUMaxOp);
+ INT_OR_FLOAT_CASE(MAXSI, SPVSMaxOp);
case vector::CombiningKind::AND:
case vector::CombiningKind::OR:
@@ -403,15 +405,23 @@
};
} // namespace
+#define CL_MAX_MIN_OPS \
+ spirv::CLFMaxOp, spirv::CLFMinOp, spirv::CLUMaxOp, spirv::CLUMinOp, \
+ spirv::CLSMaxOp, spirv::CLSMinOp
+
+#define GL_MAX_MIN_OPS \
+ spirv::GLFMaxOp, spirv::GLFMinOp, spirv::GLUMaxOp, spirv::GLUMinOp, \
+ spirv::GLSMaxOp, spirv::GLSMinOp
void mlir::populateVectorToSPIRVPatterns(SPIRVTypeConverter &typeConverter,
RewritePatternSet &patterns) {
- patterns.add<VectorBitcastConvert, VectorBroadcastConvert,
- VectorExtractElementOpConvert, VectorExtractOpConvert,
- VectorExtractStridedSliceOpConvert,
- VectorFmaOpConvert<spirv::GLFmaOp>,
- VectorFmaOpConvert<spirv::CLFmaOp>, VectorInsertElementOpConvert,
- VectorInsertOpConvert, VectorReductionPattern,
- VectorInsertStridedSliceOpConvert, VectorShuffleOpConvert,
- VectorSplatPattern>(typeConverter, patterns.getContext());
+ patterns.add<
+ VectorBitcastConvert, VectorBroadcastConvert,
+ VectorExtractElementOpConvert, VectorExtractOpConvert,
+ VectorExtractStridedSliceOpConvert, VectorFmaOpConvert<spirv::GLFmaOp>,
+ VectorFmaOpConvert<spirv::CLFmaOp>, VectorInsertElementOpConvert,
+ VectorInsertOpConvert, VectorReductionPattern<GL_MAX_MIN_OPS>,
+ VectorReductionPattern<CL_MAX_MIN_OPS>, VectorInsertStridedSliceOpConvert,
+ VectorShuffleOpConvert, VectorSplatPattern>(typeConverter,
+ patterns.getContext());
}
Index: mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp
===================================================================
--- mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp
+++ mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp
@@ -17,6 +17,7 @@
#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVEnums.h"
+#include "mlir/Dialect/SPIRV/IR/TargetAndABI.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/FunctionInterfaces.h"
#include "mlir/Transforms/DialectConversion.h"
@@ -325,6 +326,15 @@
MLIRContext *context = &getContext();
Operation *op = getOperation();
+ if (spirv::TargetEnvAttr attr = spirv::lookupTargetEnv(op)) {
+ spirv::TargetEnv targetEnv(attr);
+ if (targetEnv.allows(spirv::Capability::Kernel)) {
+ memorySpaceMap = spirv::mapMemorySpaceToOpenCLStorageClass;
+ } else if (targetEnv.allows(spirv::Capability::Shader)) {
+ memorySpaceMap = spirv::mapMemorySpaceToVulkanStorageClass;
+ }
+ }
+
auto target = spirv::getMemorySpaceToStorageClassTarget(*context);
spirv::MemorySpaceToStorageClassConverter converter(memorySpaceMap);
Index: mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
===================================================================
--- mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
+++ mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
@@ -331,4 +331,144 @@
}];
}
+// -----
+def SPV_PtrCastToGenericOp : SPV_Op<"PtrCastToGeneric", [NoSideEffect]> {
+ let summary = "Convert a pointerâs Storage Class to Generic.";
+
+ let description = [{
+ Result Type must be an OpTypePointer. Its Storage Class must be Generic.
+
+ Pointer must point to the Workgroup, CrossWorkgroup, or Function Storage
+ Class.
+
+ Result Type and Pointer must point to the same type.
+
+ <!-- End of AutoGen section -->
+
+ #### Example:
+
+ ```mlir
+ %1 = spv.PtrCastToGenericOp %0 : !spv.ptr<f32, CrossWorkGroup> to
+ !spv.ptr<f32, Generic>
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPV_V_1_0>,
+ MaxVersion<SPV_V_1_6>,
+ Extension<[]>,
+ Capability<[SPV_C_Kernel]>
+ ];
+
+ let arguments = (ins
+ SPV_AnyPtr:$pointer
+ );
+
+ let results = (outs
+ SPV_AnyPtr:$result
+ );
+
+ let assemblyFormat = [{
+ $pointer attr-dict `:` type($pointer) `to` type($result)
+ }];
+}
+
+// -----
+
+def SPV_GenericCastToPtrOp : SPV_Op<"GenericCastToPtr", [NoSideEffect]> {
+ let summary = "Convert a pointerâs Storage Class to a non-Generic class.";
+
+ let description = [{
+ Result Type must be an OpTypePointer. Its Storage Class must be
+ Workgroup, CrossWorkgroup, or Function.
+
+ Pointer must point to the Generic Storage Class.
+
+ Result Type and Pointer must point to the same type.
+
+ <!-- End of AutoGen section -->
+
+ #### Example:
+
+ ```mlir
+ %1 = spv.GenericCastToPtrOp %0 : !spv.ptr<f32, Generic> to
+ !spv.ptr<f32, CrossWorkGroup>
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPV_V_1_0>,
+ MaxVersion<SPV_V_1_6>,
+ Extension<[]>,
+ Capability<[SPV_C_Kernel]>
+ ];
+
+ let arguments = (ins
+ SPV_AnyPtr:$pointer
+ );
+
+ let results = (outs
+ SPV_AnyPtr:$result
+ );
+
+ let assemblyFormat = [{
+ $pointer attr-dict `:` type($pointer) `to` type($result)
+ }];
+}
+
+// -----
+
+def SPV_GenericCastToPtrExplicitOp : SPV_Op<"GenericCastToPtrExplicit", [NoSideEffect]> {
+ let summary = [{
+ Attempts to explicitly convert Pointer to Storage storage-class pointer
+ value.
+ }];
+
+ let description = [{
+ Result Type must be an OpTypePointer. Its Storage Class must be Storage.
+
+ Pointer must have a type of OpTypePointer whose Type is the same as the
+ Type of Result Type.Pointer must point to the Generic Storage Class. If
+ the cast fails, the instruction result is an OpConstantNull pointer in
+ the Storage Storage Class.
+
+ Storage must be one of the following literal values from Storage Class:
+ Workgroup, CrossWorkgroup, or Function.
+
+ <!-- End of AutoGen section -->
+
+ ```
+ [TODO]
+ ```mlir
+
+ #### Example:
+
+ ```mlir
+ %1 = spv.GenericCastToPtrExplicitOp %0 : !spv.ptr<f32, Generic> to
+ !spv.ptr<f32, CrossWorkGroup>
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPV_V_1_0>,
+ MaxVersion<SPV_V_1_6>,
+ Extension<[]>,
+ Capability<[SPV_C_Kernel]>
+ ];
+
+ let arguments = (ins
+ SPV_AnyPtr:$pointer
+ );
+
+ let results = (outs
+ SPV_AnyPtr:$result
+ );
+
+ let assemblyFormat = [{
+ $pointer attr-dict `:` type($pointer) `to` type($result)
+ }];
+
+ let autogenSerialization = 0;
+}
+
#endif // MLIR_DIALECT_SPIRV_IR_CAST_OPS
Index: mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
===================================================================
--- mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -4221,6 +4221,9 @@
def SPV_OC_OpUConvert : I32EnumAttrCase<"OpUConvert", 113>;
def SPV_OC_OpSConvert : I32EnumAttrCase<"OpSConvert", 114>;
def SPV_OC_OpFConvert : I32EnumAttrCase<"OpFConvert", 115>;
+def SPV_OC_OpPtrCastToGeneric : I32EnumAttrCase<"OpPtrCastToGeneric", 121>;
+def SPV_OC_OpGenericCastToPtr : I32EnumAttrCase<"OpGenericCastToPtr", 122>;
+def SPV_OC_OpGenericCastToPtrExplicit : I32EnumAttrCase<"OpGenericCastToPtrExplicit", 123>;
def SPV_OC_OpBitcast : I32EnumAttrCase<"OpBitcast", 124>;
def SPV_OC_OpSNegate : I32EnumAttrCase<"OpSNegate", 126>;
def SPV_OC_OpFNegate : I32EnumAttrCase<"OpFNegate", 127>;
@@ -4372,7 +4375,8 @@
SPV_OC_OpCompositeInsert, SPV_OC_OpTranspose, SPV_OC_OpImageDrefGather,
SPV_OC_OpImage, SPV_OC_OpImageQuerySize, SPV_OC_OpConvertFToU,
SPV_OC_OpConvertFToS, SPV_OC_OpConvertSToF, SPV_OC_OpConvertUToF,
- SPV_OC_OpUConvert, SPV_OC_OpSConvert, SPV_OC_OpFConvert, SPV_OC_OpBitcast,
+ SPV_OC_OpUConvert, SPV_OC_OpSConvert, SPV_OC_OpFConvert, SPV_OC_OpPtrCastToGeneric,
+ SPV_OC_OpGenericCastToPtr, SPV_OC_OpGenericCastToPtrExplicit, SPV_OC_OpBitcast,
SPV_OC_OpSNegate, SPV_OC_OpFNegate, SPV_OC_OpIAdd, SPV_OC_OpFAdd,
SPV_OC_OpISub, SPV_OC_OpFSub, SPV_OC_OpIMul, SPV_OC_OpFMul, SPV_OC_OpUDiv,
SPV_OC_OpSDiv, SPV_OC_OpFDiv, SPV_OC_OpUMod, SPV_OC_OpSRem, SPV_OC_OpSMod,
Index: mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
===================================================================
--- mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
+++ mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
@@ -110,6 +110,10 @@
/// Patterns that are used to bubble up extract slice op above linalg op.
void populateBubbleUpExtractSliceOpPatterns(RewritePatternSet &patterns);
+/// Adds patterns that waps tensor.extract_slice(linalg.fill(%cst, %init)) into
+/// linalg.fill(%cst, tensor.extract_slice(%init)).
+void populateSwapExtractSliceWithFillPatterns(RewritePatternSet &patterns);
+
/// Return true if two `linalg.generic` operations with producer/consumer
/// relationship through `fusedOperand` can be fused using elementwise op
/// fusion.
Index: llvm/runtimes/CMakeLists.txt
===================================================================
--- llvm/runtimes/CMakeLists.txt
+++ llvm/runtimes/CMakeLists.txt
@@ -366,7 +366,7 @@
if(runtimes)
# Create a runtimes target that uses this file as its top-level CMake file.
# The runtimes target is a configuration of all the runtime libraries
- # together in a single CMake invocaiton.
+ # together in a single CMake invocation.
set(extra_deps "")
if("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
if(TARGET opt)
Index: lld/test/COFF/map.test
===================================================================
--- lld/test/COFF/map.test
+++ lld/test/COFF/map.test
@@ -8,6 +8,9 @@
# RUN: lld-link /out:%t.exe /entry:main %t.obj %t-dll.lib /map /lldmap:%T/foo-lld.map
# RUN: FileCheck -check-prefix=MAP -strict-whitespace %s < %t.map
# RUN: FileCheck -check-prefix=LLDMAP -strict-whitespace %s < %T/foo-lld.map
+# RUN: lld-link /out:%t.dll /dll %t-dll.obj /export:exportfn1 \
+# RUN: /export:foo=exportfn2 /map /mapinfo:exports
+# RUN: FileCheck -check-prefix=MAPINFO -strict-whitespace %s < %t.map
# MAP: {{.*}}
# MAP-EMPTY:
@@ -38,3 +41,12 @@
# LLDMAP-NEXT: 00001000 00000026 4096 .text
# LLDMAP-NEXT: 00001000 00000008 4 {{.*}}map.test.tmp.obj:(.text)
# LLDMAP-NEXT: 00001000 00000000 0 main
+
+# MAPINFO: Exports
+# MAPINFO-EMPTY:
+# MAPINFO-NEXT: ordinal name
+# MAPINFO-EMPTY:
+# MAPINFO-NEXT: 1 exportfn1
+# MAPINFO-NEXT: 2 exportfn3
+# MAPINFO-NEXT: 3 exportfn2
+# MAPINFO-NEXT: exported name: foo
Index: lld/COFF/Options.td
===================================================================
--- lld/COFF/Options.td
+++ lld/COFF/Options.td
@@ -287,6 +287,7 @@
def lldmap_file : P_priv<"lldmap">;
def map : F<"map">;
def map_file : P_priv<"map">;
+def map_info : P<"mapinfo", "Include the specified information in a map file">;
def show_timing : F<"time">;
def summary : F<"summary">;
Index: lld/COFF/MapFile.cpp
===================================================================
--- lld/COFF/MapFile.cpp
+++ lld/COFF/MapFile.cpp
@@ -315,6 +315,19 @@
for (Defined *sym : staticSyms)
os << staticSymStr[sym] << '\n';
+ // Print out the exported functions
+ if (config->mapInfo) {
+ os << "\n";
+ os << " Exports\n";
+ os << "\n";
+ os << " ordinal name\n\n";
+ for (Export &e : config->exports) {
+ os << format(" %7d", e.ordinal) << " " << e.name << "\n";
+ if (!e.extName.empty() && e.extName != e.name)
+ os << " exported name: " << e.extName << "\n";
+ }
+ }
+
t4.stop();
t1.stop();
}
Index: lld/COFF/Driver.cpp
===================================================================
--- lld/COFF/Driver.cpp
+++ lld/COFF/Driver.cpp
@@ -1922,6 +1922,16 @@
config->lldmapFile = getMapFile(args, OPT_lldmap, OPT_lldmap_file);
config->mapFile = getMapFile(args, OPT_map, OPT_map_file);
+ if (config->mapFile != "" && args.hasArg(OPT_map_info)) {
+ for (auto *arg : args.filtered(OPT_map_info)) {
+ std::string s = StringRef(arg->getValue()).lower();
+ if (s == "exports")
+ config->mapInfo = true;
+ else
+ error("unknown option: /mapinfo:" + s);
+ }
+ }
+
if (config->lldmapFile != "" && config->lldmapFile == config->mapFile) {
warn("/lldmap and /map have the same output file '" + config->mapFile +
"'.\n>>> ignoring /lldmap");
Index: lld/COFF/Config.h
===================================================================
--- lld/COFF/Config.h
+++ lld/COFF/Config.h
@@ -208,6 +208,9 @@
// Used for /map.
std::string mapFile;
+ // Used for /mapinfo.
+ bool mapInfo = false;
+
// Used for /thinlto-index-only:
llvm::StringRef thinLTOIndexOnlyArg;
Index: flang/test/Semantics/atomic01.f90
===================================================================
--- /dev/null
+++ flang/test/Semantics/atomic01.f90
@@ -0,0 +1,93 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! XFAIL: *
+! This test checks for semantic errors in atomic_add() subroutine based on the
+! statement specification in section 16.9.20 of the Fortran 2018 standard.
+
+program test_atomic_add
+ use iso_fortran_env, only : atomic_int_kind
+ implicit none
+
+ integer(kind=atomic_int_kind) atom_object[*], atom_array(2)[*], quantity, array(1), coarray[*], non_coarray
+ integer non_atom_object[*], non_atom, non_scalar(1), status, stat_array(1), coindexed[*]
+ logical non_integer
+
+ !___ standard-conforming calls with required arguments _______
+
+ call atomic_add(atom_object, quantity)
+ call atomic_add(atom_object[1], quantity)
+ call atomic_add(atom_array(1), quantity)
+ call atomic_add(atom_array(1)[1], quantity)
+ call atomic_add(atom_object, array(1))
+ call atomic_add(atom_object, coarray[1])
+ call atomic_add(atom=atom_object, value=quantity)
+ call atomic_add(value=quantity, atom=atom_object)
+
+ !___ standard-conforming calls with all arguments ____________
+ call atomic_add(atom_object, quantity, status)
+ call atomic_add(atom_object, quantity, stat_array(1))
+ call atomic_add(atom=atom_object, value=quantity, stat=status)
+ call atomic_add(stat=status, value=quantity, atom=atom_object)
+
+ !___ non-standard-conforming calls _______
+
+ ! atom must be of kind atomic_int_kind
+ call atomic_add(non_atom_object, quantity)
+
+ ! atom must be a coarray
+ call atomic_add(non_coarray, quantity)
+
+ ! atom must be a scalar variable
+ call atomic_add(atom_array, quantity)
+
+ ! atom has an unknown keyword argument
+ call atomic_add(atoms=atom_object, value=quantity)
+
+ ! atom has an argument mismatch
+ call atomic_add(atom=non_atom_object, value=quantity)
+
+ ! value must be an integer
+ call atomic_add(atom_object, non_integer)
+
+ ! value must be an integer scalar
+ call atomic_add(atom_object, array)
+
+ ! value must be of kind atomic_int_kind
+ call atomic_add(atom_object, non_atom)
+
+ ! value has an unknown keyword argument
+ call atomic_add(atom_object, values=quantity)
+
+ ! value has an argument mismatch
+ call atomic_add(atom_object, value=non_integer)
+
+ ! stat must be an integer
+ call atomic_add(atom_object, quantity, non_integer)
+
+ ! stat must be an integer scalar
+ call atomic_add(atom_object, quantity, non_scalar)
+
+ ! stat is an intent(out) argument
+ call atomic_add(atom_object, quantity, 8)
+
+ ! stat has an unknown keyword argument
+ call atomic_add(atom_object, quantity, statuses=status)
+
+ ! stat has an argument mismatch
+ call atomic_add(atom_object, quantity, stat=non_integer)
+
+ ! stat must not be coindexed
+ call atomic_add(atom_object, quantity, coindexed[1])
+
+ ! Too many arguments
+ call atomic_add(atom_object, quantity, status, stat_array(1))
+
+ ! Repeated atom keyword
+ call atomic_add(atom=atom_object, atom=atom_array(1), value=quantity)
+
+ ! Repeated value keyword
+ call atomic_add(atom=atom_object, value=quantity, value=array(1))
+
+ ! Repeated stat keyword
+ call atomic_add(atom=atom_object, value=quantity, stat=status, stat=stat_array(1))
+
+end program test_atomic_add
Index: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
+++ clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
@@ -2262,8 +2262,6 @@
template<typename T>
static constexpr T x = 42;
};
-// FIXME: `<int>` should be a child of `MemberExpression` and `;` of
-// `ExpressionStatement`. This is a bug in clang, in `getSourceRange` methods.
void test(S s) [[{
s.x<int>;
}]]
@@ -2272,18 +2270,18 @@
CompoundStatement
|-'{' OpenParen
|-ExpressionStatement Statement
-| `-MemberExpression Expression
-| |-IdExpression Object
-| | `-UnqualifiedId UnqualifiedId
-| | `-'s'
-| |-'.' AccessToken
-| `-IdExpression Member
-| `-UnqualifiedId UnqualifiedId
-| `-'x'
-|-'<'
-|-'int'
-|-'>'
-|-';'
+| |-MemberExpression Expression
+| | |-IdExpression Object
+| | | `-UnqualifiedId UnqualifiedId
+| | | `-'s'
+| | |-'.' AccessToken
+| | `-IdExpression Member
+| | `-UnqualifiedId UnqualifiedId
+| | |-'x'
+| | |-'<'
+| | |-'int'
+| | `-'>'
+| `-';'
`-'}' CloseParen
)txt"}));
}
Index: clang/test/SemaCXX/cxx1z-ast-print.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-ast-print.cpp
+++ clang/test/SemaCXX/cxx1z-ast-print.cpp
@@ -4,7 +4,7 @@
template <long> static int x; // expected-note {{forward declaration of template entity is here}}
template <auto> static int y; // expected-note {{forward declaration of template entity is here}}
};
-// CHECK: int k = TypeSuffix().x + TypeSuffix().y;
+// CHECK: int k = TypeSuffix().x<0L> + TypeSuffix().y<0L>;
int k = TypeSuffix().x<0L> + TypeSuffix().y<0L>; // expected-warning {{instantiation of variable 'TypeSuffix::x<0>' required here, but no definition is available}} \
// expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::x<0>' is explicitly instantiated in another translation unit}} \
// expected-warning {{instantiation of variable 'TypeSuffix::y<0L>' required here, but no definition is available}} \
Index: clang/test/Driver/ps4-ps5-linker-jmc.c
===================================================================
--- clang/test/Driver/ps4-ps5-linker-jmc.c
+++ clang/test/Driver/ps4-ps5-linker-jmc.c
@@ -6,10 +6,10 @@
// RUN: %clang --target=x86_64-scei-ps5 -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS5,CHECK-PS5-LIB %s
// RUN: %clang --target=x86_64-scei-ps5 -flto -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS5-LTO,CHECK-PS5-LIB %s
-// CHECK-PS4-NOT: "-enable-jmc-instrument"
+// CHECK-PS4-NOT: -enable-jmc-instrument
-// CHECK-PS4-THIN-LTO: "-lto-thin-debug-options=-enable-jmc-instrument"
-// CHECK-PS4-FULL-LTO: "-lto-debug-options=-enable-jmc-instrument"
+// CHECK-PS4-THIN-LTO: -lto-thin-debug-options=-enable-jmc-instrument
+// CHECK-PS4-FULL-LTO: -lto-debug-options=-enable-jmc-instrument
// CHECK-PS5-NOT: "-enable-jmc-instrument"
Index: clang/test/Driver/debug-options.c
===================================================================
--- clang/test/Driver/debug-options.c
+++ clang/test/Driver/debug-options.c
@@ -107,6 +107,14 @@
// RUN: | FileCheck -check-prefix=CI %s
// RUN: %clang -### -c %s -gsce -target x86_64-unknown-linux 2>&1 \
// RUN: | FileCheck -check-prefix=NOCI %s
+// RUN: %clang -### %s -g -flto=thin -target x86_64-scei-ps4 2>&1 \
+// RUN: | FileCheck -check-prefix=SNLDTLTOGARANGE %s
+// RUN: %clang -### %s -g -flto=full -target x86_64-scei-ps4 2>&1 \
+// RUN: | FileCheck -check-prefix=SNLDFLTOGARANGE %s
+// RUN: %clang -### %s -g -flto -target x86_64-scei-ps5 2>&1 \
+// RUN: | FileCheck -check-prefix=LLDGARANGE %s
+// RUN: %clang -### %s -g -target x86_64-scei-ps5 2>&1 \
+// RUN: | FileCheck -check-prefix=LDGARANGE %s
// On the AIX, -g defaults to -gdbx and limited debug info.
// RUN: %clang -### -c -g %s -target powerpc-ibm-aix-xcoff 2>&1 \
@@ -365,6 +373,13 @@
// NOPUB-NOT: -ggnu-pubnames
// NOPUB-NOT: -gpubnames
//
+
+// LDGARANGE: {{".*ld.*"}} {{.*}}
+// LDGARANGE-NOT: "-generate-arange-section"
+// LLDGARANGE: {{".*lld.*"}} {{.*}} "-generate-arange-section"
+// SNLDTLTOGARANGE: {{".*orbis-ld.*"}} {{.*}} "-lto-thin-debug-options=-generate-arange-section"
+// SNLDFLTOGARANGE: {{".*orbis-ld.*"}} {{.*}} "-lto-debug-options=-generate-arange-section"
+
// PUB: -gpubnames
//
// RNGBSE: -fdebug-ranges-base-address
Index: clang/test/CodeGenHLSL/builtins/ceil.hlsl
===================================================================
--- /dev/null
+++ clang/test/CodeGenHLSL/builtins/ceil.hlsl
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -D__HLSL_ENABLE_16_BIT -o - | FileCheck %s --check-prefix=NO_HALF
+
+
+// CHECK: define noundef half @
+// CHECK: call half @llvm.ceil.f16(
+// NO_HALF: define noundef float @"?test_ceil_half@@YA$halff@$halff@@Z"(
+// NO_HALF: call float @llvm.ceil.f32(float %0)
+half test_ceil_half ( half p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <2 x half> @
+// CHECK: call <2 x half> @llvm.ceil.v2f16(
+// NO_HALF: define noundef <2 x float> @"?test_ceil_half2@@YAT?$__vector@$halff@$01@__clang@@T12@@Z"(
+// NO_HALF: call <2 x float> @llvm.ceil.v2f32(
+half2 test_ceil_half2 ( half2 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <3 x half> @
+// CHECK: call <3 x half> @llvm.ceil.v3f16(
+// NO_HALF: define noundef <3 x float> @"?test_ceil_half3@@YAT?$__vector@$halff@$02@__clang@@T12@@Z"(
+// NO_HALF: call <3 x float> @llvm.ceil.v3f32(
+half3 test_ceil_half3 ( half3 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <4 x half> @
+// CHECK: call <4 x half> @llvm.ceil.v4f16(
+// NO_HALF: define noundef <4 x float> @"?test_ceil_half4@@YAT?$__vector@$halff@$03@__clang@@T12@@Z"(
+// NO_HALF: call <4 x float> @llvm.ceil.v4f32(
+half4 test_ceil_half4 ( half4 p0 ) {
+ return ceil ( p0 );
+}
+
+// CHECK: define noundef float @
+// CHECK: call float @llvm.ceil.f32(
+float test_ceil_float ( float p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <2 x float> @
+// CHECK: call <2 x float> @llvm.ceil.v2f32(
+float2 test_ceil_float2 ( float2 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <3 x float> @
+// CHECK: call <3 x float> @llvm.ceil.v3f32(
+float3 test_ceil_float3 ( float3 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <4 x float> @
+// CHECK: call <4 x float> @llvm.ceil.v4f32(
+float4 test_ceil_float4 ( float4 p0 ) {
+ return ceil ( p0 );
+}
+
+// CHECK: define noundef double @
+// CHECK: call double @llvm.ceil.f64(
+double test_ceil_double ( double p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <2 x double> @
+// CHECK: call <2 x double> @llvm.ceil.v2f64(
+double2 test_ceil_double2 ( double2 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <3 x double> @
+// CHECK: call <3 x double> @llvm.ceil.v3f64(
+double3 test_ceil_double3 ( double3 p0 ) {
+ return ceil ( p0 );
+}
+// CHECK: define noundef <4 x double> @
+// CHECK: call <4 x double> @llvm.ceil.v4f64(
+double4 test_ceil_double4 ( double4 p0 ) {
+ return ceil ( p0 );
+}
Index: clang/test/AST/HLSL/pch_with_buf.hlsl
===================================================================
--- /dev/null
+++ clang/test/AST/HLSL/pch_with_buf.hlsl
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -finclude-default-header -emit-pch -o %t %S/Inputs/pch_with_buf.hlsl
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl \
+// RUN: -finclude-default-header -include-pch %t -fsyntax-only -ast-dump-all %s | FileCheck %s
+
+// Make sure PCH works by using function declared in PCH header.
+// CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)'
+// Make sure buffer defined in PCH works.
+// CHECK:VarDecl 0x{{[0-9a-f]+}} <line:6:1, col:17> col:17 imported Buf 'RWBuffer<float>':'hlsl::RWBuffer<>'
+// Make sure declare a RWBuffer in current file works.
+// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:11:1, col:23> col:23 Buf2 'hlsl::RWBuffer<float>':'hlsl::RWBuffer<>'
+hlsl::RWBuffer<float> Buf2;
+
+float2 bar(float2 a, float2 b) {
+// CHECK:CallExpr 0x{{[0-9a-f]+}} <col:10, col:18> 'float2':'float __attribute__((ext_vector_type(2)))'
+// CHECK-NEXT:ImplicitCastExpr 0x{{[0-9a-f]+}} <col:10> 'float2 (*)(float2, float2)' <FunctionToPointerDecay>
+// CHECK-NEXT:`-DeclRefExpr 0x{{[0-9a-f]+}} <col:10> 'float2 (float2, float2)' lvalue Function 0x[[FOO]] 'foo' 'float2 (float2, float2)'
+ return foo(a, b);
+}
Index: clang/test/AST/HLSL/pch.hlsl
===================================================================
--- /dev/null
+++ clang/test/AST/HLSL/pch.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl \
+// RUN: -finclude-default-header -emit-pch -o %t %S/Inputs/pch.hlsl
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl \
+// RUN: -finclude-default-header -include-pch %t -fsyntax-only -ast-dump-all %s \
+// RUN: | FileCheck %s
+
+// Make sure PCH works by using function declared in PCH header and declare a RWBuffer in current file.
+// CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)'
+// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:10:1, col:23> col:23 Buffer 'hlsl::RWBuffer<float>':'hlsl::RWBuffer<>'
+hlsl::RWBuffer<float> Buffer;
+
+float2 bar(float2 a, float2 b) {
+// CHECK:CallExpr 0x{{[0-9a-f]+}} <col:10, col:18> 'float2':'float __attribute__((ext_vector_type(2)))'
+// CHECK-NEXT:ImplicitCastExpr 0x{{[0-9a-f]+}} <col:10> 'float2 (*)(float2, float2)' <FunctionToPointerDecay>
+// CHECK-NEXT:`-DeclRefExpr 0x{{[0-9a-f]+}} <col:10> 'float2 (float2, float2)' lvalue Function 0x[[FOO]] 'foo' 'float2 (float2, float2)'
+ return foo(a, b);
+}
Index: clang/test/AST/HLSL/Inputs/pch_with_buf.hlsl
===================================================================
--- /dev/null
+++ clang/test/AST/HLSL/Inputs/pch_with_buf.hlsl
@@ -0,0 +1,6 @@
+
+float2 foo(float2 a, float2 b) {
+ return a + b;
+}
+
+RWBuffer<float> Buf;
Index: clang/test/AST/HLSL/Inputs/pch.hlsl
===================================================================
--- /dev/null
+++ clang/test/AST/HLSL/Inputs/pch.hlsl
@@ -0,0 +1,4 @@
+
+float2 foo(float2 a, float2 b) {
+ return a + b;
+}
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1161,10 +1161,10 @@
if (!Var->getTemplateSpecializationKind())
Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);
- return BuildMemberExpr(
- BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
- /*HadMultipleCandidates=*/false, MemberNameInfo,
- Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+ return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
+ FoundDecl, /*HadMultipleCandidates=*/false,
+ MemberNameInfo, Var->getType().getNonReferenceType(),
+ VK_LValue, OK_Ordinary, TemplateArgs);
}
// We found something that we didn't expect. Complain.
Index: clang/lib/Sema/HLSLExternalSemaSource.cpp
===================================================================
--- clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -30,6 +30,7 @@
struct BuiltinTypeDeclBuilder {
CXXRecordDecl *Record = nullptr;
ClassTemplateDecl *Template = nullptr;
+ ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;
@@ -43,48 +44,46 @@
ASTContext &AST = S.getASTContext();
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+ LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
+ CXXRecordDecl *PrevDecl = nullptr;
+ if (S.LookupQualifiedName(Result, HLSLNamespace)) {
+ NamedDecl *Found = Result.getFoundDecl();
+ if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
+ PrevDecl = TD->getTemplatedDecl();
+ PrevTemplate = TD;
+ } else
+ PrevDecl = dyn_cast<CXXRecordDecl>(Found);
+ assert(PrevDecl && "Unexpected lookup result type.");
+ }
+
+ if (PrevDecl && PrevDecl->isCompleteDefinition()) {
+ Record = PrevDecl;
+ return;
+ }
+
Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::TTK_Class,
HLSLNamespace, SourceLocation(),
- SourceLocation(), &II, nullptr, true);
+ SourceLocation(), &II, PrevDecl, true);
Record->setImplicit(true);
Record->setLexicalDeclContext(HLSLNamespace);
Record->setHasExternalLexicalStorage();
- // Don't let anyone derive from built-in types
+ // Don't let anyone derive from built-in types.
Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
AttributeCommonInfo::AS_Keyword,
FinalAttr::Keyword_final));
}
~BuiltinTypeDeclBuilder() {
- if (HLSLNamespace && !Template)
+ if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
HLSLNamespace->addDecl(Record);
}
- BuiltinTypeDeclBuilder &
- addTemplateArgumentList(llvm::ArrayRef<NamedDecl *> TemplateArgs) {
- ASTContext &AST = Record->getASTContext();
-
- auto *ParamList =
- TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
- TemplateArgs, SourceLocation(), nullptr);
- Template = ClassTemplateDecl::Create(
- AST, Record->getDeclContext(), SourceLocation(),
- DeclarationName(Record->getIdentifier()), ParamList, Record);
- Record->setDescribedClassTemplate(Template);
- Template->setImplicit(true);
- Template->setLexicalDeclContext(Record->getDeclContext());
- Record->getDeclContext()->addDecl(Template);
-
- // Requesting the class name specialization will fault in required types.
- QualType T = Template->getInjectedClassNameSpecialization();
- T = AST.getInjectedClassNameType(Record, T);
- return *this;
- }
-
BuiltinTypeDeclBuilder &
addMemberVariable(StringRef Name, QualType Type,
AccessSpecifier Access = AccessSpecifier::AS_private) {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Record->isBeingDefined() &&
"Definition must be started before adding members!");
ASTContext &AST = Record->getASTContext();
@@ -104,6 +103,8 @@
BuiltinTypeDeclBuilder &
addHandleMember(AccessSpecifier Access = AccessSpecifier::AS_private) {
+ if (Record->isCompleteDefinition())
+ return *this;
QualType Ty = Record->getASTContext().VoidPtrTy;
if (Template) {
if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
@@ -116,6 +117,8 @@
BuiltinTypeDeclBuilder &
annotateResourceClass(HLSLResourceAttr::ResourceClass RC) {
+ if (Record->isCompleteDefinition())
+ return *this;
Record->addAttr(
HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RC));
return *this;
@@ -147,6 +150,8 @@
BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
ResourceClass RC) {
+ if (Record->isCompleteDefinition())
+ return *this;
ASTContext &AST = Record->getASTContext();
QualType ConstructorType =
@@ -197,12 +202,16 @@
}
BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
+ if (Record->isCompleteDefinition())
+ return *this;
addArraySubscriptOperator(true);
addArraySubscriptOperator(false);
return *this;
}
BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Fields.count("h") > 0 &&
"Subscript operator must be added after the handle.");
@@ -279,11 +288,15 @@
}
BuiltinTypeDeclBuilder &startDefinition() {
+ if (Record->isCompleteDefinition())
+ return *this;
Record->startDefinition();
return *this;
}
BuiltinTypeDeclBuilder &completeDefinition() {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Record->isBeingDefined() &&
"Definition must be started before completing it.");
@@ -306,6 +319,8 @@
TemplateParameterListBuilder &
addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
+ if (Builder.Record->isCompleteDefinition())
+ return *this;
unsigned Position = static_cast<unsigned>(Params.size());
auto *Decl = TemplateTypeParmDecl::Create(
AST, Builder.Record->getDeclContext(), SourceLocation(),
@@ -332,6 +347,9 @@
Builder.Record->setDescribedClassTemplate(Builder.Template);
Builder.Template->setImplicit(true);
Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
+ // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
+ // make visible.
+ Builder.Template->setPreviousDecl(Builder.PrevTemplate);
Builder.Record->getDeclContext()->addDecl(Builder.Template);
Params.clear();
@@ -352,12 +370,24 @@
void HLSLExternalSemaSource::InitializeSema(Sema &S) {
SemaPtr = &S;
ASTContext &AST = SemaPtr->getASTContext();
+ // If the translation unit has external storage force external decls to load.
+ if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
+ (void)AST.getTranslationUnitDecl()->decls_begin();
+
IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
- HLSLNamespace =
- NamespaceDecl::Create(AST, AST.getTranslationUnitDecl(), false,
- SourceLocation(), SourceLocation(), &HLSL, nullptr);
+ LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
+ NamespaceDecl *PrevDecl = nullptr;
+ if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
+ PrevDecl = Result.getAsSingle<NamespaceDecl>();
+ HLSLNamespace = NamespaceDecl::Create(AST, AST.getTranslationUnitDecl(),
+ false, SourceLocation(),
+ SourceLocation(), &HLSL, PrevDecl);
HLSLNamespace->setImplicit(true);
+ HLSLNamespace->setHasExternalLexicalStorage();
AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
+
+ // Force external decls in the HLSL namespace to load from the PCH.
+ (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
defineTrivialHLSLTypes();
forwardDeclareHLSLTypes();
@@ -443,9 +473,11 @@
.addTypeParameter("element_type", SemaPtr->getASTContext().FloatTy)
.finalizeTemplateArgs()
.Record;
- Completions.insert(std::make_pair(
- Decl, std::bind(&HLSLExternalSemaSource::completeBufferType, this,
- std::placeholders::_1)));
+ if (!Decl->isCompleteDefinition())
+ Completions.insert(
+ std::make_pair(Decl->getCanonicalDecl(),
+ std::bind(&HLSLExternalSemaSource::completeBufferType,
+ this, std::placeholders::_1)));
}
void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
@@ -457,6 +489,7 @@
// declaration and complete that.
if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
+ Record = Record->getCanonicalDecl();
auto It = Completions.find(Record);
if (It == Completions.end())
return;
Index: clang/lib/Headers/hlsl/hlsl_intrinsics.h
===================================================================
--- clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -15,11 +15,6 @@
// abs builtins
-__attribute__((clang_builtin_alias(__builtin_abs))) int abs(int In);
-__attribute__((clang_builtin_alias(__builtin_labs))) int64_t abs(int64_t In);
-__attribute__((clang_builtin_alias(__builtin_fabsf))) float abs(float In);
-__attribute__((clang_builtin_alias(__builtin_fabs))) double abs(double In);
-
#ifdef __HLSL_ENABLE_16_BIT
__attribute__((clang_builtin_alias(__builtin_elementwise_abs)))
int16_t abs(int16_t);
@@ -76,5 +71,33 @@
__attribute__((clang_builtin_alias(__builtin_sqrtf16))) half sqrt(half In);
#endif
+// ceil builtins
+#ifdef __HLSL_ENABLE_16_BIT
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil))) half ceil(half);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+half2 ceil(half2);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+half3 ceil(half3);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+half4 ceil(half4);
+#endif
+
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil))) float
+ceil(float);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+float2 ceil(float2);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+float3 ceil(float3);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+float4 ceil(float4);
+
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil))) double
+ceil(double);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+double2 ceil(double2);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+double3 ceil(double3);
+__attribute__((clang_builtin_alias(__builtin_elementwise_ceil)))
+double4 ceil(double4);
#endif //_HLSL_HLSL_INTRINSICS_H_
Index: clang/lib/Frontend/FrontendAction.cpp
===================================================================
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -28,6 +28,7 @@
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
+#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -1026,9 +1027,15 @@
// Setup HLSL External Sema Source
if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
- IntrusiveRefCntPtr<ExternalASTSource> HLSLSema(
+ IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema(
new HLSLExternalSemaSource());
- CI.getASTContext().setExternalSource(HLSLSema);
+ if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>(
+ CI.getASTContext().getExternalSource())) {
+ IntrusiveRefCntPtr<ExternalSemaSource> MultiSema(
+ new MultiplexExternalSemaSource(SemaSource, HLSLSema.get()));
+ CI.getASTContext().setExternalSource(MultiSema);
+ } else
+ CI.getASTContext().setExternalSource(HLSLSema);
}
FailureCleanup.release();
Index: clang/lib/Driver/ToolChains/PS4CPU.cpp
===================================================================
--- clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -159,17 +159,32 @@
const bool IsPS5 = TC.getTriple().isPS5();
assert(IsPS4 || IsPS5);
+ ArgStringList DbgOpts;
+
// This tells LTO to perform JustMyCode instrumentation.
- if (UseLTO && UseJMC) {
- if (IsPS4 && D.getLTOMode() == LTOK_Thin) {
- CmdArgs.push_back("-lto-thin-debug-options=-enable-jmc-instrument");
- } else if (IsPS4 && D.getLTOMode() == LTOK_Full) {
- CmdArgs.push_back("-lto-debug-options=-enable-jmc-instrument");
- } else if (IsPS5) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-enable-jmc-instrument");
- } else
- llvm_unreachable("new LTO mode?");
+ if (UseLTO && UseJMC)
+ DbgOpts.push_back("-enable-jmc-instrument");
+
+ // We default to creating the arange section, but LTO does not. Enable it
+ // here.
+ if (UseLTO)
+ DbgOpts.push_back("-generate-arange-section");
+
+ if (UseLTO) {
+ if (IsPS4) {
+ StringRef F = (D.getLTOMode() == LTOK_Thin) ?
+ "-lto-thin-debug-options=" : "-lto-debug-options=";
+ F = makeArgString(Args, F.data(), DbgOpts.front(), "");
+ DbgOpts.erase(DbgOpts.begin());
+ for (auto X : DbgOpts)
+ F = makeArgString(Args, F.data(), " ", X);
+ CmdArgs.push_back(F.data());
+ } else {
+ for (auto D : DbgOpts) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(D);
+ }
+ }
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
Index: clang/include/clang/Sema/HLSLExternalSemaSource.h
===================================================================
--- clang/include/clang/Sema/HLSLExternalSemaSource.h
+++ clang/include/clang/Sema/HLSLExternalSemaSource.h
@@ -22,7 +22,7 @@
class HLSLExternalSemaSource : public ExternalSemaSource {
Sema *SemaPtr = nullptr;
- NamespaceDecl *HLSLNamespace;
+ NamespaceDecl *HLSLNamespace = nullptr;
CXXRecordDecl *ResourceDecl;
using CompletionFunction = std::function<void(CXXRecordDecl *)>;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -158,6 +158,8 @@
- Fixed a crash in C++20 mode in Clang and Clangd when compile source
with compilation errors.
`Issue 53628 <https://github.com/llvm/llvm-project/issues/53628>`_
+- The template arguments of a variable template being accessed as a
+ member will now be represented in the AST.
Improvements to Clang's diagnostics
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits