From 8f711aa32488beb3382de101a290e11b41ceb876 Mon Sep 17 00:00:00 2001 From: Mital Ashok Date: Thu, 16 May 2024 08:45:45 +0100 Subject: [PATCH 001/576] [libc++][test] `__cpp_lib_within_lifetime` -> `__cpp_lib_is_within_lifetime` (#91896) The feature test macro was renamed when [P2641R4](https://wg21.link/P2641R4) was adopted into the standard: https://github.com/cplusplus/draft/commit/0facada4cadd97e1ba15bfaea76a804f1dc5c309 https://wg21.link/version.syn#lib:__cpp_lib_is_constant_evaluated --- libcxx/docs/FeatureTestMacroTable.rst | 4 +- libcxx/include/version | 4 +- .../type_traits.version.compile.pass.cpp | 68 +++++++++---------- .../version.version.compile.pass.cpp | 68 +++++++++---------- .../generate_feature_test_macro_components.py | 18 ++--- 5 files changed, 82 insertions(+), 80 deletions(-) diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 17b3476d2c869e..17d2da907692e8 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -436,6 +436,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_hazard_pointer`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_is_within_lifetime`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_linalg`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_out_ptr`` *unimplemented* @@ -465,7 +467,5 @@ Status ``__cpp_lib_to_chars`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_tuple_like`` *unimplemented* - ---------------------------------------------------------- ----------------- - ``__cpp_lib_within_lifetime`` *unimplemented* ========================================================== ================= diff --git a/libcxx/include/version b/libcxx/include/version index ba116957b033f5..69556d731f1cfc 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -143,6 +143,7 @@ __cpp_lib_is_null_pointer 201309L __cpp_lib_is_pointer_interconvertible 201907L __cpp_lib_is_scoped_enum 202011L __cpp_lib_is_swappable 201603L +__cpp_lib_is_within_lifetime 202306L __cpp_lib_jthread 201911L __cpp_lib_latch 201907L __cpp_lib_launder 201606L @@ -251,7 +252,6 @@ __cpp_lib_unreachable 202202L __cpp_lib_unwrap_ref 201811L __cpp_lib_variant 202102L __cpp_lib_void_t 201411L -__cpp_lib_within_lifetime 202306L */ @@ -520,6 +520,7 @@ __cpp_lib_within_lifetime 202306L // # define __cpp_lib_function_ref 202306L // # define __cpp_lib_generate_random 202403L // # define __cpp_lib_hazard_pointer 202306L +// # define __cpp_lib_is_within_lifetime 202306L // # define __cpp_lib_linalg 202311L # undef __cpp_lib_out_ptr // # define __cpp_lib_out_ptr 202311L @@ -538,7 +539,6 @@ __cpp_lib_within_lifetime 202306L // # define __cpp_lib_to_chars 202306L # undef __cpp_lib_tuple_like // # define __cpp_lib_tuple_like 202311L -// # define __cpp_lib_within_lifetime 202306L #endif // clang-format on diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp index b1dd76b98720d0..98277f832f5a04 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp @@ -30,6 +30,7 @@ __cpp_lib_is_pointer_interconvertible 201907L [C++20] __cpp_lib_is_scoped_enum 202011L [C++23] __cpp_lib_is_swappable 201603L [C++17] + __cpp_lib_is_within_lifetime 202306L [C++26] __cpp_lib_logical_traits 201510L [C++17] __cpp_lib_reference_from_temporary 202202L [C++23] __cpp_lib_remove_cvref 201711L [C++20] @@ -38,7 +39,6 @@ __cpp_lib_type_identity 201806L [C++20] __cpp_lib_type_trait_variable_templates 201510L [C++17] __cpp_lib_void_t 201411L [C++17] - __cpp_lib_within_lifetime 202306L [C++26] */ #include @@ -102,6 +102,10 @@ # error "__cpp_lib_is_swappable should not be defined before c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifdef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should not be defined before c++17" # endif @@ -134,10 +138,6 @@ # error "__cpp_lib_void_t should not be defined before c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 14 # ifdef __cpp_lib_bool_constant @@ -205,6 +205,10 @@ # error "__cpp_lib_is_swappable should not be defined before c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifdef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should not be defined before c++17" # endif @@ -243,10 +247,6 @@ # error "__cpp_lib_void_t should not be defined before c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 17 # ifndef __cpp_lib_bool_constant @@ -329,6 +329,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifndef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should be defined in c++17" # endif @@ -376,10 +380,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 20 # ifndef __cpp_lib_bool_constant @@ -489,6 +489,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++20" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifndef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should be defined in c++20" # endif @@ -542,10 +546,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++20" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 23 # ifndef __cpp_lib_bool_constant @@ -658,6 +658,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++23" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifndef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should be defined in c++23" # endif @@ -720,10 +724,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++23" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER > 23 # ifndef __cpp_lib_bool_constant @@ -836,6 +836,19 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++26" # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should be defined in c++26" +# endif +# if __cpp_lib_is_within_lifetime != 202306L +# error "__cpp_lib_is_within_lifetime should have the value 202306L in c++26" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined because it is unimplemented in libc++!" +# endif +# endif + # ifndef __cpp_lib_logical_traits # error "__cpp_lib_logical_traits should be defined in c++26" # endif @@ -898,18 +911,5 @@ # error "__cpp_lib_void_t should have the value 201411L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should be defined in c++26" -# endif -# if __cpp_lib_within_lifetime != 202306L -# error "__cpp_lib_within_lifetime should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined because it is unimplemented in libc++!" -# endif -# endif - #endif // TEST_STD_VER > 23 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index d7035d7e5e3ad8..7829e06f90760b 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -130,6 +130,7 @@ __cpp_lib_is_pointer_interconvertible 201907L [C++20] __cpp_lib_is_scoped_enum 202011L [C++23] __cpp_lib_is_swappable 201603L [C++17] + __cpp_lib_is_within_lifetime 202306L [C++26] __cpp_lib_jthread 201911L [C++20] __cpp_lib_latch 201907L [C++20] __cpp_lib_launder 201606L [C++17] @@ -232,7 +233,6 @@ __cpp_lib_unwrap_ref 201811L [C++20] __cpp_lib_variant 202102L [C++17] __cpp_lib_void_t 201411L [C++17] - __cpp_lib_within_lifetime 202306L [C++26] */ #include @@ -680,6 +680,10 @@ # error "__cpp_lib_is_swappable should not be defined before c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifdef __cpp_lib_jthread # error "__cpp_lib_jthread should not be defined before c++20" # endif @@ -1060,10 +1064,6 @@ # error "__cpp_lib_void_t should not be defined before c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 14 # ifdef __cpp_lib_adaptor_iterator_pair_constructor @@ -1530,6 +1530,10 @@ # error "__cpp_lib_is_swappable should not be defined before c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifdef __cpp_lib_jthread # error "__cpp_lib_jthread should not be defined before c++20" # endif @@ -1958,10 +1962,6 @@ # error "__cpp_lib_void_t should not be defined before c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 17 # ifdef __cpp_lib_adaptor_iterator_pair_constructor @@ -2518,6 +2518,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # ifdef __cpp_lib_jthread # error "__cpp_lib_jthread should not be defined before c++20" # endif @@ -3054,10 +3058,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++17" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 20 # ifdef __cpp_lib_adaptor_iterator_pair_constructor @@ -3797,6 +3797,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++20" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC) # ifndef __cpp_lib_jthread # error "__cpp_lib_jthread should be defined in c++20" @@ -4438,10 +4442,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++20" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER == 23 # ifndef __cpp_lib_adaptor_iterator_pair_constructor @@ -5259,6 +5259,10 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++23" # endif +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined before c++26" +# endif + # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC) # ifndef __cpp_lib_jthread # error "__cpp_lib_jthread should be defined in c++23" @@ -6056,10 +6060,6 @@ # error "__cpp_lib_void_t should have the value 201411L in c++23" # endif -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined before c++26" -# endif - #elif TEST_STD_VER > 23 # ifndef __cpp_lib_adaptor_iterator_pair_constructor @@ -7042,6 +7042,19 @@ # error "__cpp_lib_is_swappable should have the value 201603L in c++26" # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should be defined in c++26" +# endif +# if __cpp_lib_is_within_lifetime != 202306L +# error "__cpp_lib_is_within_lifetime should have the value 202306L in c++26" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_is_within_lifetime +# error "__cpp_lib_is_within_lifetime should not be defined because it is unimplemented in libc++!" +# endif +# endif + # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC) # ifndef __cpp_lib_jthread # error "__cpp_lib_jthread should be defined in c++26" @@ -7911,18 +7924,5 @@ # error "__cpp_lib_void_t should have the value 201411L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should be defined in c++26" -# endif -# if __cpp_lib_within_lifetime != 202306L -# error "__cpp_lib_within_lifetime should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_within_lifetime -# error "__cpp_lib_within_lifetime should not be defined because it is unimplemented in libc++!" -# endif -# endif - #endif // TEST_STD_VER > 23 diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index d0171c84acbc32..b04cb4f5115547 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -767,6 +767,16 @@ def add_version_header(tc): "values": {"c++17": 201603}, "headers": ["type_traits"], }, + { + "name": "__cpp_lib_is_within_lifetime", + # Note this name was changed from "__cpp_lib_within_lifetime" when the paper was adopted + # https://github.com/cplusplus/draft/commit/0facada4cadd97e1ba15bfaea76a804f1dc5c309 + "values": { + "c++26": 202306 # P2641R4 Checking if a union alternative is active + }, + "headers": ["type_traits"], + "unimplemented": True, + }, { "name": "__cpp_lib_jthread", "values": {"c++20": 201911}, @@ -1342,14 +1352,6 @@ def add_version_header(tc): "values": {"c++17": 201411}, "headers": ["type_traits"], }, - { - "name": "__cpp_lib_within_lifetime", - "values": { - "c++26": 202306 # P2641R4 Checking if a union alternative is active - }, - "headers": ["type_traits"], - "unimplemented": True, - }, ] ] From dcd32bd65f16e80db2485e6e02b62d6a91c3cddf Mon Sep 17 00:00:00 2001 From: Adam Siemieniuk Date: Thu, 16 May 2024 10:05:12 +0200 Subject: [PATCH 002/576] [mlir][tensor] Fold pack-unpack with unbalanced outer_dims_perm attr (#92234) Extends pack/unpack perm attribute checker to account for cases when the optional outer_dims_perm attribute might be missing in one operation and the other one has explicit identity permutation. This enables canonicalizer to fold more unpack(pack(x)) variants. --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 8 ++++++- mlir/test/Dialect/Tensor/canonicalize.mlir | 26 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index d3b1754cbe1cd8..8a6df82abb312a 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -4112,7 +4112,13 @@ Speculation::Speculatability PackOp::getSpeculatability() { static bool hasSameInnerOuterAttribute(PackOp packOp, UnPackOp unPackOp) { if (packOp.getInnerDimsPos() != unPackOp.getInnerDimsPos()) return false; - return packOp.getOuterDimsPerm() == unPackOp.getOuterDimsPerm(); + if (packOp.getOuterDimsPerm() == unPackOp.getOuterDimsPerm()) + return true; + // Outer dims permutation is optional. + // To compare unbalanced pack-unpack pair, treat no permutation as equal to + // identity permutation. + return isIdentityPermutation(packOp.getOuterDimsPerm()) && + isIdentityPermutation(unPackOp.getOuterDimsPerm()); } // Return true if pack and unpack have the same tiles. diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 8036d996d23246..b5a82eb3e9035d 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -2252,6 +2252,32 @@ func.func @pack_unpack_dynamic_with_padding(%t: tensor, %dim1: inde // ----- +// CHECK: func.func @pack_outer_dims_unpack_no_outer_dims( +// CHECK-SAME: %[[T:.+]]: tensor<16x16x?x?xf32>, +// CHECK: return %[[T]] : tensor<16x16x?x?xf32> +func.func @pack_outer_dims_unpack_no_outer_dims(%t: tensor<16x16x?x?xf32>, %tile1: index, %tile2: index) -> tensor<16x16x?x?xf32> { + %tensor_empty = tensor.empty() : tensor<128x128xf32> + %unpacked = tensor.unpack %t inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<16x16x?x?xf32> -> tensor<128x128xf32> + %tensor_empty1 = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32> + %packed = tensor.pack %unpacked outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x?x?xf32> + return %packed : tensor<16x16x?x?xf32> +} + +// ----- + +// CHECK: func.func @pack_no_outer_dims_unpack_outer_dims( +// CHECK-SAME: %[[T:.+]]: tensor<16x16x?x?xf32>, +// CHECK: return %[[T]] : tensor<16x16x?x?xf32> +func.func @pack_no_outer_dims_unpack_outer_dims(%t: tensor<16x16x?x?xf32>, %tile1: index, %tile2: index) -> tensor<16x16x?x?xf32> { + %tensor_empty = tensor.empty() : tensor<128x128xf32> + %unpacked = tensor.unpack %t outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty : tensor<16x16x?x?xf32> -> tensor<128x128xf32> + %tensor_empty1 = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32> + %packed = tensor.pack %unpacked inner_dims_pos = [0, 1] inner_tiles = [%tile1, %tile2] into %tensor_empty1 : tensor<128x128xf32> -> tensor<16x16x?x?xf32> + return %packed : tensor<16x16x?x?xf32> +} + +// ----- + // CHECK: func.func @invalid_empty_negative_size // CHECK: %[[IDX:.*]] = index.constant // CHECK: %[[T:.*]] = tensor.empty(%[[IDX]]) : tensor<4x5x?xf32> From cd5ee2715e89ad31982f91cc85fc3939977f2f4e Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Thu, 16 May 2024 09:10:59 +0100 Subject: [PATCH 003/576] [reland][flang] Initial debug info support for local variables (#92304) This is same as #90905 with an added fix. The issue was that we generated variable info even when user asked for line-tables-only. This caused llvm dwarf generation code to fail an assertion as it expected an empty variable list. Fixed by not generating debug info for variables when user wants only line table. I also updated a test check for this case. --- .../flang}/Optimizer/CodeGen/CGOps.h | 1 + .../include/flang/Optimizer/CodeGen/CGOps.td | 34 +++++++ .../flang/Optimizer/CodeGen/CGPasses.td | 4 + .../include/flang/Optimizer/CodeGen/CodeGen.h | 6 +- flang/include/flang/Tools/CLOptions.inc | 11 ++- flang/lib/Optimizer/CodeGen/CGOps.cpp | 2 +- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 50 +++++++--- flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp | 49 ++++++++-- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 60 +++++++++++- .../Transforms/DebugTypeGenerator.cpp | 10 +- flang/test/Fir/declare-codegen.fir | 22 +++-- flang/test/Fir/dummy-scope-codegen.fir | 11 ++- flang/test/Transforms/debug-local-var-2.f90 | 94 +++++++++++++++++++ flang/test/Transforms/debug-local-var.f90 | 54 +++++++++++ 14 files changed, 361 insertions(+), 47 deletions(-) rename flang/{lib => include/flang}/Optimizer/CodeGen/CGOps.h (94%) create mode 100644 flang/test/Transforms/debug-local-var-2.f90 create mode 100644 flang/test/Transforms/debug-local-var.f90 diff --git a/flang/lib/Optimizer/CodeGen/CGOps.h b/flang/include/flang/Optimizer/CodeGen/CGOps.h similarity index 94% rename from flang/lib/Optimizer/CodeGen/CGOps.h rename to flang/include/flang/Optimizer/CodeGen/CGOps.h index b5a6d5bb9a9e6f..df909d9ee81cb4 100644 --- a/flang/lib/Optimizer/CodeGen/CGOps.h +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.h @@ -13,6 +13,7 @@ #ifndef OPTIMIZER_CODEGEN_CGOPS_H #define OPTIMIZER_CODEGEN_CGOPS_H +#include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/flang/include/flang/Optimizer/CodeGen/CGOps.td b/flang/include/flang/Optimizer/CodeGen/CGOps.td index 35e70fa2ffa3fb..c375edee1fa77f 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGOps.td +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.td @@ -16,6 +16,8 @@ include "mlir/IR/SymbolInterfaces.td" include "flang/Optimizer/Dialect/FIRTypes.td" +include "flang/Optimizer/Dialect/FIRAttr.td" +include "mlir/IR/BuiltinAttributes.td" def fircg_Dialect : Dialect { let name = "fircg"; @@ -202,4 +204,36 @@ def fircg_XArrayCoorOp : fircg_Op<"ext_array_coor", [AttrSizedOperandSegments]> }]; } +// Extended Declare operation. +def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> { + let summary = "for internal conversion only"; + + let description = [{ + Prior to lowering to LLVM IR dialect, a DeclareOp will + be converted to an extended DeclareOp. + }]; + + let arguments = (ins + AnyRefOrBox:$memref, + Variadic:$shape, + Variadic:$shift, + Variadic:$typeparams, + Optional:$dummy_scope, + Builtin_StringAttr:$uniq_name + ); + let results = (outs AnyRefOrBox); + + let assemblyFormat = [{ + $memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)? + (`dummy_scope` $dummy_scope^)? + attr-dict `:` functional-type(operands, results) + }]; + + let extraClassDeclaration = [{ + // Shape is optional, but if it exists, it will be at offset 1. + unsigned shapeOffset() { return 1; } + unsigned shiftOffset() { return shapeOffset() + getShape().size(); } + }]; +} + #endif diff --git a/flang/include/flang/Optimizer/CodeGen/CGPasses.td b/flang/include/flang/Optimizer/CodeGen/CGPasses.td index f524fb42373444..565920e55e6a8d 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGPasses.td +++ b/flang/include/flang/Optimizer/CodeGen/CGPasses.td @@ -47,6 +47,10 @@ def CodeGenRewrite : Pass<"cg-rewrite", "mlir::ModuleOp"> { let dependentDialects = [ "fir::FIROpsDialect", "fir::FIRCodeGenDialect" ]; + let options = [ + Option<"preserveDeclare", "preserve-declare", "bool", /*default=*/"false", + "Preserve DeclareOp during pre codegen re-write."> + ]; let statistics = [ Statistic<"numDCE", "num-dce'd", "Number of operations eliminated"> ]; diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index 26097dabf56c45..4d2b191b46d088 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -30,7 +30,8 @@ struct NameUniquer; /// Prerequiste pass for code gen. Perform intermediate rewrites to perform /// the code gen (to LLVM-IR dialect) conversion. -std::unique_ptr createFirCodeGenRewritePass(); +std::unique_ptr createFirCodeGenRewritePass( + CodeGenRewriteOptions Options = CodeGenRewriteOptions{}); /// FirTargetRewritePass options. struct TargetRewriteOptions { @@ -88,7 +89,8 @@ void populateFIRToLLVMConversionPatterns(fir::LLVMTypeConverter &converter, fir::FIRToLLVMPassOptions &options); /// Populate the pattern set with the PreCGRewrite patterns. -void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns); +void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, + bool preserveDeclare); // declarative passes #define GEN_PASS_REGISTRATION diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 1817dd6ca4a7df..9c4a30dcf30199 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -174,9 +174,11 @@ inline void addMemoryAllocationOpt(mlir::PassManager &pm) { } #if !defined(FLANG_EXCLUDE_CODEGEN) -inline void addCodeGenRewritePass(mlir::PassManager &pm) { - addPassConditionally( - pm, disableCodeGenRewrite, fir::createFirCodeGenRewritePass); +inline void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) { + fir::CodeGenRewriteOptions options; + options.preserveDeclare = preserveDeclare; + addPassConditionally(pm, disableCodeGenRewrite, + [&]() { return fir::createFirCodeGenRewritePass(options); }); } inline void addTargetRewritePass(mlir::PassManager &pm) { @@ -358,7 +360,8 @@ inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) { fir::addBoxedProcedurePass(pm); addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); - fir::addCodeGenRewritePass(pm); + fir::addCodeGenRewritePass( + pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo)); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename); diff --git a/flang/lib/Optimizer/CodeGen/CGOps.cpp b/flang/lib/Optimizer/CodeGen/CGOps.cpp index 44d07d26dd2b68..6b8ba74525556e 100644 --- a/flang/lib/Optimizer/CodeGen/CGOps.cpp +++ b/flang/lib/Optimizer/CodeGen/CGOps.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "CGOps.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 21154902d23f8f..72172f63888e1c 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -12,7 +12,7 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" -#include "CGOps.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/CodeGen/CodeGenOpenMP.h" #include "flang/Optimizer/CodeGen/FIROpPatterns.h" #include "flang/Optimizer/CodeGen/TypeConverter.h" @@ -170,6 +170,28 @@ genAllocationScaleSize(OP op, mlir::Type ity, return nullptr; } +namespace { +struct DeclareOpConversion : public fir::FIROpConversion { +public: + using FIROpConversion::FIROpConversion; + mlir::LogicalResult + matchAndRewrite(fir::cg::XDeclareOp declareOp, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto memRef = adaptor.getOperands()[0]; + if (auto fusedLoc = mlir::dyn_cast(declareOp.getLoc())) { + if (auto varAttr = + mlir::dyn_cast_or_null( + fusedLoc.getMetadata())) { + rewriter.create(memRef.getLoc(), memRef, + varAttr, nullptr); + } + } + rewriter.replaceOp(declareOp, memRef); + return mlir::success(); + } +}; +} // namespace + namespace { /// convert to LLVM IR dialect `alloca` struct AllocaOpConversion : public fir::FIROpConversion { @@ -3714,19 +3736,19 @@ void fir::populateFIRToLLVMConversionPatterns( BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, CmpcOpConversion, ConstcOpConversion, ConvertOpConversion, - CoordinateOpConversion, DTEntryOpConversion, DivcOpConversion, - EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, - ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, - FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, - HasValueOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, - IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion, - MulcOpConversion, NegcOpConversion, NoReassocOpConversion, - SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion, - SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion, - ShiftOpConversion, SliceOpConversion, StoreOpConversion, - StringLitOpConversion, SubcOpConversion, TypeDescOpConversion, - TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion, - UndefOpConversion, UnreachableOpConversion, + CoordinateOpConversion, DTEntryOpConversion, DeclareOpConversion, + DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion, + EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion, + FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion, + GlobalOpConversion, HasValueOpConversion, InsertOnRangeOpConversion, + InsertValueOpConversion, IsPresentOpConversion, LenParamIndexOpConversion, + LoadOpConversion, MulcOpConversion, NegcOpConversion, + NoReassocOpConversion, SelectCaseOpConversion, SelectOpConversion, + SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion, + ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion, + StoreOpConversion, StringLitOpConversion, SubcOpConversion, + TypeDescOpConversion, TypeInfoOpConversion, UnboxCharOpConversion, + UnboxProcOpConversion, UndefOpConversion, UnreachableOpConversion, UnrealizedConversionCastOpConversion, XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter, options); diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp index 5bd3ec8d18450e..c54a7457db7610 100644 --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -12,8 +12,8 @@ #include "flang/Optimizer/CodeGen/CodeGen.h" -#include "CGOps.h" #include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -270,13 +270,43 @@ class ArrayCoorConversion : public mlir::OpRewritePattern { }; class DeclareOpConversion : public mlir::OpRewritePattern { + bool preserveDeclare; + public: using OpRewritePattern::OpRewritePattern; + DeclareOpConversion(mlir::MLIRContext *ctx, bool preserveDecl) + : OpRewritePattern(ctx), preserveDeclare(preserveDecl) {} mlir::LogicalResult matchAndRewrite(fir::DeclareOp declareOp, mlir::PatternRewriter &rewriter) const override { - rewriter.replaceOp(declareOp, declareOp.getMemref()); + if (!preserveDeclare) { + rewriter.replaceOp(declareOp, declareOp.getMemref()); + return mlir::success(); + } + auto loc = declareOp.getLoc(); + llvm::SmallVector shapeOpers; + llvm::SmallVector shiftOpers; + if (auto shapeVal = declareOp.getShape()) { + if (auto shapeOp = mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShape(shapeOpers, shapeOp); + else if (auto shiftOp = + mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShapeAndShift(shapeOpers, shiftOpers, shiftOp); + else if (auto shiftOp = + mlir::dyn_cast(shapeVal.getDefiningOp())) + populateShift(shiftOpers, shiftOp); + else + return mlir::failure(); + } + // FIXME: Add FortranAttrs and CudaAttrs + auto xDeclOp = rewriter.create( + loc, declareOp.getType(), declareOp.getMemref(), shapeOpers, shiftOpers, + declareOp.getTypeparams(), declareOp.getDummyScope(), + declareOp.getUniqName()); + LLVM_DEBUG(llvm::dbgs() + << "rewriting " << declareOp << " to " << xDeclOp << '\n'); + rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults()); return mlir::success(); } }; @@ -297,6 +327,7 @@ class DummyScopeOpConversion class CodeGenRewrite : public fir::impl::CodeGenRewriteBase { public: + CodeGenRewrite(fir::CodeGenRewriteOptions opts) : Base(opts) {} void runOnOperation() override final { mlir::ModuleOp mod = getOperation(); @@ -314,7 +345,7 @@ class CodeGenRewrite : public fir::impl::CodeGenRewriteBase { mlir::cast(embox.getType()).getEleTy())); }); mlir::RewritePatternSet patterns(&context); - fir::populatePreCGRewritePatterns(patterns); + fir::populatePreCGRewritePatterns(patterns, preserveDeclare); if (mlir::failed( mlir::applyPartialConversion(mod, target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(&context), @@ -330,12 +361,14 @@ class CodeGenRewrite : public fir::impl::CodeGenRewriteBase { } // namespace -std::unique_ptr fir::createFirCodeGenRewritePass() { - return std::make_unique(); +std::unique_ptr +fir::createFirCodeGenRewritePass(fir::CodeGenRewriteOptions Options) { + return std::make_unique(Options); } -void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns) { +void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns, + bool preserveDeclare) { patterns.insert( - patterns.getContext()); + DummyScopeOpConversion>(patterns.getContext()); + patterns.add(patterns.getContext(), preserveDeclare); } diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 908c8fc96f633e..07e8aed4cd07b6 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -15,6 +15,7 @@ #include "flang/Common/Version.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/CodeGen/CGOps.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -45,13 +46,59 @@ namespace fir { namespace { class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { + void handleDeclareOp(fir::cg::XDeclareOp declOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scopeAttr, + fir::DebugTypeGenerator &typeGen); + public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} void runOnOperation() override; }; +static uint32_t getLineFromLoc(mlir::Location loc) { + uint32_t line = 1; + if (auto fileLoc = mlir::dyn_cast(loc)) + line = fileLoc.getLine(); + return line; +} + } // namespace +void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scopeAttr, + fir::DebugTypeGenerator &typeGen) { + mlir::MLIRContext *context = &getContext(); + mlir::OpBuilder builder(context); + auto result = fir::NameUniquer::deconstruct(declOp.getUniqName()); + + if (result.first != fir::NameUniquer::NameKind::VARIABLE) + return; + + // Only accept local variables. + if (result.second.procs.empty()) + return; + + // FIXME: There may be cases where an argument is processed a bit before + // DeclareOp is generated. In that case, DeclareOp may point to an + // intermediate op and not to BlockArgument. We need to find those cases and + // walk the chain to get to the actual argument. + + unsigned argNo = 0; + if (auto Arg = llvm::dyn_cast(declOp.getMemref())) + argNo = Arg.getArgNumber() + 1; + + auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()), + fileAttr, scopeAttr, declOp.getLoc()); + + auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get( + context, scopeAttr, mlir::StringAttr::get(context, result.second.name), + fileAttr, getLineFromLoc(declOp.getLoc()), argNo, /* alignInBits*/ 0, + tyAttr); + declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr)); +} + void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); @@ -144,14 +191,19 @@ void AddDebugInfoPass::runOnOperation() { subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } - unsigned line = 1; - if (auto funcLoc = mlir::dyn_cast(l)) - line = funcLoc.getLine(); - + unsigned line = getLineFromLoc(l); auto spAttr = mlir::LLVM::DISubprogramAttr::get( context, id, compilationUnit, fileAttr, funcName, fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); + + // Don't process variables if user asked for line tables only. + if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly) + return; + + funcOp.walk([&](fir::cg::XDeclareOp declOp) { + handleDeclareOp(declOp, fileAttr, spAttr, typeGen); + }); }); } diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index e5b4050dfb2426..64c6547e06e0f9 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -24,11 +24,6 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m) LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n"); } -static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { - return mlir::LLVM::DIBasicTypeAttr::get( - context, llvm::dwarf::DW_TAG_base_type, "void", 32, 1); -} - static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, mlir::StringAttr name, unsigned bitSize, @@ -37,6 +32,11 @@ static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, context, llvm::dwarf::DW_TAG_base_type, name, bitSize, decoding); } +static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { + return genBasicType(context, mlir::StringAttr::get(context, "integer"), 32, + llvm::dwarf::DW_ATE_signed); +} + mlir::LLVM::DITypeAttr DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, diff --git a/flang/test/Fir/declare-codegen.fir b/flang/test/Fir/declare-codegen.fir index 9d68d3b2f9d4de..c5879facb1572f 100644 --- a/flang/test/Fir/declare-codegen.fir +++ b/flang/test/Fir/declare-codegen.fir @@ -1,5 +1,7 @@ // Test rewrite of fir.declare. The result is replaced by the memref operand. -// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s +// RUN: fir-opt --cg-rewrite="preserve-declare=true" %s -o - | FileCheck %s --check-prefixes DECL +// RUN: fir-opt --cg-rewrite="preserve-declare=false" %s -o - | FileCheck %s --check-prefixes NODECL +// RUN: fir-opt --cg-rewrite %s -o - | FileCheck %s --check-prefixes NODECL func.func @test(%arg0: !fir.ref>) { @@ -15,9 +17,14 @@ func.func @test(%arg0: !fir.ref>) { func.func private @bar(%arg0: !fir.ref>) -// CHECK-LABEL: func.func @test( -// CHECK-SAME: %[[arg0:.*]]: !fir.ref>) { -// CHECK-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () +// NODECL-LABEL: func.func @test( +// NODECL-SAME: %[[arg0:.*]]: !fir.ref>) { +// NODECL-NEXT: fir.call @bar(%[[arg0]]) : (!fir.ref>) -> () + +// DECL-LABEL: func.func @test( +// DECL-SAME: %[[arg0:.*]]: !fir.ref>) { +// DECL: fircg.ext_declare + func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref>) { %c3 = arith.constant 3 : index @@ -26,5 +33,8 @@ func.func @useless_shape_with_duplicate_extent_operand(%arg0: !fir.ref) { %scope = fir.dummy_scope : !fir.dscope %0 = fir.declare %arg0 dummy_scope %scope {uniq_name = "x"} : (!fir.ref, !fir.dscope) -> !fir.ref return } -// CHECK-LABEL: func.func @dummy_scope( -// CHECK-NEXT: return +// DECL-LABEL: func.func @dummy_scope( +// DECL: fircg.ext_declare + +// NODECL-LABEL: func.func @dummy_scope( +// NODECL-NEXT: return \ No newline at end of file diff --git a/flang/test/Transforms/debug-local-var-2.f90 b/flang/test/Transforms/debug-local-var-2.f90 new file mode 100644 index 00000000000000..0fe1b81c27e61e --- /dev/null +++ b/flang/test/Transforms/debug-local-var-2.f90 @@ -0,0 +1,94 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck --check-prefix=LINEONLY %s + +! This tests checks the debug information for local variables in llvm IR. + +! CHECK-LABEL: define void @_QQmain +! CHECK-DAG: %[[AL11:.*]] = alloca i32 +! CHECK-DAG: %[[AL12:.*]] = alloca i64 +! CHECK-DAG: %[[AL13:.*]] = alloca i8 +! CHECK-DAG: %[[AL14:.*]] = alloca i32 +! CHECK-DAG: %[[AL15:.*]] = alloca float +! CHECK-DAG: %[[AL16:.*]] = alloca double +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL11]], metadata ![[I4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL12]], metadata ![[I8:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL13]], metadata ![[L1:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL14]], metadata ![[L4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL15]], metadata ![[R4:.*]], metadata !DIExpression()) +! CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[AL16]], metadata ![[R8:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +! CHECK-LABEL: define {{.*}}i64 @_QFPfn1 +! CHECK-SAME: (ptr %[[ARG1:.*]], ptr %[[ARG2:.*]], ptr %[[ARG3:.*]]) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG1]], metadata ![[A1:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG2]], metadata ![[B1:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[ARG3]], metadata ![[C1:.*]], metadata !DIExpression()) +! CHECK-DAG: %[[AL2:.*]] = alloca i64 +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL2]], metadata ![[RES1:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +! CHECK-LABEL: define {{.*}}i32 @_QFPfn2 +! CHECK-SAME: (ptr %[[FN2ARG1:.*]], ptr %[[FN2ARG2:.*]], ptr %[[FN2ARG3:.*]]) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG1]], metadata ![[A2:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG2]], metadata ![[B2:.*]], metadata !DIExpression()) +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[FN2ARG3]], metadata ![[C2:.*]], metadata !DIExpression()) +! CHECK-DAG: %[[AL3:.*]] = alloca i32 +! CHECK-DAG: tail call void @llvm.dbg.declare(metadata ptr %[[AL3]], metadata ![[RES2:.*]], metadata !DIExpression()) +! CHECK-LABEL: } + +program mn +! CHECK-DAG: ![[MAIN:.*]] = distinct !DISubprogram(name: "_QQmain", {{.*}}) + +! CHECK-DAG: ![[TYI32:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) +! CHECK-DAG: ![[TYI64:.*]] = !DIBasicType(name: "integer", size: 64, encoding: DW_ATE_signed) +! CHECK-DAG: ![[TYL8:.*]] = !DIBasicType(name: "logical", size: 8, encoding: DW_ATE_boolean) +! CHECK-DAG: ![[TYL32:.*]] = !DIBasicType(name: "logical", size: 32, encoding: DW_ATE_boolean) +! CHECK-DAG: ![[TYR32:.*]] = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float) +! CHECK-DAG: ![[TYR64:.*]] = !DIBasicType(name: "real", size: 64, encoding: DW_ATE_float) + +! CHECK-DAG: ![[I4]] = !DILocalVariable(name: "i4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI32]]) +! CHECK-DAG: ![[I8]] = !DILocalVariable(name: "i8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYI64]]) +! CHECK-DAG: ![[R4]] = !DILocalVariable(name: "r4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR32]]) +! CHECK-DAG: ![[R8]] = !DILocalVariable(name: "r8", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYR64]]) +! CHECK-DAG: ![[L1]] = !DILocalVariable(name: "l1", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL8]]) +! CHECK-DAG: ![[L4]] = !DILocalVariable(name: "l4", scope: ![[MAIN]], file: !{{.*}}, line: [[@LINE+6]], type: ![[TYL32]]) + integer(kind=4) :: i4 + integer(kind=8) :: i8 + real(kind=4) :: r4 + real(kind=8) :: r8 + logical(kind=1) :: l1 + logical(kind=4) :: l4 + + i8 = fn1(i4, r8, l1) + i4 = fn2(i8, r4, l4) +contains +! CHECK-DAG: ![[FN1:.*]] = distinct !DISubprogram(name: "fn1", {{.*}}) +! CHECK-DAG: ![[A1]] = !DILocalVariable(name: "a1", arg: 1, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) +! CHECK-DAG: ![[B1]] = !DILocalVariable(name: "b1", arg: 2, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR64]]) +! CHECK-DAG: ![[C1]] = !DILocalVariable(name: "c1", arg: 3, scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL8]]) +! CHECK-DAG: ![[RES1]] = !DILocalVariable(name: "res1", scope: ![[FN1]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) + function fn1(a1, b1, c1) result (res1) + integer(kind=4), intent(in) :: a1 + real(kind=8), intent(in) :: b1 + logical(kind=1), intent(in) :: c1 + integer(kind=8) :: res1 + + res1 = a1 + b1 + end function + +! CHECK-DAG: ![[FN2:.*]] = distinct !DISubprogram(name: "fn2", {{.*}}) +! CHECK-DAG: ![[A2]] = !DILocalVariable(name: "a2", arg: 1, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI64]]) +! CHECK-DAG: ![[B2]] = !DILocalVariable(name: "b2", arg: 2, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYR32]]) +! CHECK-DAG: ![[C2]] = !DILocalVariable(name: "c2", arg: 3, scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYL32]]) +! CHECK-DAG: ![[RES2]] = !DILocalVariable(name: "res2", scope: ![[FN2]], file: !{{.*}}, line: [[@LINE+5]], type: ![[TYI32]]) + function fn2(a2, b2, c2) result (res2) + integer(kind=8), intent(in) :: a2 + real(kind=4), intent(in) :: b2 + logical(kind=4), intent(in) :: c2 + integer(kind=4) :: res2 + + res2 = a2 + b2 + end function +end program + +LINEONLY-NOT: DILocalVariable diff --git a/flang/test/Transforms/debug-local-var.f90 b/flang/test/Transforms/debug-local-var.f90 new file mode 100644 index 00000000000000..96dc111ad308e1 --- /dev/null +++ b/flang/test/Transforms/debug-local-var.f90 @@ -0,0 +1,54 @@ +! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | \ +! RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s + +! CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[MAIN:.*]] = #llvm.di_subprogram<{{.*}}name = "_QQmain"{{.*}}> +! CHECK-DAG: #[[FN1:.*]] = #llvm.di_subprogram<{{.*}}name = "fn1"{{.*}}> +! CHECK-DAG: #[[FN2:.*]] = #llvm.di_subprogram<{{.*}}name = "fn2"{{.*}}> + +program mn +! CHECK-DAG: #[[I4:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[I8:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[R4:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[R8:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[L1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[L4:.*]] = #llvm.di_local_variable + integer(kind=4) :: i4 + integer(kind=8) :: i8 + real(kind=4) :: r4 + real(kind=8) :: r8 + logical(kind=1) :: l1 + logical(kind=4) :: l4 + i8 = fn1(i4, r8, l1) + i4 = fn2(i8, r4, l4) +contains + function fn1(a1, b1, c1) result (res1) +! CHECK-DAG: #[[A1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[B1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[C1:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[RES1:.*]] = #llvm.di_local_variable + integer(kind=4), intent(in) :: a1 + real(kind=8), intent(in) :: b1 + logical(kind=1), intent(in) :: c1 + integer(kind=8) :: res1 + res1 = a1 + b1 + end function + + function fn2(a2, b2, c2) result (res2) + implicit none +! CHECK-DAG: #[[A2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[B2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[C2:.*]] = #llvm.di_local_variable +! CHECK-DAG: #[[RES2:.*]] = #llvm.di_local_variable + integer(kind=8), intent(in) :: a2 + real(kind=4), intent(in) :: b2 + logical(kind=4), intent(in) :: c2 + integer(kind=4) :: res2 + res2 = a2 + b2 + end function +end program From 0ea178b085ba386d9d7bfea5afa072aa37f633fd Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 16 May 2024 10:24:56 +0200 Subject: [PATCH 004/576] SimplifyLibCalls: Emit vector ldexp intrinsics in exp2->ldexp combine (#92219) Co-authored-by: Nikita Popov --- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 17 +++++----- llvm/test/Transforms/InstCombine/exp2-1.ll | 13 +++----- .../Transforms/InstCombine/exp2-to-ldexp.ll | 32 +++++++++++++------ .../test/Transforms/InstCombine/pow_fp_int.ll | 4 +-- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 134eeba3996aa6..c9f6839e4b94a5 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1992,11 +1992,12 @@ static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth) { Value *Op = cast(I2F)->getOperand(0); // Make sure that the exponent fits inside an "int" of size DstWidth, // thus avoiding any range issues that FP has not. - unsigned BitWidth = Op->getType()->getPrimitiveSizeInBits(); - if (BitWidth < DstWidth || - (BitWidth == DstWidth && isa(I2F))) - return isa(I2F) ? B.CreateSExt(Op, B.getIntNTy(DstWidth)) - : B.CreateZExt(Op, B.getIntNTy(DstWidth)); + unsigned BitWidth = Op->getType()->getScalarSizeInBits(); + if (BitWidth < DstWidth || (BitWidth == DstWidth && isa(I2F))) { + Type *IntTy = Op->getType()->getWithNewBitWidth(DstWidth); + return isa(I2F) ? B.CreateSExt(Op, IntTy) + : B.CreateZExt(Op, IntTy); + } } return nullptr; @@ -2366,10 +2367,10 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { hasFloatVersion(M, Name)) Ret = optimizeUnaryDoubleFP(CI, B, TLI, true); + const bool UseIntrinsic = CI->doesNotAccessMemory(); // Bail out for vectors because the code below only expects scalars. - // TODO: This could be allowed if we had a ldexp intrinsic (D14327). Type *Ty = CI->getType(); - if (Ty->isVectorTy()) + if (!UseIntrinsic && Ty->isVectorTy()) return Ret; // exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= IntSize @@ -2382,7 +2383,7 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { // TODO: Emitting the intrinsic should not depend on whether the libcall // is available. - if (CI->doesNotAccessMemory()) { + if (UseIntrinsic) { return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp, {Ty, Exp->getType()}, {One, Exp}, CI)); diff --git a/llvm/test/Transforms/InstCombine/exp2-1.ll b/llvm/test/Transforms/InstCombine/exp2-1.ll index 5bf70320d9ec44..2dff0b08ecf97b 100644 --- a/llvm/test/Transforms/InstCombine/exp2-1.ll +++ b/llvm/test/Transforms/InstCombine/exp2-1.ll @@ -308,20 +308,15 @@ define float @sitofp_scalar_intrinsic_with_FMF(i8 %x) { define <2 x float> @sitofp_vector_intrinsic_with_FMF(<2 x i8> %x) { ; LDEXP32-LABEL: @sitofp_vector_intrinsic_with_FMF( -; LDEXP32-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float> -; LDEXP32-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) +; LDEXP32-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32> +; LDEXP32-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[TMP1]]) ; LDEXP32-NEXT: ret <2 x float> [[R]] ; ; LDEXP16-LABEL: @sitofp_vector_intrinsic_with_FMF( -; LDEXP16-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float> -; LDEXP16-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) +; LDEXP16-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i16> +; LDEXP16-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.ldexp.v2f32.v2i16(<2 x float> , <2 x i16> [[TMP1]]) ; LDEXP16-NEXT: ret <2 x float> [[R]] ; -; NOLDEXPF-LABEL: @sitofp_vector_intrinsic_with_FMF( -; NOLDEXPF-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float> -; NOLDEXPF-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) -; NOLDEXPF-NEXT: ret <2 x float> [[R]] -; ; NOLDEXP-LABEL: @sitofp_vector_intrinsic_with_FMF( ; NOLDEXP-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float> ; NOLDEXP-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) diff --git a/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll index 3069ee65e238ad..6e5be5a19d6da5 100644 --- a/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll +++ b/llvm/test/Transforms/InstCombine/exp2-to-ldexp.ll @@ -39,11 +39,17 @@ define float @exp2_f32_sitofp_i8_flags(i8 %x) { } define <2 x float> @exp2_v2f32_sitofp_v2i8(<2 x i8> %x) { -; CHECK-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( -; CHECK-SAME: <2 x i8> [[X:%.*]]) { -; CHECK-NEXT: [[ITOFP:%.*]] = sitofp <2 x i8> [[X]] to <2 x float> -; CHECK-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]]) -; CHECK-NEXT: ret <2 x float> [[EXP2]] +; LDEXP-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( +; LDEXP-SAME: <2 x i8> [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X]] to <2 x i32> +; LDEXP-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[TMP1]]) +; LDEXP-NEXT: ret <2 x float> [[EXP2]] +; +; NOLDEXP-LABEL: define <2 x float> @exp2_v2f32_sitofp_v2i8( +; NOLDEXP-SAME: <2 x i8> [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp <2 x i8> [[X]] to <2 x float> +; NOLDEXP-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[ITOFP]]) +; NOLDEXP-NEXT: ret <2 x float> [[EXP2]] ; %itofp = sitofp <2 x i8> %x to <2 x float> %exp2 = call <2 x float> @llvm.exp2.v2f32(<2 x float> %itofp) @@ -117,11 +123,17 @@ define fp128 @exp2_fp128_sitofp_i8(i8 %x) { } define @exp2_nxv4f32_sitofp_i8( %x) { -; CHECK-LABEL: define @exp2_nxv4f32_sitofp_i8( -; CHECK-SAME: [[X:%.*]]) { -; CHECK-NEXT: [[ITOFP:%.*]] = sitofp [[X]] to -; CHECK-NEXT: [[EXP2:%.*]] = call @llvm.exp2.nxv4f32( [[ITOFP]]) -; CHECK-NEXT: ret [[EXP2]] +; LDEXP-LABEL: define @exp2_nxv4f32_sitofp_i8( +; LDEXP-SAME: [[X:%.*]]) { +; LDEXP-NEXT: [[TMP1:%.*]] = sext [[X]] to +; LDEXP-NEXT: [[EXP2:%.*]] = call @llvm.ldexp.nxv4f32.nxv4i32( shufflevector ( insertelement ( poison, float 1.000000e+00, i64 0), poison, zeroinitializer), [[TMP1]]) +; LDEXP-NEXT: ret [[EXP2]] +; +; NOLDEXP-LABEL: define @exp2_nxv4f32_sitofp_i8( +; NOLDEXP-SAME: [[X:%.*]]) { +; NOLDEXP-NEXT: [[ITOFP:%.*]] = sitofp [[X]] to +; NOLDEXP-NEXT: [[EXP2:%.*]] = call @llvm.exp2.nxv4f32( [[ITOFP]]) +; NOLDEXP-NEXT: ret [[EXP2]] ; %itofp = sitofp %x to %exp2 = call @llvm.exp2.nxv4f32( %itofp) diff --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll index 9c1fa88f3183ea..7b194b3f8925f4 100644 --- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -530,8 +530,8 @@ define double @powf_exp_const2_int_no_fast(double %base) { define <2 x float> @pow_sitofp_const_base_2_no_fast_vector(<2 x i8> %x) { ; CHECK-LABEL: define <2 x float> @pow_sitofp_const_base_2_no_fast_vector( ; CHECK-SAME: <2 x i8> [[X:%.*]]) { -; CHECK-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X]] to <2 x float> -; CHECK-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]]) +; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i8> [[X]] to <2 x i32> +; CHECK-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[TMP1]]) ; CHECK-NEXT: ret <2 x float> [[EXP2]] ; %s = sitofp <2 x i8> %x to <2 x float> From 710f4bd054a857dd25012c9fef0cb66104f17ec0 Mon Sep 17 00:00:00 2001 From: Alex Zinenko Date: Thu, 16 May 2024 10:20:57 +0200 Subject: [PATCH 005/576] [mlir] add missing include to MemRefTransformOps.h The ODS-generated code has the following: ``` ::mlir::TypedValue<::mlir::transform::OperationType> getAlloca() { return ::llvm::cast<::mlir::TypedValue<::mlir::transform::OperationType>>( *getODSOperands(0).begin()); } ``` that may require the compiler seing the definition of `OperationType` so include the corresponding header. --- .../mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h index a87767acdd3b8f..5ef901ade91d11 100644 --- a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h +++ b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h @@ -10,6 +10,7 @@ #define MLIR_DIALECT_MEMREF_TRANSFORMOPS_MEMREFTRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" +#include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" From 51403ada789e63e98e0dd5ac0ceba351465490d1 Mon Sep 17 00:00:00 2001 From: Alex Zinenko Date: Thu, 16 May 2024 10:25:46 +0200 Subject: [PATCH 006/576] [mlir] fix orphaned IRDLExtensionOps documentation .md files should be included into other .md files so they don't show up in the top-level menu. --- mlir/docs/Dialects/Transform.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mlir/docs/Dialects/Transform.md b/mlir/docs/Dialects/Transform.md index 02f4a766ff429d..37fcc0c8880335 100644 --- a/mlir/docs/Dialects/Transform.md +++ b/mlir/docs/Dialects/Transform.md @@ -427,6 +427,10 @@ ops rather than having the methods directly act on the payload IR. [include "Dialects/DebugExtensionOps.md"] +## IRDL (extension) Transform Operations + +[include "Dialects/IRDLExtensionOps.md"] + ## Func Transform Operations [include "Dialects/FuncTransformOps.md"] From 72a895336b1e4df1ec2f485f8786ead6c356edb8 Mon Sep 17 00:00:00 2001 From: Tomas Matheson Date: Thu, 16 May 2024 09:45:14 +0100 Subject: [PATCH 007/576] [AArch64][TargetParser] move ArchInfo into tablegen [NFC] (#92037) This moves the architecture version, profile and extension information into tablegen, and generates the TargetParser ArchInfo objects from this data. There are two lists of "dependencies" defined for each architecture: the SubtargetFeature::Implies which controls which features are automatically enabled in the backend when the corresponding architecture SubtargetFeature is enabled; and the list of Extensions which are enabled by default for this architecture. As far as I can tell, the idea here is that the SubtargetFeature models the mandatory dependencies (although they can still be disabled if desired) while the default extensions models the typical use case for that architecture. --- .../llvm/TargetParser/AArch64TargetParser.h | 48 +---- llvm/lib/Target/AArch64/AArch64Features.td | 174 ++++++++++-------- llvm/utils/TableGen/ARMTargetDefEmitter.cpp | 65 +++++++ 3 files changed, 163 insertions(+), 124 deletions(-) diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index b662a74e5fc68d..b3fff3c99025a5 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -239,8 +239,8 @@ enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' }; struct ArchInfo { VersionTuple Version; // Architecture version, major + minor. ArchProfile Profile; // Architecuture profile - StringRef Name; // Human readable name, e.g. "armv8.1-a" - StringRef ArchFeature; // Command line feature flag, e.g. +v8a + StringRef Name; // Name as supplied to -march e.g. "armv8.1-a" + StringRef ArchFeature; // Name as supplied to -target-feature, e.g. "+v8a" AArch64::ExtensionBitset DefaultExts; // bitfield of default extensions ArchExtKind @@ -289,48 +289,8 @@ struct ArchInfo { static std::optional findBySubArch(StringRef SubArch); }; -// clang-format off -inline constexpr ArchInfo ARMV8A = { VersionTuple{8, 0}, AProfile, "armv8-a", "+v8a", ( - AArch64::ExtensionBitset({AArch64::AEK_FP, AArch64::AEK_SIMD})), }; -inline constexpr ArchInfo ARMV8_1A = { VersionTuple{8, 1}, AProfile, "armv8.1-a", "+v8.1a", (ARMV8A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_CRC, AArch64::AEK_LSE, AArch64::AEK_RDM}))}; -inline constexpr ArchInfo ARMV8_2A = { VersionTuple{8, 2}, AProfile, "armv8.2-a", "+v8.2a", (ARMV8_1A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_RAS}))}; -inline constexpr ArchInfo ARMV8_3A = { VersionTuple{8, 3}, AProfile, "armv8.3-a", "+v8.3a", (ARMV8_2A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_FCMA, AArch64::AEK_JSCVT, AArch64::AEK_PAUTH, AArch64::AEK_RCPC}))}; -inline constexpr ArchInfo ARMV8_4A = { VersionTuple{8, 4}, AProfile, "armv8.4-a", "+v8.4a", (ARMV8_3A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_DOTPROD}))}; -inline constexpr ArchInfo ARMV8_5A = { VersionTuple{8, 5}, AProfile, "armv8.5-a", "+v8.5a", (ARMV8_4A.DefaultExts)}; -inline constexpr ArchInfo ARMV8_6A = { VersionTuple{8, 6}, AProfile, "armv8.6-a", "+v8.6a", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))}; -inline constexpr ArchInfo ARMV8_7A = { VersionTuple{8, 7}, AProfile, "armv8.7-a", "+v8.7a", (ARMV8_6A.DefaultExts)}; -inline constexpr ArchInfo ARMV8_8A = { VersionTuple{8, 8}, AProfile, "armv8.8-a", "+v8.8a", (ARMV8_7A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))}; -inline constexpr ArchInfo ARMV8_9A = { VersionTuple{8, 9}, AProfile, "armv8.9-a", "+v8.9a", (ARMV8_8A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))}; -inline constexpr ArchInfo ARMV9A = { VersionTuple{9, 0}, AProfile, "armv9-a", "+v9a", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_FP16, AArch64::AEK_SVE, AArch64::AEK_SVE2}))}; -inline constexpr ArchInfo ARMV9_1A = { VersionTuple{9, 1}, AProfile, "armv9.1-a", "+v9.1a", (ARMV9A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_BF16, AArch64::AEK_I8MM}))}; -inline constexpr ArchInfo ARMV9_2A = { VersionTuple{9, 2}, AProfile, "armv9.2-a", "+v9.2a", (ARMV9_1A.DefaultExts)}; -inline constexpr ArchInfo ARMV9_3A = { VersionTuple{9, 3}, AProfile, "armv9.3-a", "+v9.3a", (ARMV9_2A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))}; -inline constexpr ArchInfo ARMV9_4A = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASV2}))}; -inline constexpr ArchInfo ARMV9_5A = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_CPA}))}; -// For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions. -inline constexpr ArchInfo ARMV8R = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", (ARMV8_5A.DefaultExts | - AArch64::ExtensionBitset({AArch64::AEK_SSBS, - AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_SB}).flip(AArch64::AEK_LSE))}; -// clang-format on - -// The set of all architectures -static constexpr std::array ArchInfos = { - &ARMV8A, &ARMV8_1A, &ARMV8_2A, &ARMV8_3A, &ARMV8_4A, &ARMV8_5A, - &ARMV8_6A, &ARMV8_7A, &ARMV8_8A, &ARMV8_9A, &ARMV9A, &ARMV9_1A, - &ARMV9_2A, &ARMV9_3A, &ARMV9_4A, &ARMV9_5A, &ARMV8R, -}; +#define EMIT_ARCHITECTURES +#include "llvm/TargetParser/AArch64TargetParserDef.inc" // Details of a specific CPU. struct CpuInfo { diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index b9c26e99ae0342..ba0b760ce3d738 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -792,90 +792,104 @@ def FeatureTLBIW : Extension<"tlbiw", "TLBIW", //===----------------------------------------------------------------------===// // Architectures. // -def HasV8_0aOps : SubtargetFeature<"v8a", "HasV8_0aOps", "true", - "Support ARM v8.0a instructions", [FeatureEL2VMSA, FeatureEL3]>; - -def HasV8_1aOps : SubtargetFeature<"v8.1a", "HasV8_1aOps", "true", - "Support ARM v8.1a instructions", [HasV8_0aOps, FeatureCRC, FeatureLSE, - FeatureRDM, FeaturePAN, FeatureLOR, FeatureVH]>; - -def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true", - "Support ARM v8.2a instructions", [HasV8_1aOps, FeaturePsUAO, - FeaturePAN_RWV, FeatureRAS, FeatureCCPP]>; - -def HasV8_3aOps : SubtargetFeature<"v8.3a", "HasV8_3aOps", "true", - "Support ARM v8.3a instructions", [HasV8_2aOps, FeatureRCPC, FeaturePAuth, - FeatureJS, FeatureCCIDX, FeatureComplxNum]>; - -def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true", - "Support ARM v8.4a instructions", [HasV8_3aOps, FeatureDotProd, - FeatureNV, FeatureMPAM, FeatureDIT, - FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI, - FeatureFlagM, FeatureRCPC_IMMO, FeatureLSE2]>; +class Architecture64< + int major, int minor, string profile, + string target_feature_name, + list implied_features, + list default_extensions +> : SubtargetFeature { + int Major = major; + int Minor = minor; + string Profile = profile; + + // Extensions enabled by default. Not the same as implied SubtargetFeatures. + list DefaultExts = default_extensions; +} -def HasV8_5aOps : SubtargetFeature< - "v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions", +def HasV8_0aOps : Architecture64<8, 0, "a", "v8a", + [FeatureEL2VMSA, FeatureEL3], + [FeatureFPARMv8, FeatureNEON]>; +def HasV8_1aOps : Architecture64<8, 1, "a", "v8.1a", + [HasV8_0aOps, FeatureCRC, FeatureLSE, FeatureRDM, FeaturePAN, FeatureLOR, + FeatureVH], + !listconcat(HasV8_0aOps.DefaultExts, [FeatureCRC, FeatureLSE, FeatureRDM])>; +def HasV8_2aOps : Architecture64<8, 2, "a", "v8.2a", + [HasV8_1aOps, FeaturePsUAO, FeaturePAN_RWV, FeatureRAS, FeatureCCPP], + !listconcat(HasV8_1aOps.DefaultExts, [FeatureRAS])>; +def HasV8_3aOps : Architecture64<8, 3, "a", "v8.3a", + [HasV8_2aOps, FeatureRCPC, FeaturePAuth, FeatureJS, FeatureCCIDX, + FeatureComplxNum], + !listconcat(HasV8_2aOps.DefaultExts, [FeatureComplxNum, FeatureJS, + FeaturePAuth, FeatureRCPC])>; +def HasV8_4aOps : Architecture64<8, 4, "a", "v8.4a", + [HasV8_3aOps, FeatureDotProd, FeatureNV, FeatureMPAM, FeatureDIT, + FeatureTRACEV8_4, FeatureAM, FeatureSEL2, FeatureTLB_RMI, FeatureFlagM, + FeatureRCPC_IMMO, FeatureLSE2], + !listconcat(HasV8_3aOps.DefaultExts, [FeatureDotProd])>; +def HasV8_5aOps : Architecture64<8, 5, "a", "v8.5a", [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecRestrict, - FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, - FeatureBranchTargetId]>; - -def HasV8_6aOps : SubtargetFeature< - "v8.6a", "HasV8_6aOps", "true", "Support ARM v8.6a instructions", + FeatureSSBS, FeatureSB, FeaturePredRes, FeatureCacheDeepPersist, + FeatureBranchTargetId], + !listconcat(HasV8_4aOps.DefaultExts, [])>; +def HasV8_6aOps : Architecture64<8, 6, "a", "v8.6a", [HasV8_5aOps, FeatureAMVS, FeatureBF16, FeatureFineGrainedTraps, - FeatureEnhancedCounterVirtualization, FeatureMatMulInt8]>; - -def HasV8_7aOps : SubtargetFeature< - "v8.7a", "HasV8_7aOps", "true", "Support ARM v8.7a instructions", - [HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX]>; - -def HasV8_8aOps : SubtargetFeature< - "v8.8a", "HasV8_8aOps", "true", "Support ARM v8.8a instructions", - [HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI]>; - -def HasV8_9aOps : SubtargetFeature< - "v8.9a", "HasV8_9aOps", "true", "Support ARM v8.9a instructions", + FeatureEnhancedCounterVirtualization, FeatureMatMulInt8], + !listconcat(HasV8_5aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>; +def HasV8_7aOps : Architecture64<8, 7, "a", "v8.7a", + [HasV8_6aOps, FeatureXS, FeatureWFxT, FeatureHCX], + !listconcat(HasV8_6aOps.DefaultExts, [])>; +def HasV8_8aOps : Architecture64<8, 8, "a", "v8.8a", + [HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI], + !listconcat(HasV8_7aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>; +def HasV8_9aOps : Architecture64<8, 9, "a", "v8.9a", [HasV8_8aOps, FeatureCLRBHB, FeaturePRFM_SLC, FeatureSPECRES2, - FeatureCSSC, FeatureRASv2, FeatureCHK]>; - -def HasV9_0aOps : SubtargetFeature< - "v9a", "HasV9_0aOps", "true", "Support ARM v9a instructions", - [HasV8_5aOps, FeatureMEC, FeatureSVE2]>; - -def HasV9_1aOps : SubtargetFeature< - "v9.1a", "HasV9_1aOps", "true", "Support ARM v9.1a instructions", - [HasV8_6aOps, HasV9_0aOps]>; - -def HasV9_2aOps : SubtargetFeature< - "v9.2a", "HasV9_2aOps", "true", "Support ARM v9.2a instructions", - [HasV8_7aOps, HasV9_1aOps]>; - -def HasV9_3aOps : SubtargetFeature< - "v9.3a", "HasV9_3aOps", "true", "Support ARM v9.3a instructions", - [HasV8_8aOps, HasV9_2aOps]>; - -def HasV9_4aOps : SubtargetFeature< - "v9.4a", "HasV9_4aOps", "true", "Support ARM v9.4a instructions", - [HasV8_9aOps, HasV9_3aOps]>; - -def HasV9_5aOps : SubtargetFeature< - "v9.5a", "HasV9_5aOps", "true", "Support ARM v9.5a instructions", - [HasV9_4aOps, FeatureCPA]>; - -def HasV8_0rOps : SubtargetFeature< - "v8r", "HasV8_0rOps", "true", "Support ARM v8r instructions", - [//v8.1 - FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2, - //v8.2 - FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV, - //v8.3 - FeatureCCIDX, FeaturePAuth, FeatureRCPC, - //v8.4 - FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2, - FeatureRCPC_IMMO, - // Not mandatory in v8.0-R, but included here on the grounds that it - // only enables names of system registers - FeatureSpecRestrict - ]>; + FeatureCSSC, FeatureRASv2, FeatureCHK], + !listconcat(HasV8_8aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC, + FeatureRASv2])>; +def HasV9_0aOps : Architecture64<9, 0, "a", "v9a", + [HasV8_5aOps, FeatureMEC, FeatureSVE2], + !listconcat(HasV8_5aOps.DefaultExts, [FeatureFullFP16, FeatureSVE, + FeatureSVE2])>; +def HasV9_1aOps : Architecture64<9, 1, "a", "v9.1a", + [HasV8_6aOps, HasV9_0aOps], + !listconcat(HasV9_0aOps.DefaultExts, [FeatureBF16, FeatureMatMulInt8])>; +def HasV9_2aOps : Architecture64<9, 2, "a", "v9.2a", + [HasV8_7aOps, HasV9_1aOps], + !listconcat(HasV9_1aOps.DefaultExts, [])>; +def HasV9_3aOps : Architecture64<9, 3, "a", "v9.3a", + [HasV8_8aOps, HasV9_2aOps], + !listconcat(HasV9_2aOps.DefaultExts, [FeatureMOPS, FeatureHBC])>; +def HasV9_4aOps : Architecture64<9, 4, "a", "v9.4a", + [HasV8_9aOps, HasV9_3aOps], + !listconcat(HasV9_3aOps.DefaultExts, [FeatureSPECRES2, FeatureCSSC, + FeatureRASv2])>; +def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a", + [HasV9_4aOps, FeatureCPA], + !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA])>; +def HasV8_0rOps : Architecture64<8, 0, "r", "v8r", + [ //v8.1 + FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2, + //v8.2 + FeatureRAS, FeaturePsUAO, FeatureCCPP, FeaturePAN_RWV, + //v8.3 + FeatureCCIDX, FeaturePAuth, FeatureRCPC, + //v8.4 + FeatureTRACEV8_4, FeatureTLB_RMI, FeatureFlagM, FeatureDIT, FeatureSEL2, + FeatureRCPC_IMMO, + // Not mandatory in v8.0-R, but included here on the grounds that it + // only enables names of system registers + FeatureSpecRestrict + ], + // For v8-R, we do not enable crypto and align with GCC that enables a more + // minimal set of optional architecture extensions. + !listconcat( + !listremove(HasV8_5aOps.DefaultExts, [FeatureLSE]), + [FeatureSSBS, FeatureFullFP16, FeatureFP16FML, FeatureSB] + )>; //===----------------------------------------------------------------------===// // Access to privileged registers diff --git a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp index 0e90f57af49389..491011643bbfb1 100644 --- a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp @@ -13,9 +13,12 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Format.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include +#include using namespace llvm; @@ -112,6 +115,68 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { << "#undef EMIT_EXTENSIONS\n" << "#endif // EMIT_EXTENSIONS\n" << "\n"; + + // Emit architecture information + OS << "#ifdef EMIT_ARCHITECTURES\n"; + + auto Architectures = RK.getAllDerivedDefinitionsIfDefined("Architecture64"); + std::vector CppSpellings; + for (const Record *Rec : Architectures) { + const int Major = Rec->getValueAsInt("Major"); + const int Minor = Rec->getValueAsInt("Minor"); + const std::string ProfileLower = Rec->getValueAsString("Profile").str(); + const std::string ProfileUpper = Rec->getValueAsString("Profile").upper(); + + if (ProfileLower != "a" && ProfileLower != "r") + PrintFatalError(Rec->getLoc(), + "error: Profile must be one of 'a' or 'r', got '" + + ProfileLower + "'"); + + // Name of the object in C++ + const std::string CppSpelling = + Minor == 0 ? "ARMV" + std::to_string(Major) + ProfileUpper.c_str() + : "ARMV" + std::to_string(Major) + "_" + + std::to_string(Minor) + ProfileUpper.c_str(); + OS << "inline constexpr ArchInfo " << CppSpelling << " = {\n"; + CppSpellings.push_back(CppSpelling); + + OS << llvm::format(" VersionTuple{%d, %d},\n", Major, Minor); + OS << llvm::format(" %sProfile,\n", ProfileUpper.c_str()); + + // Name as spelled for -march. + if (Minor == 0) + OS << llvm::format(" \"armv%d-%s\",\n", Major, ProfileLower.c_str()); + else + OS << llvm::format(" \"armv%d.%d-%s\",\n", Major, Minor, + ProfileLower.c_str()); + + // SubtargetFeature::Name, used for -target-feature. Here the "+" is added. + const auto TargetFeatureName = Rec->getValueAsString("Name"); + OS << " \"+" << TargetFeatureName << "\",\n"; + + // Construct the list of default extensions + OS << " (AArch64::ExtensionBitset({"; + for (auto *E : Rec->getValueAsListOfDefs("DefaultExts")) { + // Only process subclasses of Extension + OS << "AArch64::" << E->getValueAsString("ArchExtKindSpelling").upper() + << ", "; + } + OS << "}))\n"; + + OS << "};\n"; + } + + OS << "\n" + << "/// The set of all architectures\n" + << "static constexpr std::array ArchInfos = {\n"; + for (auto CppSpelling : CppSpellings) + OS << " &" << CppSpelling << ",\n"; + OS << "};\n"; + + OS << "#undef EMIT_ARCHITECTURES\n" + << "#endif // EMIT_ARCHITECTURES\n" + << "\n"; } static TableGen::Emitter::Opt From ca02f36bacaec58071a26ff65329fbab5526d1d7 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 16 May 2024 09:52:21 +0100 Subject: [PATCH 008/576] [mlir][vector] Teach `TransferOptimization` to forward masked stores (#87794) This only handles one case (that's fairly common in practice*), storing a masked constant splat, then reloading again with the same mask and a padding value that matches the splat. * For SVE/SME (without peeling) this occurs when you have a `linalg.fill` preceding a `linalg.matmul`. --- mlir/lib/Dialect/Vector/IR/VectorOps.cpp | 37 ++++- .../Dialect/Vector/vector-transferop-opt.mlir | 127 +++++++++++++++++- 2 files changed, 160 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp index d10a31941db4f6..58951641d33ce2 100644 --- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp +++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp @@ -170,12 +170,43 @@ AffineMap mlir::vector::getTransferMinorIdentityMap(ShapedType shapedType, shapedType.getContext()); } +/// Check if `write` is of a constant splat and the masked `read` is padded with +/// the same splat value -- meaning it could be the same value as the initial +/// constant splat. +static bool isSplatWriteConsistentWithMaskedRead(vector::TransferWriteOp write, + vector::TransferReadOp read) { + auto readMask = read.getMask(); + auto writeMask = write.getMask(); + // Check if the masks are consistent. The splat value could be the same if the + // read is masked (and padded with the splat value), and the write is unmasked + // or has the same mask. Note this does not allow the case where the write is + // masked and the read is unmasked, as then the read could be of more elements + // than the write (which may not be the same value). + bool couldBeSameSplat = readMask && (!writeMask || writeMask == readMask); + if (!couldBeSameSplat) + return false; + // Check for constant splat (as the source of the write). + DenseElementsAttr splatAttr; + if (!matchPattern(write.getVector(), + m_Constant(&splatAttr)) || + !splatAttr.isSplat()) { + return false; + } + // The padding of the read and the constant splat value must be the same. + Attribute padAttr; + if (!matchPattern(read.getPadding(), m_Constant(&padAttr))) + return false; + return padAttr == splatAttr.getSplatValue(); +} + bool mlir::vector::checkSameValueRAW(vector::TransferWriteOp defWrite, vector::TransferReadOp read) { - return !defWrite.hasOutOfBoundsDim() && !defWrite.getMask() && - !read.getMask() && defWrite.getIndices() == read.getIndices() && + return !defWrite.hasOutOfBoundsDim() && + defWrite.getIndices() == read.getIndices() && defWrite.getVectorType() == read.getVectorType() && - defWrite.getPermutationMap() == read.getPermutationMap(); + defWrite.getPermutationMap() == read.getPermutationMap() && + ((!defWrite.getMask() && !read.getMask()) || + isSplatWriteConsistentWithMaskedRead(defWrite, read)); } bool mlir::vector::checkSameValueWAW(vector::TransferWriteOp write, diff --git a/mlir/test/Dialect/Vector/vector-transferop-opt.mlir b/mlir/test/Dialect/Vector/vector-transferop-opt.mlir index 13957af014b89e..0719c0dd17427f 100644 --- a/mlir/test/Dialect/Vector/vector-transferop-opt.mlir +++ b/mlir/test/Dialect/Vector/vector-transferop-opt.mlir @@ -222,7 +222,7 @@ func.func @forward_dead_store_negative(%arg0: i1, %arg1 : memref<4x4xf32>, // `vector.transfer_write` would not be safe: // %1 = vector.transfer_read %subview // vector.transfer_write %1, %alloca -// vector.transfer_write %vec, %collapse_shape +// vector.transfer_write %vec, %collapse_shape // %2 = vector.transfer_read %alloca // vector.transfer_write %1, %subview // Indeed, %alloca and %collapse_shape alias and hence %2 != %1. Instead, the @@ -360,3 +360,128 @@ func.func @forward_dead_store_dynamic_non_overlap_trailing_dim( vector.transfer_write %x, %buffer[%i0, %i0] {in_bounds = [true]} : vector<4xf32>, memref return } + +// CHECK-LABEL: func @forward_dead_constant_splat_store_with_masking +// CHECK: %[[SPLAT:.*]] = arith.constant dense<0.000000e+00> : vector<[8]x[8]xf32> +// CHECK-NOT: vector.transfer_write +// CHECK-NOT: vector.transfer_read +// CHECK: scf.for +// CHECK-SAME: iter_args(%{{.*}} = %[[SPLAT]]) +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_dead_constant_splat_store_with_masking(%buffer : memref, %mask: vector<[8]x[8]xi1>) { + %zero_splat = arith.constant dense<0.0> : vector<[8]x[8]xf32> + %read_padding = arith.constant 0.0 : f32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %c512 = arith.constant 512 : index + vector.transfer_write %zero_splat, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %0 = vector.transfer_read %buffer[%c0, %c0], %read_padding, %mask {in_bounds = [true, true]} : memref, vector<[8]x[8]xf32> + %x = scf.for %arg2 = %c0 to %c512 step %c1 iter_args(%acc = %0) -> (vector<[8]x[8]xf32>) { + %1 = arith.addf %acc, %acc : vector<[8]x[8]xf32> + scf.yield %1 : vector<[8]x[8]xf32> + } + vector.transfer_write %x, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + return +} + +// Here the read can be eliminated but not the write (due to mismatched masks). +// CHECK-LABEL: func @forward_dead_constant_splat_store_with_masking_unmasked_write +// CHECK: %[[SPLAT:.*]] = arith.constant dense<0.000000e+00> : vector<[8]x[8]xf32> +// CHECK: vector.transfer_write %[[SPLAT]] +// CHECK: scf.for +// CHECK-SAME: iter_args(%{{.*}} = %[[SPLAT]]) +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_dead_constant_splat_store_with_masking_unmasked_write(%buffer : memref, %mask: vector<[8]x[8]xi1>) { + %zero_splat = arith.constant dense<0.0> : vector<[8]x[8]xf32> + %read_padding = arith.constant 0.0 : f32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %c512 = arith.constant 512 : index + vector.transfer_write %zero_splat, %buffer[%c0, %c0] {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %0 = vector.transfer_read %buffer[%c0, %c0], %read_padding, %mask {in_bounds = [true, true]} : memref, vector<[8]x[8]xf32> + %x = scf.for %arg2 = %c0 to %c512 step %c1 iter_args(%acc = %0) -> (vector<[8]x[8]xf32>) { + %1 = arith.addf %acc, %acc : vector<[8]x[8]xf32> + scf.yield %1 : vector<[8]x[8]xf32> + } + vector.transfer_write %x, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + return +} + +// Negative test, the padding does not match the constant splat, so we can't +// forward the store. +// CHECK-LABEL: func @forward_dead_constant_splat_store_with_masking_negative_0 +// CHECK: vector.transfer_write +// CHECK: vector.transfer_read +// CHECK: scf.for +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_dead_constant_splat_store_with_masking_negative_0(%buffer : memref, %mask: vector<[8]x[8]xi1>) { + %zero_splat = arith.constant dense<0.0> : vector<[8]x[8]xf32> + %read_padding = arith.constant 1.0 : f32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %c512 = arith.constant 512 : index + vector.transfer_write %zero_splat, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %0 = vector.transfer_read %buffer[%c0, %c0], %read_padding, %mask {in_bounds = [true, true]} : memref, vector<[8]x[8]xf32> + %x = scf.for %arg2 = %c0 to %c512 step %c1 iter_args(%acc = %0) -> (vector<[8]x[8]xf32>) { + %1 = arith.addf %acc, %acc : vector<[8]x[8]xf32> + scf.yield %1 : vector<[8]x[8]xf32> + } + vector.transfer_write %x, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + return +} + +// Negative test, the masks don't match between the read and write, so we can't +// foward the store. +// CHECK-LABEL: func @forward_dead_constant_splat_store_with_masking_negative_1 +// CHECK: vector.transfer_write +// CHECK: vector.transfer_read +// CHECK: scf.for +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_dead_constant_splat_store_with_masking_negative_1(%buffer : memref, %mask_a: vector<[8]x[8]xi1>, %mask_b: vector<[8]x[8]xi1>) { + %zero_splat = arith.constant dense<0.0> : vector<[8]x[8]xf32> + %read_padding = arith.constant 0.0 : f32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %c512 = arith.constant 512 : index + vector.transfer_write %zero_splat, %buffer[%c0, %c0], %mask_a {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %0 = vector.transfer_read %buffer[%c0, %c0], %read_padding, %mask_b {in_bounds = [true, true]} : memref, vector<[8]x[8]xf32> + %x = scf.for %arg2 = %c0 to %c512 step %c1 iter_args(%acc = %0) -> (vector<[8]x[8]xf32>) { + %1 = arith.addf %acc, %acc : vector<[8]x[8]xf32> + scf.yield %1 : vector<[8]x[8]xf32> + } + vector.transfer_write %x, %buffer[%c0, %c0], %mask_a {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + return +} + +// Negative test, here the write is masked but the read is unmasked. We can't +// forward the store (as the write could be of less elements then the read). +// CHECK-LABEL: func @forward_dead_constant_splat_store_with_masking_negative_3 +// CHECK: vector.transfer_write +// CHECK: vector.transfer_read +// CHECK: scf.for +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_dead_constant_splat_store_with_masking_negative_3(%buffer : memref, %mask: vector<[8]x[8]xi1>) { + %zero_splat = arith.constant dense<0.0> : vector<[8]x[8]xf32> + %read_padding = arith.constant 0.0 : f32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %c512 = arith.constant 512 : index + vector.transfer_write %zero_splat, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %0 = vector.transfer_read %buffer[%c0, %c0], %read_padding {in_bounds = [true, true]} : memref, vector<[8]x[8]xf32> + %x = scf.for %arg2 = %c0 to %c512 step %c1 iter_args(%acc = %0) -> (vector<[8]x[8]xf32>) { + %1 = arith.addf %acc, %acc : vector<[8]x[8]xf32> + scf.yield %1 : vector<[8]x[8]xf32> + } + vector.transfer_write %x, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + return +} From 30410018d32b2cc19552c6d6a3b7b6de84d99382 Mon Sep 17 00:00:00 2001 From: wanglei Date: Thu, 16 May 2024 16:54:18 +0800 Subject: [PATCH 009/576] [LoongArch] Enable all -target-abi options This is a pre-commit for modifying `computeTargetABI` logic. This patch will provide warning prompts when using those ABIs that have not yet been standardized. Reviewed By: xen0n, SixWeining Pull Request: https://github.com/llvm/llvm-project/pull/92222 --- .../LoongArch/LoongArchISelLowering.cpp | 5 ++- .../MCTargetDesc/LoongArchBaseInfo.cpp | 36 ++++++++++++++++--- llvm/test/CodeGen/LoongArch/target-abi.ll | 26 ++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/LoongArch/target-abi.ll diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 21d520656091c9..6740563b90b455 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -3575,15 +3575,14 @@ static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, switch (ABI) { default: llvm_unreachable("Unexpected ABI"); - case LoongArchABI::ABI_ILP32S: + break; case LoongArchABI::ABI_ILP32F: case LoongArchABI::ABI_LP64F: - report_fatal_error("Unimplemented ABI"); - break; case LoongArchABI::ABI_ILP32D: case LoongArchABI::ABI_LP64D: UseGPRForFloat = !IsFixed; break; + case LoongArchABI::ABI_ILP32S: case LoongArchABI::ABI_LP64S: break; } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp index 928adb03f09894..6d75e575cd3cfa 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp @@ -14,6 +14,7 @@ #include "LoongArchBaseInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" @@ -21,6 +22,33 @@ namespace llvm { namespace LoongArchABI { +// Check if ABI has been standardized; issue a warning if it hasn't. +// FIXME: Once all ABIs are standardized, this will be removed. +static ABI checkABIStandardized(ABI Abi) { + StringRef ABIName; + switch (Abi) { + case ABI_ILP32S: + ABIName = "ilp32s"; + break; + case ABI_ILP32F: + ABIName = "ilp32f"; + break; + case ABI_ILP32D: + ABIName = "ilp32d"; + break; + case ABI_LP64F: + ABIName = "lp64f"; + break; + case ABI_LP64S: + case ABI_LP64D: + return Abi; + default: + llvm_unreachable(""); + } + errs() << "warning: '" << ABIName << "' has not been standardized\n"; + return Abi; +} + ABI computeTargetABI(const Triple &TT, StringRef ABIName) { ABI ArgProvidedABI = getTargetABI(ABIName); bool Is64Bit = TT.isArch64Bit(); @@ -50,7 +78,7 @@ ABI computeTargetABI(const Triple &TT, StringRef ABIName) { errs() << "'" << ABIName << "' is not a recognized ABI for this target, ignoring and using " "triple-implied ABI\n"; - return TripleABI; + return checkABIStandardized(TripleABI); case LoongArchABI::ABI_ILP32S: case LoongArchABI::ABI_ILP32F: @@ -58,7 +86,7 @@ ABI computeTargetABI(const Triple &TT, StringRef ABIName) { if (Is64Bit) { errs() << "32-bit ABIs are not supported for 64-bit targets, ignoring " "target-abi and using triple-implied ABI\n"; - return TripleABI; + return checkABIStandardized(TripleABI); } break; @@ -68,7 +96,7 @@ ABI computeTargetABI(const Triple &TT, StringRef ABIName) { if (!Is64Bit) { errs() << "64-bit ABIs are not supported for 32-bit targets, ignoring " "target-abi and using triple-implied ABI\n"; - return TripleABI; + return checkABIStandardized(TripleABI); } break; } @@ -77,7 +105,7 @@ ABI computeTargetABI(const Triple &TT, StringRef ABIName) { errs() << "warning: triple-implied ABI conflicts with provided target-abi '" << ABIName << "', using target-abi\n"; - return ArgProvidedABI; + return checkABIStandardized(ArgProvidedABI); } ABI getTargetABI(StringRef ABIName) { diff --git a/llvm/test/CodeGen/LoongArch/target-abi.ll b/llvm/test/CodeGen/LoongArch/target-abi.ll new file mode 100644 index 00000000000000..de834c152b180b --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/target-abi.ll @@ -0,0 +1,26 @@ +; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32s < %s 2>&1 \ +; RUN: | FileCheck %s -DABI=ilp32s --check-prefixes=CHECK,WARNING +; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32f < %s 2>&1 \ +; RUN: | FileCheck %s -DABI=ilp32f --check-prefixes=CHECK,WARNING +; RUN: llc --mtriple=loongarch32 --mattr=+d --target-abi=ilp32d < %s 2>&1 \ +; RUN: | FileCheck %s -DABI=ilp32d --check-prefixes=CHECK,WARNING +; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64f < %s 2>&1 \ +; RUN: | FileCheck %s -DABI=lp64f --check-prefixes=CHECK,WARNING + +; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64s < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=CHECK,NO-WARNING +; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64d < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=CHECK,NO-WARNING + +;; Check if the ABI has been standardized; issue a warning if it hasn't. + +; WARNING: warning: '[[ABI]]' has not been standardized + +; NO-WARNING-NOT: warning + +define void @nothing() nounwind { +; CHECK-LABEL: nothing: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + ret void +} From 70608c24fae8943cb93276db4d0358722705507b Mon Sep 17 00:00:00 2001 From: wanglei Date: Thu, 16 May 2024 17:15:21 +0800 Subject: [PATCH 010/576] [LoongArch] Refactor LoongArchABI::computeTargetABI The previous logic did not consider whether the architectural features meet the requirements of the ABI, resulting in the generation of incorrect object files in some cases. For example: ``` llc -mtriple=loongarch64 -filetype=obj test/CodeGen/LoongArch/ir-instruction/fadd.ll -o t.o llvm-readelf -h t.o ``` The object file indicates the ABI as lp64d, however, the generated code is lp64s. The new logic introduces the `feature-implied` ABI. When both target-abi and triple-implied ABI are invalid, the feature-implied ABI is used. Reviewed By: SixWeining, xen0n Pull Request: https://github.com/llvm/llvm-project/pull/92223 --- .../Target/LoongArch/LoongArchSubtarget.cpp | 2 +- .../MCTargetDesc/LoongArchBaseInfo.cpp | 139 +++++++++++++----- .../MCTargetDesc/LoongArchBaseInfo.h | 3 +- .../MCTargetDesc/LoongArchELFStreamer.cpp | 3 +- llvm/test/CodeGen/LoongArch/e_flags.ll | 6 +- .../target-abi-from-triple-edge-cases.ll | 35 ++++- 6 files changed, 142 insertions(+), 46 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp index ffcde7dd1fa741..57babfc917f897 100644 --- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp @@ -50,7 +50,7 @@ LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies( if (!Is64Bit && HasLA64) report_fatal_error("Feature 64bit should be used for loongarch64 target."); - TargetABI = LoongArchABI::computeTargetABI(TT, ABIName); + TargetABI = LoongArchABI::computeTargetABI(TT, getFeatureBits(), ABIName); return *this; } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp index 6d75e575cd3cfa..17bcacedfc5114 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "LoongArchBaseInfo.h" +#include "LoongArchMCTargetDesc.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" @@ -49,63 +50,127 @@ static ABI checkABIStandardized(ABI Abi) { return Abi; } -ABI computeTargetABI(const Triple &TT, StringRef ABIName) { - ABI ArgProvidedABI = getTargetABI(ABIName); +static ABI getTripleABI(const Triple &TT) { bool Is64Bit = TT.isArch64Bit(); ABI TripleABI; - - // Figure out the ABI explicitly requested via the triple's environment type. switch (TT.getEnvironment()) { case llvm::Triple::EnvironmentType::GNUSF: - TripleABI = Is64Bit ? LoongArchABI::ABI_LP64S : LoongArchABI::ABI_ILP32S; + TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S; break; case llvm::Triple::EnvironmentType::GNUF32: - TripleABI = Is64Bit ? LoongArchABI::ABI_LP64F : LoongArchABI::ABI_ILP32F; + TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F; break; - // Let the fallback case behave like {ILP32,LP64}D. case llvm::Triple::EnvironmentType::GNUF64: default: - TripleABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D; + TripleABI = Is64Bit ? ABI_LP64D : ABI_ILP32D; break; } + return TripleABI; +} - switch (ArgProvidedABI) { - case LoongArchABI::ABI_Unknown: - // Fallback to the triple-implied ABI if ABI name is not specified or - // invalid. - if (!ABIName.empty()) - errs() << "'" << ABIName - << "' is not a recognized ABI for this target, ignoring and using " - "triple-implied ABI\n"; - return checkABIStandardized(TripleABI); +ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, + StringRef ABIName) { + bool Is64Bit = TT.isArch64Bit(); + ABI ArgProvidedABI = getTargetABI(ABIName); + ABI TripleABI = getTripleABI(TT); + + auto IsABIValidForFeature = [=](ABI Abi) { + switch (Abi) { + default: + return false; + case ABI_ILP32S: + return !Is64Bit; + case ABI_ILP32F: + return !Is64Bit && FeatureBits[LoongArch::FeatureBasicF]; + case ABI_ILP32D: + return !Is64Bit && FeatureBits[LoongArch::FeatureBasicD]; + case ABI_LP64S: + return Is64Bit; + case ABI_LP64F: + return Is64Bit && FeatureBits[LoongArch::FeatureBasicF]; + case ABI_LP64D: + return Is64Bit && FeatureBits[LoongArch::FeatureBasicD]; + } + }; + + // 1. If the '-target-abi' is valid, use it. + if (IsABIValidForFeature(ArgProvidedABI)) { + if (TT.hasEnvironment() && ArgProvidedABI != TripleABI) + errs() + << "warning: triple-implied ABI conflicts with provided target-abi '" + << ABIName << "', using target-abi\n"; + return checkABIStandardized(ArgProvidedABI); + } - case LoongArchABI::ABI_ILP32S: - case LoongArchABI::ABI_ILP32F: - case LoongArchABI::ABI_ILP32D: - if (Is64Bit) { - errs() << "32-bit ABIs are not supported for 64-bit targets, ignoring " - "target-abi and using triple-implied ABI\n"; + // 2. If the triple-implied ABI is valid, use it. + if (IsABIValidForFeature(TripleABI)) { + // If target-abi is not specified, use the valid triple-implied ABI. + if (ABIName.empty()) return checkABIStandardized(TripleABI); - } - break; - case LoongArchABI::ABI_LP64S: - case LoongArchABI::ABI_LP64F: - case LoongArchABI::ABI_LP64D: - if (!Is64Bit) { - errs() << "64-bit ABIs are not supported for 32-bit targets, ignoring " - "target-abi and using triple-implied ABI\n"; + switch (ArgProvidedABI) { + case ABI_Unknown: + // Fallback to the triple-implied ABI if ABI name is specified but + // invalid. + errs() << "warning: the '" << ABIName + << "' is not a recognized ABI for this target, ignoring and " + "using triple-implied ABI\n"; return checkABIStandardized(TripleABI); + case ABI_ILP32S: + case ABI_ILP32F: + case ABI_ILP32D: + if (Is64Bit) { + errs() << "warning: 32-bit ABIs are not supported for 64-bit targets, " + "ignoring and using triple-implied ABI\n"; + return checkABIStandardized(TripleABI); + } + break; + case ABI_LP64S: + case ABI_LP64F: + case ABI_LP64D: + if (!Is64Bit) { + errs() << "warning: 64-bit ABIs are not supported for 32-bit targets, " + "ignoring and using triple-implied ABI\n"; + return checkABIStandardized(TripleABI); + } + break; } - break; - } - if (!ABIName.empty() && TT.hasEnvironment() && ArgProvidedABI != TripleABI) - errs() << "warning: triple-implied ABI conflicts with provided target-abi '" - << ABIName << "', using target-abi\n"; + switch (ArgProvidedABI) { + case ABI_ILP32F: + case ABI_LP64F: + errs() << "warning: the '" << ABIName + << "' ABI can't be used for a target that doesn't support the 'F' " + "instruction set, ignoring and using triple-implied ABI\n"; + break; + case ABI_ILP32D: + case ABI_LP64D: + errs() << "warning: the '" << ABIName + << "' ABI can't be used for a target that doesn't support the 'D' " + "instruction set, ignoring and using triple-implied ABI\n"; + break; + default: + llvm_unreachable(""); + } + return checkABIStandardized(TripleABI); + } - return checkABIStandardized(ArgProvidedABI); + // 3. Parse the 'feature-abi', and use it. + auto GetFeatureABI = [=]() { + if (FeatureBits[LoongArch::FeatureBasicD]) + return Is64Bit ? ABI_LP64D : ABI_ILP32D; + if (FeatureBits[LoongArch::FeatureBasicF]) + return Is64Bit ? ABI_LP64F : ABI_ILP32F; + return Is64Bit ? ABI_LP64S : ABI_ILP32S; + }; + if (ABIName.empty()) + errs() << "warning: the triple-implied ABI is invalid, ignoring and using " + "feature-implied ABI\n"; + else + errs() << "warning: both target-abi and the triple-implied ABI are " + "invalid, ignoring and using feature-implied ABI\n"; + return checkABIStandardized(GetFeatureABI()); } ABI getTargetABI(StringRef ABIName) { diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h index 3c3fed7d43ed98..1a12fb492a60f5 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h @@ -69,7 +69,8 @@ enum ABI { ABI_Unknown }; -ABI computeTargetABI(const Triple &TT, StringRef ABIName); +ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, + StringRef ABIName); ABI getTargetABI(StringRef ABIName); // Returns the register used to hold the stack pointer after realignment. diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp index 9e56333e5fd9b5..a8a4f1ed327d38 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp @@ -27,7 +27,8 @@ LoongArchTargetELFStreamer::LoongArchTargetELFStreamer( auto &MAB = static_cast( getStreamer().getAssembler().getBackend()); setTargetABI(LoongArchABI::computeTargetABI( - STI.getTargetTriple(), MAB.getTargetOptions().getABIName())); + STI.getTargetTriple(), STI.getFeatureBits(), + MAB.getTargetOptions().getABIName())); } MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() { diff --git a/llvm/test/CodeGen/LoongArch/e_flags.ll b/llvm/test/CodeGen/LoongArch/e_flags.ll index 25f3285bdf3288..2feb9d832bca9a 100644 --- a/llvm/test/CodeGen/LoongArch/e_flags.ll +++ b/llvm/test/CodeGen/LoongArch/e_flags.ll @@ -4,10 +4,10 @@ ; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32s -o %t-ilp32s ; RUN: llvm-readelf -h %t-ilp32s | FileCheck %s --check-prefixes=ILP32,ABI-S --match-full-lines -; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f +; RUN: llc --mtriple=loongarch32 -mattr=+f --filetype=obj %s --target-abi=ilp32f -o %t-ilp32f ; RUN: llvm-readelf -h %t-ilp32f | FileCheck %s --check-prefixes=ILP32,ABI-F --match-full-lines -; RUN: llc --mtriple=loongarch32 --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d +; RUN: llc --mtriple=loongarch32 -mattr=+d --filetype=obj %s --target-abi=ilp32d -o %t-ilp32d ; RUN: llvm-readelf -h %t-ilp32d | FileCheck %s --check-prefixes=ILP32,ABI-D --match-full-lines ; RUN: llc --mtriple=loongarch64 -mattr=+d --filetype=obj %s -o %t-la64 @@ -16,7 +16,7 @@ ; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64s -o %t-lp64s ; RUN: llvm-readelf -h %t-lp64s | FileCheck %s --check-prefixes=LP64,ABI-S --match-full-lines -; RUN: llc --mtriple=loongarch64 --filetype=obj %s --target-abi=lp64f -o %t-lp64f +; RUN: llc --mtriple=loongarch64 -mattr=+f --filetype=obj %s --target-abi=lp64f -o %t-lp64f ; RUN: llvm-readelf -h %t-lp64f | FileCheck %s --check-prefixes=LP64,ABI-F --match-full-lines ; RUN: llc --mtriple=loongarch64 --filetype=obj %s --mattr=+d --target-abi=lp64d -o %t-lp64d diff --git a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll index 1d5ed089c69fa1..36b78ea2ea02c0 100644 --- a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll +++ b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll @@ -5,7 +5,7 @@ ; RUN: llc --mtriple=loongarch64-linux-gnu --target-abi=foo --mattr=+d < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=LP64D,UNKNOWN -; UNKNOWN: 'foo' is not a recognized ABI for this target, ignoring and using triple-implied ABI +; UNKNOWN: warning: the 'foo' is not a recognized ABI for this target, ignoring and using triple-implied ABI ;; Check that --target-abi takes precedence over triple-supplied ABI modifiers. ; RUN: llc --mtriple=loongarch32-linux-gnusf --target-abi=ilp32d --mattr=+d < %s 2>&1 \ @@ -29,8 +29,31 @@ ; RUN: llc --mtriple=loongarch32 --target-abi=lp64d --mattr=+d < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=ILP32D,64ON32 -; 32ON64: 32-bit ABIs are not supported for 64-bit targets, ignoring target-abi and using triple-implied ABI -; 64ON32: 64-bit ABIs are not supported for 32-bit targets, ignoring target-abi and using triple-implied ABI +; 32ON64: warning: 32-bit ABIs are not supported for 64-bit targets, ignoring and using triple-implied ABI +; 64ON32: warning: 64-bit ABIs are not supported for 32-bit targets, ignoring and using triple-implied ABI + +;; Check that target-abi is invalid but triple-implied ABI is valid, use triple-implied ABI +; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64f --mattr=-f < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=LP64S,LP64S-LP64F-NOF +; RUN: llc --mtriple=loongarch64-linux-gnusf --target-abi=lp64d --mattr=-d < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=LP64S,LP64S-LP64D-NOD + +; LP64S-LP64F-NOF: warning: the 'lp64f' ABI can't be used for a target that doesn't support the 'F' instruction set, ignoring and using triple-implied ABI +; LP64S-LP64D-NOD: warning: the 'lp64d' ABI can't be used for a target that doesn't support the 'D' instruction set, ignoring and using triple-implied ABI + +;; Check that both target-abi and triple-implied ABI are invalid, use feature-implied ABI +; RUN: llc --mtriple=loongarch64-linux-gnuf64 --target-abi=lp64f --mattr=-f < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF +; RUN: llc --mtriple=loongarch64 --target-abi=lp64f --mattr=-f < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-LP64F-NOF + +; LP64D-LP64F-NOF: warning: both target-abi and the triple-implied ABI are invalid, ignoring and using feature-implied ABI + +;; Check that triple-implied ABI are invalid, use feature-implied ABI +; RUN: llc --mtriple=loongarch64 --mattr=-f < %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-NONE-NOF + +; LP64D-NONE-NOF: warning: the triple-implied ABI is invalid, ignoring and using feature-implied ABI define float @f(float %a) { ; ILP32D-LABEL: f: @@ -48,6 +71,9 @@ define float @f(float %a) { ; LP64D-NEXT: ffint.s.w $fa1, $fa1 ; LP64D-NEXT: fadd.s $fa0, $fa0, $fa1 ; LP64D-NEXT: ret +; +; LP64S-LABEL: f: +; LP64S: bl %plt(__addsf3) %1 = fadd float %a, 1.0 ret float %1 } @@ -69,6 +95,9 @@ define double @g(double %a) { ; LP64D-NEXT: ffint.d.l $fa1, $fa1 ; LP64D-NEXT: fadd.d $fa0, $fa0, $fa1 ; LP64D-NEXT: ret +; +; LP64S-LABEL: g: +; LP64S: bl %plt(__adddf3) %1 = fadd double %a, 1.0 ret double %1 } From 53bdcee9d7a921a0ea5e0c8fa3f889f16f1d268f Mon Sep 17 00:00:00 2001 From: Oleg Shyshkov Date: Thu, 16 May 2024 11:37:55 +0200 Subject: [PATCH 011/576] [mlir][bazel] Fix bazel build. --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 751cd94d5ff101..62ac56f8b46e99 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -2217,6 +2217,7 @@ cc_library( ":ArithDialect", ":ArmSMEDialect", ":ArmSMETransforms", + ":ControlFlowDialect", ":ConversionPassIncGen", ":FuncDialect", ":FunctionInterfaces", From cfcbe3ae55144635cac4ab00c017e3e93dad1c4b Mon Sep 17 00:00:00 2001 From: wanglei Date: Thu, 16 May 2024 17:49:10 +0800 Subject: [PATCH 012/576] [lld][test] Fix test failure after #92223 https://lab.llvm.org/buildbot/#/builders/272/builds/16745 --- lld/test/ELF/emulation-loongarch.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/test/ELF/emulation-loongarch.s b/lld/test/ELF/emulation-loongarch.s index 343e836274a3e6..28b879f7584689 100644 --- a/lld/test/ELF/emulation-loongarch.s +++ b/lld/test/ELF/emulation-loongarch.s @@ -25,8 +25,8 @@ # LA32-NEXT: Entry: # LA32-NEXT: ProgramHeaderOffset: 0x34 # LA32-NEXT: SectionHeaderOffset: -# LA32-NEXT: Flags [ (0x43) -# LA32-NEXT: EF_LOONGARCH_ABI_DOUBLE_FLOAT (0x3) +# LA32-NEXT: Flags [ (0x41) +# LA32-NEXT: EF_LOONGARCH_ABI_SOFT_FLOAT (0x1) # LA32-NEXT: EF_LOONGARCH_OBJABI_V1 (0x40) # LA32-NEXT: ] # LA32-NEXT: HeaderSize: 52 From 90d2f8c630e1ddddd034e4a0e575929c08dd26bf Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 16 May 2024 10:53:14 +0100 Subject: [PATCH 013/576] [mlir][vector] Teach `TransferOptimization` to look through trivial aliases (#87805) This allows `TransferOptimization` to eliminate and forward stores that are to trivial aliases (rather than just to identical memref values). A trivial aliases is (currently) defined as: 1. A `memref.cast` 2. A `memref.subview` with a zero offset and unit strides 3. A chain of 1 and 2 --- .../mlir/Dialect/MemRef/Utils/MemRefUtils.h | 17 ++++++++++ mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp | 30 +++++++++++++++++ .../Transforms/VectorTransferOpTransforms.cpp | 33 +++++++++---------- .../Dialect/Vector/vector-transferop-opt.mlir | 30 +++++++++++++++++ 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/mlir/include/mlir/Dialect/MemRef/Utils/MemRefUtils.h b/mlir/include/mlir/Dialect/MemRef/Utils/MemRefUtils.h index 46003ed8468695..1c094c1c1328a9 100644 --- a/mlir/include/mlir/Dialect/MemRef/Utils/MemRefUtils.h +++ b/mlir/include/mlir/Dialect/MemRef/Utils/MemRefUtils.h @@ -22,6 +22,9 @@ namespace mlir { class MemRefType; +/// A value with a memref type. +using MemrefValue = TypedValue; + namespace memref { /// Returns true, if the memref type has static shapes and represents a @@ -93,6 +96,20 @@ computeStridesIRBlock(Location loc, OpBuilder &builder, return computeSuffixProductIRBlock(loc, builder, sizes); } +/// Walk up the source chain until an operation that changes/defines the view of +/// memory is found (i.e. skip operations that alias the entire view). +MemrefValue skipFullyAliasingOperations(MemrefValue source); + +/// Checks if two (memref) values are the same or are statically known to alias +/// the same region of memory. +inline bool isSameViewOrTrivialAlias(MemrefValue a, MemrefValue b) { + return skipFullyAliasingOperations(a) == skipFullyAliasingOperations(b); +} + +/// Walk up the source chain until something an op other than a `memref.subview` +/// or `memref.cast` is found. +MemrefValue skipSubViewsAndCasts(MemrefValue source); + } // namespace memref } // namespace mlir diff --git a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp index c93e5a9dcd39fa..05d5ca2ce12f4e 100644 --- a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp +++ b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp @@ -178,5 +178,35 @@ computeSuffixProductIRBlock(Location loc, OpBuilder &builder, return computeSuffixProductIRBlockImpl(loc, builder, sizes, unit); } +MemrefValue skipFullyAliasingOperations(MemrefValue source) { + while (auto op = source.getDefiningOp()) { + if (auto subViewOp = dyn_cast(op); + subViewOp && subViewOp.hasZeroOffset() && subViewOp.hasUnitStride()) { + // A `memref.subview` with an all zero offset, and all unit strides, still + // points to the same memory. + source = cast(subViewOp.getSource()); + } else if (auto castOp = dyn_cast(op)) { + // A `memref.cast` still points to the same memory. + source = castOp.getSource(); + } else { + return source; + } + } + return source; +} + +MemrefValue skipSubViewsAndCasts(MemrefValue source) { + while (auto op = source.getDefiningOp()) { + if (auto subView = dyn_cast(op)) { + source = cast(subView.getSource()); + } else if (auto cast = dyn_cast(op)) { + source = cast.getSource(); + } else { + return source; + } + } + return source; +} + } // namespace memref } // namespace mlir diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp index 0ffef6aabccc18..997b56a1ce1426 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp @@ -14,6 +14,7 @@ #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/MemRef/Utils/MemRefUtils.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" @@ -104,10 +105,8 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) { << "\n"); llvm::SmallVector blockingAccesses; Operation *firstOverwriteCandidate = nullptr; - Value source = write.getSource(); - // Skip subview ops. - while (auto subView = source.getDefiningOp()) - source = subView.getSource(); + Value source = + memref::skipSubViewsAndCasts(cast(write.getSource())); llvm::SmallVector users(source.getUsers().begin(), source.getUsers().end()); llvm::SmallDenseSet processed; @@ -116,8 +115,8 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) { // If the user has already been processed skip. if (!processed.insert(user).second) continue; - if (auto subView = dyn_cast(user)) { - users.append(subView->getUsers().begin(), subView->getUsers().end()); + if (isa(user)) { + users.append(user->getUsers().begin(), user->getUsers().end()); continue; } if (isMemoryEffectFree(user)) @@ -126,7 +125,9 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) { continue; if (auto nextWrite = dyn_cast(user)) { // Check candidate that can override the store. - if (write.getSource() == nextWrite.getSource() && + if (memref::isSameViewOrTrivialAlias( + cast(nextWrite.getSource()), + cast(write.getSource())) && checkSameValueWAW(nextWrite, write) && postDominators.postDominates(nextWrite, write)) { if (firstOverwriteCandidate == nullptr || @@ -191,10 +192,8 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) { << "\n"); SmallVector blockingWrites; vector::TransferWriteOp lastwrite = nullptr; - Value source = read.getSource(); - // Skip subview ops. - while (auto subView = source.getDefiningOp()) - source = subView.getSource(); + Value source = + memref::skipSubViewsAndCasts(cast(read.getSource())); llvm::SmallVector users(source.getUsers().begin(), source.getUsers().end()); llvm::SmallDenseSet processed; @@ -203,12 +202,8 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) { // If the user has already been processed skip. if (!processed.insert(user).second) continue; - if (auto subView = dyn_cast(user)) { - users.append(subView->getUsers().begin(), subView->getUsers().end()); - continue; - } - if (auto collapsed = dyn_cast(user)) { - users.append(collapsed->getUsers().begin(), collapsed->getUsers().end()); + if (isa(user)) { + users.append(user->getUsers().begin(), user->getUsers().end()); continue; } if (isMemoryEffectFree(user) || isa(user)) @@ -221,7 +216,9 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) { cast(read.getOperation()), /*testDynamicValueUsingBounds=*/true)) continue; - if (write.getSource() == read.getSource() && + if (memref::isSameViewOrTrivialAlias( + cast(read.getSource()), + cast(write.getSource())) && dominators.dominates(write, read) && checkSameValueRAW(write, read)) { if (lastwrite == nullptr || dominators.dominates(lastwrite, write)) lastwrite = write; diff --git a/mlir/test/Dialect/Vector/vector-transferop-opt.mlir b/mlir/test/Dialect/Vector/vector-transferop-opt.mlir index 0719c0dd17427f..3ddfacf40cf64a 100644 --- a/mlir/test/Dialect/Vector/vector-transferop-opt.mlir +++ b/mlir/test/Dialect/Vector/vector-transferop-opt.mlir @@ -485,3 +485,33 @@ func.func @forward_dead_constant_splat_store_with_masking_negative_3(%buffer : m vector.transfer_write %x, %buffer[%c0, %c0], %mask {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref return } + +// Here each read/write is to a different subview, but they all point to exact +// same bit of memory (just through casts and subviews with unit strides and +// zero offsets). +// CHECK-LABEL: func @forward_and_eliminate_stores_through_trivial_aliases +// CHECK-NOT: vector.transfer_write +// CHECK-NOT: vector.transfer_read +// CHECK: scf.for +// CHECK: } +// CHECK: vector.transfer_write +// CHECK: return +func.func @forward_and_eliminate_stores_through_trivial_aliases( + %buffer : memref, %vec: vector<[8]x[8]xf32>, %size: index, %a_size: index, %another_size: index +) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c32 = arith.constant 32 : index + %cst = arith.constant 0.0 : f32 + vector.transfer_write %vec, %buffer[%c0, %c0] {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref + %direct_subview = memref.subview %buffer[0, 0] [%a_size, %a_size] [1, 1] : memref to memref> + %cast = memref.cast %direct_subview : memref> to memref + %subview_of_cast = memref.subview %cast[0, 0] [%another_size, %another_size] [1, 1] : memref to memref> + %21 = vector.transfer_read %direct_subview[%c0, %c0], %cst {in_bounds = [true, true]} : memref>, vector<[8]x[8]xf32> + %23 = scf.for %arg2 = %c0 to %c32 step %c1 iter_args(%arg3 = %21) -> (vector<[8]x[8]xf32>) { + %24 = arith.addf %arg3, %arg3 : vector<[8]x[8]xf32> + scf.yield %24 : vector<[8]x[8]xf32> + } + vector.transfer_write %23, %subview_of_cast[%c0, %c0] {in_bounds = [true, true]} : vector<[8]x[8]xf32>, memref> + return +} From 1795fa58bac5092f758bf27e1b27a2b333307bab Mon Sep 17 00:00:00 2001 From: Sirraide Date: Thu, 16 May 2024 12:08:39 +0200 Subject: [PATCH 014/576] [NFC] Update example in comment --- clang/lib/Sema/SemaExpr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cc507524e2fc28..151cda5d68b016 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7133,10 +7133,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // // But: C99-C23 6.5.2.5 Compound literals constraint 1: The type name // shall specify an object type or an array of unknown size, but not a - // variable length array type. This seems odd, as it allows int a[size] = - // {}; but forbids int a[size] = (int[size]){}; As this is what the - // standard says, this is what's implemented here for C (except for the - // extension that permits constant foldable size arrays) + // variable length array type. This seems odd, as it allows 'int a[size] = + // {}', but forbids 'int *a = (int[size]){}'. As this is what the standard + // says, this is what's implemented here for C (except for the extension + // that permits constant foldable size arrays) auto diagID = LangOpts.CPlusPlus ? diag::err_variable_object_no_init From 5ffd154cf61390c1ed32a1b0eb134929f78c0fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= Date: Thu, 16 May 2024 12:10:56 +0200 Subject: [PATCH 015/576] [analyzer] Clean up list of taint propagation functions (#91635) This commit refactors GenericTaintChecker and performs various improvements in the list of taint propagation functions: 1. The matching mode (usually `CDM::CLibrary` or `CDM::CLibraryMaybeHardened`) was specified to avoid matching e.g. C++ methods or functions from a user-defined namespace that happen to share the name of a well-known library function. 2. With these matching modes, a `CallDescription` can automatically match builtin variants of the functions, so entries that explicitly specified a builtin function were removed. This eliminated inconsistencies where the "normal" and the builtin variant of the same function was handled differently (e.g. `__builtin_strlcat` was covered, while plain `strlcat` wasn't; while `__builtin_memcpy` and `memcpy` were both on the list with different propagation rules). 3. The modeling of the functions `strlcat` and `strncat` was updated to propagate taint from the first argument (index 0), because a tainted string should remain tainted even if we append something else to it. Note that this was already applied to `strcat` and `wcsncat` by commit 6ceb1c0ef9f544be0eed65e46cc7d99941a001bf. 4. Some functions were updated to propagate taint from a size/length argument to the result: e.g. `memcmp(p, q, get_tainted_int())` will now return a tainted value (because the attacker can manipulate it). This principle was already present in some propagation rules (e.g. `__builtin_memcpy` was handled this way), and even after this commit there are still some functions where it isn't applied. (I only aimed for consistency within the same function family.) 5. Functions that have hardened `__FOO_chk()` variants are matched in `CDM:CLibraryMaybeHardened` to ensure consistent handling of the "normal" and the hardened variant. I added special handling for the hardened variants of "sprintf" and "snprintf" because there the extra parameters are inserted into the middle of the parameter list. 6. Modeling of `sscanf_s` was added, to complete the group of `fscanf`, `fscanf_s` and `sscanf`. 7. The `Source()` specifications for `gets`, `gets_s` and `wgetch` were ill-formed: they were specifying variadic arguments starting at argument index `ReturnValueIndex`. (That is, in addition to the return value they were propagating taint to all arguments.) 8. Functions that were related to each other were grouped together. (I know that this makes the diff harder to read, but I felt that the full list is unreadable without some reorganization.) 9. I spotted and removed some redundant curly braces. Perhaps would be good to switch to a cleaner layout with less nested braces... 10. I updated some obsolete comments and added two TODOs for issues that should be fixed in followup commits. --- .../Checkers/GenericTaintChecker.cpp | 370 ++++++++++-------- 1 file changed, 204 insertions(+), 166 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index a0190c30bfd28a..eb40a4cd3d9024 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -400,17 +400,14 @@ class GenericTaintChecker : public Checker { void taintUnsafeSocketProtocol(const CallEvent &Call, CheckerContext &C) const; - /// Default taint rules are initalized with the help of a CheckerContext to - /// access the names of built-in functions like memcpy. + /// The taint rules are initalized with the help of a CheckerContext to + /// access user-provided configuration. void initTaintRules(CheckerContext &C) const; - /// CallDescription currently cannot restrict matches to the global namespace - /// only, which is why multiple CallDescriptionMaps are used, as we want to - /// disambiguate global C functions from functions inside user-defined - /// namespaces. - // TODO: Remove separation to simplify matching logic once CallDescriptions - // are more expressive. - + // TODO: The two separate `CallDescriptionMap`s were introduced when + // `CallDescription` was unable to restrict matches to the global namespace + // only. This limitation no longer exists, so the following two maps should + // be unified. mutable std::optional StaticTaintRules; mutable std::optional DynamicTaintRules; }; @@ -506,7 +503,8 @@ void GenericTaintRuleParser::consumeRulesFromConfig(const Config &C, GenericTaintRule &&Rule, RulesContTy &Rules) { NamePartsTy NameParts = parseNameParts(C); - Rules.emplace_back(CallDescription(NameParts), std::move(Rule)); + Rules.emplace_back(CallDescription(CDM::Unspecified, NameParts), + std::move(Rule)); } void GenericTaintRuleParser::parseConfig(const std::string &Option, @@ -572,196 +570,236 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const { std::vector>; using TR = GenericTaintRule; - const Builtin::Context &BI = C.getASTContext().BuiltinInfo; - RulesConstructionTy GlobalCRules{ // Sources - {{{"fdopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"fopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"freopen"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getch"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getchar"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getchar_unlocked"}}, TR::Source({{ReturnValueIndex}})}, - {{{"gets"}}, TR::Source({{0}, ReturnValueIndex})}, - {{{"gets_s"}}, TR::Source({{0}, ReturnValueIndex})}, - {{{"scanf"}}, TR::Source({{}, 1})}, - {{{"scanf_s"}}, TR::Source({{}, {1}})}, - {{{"wgetch"}}, TR::Source({{}, ReturnValueIndex})}, + {{CDM::CLibrary, {"fdopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"freopen"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getch"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getchar"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getchar_unlocked"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"gets"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"gets_s"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"scanf"}}, TR::Source({{}, 1})}, + {{CDM::CLibrary, {"scanf_s"}}, TR::Source({{}, 1})}, + {{CDM::CLibrary, {"wgetch"}}, TR::Source({{ReturnValueIndex}})}, // Sometimes the line between taint sources and propagators is blurry. // _IO_getc is choosen to be a source, but could also be a propagator. // This way it is simpler, as modeling it as a propagator would require // to model the possible sources of _IO_FILE * values, which the _IO_getc // function takes as parameters. - {{{"_IO_getc"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getcwd"}}, TR::Source({{0, ReturnValueIndex}})}, - {{{"getwd"}}, TR::Source({{0, ReturnValueIndex}})}, - {{{"readlink"}}, TR::Source({{1, ReturnValueIndex}})}, - {{{"readlinkat"}}, TR::Source({{2, ReturnValueIndex}})}, - {{{"get_current_dir_name"}}, TR::Source({{ReturnValueIndex}})}, - {{{"gethostname"}}, TR::Source({{0}})}, - {{{"getnameinfo"}}, TR::Source({{2, 4}})}, - {{{"getseuserbyname"}}, TR::Source({{1, 2}})}, - {{{"getgroups"}}, TR::Source({{1, ReturnValueIndex}})}, - {{{"getlogin"}}, TR::Source({{ReturnValueIndex}})}, - {{{"getlogin_r"}}, TR::Source({{0}})}, + {{CDM::CLibrary, {"_IO_getc"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getcwd"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"getwd"}}, TR::Source({{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"readlink"}}, TR::Source({{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"readlinkat"}}, TR::Source({{2, ReturnValueIndex}})}, + {{CDM::CLibrary, {"get_current_dir_name"}}, + TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"gethostname"}}, TR::Source({{0}})}, + {{CDM::CLibrary, {"getnameinfo"}}, TR::Source({{2, 4}})}, + {{CDM::CLibrary, {"getseuserbyname"}}, TR::Source({{1, 2}})}, + {{CDM::CLibrary, {"getgroups"}}, TR::Source({{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"getlogin"}}, TR::Source({{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getlogin_r"}}, TR::Source({{0}})}, // Props - {{{"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fgets"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})}, - {{{"fgetws"}}, TR::Prop({{2}}, {{0, ReturnValueIndex}})}, - {{{"fscanf"}}, TR::Prop({{0}}, {{}, 2})}, - {{{"fscanf_s"}}, TR::Prop({{0}}, {{}, {2}})}, - {{{"sscanf"}}, TR::Prop({{0}}, {{}, 2})}, - - {{{"getc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"getc_unlocked"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"getdelim"}}, TR::Prop({{3}}, {{0}})}, - {{{"getline"}}, TR::Prop({{2}}, {{0}})}, - {{{"getw"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"pread"}}, TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})}, - {{{"read"}}, TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})}, - {{{"strchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"tolower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"toupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fread"}}, TR::Prop({{3}}, {{0, ReturnValueIndex}})}, - {{{"recv"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"recvfrom"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"ttyname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"ttyname_r"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"basename"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"dirname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"fnmatch"}}, TR::Prop({{1}}, {{ReturnValueIndex}})}, - {{{"memchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"memrchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"rawmemchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"mbtowc"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"wctomb"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"wcwidth"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"memcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"memcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{{"memmove"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - // If memmem was called with a tainted needle and the search was - // successful, that would mean that the value pointed by the return value - // has the same content as the needle. If we choose to go by the policy of - // content equivalence implies taintedness equivalence, that would mean - // haystack should be considered a propagation source argument. - {{{"memmem"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - // The comment for memmem above also applies to strstr. - {{{"strstr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strcasestr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"strchrnul"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{{"index"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"rindex"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"accept"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atoi"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atol"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"atoll"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fgetc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fgetln"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fgets"}}, + TR::Prop({{2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fgetws"}}, + TR::Prop({{2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"fscanf"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"fscanf_s"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"sscanf"}}, TR::Prop({{0}}, {{}, 2})}, + {{CDM::CLibrary, {"sscanf_s"}}, TR::Prop({{0}}, {{}, 2})}, + + {{CDM::CLibrary, {"getc"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getc_unlocked"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"getdelim"}}, TR::Prop({{3}}, {{0}})}, + // TODO: this intends to match the C function `getline()`, but the call + // description also matches the C++ function `std::getline()`; it should + // be ruled out by some additional logic. + {{CDM::CLibrary, {"getline"}}, TR::Prop({{2}}, {{0}})}, + {{CDM::CLibrary, {"getw"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"pread"}}, + TR::Prop({{0, 1, 2, 3}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"read"}}, + TR::Prop({{0, 2}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"fread"}}, + TR::Prop({{3}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"recv"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"recvfrom"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"ttyname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"ttyname_r"}}, + TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"basename"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"dirname"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"fnmatch"}}, TR::Prop({{1}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"mbtowc"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"wctomb"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {"wcwidth"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"memcmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memcpy"}}, + TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memmove"}}, + TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"bcopy"}}, TR::Prop({{0, 2}}, {{1}})}, + + // Note: "memmem" and its variants search for a byte sequence ("needle") + // in a larger area ("haystack"). Currently we only propagate taint from + // the haystack to the result, but in theory tampering with the needle + // could also produce incorrect results. + {{CDM::CLibrary, {"memmem"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strstr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcasestr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + // Analogously, the following functions search for a byte within a buffer + // and we only propagate taint from the buffer to the result. + {{CDM::CLibraryMaybeHardened, {"memchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"memrchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"rawmemchr"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strrchr"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strchrnul"}}, + TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"index"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"rindex"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, // FIXME: In case of arrays, only the first element of the array gets // tainted. - {{{"qsort"}}, TR::Prop({{0}}, {{0}})}, - {{{"qsort_r"}}, TR::Prop({{0}}, {{0}})}, - - {{{"strcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strcasecmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strncmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, - {{{"strncasecmp"}}, TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, - {{{"strspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strcspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{{"strpbrk"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strndup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"strndupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"qsort"}}, TR::Prop({{0}}, {{0}})}, + {{CDM::CLibrary, {"qsort_r"}}, TR::Prop({{0}}, {{0}})}, + + {{CDM::CLibrary, {"strcmp"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcasecmp"}}, + TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strncmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strncasecmp"}}, + TR::Prop({{0, 1, 2}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strcspn"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strpbrk"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"strndup"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strndupa"}}, TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"strdupa"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"wcsdup"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, // strlen, wcslen, strnlen and alike intentionally don't propagate taint. // See the details here: https://github.com/llvm/llvm-project/pull/66086 - {{{"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoul"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - {{{"strtoull"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, - - {{{"isalnum"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isalpha"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isascii"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isblank"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"iscntrl"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isgraph"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"islower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isprint"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"ispunct"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isspace"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{{"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrncat)}}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrlcpy)}}, - TR::Prop({{1, 2}}, {{0}})}, - {{CDM::CLibraryMaybeHardened, {BI.getName(Builtin::BIstrlcat)}}, - TR::Prop({{1, 2}}, {{0}})}, - {{CDM::CLibraryMaybeHardened, {{"snprintf"}}}, - TR::Prop({{1}, 3}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"sprintf"}}}, - TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"strcpy"}}}, + {{CDM::CLibrary, {"strtol"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoll"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoul"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + {{CDM::CLibrary, {"strtoull"}}, TR::Prop({{0}}, {{1, ReturnValueIndex}})}, + + {{CDM::CLibrary, {"tolower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"toupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibrary, {"isalnum"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isalpha"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isascii"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isblank"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"iscntrl"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isgraph"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"islower"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isprint"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"ispunct"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isspace"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + + {{CDM::CLibraryMaybeHardened, {"strcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"stpcpy"}}}, + {{CDM::CLibraryMaybeHardened, {"stpcpy"}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"strcat"}}}, + {{CDM::CLibraryMaybeHardened, {"strcat"}}, TR::Prop({{0, 1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibraryMaybeHardened, {{"wcsncat"}}}, + {{CDM::CLibraryMaybeHardened, {"wcsncat"}}, TR::Prop({{0, 1}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {{"strdupa"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, BI.getName(Builtin::BImemcpy)}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BImemmove)}}, + {{CDM::CLibraryMaybeHardened, {"strncpy"}}, TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BIstrncpy)}}, - TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDM::CLibrary, {BI.getName(Builtin::BIstrndup)}}, - TR::Prop({{0, 1}}, {{ReturnValueIndex}})}, - {{CDM::CLibrary, {"bcopy"}}, TR::Prop({{0, 2}}, {{1}})}, + {{CDM::CLibraryMaybeHardened, {"strncat"}}, + TR::Prop({{0, 1, 2}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibraryMaybeHardened, {"strlcpy"}}, TR::Prop({{1, 2}}, {{0}})}, + {{CDM::CLibraryMaybeHardened, {"strlcat"}}, TR::Prop({{0, 1, 2}}, {{0}})}, + + // Usually the matching mode `CDM::CLibraryMaybeHardened` is sufficient + // for unified handling of a function `FOO()` and its hardened variant + // `__FOO_chk()`, but in the "sprintf" family the extra parameters of the + // hardened variants are inserted into the middle of the parameter list, + // so that would not work in their case. + // int snprintf(char * str, size_t maxlen, const char * format, ...); + {{CDM::CLibrary, {"snprintf"}}, + TR::Prop({{1, 2}, 3}, {{0, ReturnValueIndex}})}, + // int sprintf(char * str, const char * format, ...); + {{CDM::CLibrary, {"sprintf"}}, + TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})}, + // int __snprintf_chk(char * str, size_t maxlen, int flag, size_t strlen, + // const char * format, ...); + {{CDM::CLibrary, {"__snprintf_chk"}}, + TR::Prop({{1, 4}, 5}, {{0, ReturnValueIndex}})}, + // int __sprintf_chk(char * str, int flag, size_t strlen, const char * + // format, ...); + {{CDM::CLibrary, {"__sprintf_chk"}}, + TR::Prop({{3}, 4}, {{0, ReturnValueIndex}})}, // Sinks - {{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, - {{{"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, - {{{"execl"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execle"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execlp"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, - {{{"execv"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, - {{{"execve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"fexecve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, - {{{"execvpe"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, - {{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execl"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execle"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execlp"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execv"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execve"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"fexecve"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"execvpe"}}, + TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, + {{CDM::CLibrary, {"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, // malloc, calloc, alloca, realloc, memccpy // are intentionally not marked as taint sinks because unconditional // reporting for these functions generates many false positives. // These taint sinks should be implemented in other checkers with more // sophisticated sanitation heuristics. - {{{{"setproctitle"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, - {{{{"setproctitle_fast"}}}, + + {{CDM::CLibrary, {"setproctitle"}}, + TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, + {{CDM::CLibrary, {"setproctitle_fast"}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}}; - // `getenv` returns taint only in untrusted environments. if (TR::UntrustedEnv(C)) { // void setproctitle_init(int argc, char *argv[], char *envp[]) + // TODO: replace `MsgCustomSink` with a message that fits this situation. + GlobalCRules.push_back({{CDM::CLibrary, {"setproctitle_init"}}, + TR::Sink({{1, 2}}, MsgCustomSink)}); + + // `getenv` returns taint only in untrusted environments. GlobalCRules.push_back( - {{{"setproctitle_init"}}, TR::Sink({{1, 2}}, MsgCustomSink)}); - GlobalCRules.push_back({{{"getenv"}}, TR::Source({{ReturnValueIndex}})}); + {{CDM::CLibrary, {"getenv"}}, TR::Source({{ReturnValueIndex}})}); } StaticTaintRules.emplace(std::make_move_iterator(GlobalCRules.begin()), From 83974a4b92d1fd33b8e21d7a868862893d9430e9 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 16 May 2024 12:05:13 +0200 Subject: [PATCH 016/576] Revert "[LoopUnroll] Clamp PartialThreshold for large LoopMicroOpBufferSize (#67657)" This reverts commit f0b3654701bde1cf7821d60698b42383edaff9f3. This commit triggers UB by reading an uninitialized variable. `UP.PartialThreshold` is used uninitialized in `getUnrollingPreferences()` when it is called from `LoopVectorizationPlanner::executePlan()`. In this case the `UP` variable is created on the stack and its fields are not initialized. ``` ==8802==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x557c0b081b99 in llvm::BasicTTIImplBase::getUnrollingPreferences(llvm::Loop*, llvm::ScalarEvolution&, llvm::TargetTransformInfo::UnrollingPreferences&, llvm::OptimizationRemarkEmitter*) llvm-project/llvm/include/llvm/CodeGen/BasicTTIImpl.h #1 0x557c0b07a40c in llvm::TargetTransformInfo::Model::getUnrollingPreferences(llvm::Loop*, llvm::ScalarEvolution&, llvm::TargetTransformInfo::UnrollingPreferences&, llvm::OptimizationRemarkEmitter*) llvm-project/llvm/include/llvm/Analysis/TargetTransformInfo.h:2277:17 #2 0x557c0f5d69ee in llvm::TargetTransformInfo::getUnrollingPreferences(llvm::Loop*, llvm::ScalarEvolution&, llvm::TargetTransformInfo::UnrollingPreferences&, llvm::OptimizationRemarkEmitter*) const llvm-project/llvm/lib/Analysis/TargetTransformInfo.cpp:387:19 #3 0x557c0e6b96a0 in llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool, llvm::DenseMap, llvm::detail::DenseMapPair> const*) llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7624:7 #4 0x557c0e6e4b63 in llvm::LoopVectorizePass::processLoop(llvm::Loop*) llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:10253:13 #5 0x557c0e6f2429 in llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:10344:30 #6 0x557c0e6f2f97 in llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager&) llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:10383:9 [...] Uninitialized value was created by an allocation of 'UP' in the stack frame #0 0x557c0e6b961e in llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, bool, llvm::DenseMap, llvm::detail::DenseMapPair> const*) llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7623:3 ``` --- llvm/include/llvm/CodeGen/BasicTTIImpl.h | 8 +- llvm/test/Transforms/LoopUnroll/X86/znver3.ll | 764 +++++++++++++++++- 2 files changed, 742 insertions(+), 30 deletions(-) diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h index 8dba6a64128528..2091432d4fe276 100644 --- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -612,13 +612,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { if (PartialUnrollingThreshold.getNumOccurrences() > 0) MaxOps = PartialUnrollingThreshold; else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) - // Upper bound by the default PartialThreshold, which is the same as - // the default full-unroll Threshold. Even if the loop micro-op buffer - // is very large, this does not mean that we want to unroll all loops - // to that length, as it would increase code size beyond the limits of - // what unrolling normally allows. - MaxOps = std::min(ST->getSchedModel().LoopMicroOpBufferSize, - UP.PartialThreshold); + MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; else return; diff --git a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll index 467c57906d8882..30389062a09678 100644 --- a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll +++ b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll @@ -9,8 +9,8 @@ define i32 @test(ptr %ary) "target-cpu"="znver3" { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_31:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT_31:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_127:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT_127:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[SUM_NEXT:%.*]] = add nsw i32 [[VAL]], [[SUM]] @@ -137,12 +137,396 @@ define i32 @test(ptr %ary) "target-cpu"="znver3" { ; CHECK-NEXT: [[INDVARS_IV_NEXT_30:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 31 ; CHECK-NEXT: [[ARRAYIDX_31:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_30]] ; CHECK-NEXT: [[VAL_31:%.*]] = load i32, ptr [[ARRAYIDX_31]], align 4 -; CHECK-NEXT: [[SUM_NEXT_31]] = add nsw i32 [[VAL_31]], [[SUM_NEXT_30]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_31]] = add nuw nsw i64 [[INDVARS_IV]], 32 -; CHECK-NEXT: [[EXITCOND_NOT_31:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_31]], 8192 -; CHECK-NEXT: br i1 [[EXITCOND_NOT_31]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: [[SUM_NEXT_31:%.*]] = add nsw i32 [[VAL_31]], [[SUM_NEXT_30]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_31:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 32 +; CHECK-NEXT: [[ARRAYIDX_32:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_31]] +; CHECK-NEXT: [[VAL_32:%.*]] = load i32, ptr [[ARRAYIDX_32]], align 4 +; CHECK-NEXT: [[SUM_NEXT_32:%.*]] = add nsw i32 [[VAL_32]], [[SUM_NEXT_31]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_32:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 33 +; CHECK-NEXT: [[ARRAYIDX_33:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_32]] +; CHECK-NEXT: [[VAL_33:%.*]] = load i32, ptr [[ARRAYIDX_33]], align 4 +; CHECK-NEXT: [[SUM_NEXT_33:%.*]] = add nsw i32 [[VAL_33]], [[SUM_NEXT_32]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_33:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 34 +; CHECK-NEXT: [[ARRAYIDX_34:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_33]] +; CHECK-NEXT: [[VAL_34:%.*]] = load i32, ptr [[ARRAYIDX_34]], align 4 +; CHECK-NEXT: [[SUM_NEXT_34:%.*]] = add nsw i32 [[VAL_34]], [[SUM_NEXT_33]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_34:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 35 +; CHECK-NEXT: [[ARRAYIDX_35:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_34]] +; CHECK-NEXT: [[VAL_35:%.*]] = load i32, ptr [[ARRAYIDX_35]], align 4 +; CHECK-NEXT: [[SUM_NEXT_35:%.*]] = add nsw i32 [[VAL_35]], [[SUM_NEXT_34]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_35:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 36 +; CHECK-NEXT: [[ARRAYIDX_36:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_35]] +; CHECK-NEXT: [[VAL_36:%.*]] = load i32, ptr [[ARRAYIDX_36]], align 4 +; CHECK-NEXT: [[SUM_NEXT_36:%.*]] = add nsw i32 [[VAL_36]], [[SUM_NEXT_35]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_36:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 37 +; CHECK-NEXT: [[ARRAYIDX_37:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_36]] +; CHECK-NEXT: [[VAL_37:%.*]] = load i32, ptr [[ARRAYIDX_37]], align 4 +; CHECK-NEXT: [[SUM_NEXT_37:%.*]] = add nsw i32 [[VAL_37]], [[SUM_NEXT_36]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_37:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 38 +; CHECK-NEXT: [[ARRAYIDX_38:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_37]] +; CHECK-NEXT: [[VAL_38:%.*]] = load i32, ptr [[ARRAYIDX_38]], align 4 +; CHECK-NEXT: [[SUM_NEXT_38:%.*]] = add nsw i32 [[VAL_38]], [[SUM_NEXT_37]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_38:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 39 +; CHECK-NEXT: [[ARRAYIDX_39:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_38]] +; CHECK-NEXT: [[VAL_39:%.*]] = load i32, ptr [[ARRAYIDX_39]], align 4 +; CHECK-NEXT: [[SUM_NEXT_39:%.*]] = add nsw i32 [[VAL_39]], [[SUM_NEXT_38]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_39:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 40 +; CHECK-NEXT: [[ARRAYIDX_40:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_39]] +; CHECK-NEXT: [[VAL_40:%.*]] = load i32, ptr [[ARRAYIDX_40]], align 4 +; CHECK-NEXT: [[SUM_NEXT_40:%.*]] = add nsw i32 [[VAL_40]], [[SUM_NEXT_39]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_40:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 41 +; CHECK-NEXT: [[ARRAYIDX_41:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_40]] +; CHECK-NEXT: [[VAL_41:%.*]] = load i32, ptr [[ARRAYIDX_41]], align 4 +; CHECK-NEXT: [[SUM_NEXT_41:%.*]] = add nsw i32 [[VAL_41]], [[SUM_NEXT_40]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_41:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 42 +; CHECK-NEXT: [[ARRAYIDX_42:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_41]] +; CHECK-NEXT: [[VAL_42:%.*]] = load i32, ptr [[ARRAYIDX_42]], align 4 +; CHECK-NEXT: [[SUM_NEXT_42:%.*]] = add nsw i32 [[VAL_42]], [[SUM_NEXT_41]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_42:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 43 +; CHECK-NEXT: [[ARRAYIDX_43:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_42]] +; CHECK-NEXT: [[VAL_43:%.*]] = load i32, ptr [[ARRAYIDX_43]], align 4 +; CHECK-NEXT: [[SUM_NEXT_43:%.*]] = add nsw i32 [[VAL_43]], [[SUM_NEXT_42]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_43:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 44 +; CHECK-NEXT: [[ARRAYIDX_44:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_43]] +; CHECK-NEXT: [[VAL_44:%.*]] = load i32, ptr [[ARRAYIDX_44]], align 4 +; CHECK-NEXT: [[SUM_NEXT_44:%.*]] = add nsw i32 [[VAL_44]], [[SUM_NEXT_43]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_44:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 45 +; CHECK-NEXT: [[ARRAYIDX_45:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_44]] +; CHECK-NEXT: [[VAL_45:%.*]] = load i32, ptr [[ARRAYIDX_45]], align 4 +; CHECK-NEXT: [[SUM_NEXT_45:%.*]] = add nsw i32 [[VAL_45]], [[SUM_NEXT_44]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_45:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 46 +; CHECK-NEXT: [[ARRAYIDX_46:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_45]] +; CHECK-NEXT: [[VAL_46:%.*]] = load i32, ptr [[ARRAYIDX_46]], align 4 +; CHECK-NEXT: [[SUM_NEXT_46:%.*]] = add nsw i32 [[VAL_46]], [[SUM_NEXT_45]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_46:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 47 +; CHECK-NEXT: [[ARRAYIDX_47:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_46]] +; CHECK-NEXT: [[VAL_47:%.*]] = load i32, ptr [[ARRAYIDX_47]], align 4 +; CHECK-NEXT: [[SUM_NEXT_47:%.*]] = add nsw i32 [[VAL_47]], [[SUM_NEXT_46]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_47:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 48 +; CHECK-NEXT: [[ARRAYIDX_48:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_47]] +; CHECK-NEXT: [[VAL_48:%.*]] = load i32, ptr [[ARRAYIDX_48]], align 4 +; CHECK-NEXT: [[SUM_NEXT_48:%.*]] = add nsw i32 [[VAL_48]], [[SUM_NEXT_47]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_48:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 49 +; CHECK-NEXT: [[ARRAYIDX_49:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_48]] +; CHECK-NEXT: [[VAL_49:%.*]] = load i32, ptr [[ARRAYIDX_49]], align 4 +; CHECK-NEXT: [[SUM_NEXT_49:%.*]] = add nsw i32 [[VAL_49]], [[SUM_NEXT_48]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_49:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 50 +; CHECK-NEXT: [[ARRAYIDX_50:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_49]] +; CHECK-NEXT: [[VAL_50:%.*]] = load i32, ptr [[ARRAYIDX_50]], align 4 +; CHECK-NEXT: [[SUM_NEXT_50:%.*]] = add nsw i32 [[VAL_50]], [[SUM_NEXT_49]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_50:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 51 +; CHECK-NEXT: [[ARRAYIDX_51:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_50]] +; CHECK-NEXT: [[VAL_51:%.*]] = load i32, ptr [[ARRAYIDX_51]], align 4 +; CHECK-NEXT: [[SUM_NEXT_51:%.*]] = add nsw i32 [[VAL_51]], [[SUM_NEXT_50]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_51:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 52 +; CHECK-NEXT: [[ARRAYIDX_52:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_51]] +; CHECK-NEXT: [[VAL_52:%.*]] = load i32, ptr [[ARRAYIDX_52]], align 4 +; CHECK-NEXT: [[SUM_NEXT_52:%.*]] = add nsw i32 [[VAL_52]], [[SUM_NEXT_51]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_52:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 53 +; CHECK-NEXT: [[ARRAYIDX_53:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_52]] +; CHECK-NEXT: [[VAL_53:%.*]] = load i32, ptr [[ARRAYIDX_53]], align 4 +; CHECK-NEXT: [[SUM_NEXT_53:%.*]] = add nsw i32 [[VAL_53]], [[SUM_NEXT_52]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_53:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 54 +; CHECK-NEXT: [[ARRAYIDX_54:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_53]] +; CHECK-NEXT: [[VAL_54:%.*]] = load i32, ptr [[ARRAYIDX_54]], align 4 +; CHECK-NEXT: [[SUM_NEXT_54:%.*]] = add nsw i32 [[VAL_54]], [[SUM_NEXT_53]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_54:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 55 +; CHECK-NEXT: [[ARRAYIDX_55:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_54]] +; CHECK-NEXT: [[VAL_55:%.*]] = load i32, ptr [[ARRAYIDX_55]], align 4 +; CHECK-NEXT: [[SUM_NEXT_55:%.*]] = add nsw i32 [[VAL_55]], [[SUM_NEXT_54]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_55:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 56 +; CHECK-NEXT: [[ARRAYIDX_56:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_55]] +; CHECK-NEXT: [[VAL_56:%.*]] = load i32, ptr [[ARRAYIDX_56]], align 4 +; CHECK-NEXT: [[SUM_NEXT_56:%.*]] = add nsw i32 [[VAL_56]], [[SUM_NEXT_55]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_56:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 57 +; CHECK-NEXT: [[ARRAYIDX_57:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_56]] +; CHECK-NEXT: [[VAL_57:%.*]] = load i32, ptr [[ARRAYIDX_57]], align 4 +; CHECK-NEXT: [[SUM_NEXT_57:%.*]] = add nsw i32 [[VAL_57]], [[SUM_NEXT_56]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_57:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 58 +; CHECK-NEXT: [[ARRAYIDX_58:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_57]] +; CHECK-NEXT: [[VAL_58:%.*]] = load i32, ptr [[ARRAYIDX_58]], align 4 +; CHECK-NEXT: [[SUM_NEXT_58:%.*]] = add nsw i32 [[VAL_58]], [[SUM_NEXT_57]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_58:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 59 +; CHECK-NEXT: [[ARRAYIDX_59:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_58]] +; CHECK-NEXT: [[VAL_59:%.*]] = load i32, ptr [[ARRAYIDX_59]], align 4 +; CHECK-NEXT: [[SUM_NEXT_59:%.*]] = add nsw i32 [[VAL_59]], [[SUM_NEXT_58]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_59:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 60 +; CHECK-NEXT: [[ARRAYIDX_60:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_59]] +; CHECK-NEXT: [[VAL_60:%.*]] = load i32, ptr [[ARRAYIDX_60]], align 4 +; CHECK-NEXT: [[SUM_NEXT_60:%.*]] = add nsw i32 [[VAL_60]], [[SUM_NEXT_59]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_60:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 61 +; CHECK-NEXT: [[ARRAYIDX_61:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_60]] +; CHECK-NEXT: [[VAL_61:%.*]] = load i32, ptr [[ARRAYIDX_61]], align 4 +; CHECK-NEXT: [[SUM_NEXT_61:%.*]] = add nsw i32 [[VAL_61]], [[SUM_NEXT_60]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_61:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 62 +; CHECK-NEXT: [[ARRAYIDX_62:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_61]] +; CHECK-NEXT: [[VAL_62:%.*]] = load i32, ptr [[ARRAYIDX_62]], align 4 +; CHECK-NEXT: [[SUM_NEXT_62:%.*]] = add nsw i32 [[VAL_62]], [[SUM_NEXT_61]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_62:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 63 +; CHECK-NEXT: [[ARRAYIDX_63:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_62]] +; CHECK-NEXT: [[VAL_63:%.*]] = load i32, ptr [[ARRAYIDX_63]], align 4 +; CHECK-NEXT: [[SUM_NEXT_63:%.*]] = add nsw i32 [[VAL_63]], [[SUM_NEXT_62]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_63:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 64 +; CHECK-NEXT: [[ARRAYIDX_64:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_63]] +; CHECK-NEXT: [[VAL_64:%.*]] = load i32, ptr [[ARRAYIDX_64]], align 4 +; CHECK-NEXT: [[SUM_NEXT_64:%.*]] = add nsw i32 [[VAL_64]], [[SUM_NEXT_63]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_64:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 65 +; CHECK-NEXT: [[ARRAYIDX_65:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_64]] +; CHECK-NEXT: [[VAL_65:%.*]] = load i32, ptr [[ARRAYIDX_65]], align 4 +; CHECK-NEXT: [[SUM_NEXT_65:%.*]] = add nsw i32 [[VAL_65]], [[SUM_NEXT_64]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_65:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 66 +; CHECK-NEXT: [[ARRAYIDX_66:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_65]] +; CHECK-NEXT: [[VAL_66:%.*]] = load i32, ptr [[ARRAYIDX_66]], align 4 +; CHECK-NEXT: [[SUM_NEXT_66:%.*]] = add nsw i32 [[VAL_66]], [[SUM_NEXT_65]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_66:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 67 +; CHECK-NEXT: [[ARRAYIDX_67:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_66]] +; CHECK-NEXT: [[VAL_67:%.*]] = load i32, ptr [[ARRAYIDX_67]], align 4 +; CHECK-NEXT: [[SUM_NEXT_67:%.*]] = add nsw i32 [[VAL_67]], [[SUM_NEXT_66]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_67:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 68 +; CHECK-NEXT: [[ARRAYIDX_68:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_67]] +; CHECK-NEXT: [[VAL_68:%.*]] = load i32, ptr [[ARRAYIDX_68]], align 4 +; CHECK-NEXT: [[SUM_NEXT_68:%.*]] = add nsw i32 [[VAL_68]], [[SUM_NEXT_67]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_68:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 69 +; CHECK-NEXT: [[ARRAYIDX_69:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_68]] +; CHECK-NEXT: [[VAL_69:%.*]] = load i32, ptr [[ARRAYIDX_69]], align 4 +; CHECK-NEXT: [[SUM_NEXT_69:%.*]] = add nsw i32 [[VAL_69]], [[SUM_NEXT_68]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_69:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 70 +; CHECK-NEXT: [[ARRAYIDX_70:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_69]] +; CHECK-NEXT: [[VAL_70:%.*]] = load i32, ptr [[ARRAYIDX_70]], align 4 +; CHECK-NEXT: [[SUM_NEXT_70:%.*]] = add nsw i32 [[VAL_70]], [[SUM_NEXT_69]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_70:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 71 +; CHECK-NEXT: [[ARRAYIDX_71:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_70]] +; CHECK-NEXT: [[VAL_71:%.*]] = load i32, ptr [[ARRAYIDX_71]], align 4 +; CHECK-NEXT: [[SUM_NEXT_71:%.*]] = add nsw i32 [[VAL_71]], [[SUM_NEXT_70]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_71:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 72 +; CHECK-NEXT: [[ARRAYIDX_72:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_71]] +; CHECK-NEXT: [[VAL_72:%.*]] = load i32, ptr [[ARRAYIDX_72]], align 4 +; CHECK-NEXT: [[SUM_NEXT_72:%.*]] = add nsw i32 [[VAL_72]], [[SUM_NEXT_71]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_72:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 73 +; CHECK-NEXT: [[ARRAYIDX_73:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_72]] +; CHECK-NEXT: [[VAL_73:%.*]] = load i32, ptr [[ARRAYIDX_73]], align 4 +; CHECK-NEXT: [[SUM_NEXT_73:%.*]] = add nsw i32 [[VAL_73]], [[SUM_NEXT_72]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_73:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 74 +; CHECK-NEXT: [[ARRAYIDX_74:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_73]] +; CHECK-NEXT: [[VAL_74:%.*]] = load i32, ptr [[ARRAYIDX_74]], align 4 +; CHECK-NEXT: [[SUM_NEXT_74:%.*]] = add nsw i32 [[VAL_74]], [[SUM_NEXT_73]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_74:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 75 +; CHECK-NEXT: [[ARRAYIDX_75:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_74]] +; CHECK-NEXT: [[VAL_75:%.*]] = load i32, ptr [[ARRAYIDX_75]], align 4 +; CHECK-NEXT: [[SUM_NEXT_75:%.*]] = add nsw i32 [[VAL_75]], [[SUM_NEXT_74]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_75:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 76 +; CHECK-NEXT: [[ARRAYIDX_76:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_75]] +; CHECK-NEXT: [[VAL_76:%.*]] = load i32, ptr [[ARRAYIDX_76]], align 4 +; CHECK-NEXT: [[SUM_NEXT_76:%.*]] = add nsw i32 [[VAL_76]], [[SUM_NEXT_75]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_76:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 77 +; CHECK-NEXT: [[ARRAYIDX_77:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_76]] +; CHECK-NEXT: [[VAL_77:%.*]] = load i32, ptr [[ARRAYIDX_77]], align 4 +; CHECK-NEXT: [[SUM_NEXT_77:%.*]] = add nsw i32 [[VAL_77]], [[SUM_NEXT_76]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_77:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 78 +; CHECK-NEXT: [[ARRAYIDX_78:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_77]] +; CHECK-NEXT: [[VAL_78:%.*]] = load i32, ptr [[ARRAYIDX_78]], align 4 +; CHECK-NEXT: [[SUM_NEXT_78:%.*]] = add nsw i32 [[VAL_78]], [[SUM_NEXT_77]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_78:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 79 +; CHECK-NEXT: [[ARRAYIDX_79:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_78]] +; CHECK-NEXT: [[VAL_79:%.*]] = load i32, ptr [[ARRAYIDX_79]], align 4 +; CHECK-NEXT: [[SUM_NEXT_79:%.*]] = add nsw i32 [[VAL_79]], [[SUM_NEXT_78]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_79:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 80 +; CHECK-NEXT: [[ARRAYIDX_80:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_79]] +; CHECK-NEXT: [[VAL_80:%.*]] = load i32, ptr [[ARRAYIDX_80]], align 4 +; CHECK-NEXT: [[SUM_NEXT_80:%.*]] = add nsw i32 [[VAL_80]], [[SUM_NEXT_79]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_80:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 81 +; CHECK-NEXT: [[ARRAYIDX_81:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_80]] +; CHECK-NEXT: [[VAL_81:%.*]] = load i32, ptr [[ARRAYIDX_81]], align 4 +; CHECK-NEXT: [[SUM_NEXT_81:%.*]] = add nsw i32 [[VAL_81]], [[SUM_NEXT_80]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_81:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 82 +; CHECK-NEXT: [[ARRAYIDX_82:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_81]] +; CHECK-NEXT: [[VAL_82:%.*]] = load i32, ptr [[ARRAYIDX_82]], align 4 +; CHECK-NEXT: [[SUM_NEXT_82:%.*]] = add nsw i32 [[VAL_82]], [[SUM_NEXT_81]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_82:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 83 +; CHECK-NEXT: [[ARRAYIDX_83:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_82]] +; CHECK-NEXT: [[VAL_83:%.*]] = load i32, ptr [[ARRAYIDX_83]], align 4 +; CHECK-NEXT: [[SUM_NEXT_83:%.*]] = add nsw i32 [[VAL_83]], [[SUM_NEXT_82]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_83:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 84 +; CHECK-NEXT: [[ARRAYIDX_84:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_83]] +; CHECK-NEXT: [[VAL_84:%.*]] = load i32, ptr [[ARRAYIDX_84]], align 4 +; CHECK-NEXT: [[SUM_NEXT_84:%.*]] = add nsw i32 [[VAL_84]], [[SUM_NEXT_83]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_84:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 85 +; CHECK-NEXT: [[ARRAYIDX_85:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_84]] +; CHECK-NEXT: [[VAL_85:%.*]] = load i32, ptr [[ARRAYIDX_85]], align 4 +; CHECK-NEXT: [[SUM_NEXT_85:%.*]] = add nsw i32 [[VAL_85]], [[SUM_NEXT_84]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_85:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 86 +; CHECK-NEXT: [[ARRAYIDX_86:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_85]] +; CHECK-NEXT: [[VAL_86:%.*]] = load i32, ptr [[ARRAYIDX_86]], align 4 +; CHECK-NEXT: [[SUM_NEXT_86:%.*]] = add nsw i32 [[VAL_86]], [[SUM_NEXT_85]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_86:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 87 +; CHECK-NEXT: [[ARRAYIDX_87:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_86]] +; CHECK-NEXT: [[VAL_87:%.*]] = load i32, ptr [[ARRAYIDX_87]], align 4 +; CHECK-NEXT: [[SUM_NEXT_87:%.*]] = add nsw i32 [[VAL_87]], [[SUM_NEXT_86]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_87:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 88 +; CHECK-NEXT: [[ARRAYIDX_88:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_87]] +; CHECK-NEXT: [[VAL_88:%.*]] = load i32, ptr [[ARRAYIDX_88]], align 4 +; CHECK-NEXT: [[SUM_NEXT_88:%.*]] = add nsw i32 [[VAL_88]], [[SUM_NEXT_87]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_88:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 89 +; CHECK-NEXT: [[ARRAYIDX_89:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_88]] +; CHECK-NEXT: [[VAL_89:%.*]] = load i32, ptr [[ARRAYIDX_89]], align 4 +; CHECK-NEXT: [[SUM_NEXT_89:%.*]] = add nsw i32 [[VAL_89]], [[SUM_NEXT_88]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_89:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 90 +; CHECK-NEXT: [[ARRAYIDX_90:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_89]] +; CHECK-NEXT: [[VAL_90:%.*]] = load i32, ptr [[ARRAYIDX_90]], align 4 +; CHECK-NEXT: [[SUM_NEXT_90:%.*]] = add nsw i32 [[VAL_90]], [[SUM_NEXT_89]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_90:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 91 +; CHECK-NEXT: [[ARRAYIDX_91:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_90]] +; CHECK-NEXT: [[VAL_91:%.*]] = load i32, ptr [[ARRAYIDX_91]], align 4 +; CHECK-NEXT: [[SUM_NEXT_91:%.*]] = add nsw i32 [[VAL_91]], [[SUM_NEXT_90]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_91:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 92 +; CHECK-NEXT: [[ARRAYIDX_92:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_91]] +; CHECK-NEXT: [[VAL_92:%.*]] = load i32, ptr [[ARRAYIDX_92]], align 4 +; CHECK-NEXT: [[SUM_NEXT_92:%.*]] = add nsw i32 [[VAL_92]], [[SUM_NEXT_91]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_92:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 93 +; CHECK-NEXT: [[ARRAYIDX_93:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_92]] +; CHECK-NEXT: [[VAL_93:%.*]] = load i32, ptr [[ARRAYIDX_93]], align 4 +; CHECK-NEXT: [[SUM_NEXT_93:%.*]] = add nsw i32 [[VAL_93]], [[SUM_NEXT_92]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_93:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 94 +; CHECK-NEXT: [[ARRAYIDX_94:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_93]] +; CHECK-NEXT: [[VAL_94:%.*]] = load i32, ptr [[ARRAYIDX_94]], align 4 +; CHECK-NEXT: [[SUM_NEXT_94:%.*]] = add nsw i32 [[VAL_94]], [[SUM_NEXT_93]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_94:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 95 +; CHECK-NEXT: [[ARRAYIDX_95:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_94]] +; CHECK-NEXT: [[VAL_95:%.*]] = load i32, ptr [[ARRAYIDX_95]], align 4 +; CHECK-NEXT: [[SUM_NEXT_95:%.*]] = add nsw i32 [[VAL_95]], [[SUM_NEXT_94]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_95:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 96 +; CHECK-NEXT: [[ARRAYIDX_96:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_95]] +; CHECK-NEXT: [[VAL_96:%.*]] = load i32, ptr [[ARRAYIDX_96]], align 4 +; CHECK-NEXT: [[SUM_NEXT_96:%.*]] = add nsw i32 [[VAL_96]], [[SUM_NEXT_95]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_96:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 97 +; CHECK-NEXT: [[ARRAYIDX_97:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_96]] +; CHECK-NEXT: [[VAL_97:%.*]] = load i32, ptr [[ARRAYIDX_97]], align 4 +; CHECK-NEXT: [[SUM_NEXT_97:%.*]] = add nsw i32 [[VAL_97]], [[SUM_NEXT_96]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_97:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 98 +; CHECK-NEXT: [[ARRAYIDX_98:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_97]] +; CHECK-NEXT: [[VAL_98:%.*]] = load i32, ptr [[ARRAYIDX_98]], align 4 +; CHECK-NEXT: [[SUM_NEXT_98:%.*]] = add nsw i32 [[VAL_98]], [[SUM_NEXT_97]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_98:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 99 +; CHECK-NEXT: [[ARRAYIDX_99:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_98]] +; CHECK-NEXT: [[VAL_99:%.*]] = load i32, ptr [[ARRAYIDX_99]], align 4 +; CHECK-NEXT: [[SUM_NEXT_99:%.*]] = add nsw i32 [[VAL_99]], [[SUM_NEXT_98]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_99:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 100 +; CHECK-NEXT: [[ARRAYIDX_100:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_99]] +; CHECK-NEXT: [[VAL_100:%.*]] = load i32, ptr [[ARRAYIDX_100]], align 4 +; CHECK-NEXT: [[SUM_NEXT_100:%.*]] = add nsw i32 [[VAL_100]], [[SUM_NEXT_99]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_100:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 101 +; CHECK-NEXT: [[ARRAYIDX_101:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_100]] +; CHECK-NEXT: [[VAL_101:%.*]] = load i32, ptr [[ARRAYIDX_101]], align 4 +; CHECK-NEXT: [[SUM_NEXT_101:%.*]] = add nsw i32 [[VAL_101]], [[SUM_NEXT_100]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_101:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 102 +; CHECK-NEXT: [[ARRAYIDX_102:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_101]] +; CHECK-NEXT: [[VAL_102:%.*]] = load i32, ptr [[ARRAYIDX_102]], align 4 +; CHECK-NEXT: [[SUM_NEXT_102:%.*]] = add nsw i32 [[VAL_102]], [[SUM_NEXT_101]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_102:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 103 +; CHECK-NEXT: [[ARRAYIDX_103:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_102]] +; CHECK-NEXT: [[VAL_103:%.*]] = load i32, ptr [[ARRAYIDX_103]], align 4 +; CHECK-NEXT: [[SUM_NEXT_103:%.*]] = add nsw i32 [[VAL_103]], [[SUM_NEXT_102]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_103:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 104 +; CHECK-NEXT: [[ARRAYIDX_104:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_103]] +; CHECK-NEXT: [[VAL_104:%.*]] = load i32, ptr [[ARRAYIDX_104]], align 4 +; CHECK-NEXT: [[SUM_NEXT_104:%.*]] = add nsw i32 [[VAL_104]], [[SUM_NEXT_103]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_104:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 105 +; CHECK-NEXT: [[ARRAYIDX_105:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_104]] +; CHECK-NEXT: [[VAL_105:%.*]] = load i32, ptr [[ARRAYIDX_105]], align 4 +; CHECK-NEXT: [[SUM_NEXT_105:%.*]] = add nsw i32 [[VAL_105]], [[SUM_NEXT_104]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_105:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 106 +; CHECK-NEXT: [[ARRAYIDX_106:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_105]] +; CHECK-NEXT: [[VAL_106:%.*]] = load i32, ptr [[ARRAYIDX_106]], align 4 +; CHECK-NEXT: [[SUM_NEXT_106:%.*]] = add nsw i32 [[VAL_106]], [[SUM_NEXT_105]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_106:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 107 +; CHECK-NEXT: [[ARRAYIDX_107:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_106]] +; CHECK-NEXT: [[VAL_107:%.*]] = load i32, ptr [[ARRAYIDX_107]], align 4 +; CHECK-NEXT: [[SUM_NEXT_107:%.*]] = add nsw i32 [[VAL_107]], [[SUM_NEXT_106]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_107:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 108 +; CHECK-NEXT: [[ARRAYIDX_108:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_107]] +; CHECK-NEXT: [[VAL_108:%.*]] = load i32, ptr [[ARRAYIDX_108]], align 4 +; CHECK-NEXT: [[SUM_NEXT_108:%.*]] = add nsw i32 [[VAL_108]], [[SUM_NEXT_107]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_108:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 109 +; CHECK-NEXT: [[ARRAYIDX_109:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_108]] +; CHECK-NEXT: [[VAL_109:%.*]] = load i32, ptr [[ARRAYIDX_109]], align 4 +; CHECK-NEXT: [[SUM_NEXT_109:%.*]] = add nsw i32 [[VAL_109]], [[SUM_NEXT_108]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_109:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 110 +; CHECK-NEXT: [[ARRAYIDX_110:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_109]] +; CHECK-NEXT: [[VAL_110:%.*]] = load i32, ptr [[ARRAYIDX_110]], align 4 +; CHECK-NEXT: [[SUM_NEXT_110:%.*]] = add nsw i32 [[VAL_110]], [[SUM_NEXT_109]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_110:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 111 +; CHECK-NEXT: [[ARRAYIDX_111:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_110]] +; CHECK-NEXT: [[VAL_111:%.*]] = load i32, ptr [[ARRAYIDX_111]], align 4 +; CHECK-NEXT: [[SUM_NEXT_111:%.*]] = add nsw i32 [[VAL_111]], [[SUM_NEXT_110]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_111:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 112 +; CHECK-NEXT: [[ARRAYIDX_112:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_111]] +; CHECK-NEXT: [[VAL_112:%.*]] = load i32, ptr [[ARRAYIDX_112]], align 4 +; CHECK-NEXT: [[SUM_NEXT_112:%.*]] = add nsw i32 [[VAL_112]], [[SUM_NEXT_111]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_112:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 113 +; CHECK-NEXT: [[ARRAYIDX_113:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_112]] +; CHECK-NEXT: [[VAL_113:%.*]] = load i32, ptr [[ARRAYIDX_113]], align 4 +; CHECK-NEXT: [[SUM_NEXT_113:%.*]] = add nsw i32 [[VAL_113]], [[SUM_NEXT_112]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_113:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 114 +; CHECK-NEXT: [[ARRAYIDX_114:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_113]] +; CHECK-NEXT: [[VAL_114:%.*]] = load i32, ptr [[ARRAYIDX_114]], align 4 +; CHECK-NEXT: [[SUM_NEXT_114:%.*]] = add nsw i32 [[VAL_114]], [[SUM_NEXT_113]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_114:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 115 +; CHECK-NEXT: [[ARRAYIDX_115:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_114]] +; CHECK-NEXT: [[VAL_115:%.*]] = load i32, ptr [[ARRAYIDX_115]], align 4 +; CHECK-NEXT: [[SUM_NEXT_115:%.*]] = add nsw i32 [[VAL_115]], [[SUM_NEXT_114]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_115:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 116 +; CHECK-NEXT: [[ARRAYIDX_116:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_115]] +; CHECK-NEXT: [[VAL_116:%.*]] = load i32, ptr [[ARRAYIDX_116]], align 4 +; CHECK-NEXT: [[SUM_NEXT_116:%.*]] = add nsw i32 [[VAL_116]], [[SUM_NEXT_115]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_116:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 117 +; CHECK-NEXT: [[ARRAYIDX_117:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_116]] +; CHECK-NEXT: [[VAL_117:%.*]] = load i32, ptr [[ARRAYIDX_117]], align 4 +; CHECK-NEXT: [[SUM_NEXT_117:%.*]] = add nsw i32 [[VAL_117]], [[SUM_NEXT_116]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_117:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 118 +; CHECK-NEXT: [[ARRAYIDX_118:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_117]] +; CHECK-NEXT: [[VAL_118:%.*]] = load i32, ptr [[ARRAYIDX_118]], align 4 +; CHECK-NEXT: [[SUM_NEXT_118:%.*]] = add nsw i32 [[VAL_118]], [[SUM_NEXT_117]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_118:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 119 +; CHECK-NEXT: [[ARRAYIDX_119:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_118]] +; CHECK-NEXT: [[VAL_119:%.*]] = load i32, ptr [[ARRAYIDX_119]], align 4 +; CHECK-NEXT: [[SUM_NEXT_119:%.*]] = add nsw i32 [[VAL_119]], [[SUM_NEXT_118]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_119:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 120 +; CHECK-NEXT: [[ARRAYIDX_120:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_119]] +; CHECK-NEXT: [[VAL_120:%.*]] = load i32, ptr [[ARRAYIDX_120]], align 4 +; CHECK-NEXT: [[SUM_NEXT_120:%.*]] = add nsw i32 [[VAL_120]], [[SUM_NEXT_119]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_120:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 121 +; CHECK-NEXT: [[ARRAYIDX_121:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_120]] +; CHECK-NEXT: [[VAL_121:%.*]] = load i32, ptr [[ARRAYIDX_121]], align 4 +; CHECK-NEXT: [[SUM_NEXT_121:%.*]] = add nsw i32 [[VAL_121]], [[SUM_NEXT_120]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_121:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 122 +; CHECK-NEXT: [[ARRAYIDX_122:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_121]] +; CHECK-NEXT: [[VAL_122:%.*]] = load i32, ptr [[ARRAYIDX_122]], align 4 +; CHECK-NEXT: [[SUM_NEXT_122:%.*]] = add nsw i32 [[VAL_122]], [[SUM_NEXT_121]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_122:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 123 +; CHECK-NEXT: [[ARRAYIDX_123:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_122]] +; CHECK-NEXT: [[VAL_123:%.*]] = load i32, ptr [[ARRAYIDX_123]], align 4 +; CHECK-NEXT: [[SUM_NEXT_123:%.*]] = add nsw i32 [[VAL_123]], [[SUM_NEXT_122]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_123:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 124 +; CHECK-NEXT: [[ARRAYIDX_124:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_123]] +; CHECK-NEXT: [[VAL_124:%.*]] = load i32, ptr [[ARRAYIDX_124]], align 4 +; CHECK-NEXT: [[SUM_NEXT_124:%.*]] = add nsw i32 [[VAL_124]], [[SUM_NEXT_123]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_124:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 125 +; CHECK-NEXT: [[ARRAYIDX_125:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_124]] +; CHECK-NEXT: [[VAL_125:%.*]] = load i32, ptr [[ARRAYIDX_125]], align 4 +; CHECK-NEXT: [[SUM_NEXT_125:%.*]] = add nsw i32 [[VAL_125]], [[SUM_NEXT_124]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_125:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 126 +; CHECK-NEXT: [[ARRAYIDX_126:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_125]] +; CHECK-NEXT: [[VAL_126:%.*]] = load i32, ptr [[ARRAYIDX_126]], align 4 +; CHECK-NEXT: [[SUM_NEXT_126:%.*]] = add nsw i32 [[VAL_126]], [[SUM_NEXT_125]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_126:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 127 +; CHECK-NEXT: [[ARRAYIDX_127:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_126]] +; CHECK-NEXT: [[VAL_127:%.*]] = load i32, ptr [[ARRAYIDX_127]], align 4 +; CHECK-NEXT: [[SUM_NEXT_127]] = add nsw i32 [[VAL_127]], [[SUM_NEXT_126]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_127]] = add nuw nsw i64 [[INDVARS_IV]], 128 +; CHECK-NEXT: [[EXITCOND_NOT_127:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_127]], 8192 +; CHECK-NEXT: br i1 [[EXITCOND_NOT_127]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_31]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_127]], [[FOR_BODY]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] ; entry: @@ -167,16 +551,16 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-SAME: ptr [[ARY:%.*]], i64 [[N:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 -; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 1 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 1 +; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 7 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7 ; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_COND_CLEANUP_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]] ; CHECK: entry.new: ; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[N]], [[XTRAITER]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_1:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[SUM_NEXT_1:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[NITER:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_1:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_7:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[SUM_NEXT_7:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[NITER:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_7:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[DUMMY1:%.*]] = mul i32 [[VAL]], [[VAL]] @@ -283,15 +667,339 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-NEXT: [[DUMMY48_1:%.*]] = mul i32 [[DUMMY47_1]], [[DUMMY47_1]] ; CHECK-NEXT: [[DUMMY49_1:%.*]] = mul i32 [[DUMMY48_1]], [[DUMMY48_1]] ; CHECK-NEXT: [[DUMMY50_1:%.*]] = mul i32 [[DUMMY49_1]], [[DUMMY49_1]] -; CHECK-NEXT: [[SUM_NEXT_1]] = add nsw i32 [[DUMMY50_1]], [[SUM_NEXT]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_1]] = add nuw nsw i64 [[INDVARS_IV]], 2 -; CHECK-NEXT: [[NITER_NEXT_1]] = add i64 [[NITER]], 2 -; CHECK-NEXT: [[NITER_NCMP_1:%.*]] = icmp eq i64 [[NITER_NEXT_1]], [[UNROLL_ITER]] -; CHECK-NEXT: br i1 [[NITER_NCMP_1]], label [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: [[SUM_NEXT_1:%.*]] = add nsw i32 [[DUMMY50_1]], [[SUM_NEXT]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2 +; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_1]] +; CHECK-NEXT: [[VAL_2:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4 +; CHECK-NEXT: [[DUMMY1_2:%.*]] = mul i32 [[VAL_2]], [[VAL_2]] +; CHECK-NEXT: [[DUMMY2_2:%.*]] = mul i32 [[DUMMY1_2]], [[DUMMY1_2]] +; CHECK-NEXT: [[DUMMY3_2:%.*]] = mul i32 [[DUMMY2_2]], [[DUMMY2_2]] +; CHECK-NEXT: [[DUMMY4_2:%.*]] = mul i32 [[DUMMY3_2]], [[DUMMY3_2]] +; CHECK-NEXT: [[DUMMY5_2:%.*]] = mul i32 [[DUMMY4_2]], [[DUMMY4_2]] +; CHECK-NEXT: [[DUMMY6_2:%.*]] = mul i32 [[DUMMY5_2]], [[DUMMY5_2]] +; CHECK-NEXT: [[DUMMY7_2:%.*]] = mul i32 [[DUMMY6_2]], [[DUMMY6_2]] +; CHECK-NEXT: [[DUMMY8_2:%.*]] = mul i32 [[DUMMY7_2]], [[DUMMY7_2]] +; CHECK-NEXT: [[DUMMY9_2:%.*]] = mul i32 [[DUMMY8_2]], [[DUMMY8_2]] +; CHECK-NEXT: [[DUMMY10_2:%.*]] = mul i32 [[DUMMY9_2]], [[DUMMY9_2]] +; CHECK-NEXT: [[DUMMY11_2:%.*]] = mul i32 [[DUMMY10_2]], [[DUMMY10_2]] +; CHECK-NEXT: [[DUMMY12_2:%.*]] = mul i32 [[DUMMY11_2]], [[DUMMY11_2]] +; CHECK-NEXT: [[DUMMY13_2:%.*]] = mul i32 [[DUMMY12_2]], [[DUMMY12_2]] +; CHECK-NEXT: [[DUMMY14_2:%.*]] = mul i32 [[DUMMY13_2]], [[DUMMY13_2]] +; CHECK-NEXT: [[DUMMY15_2:%.*]] = mul i32 [[DUMMY14_2]], [[DUMMY14_2]] +; CHECK-NEXT: [[DUMMY16_2:%.*]] = mul i32 [[DUMMY15_2]], [[DUMMY15_2]] +; CHECK-NEXT: [[DUMMY17_2:%.*]] = mul i32 [[DUMMY16_2]], [[DUMMY16_2]] +; CHECK-NEXT: [[DUMMY18_2:%.*]] = mul i32 [[DUMMY17_2]], [[DUMMY17_2]] +; CHECK-NEXT: [[DUMMY19_2:%.*]] = mul i32 [[DUMMY18_2]], [[DUMMY18_2]] +; CHECK-NEXT: [[DUMMY20_2:%.*]] = mul i32 [[DUMMY19_2]], [[DUMMY19_2]] +; CHECK-NEXT: [[DUMMY21_2:%.*]] = mul i32 [[DUMMY20_2]], [[DUMMY20_2]] +; CHECK-NEXT: [[DUMMY22_2:%.*]] = mul i32 [[DUMMY21_2]], [[DUMMY21_2]] +; CHECK-NEXT: [[DUMMY23_2:%.*]] = mul i32 [[DUMMY22_2]], [[DUMMY22_2]] +; CHECK-NEXT: [[DUMMY24_2:%.*]] = mul i32 [[DUMMY23_2]], [[DUMMY23_2]] +; CHECK-NEXT: [[DUMMY25_2:%.*]] = mul i32 [[DUMMY24_2]], [[DUMMY24_2]] +; CHECK-NEXT: [[DUMMY26_2:%.*]] = mul i32 [[DUMMY25_2]], [[DUMMY25_2]] +; CHECK-NEXT: [[DUMMY27_2:%.*]] = mul i32 [[DUMMY26_2]], [[DUMMY26_2]] +; CHECK-NEXT: [[DUMMY28_2:%.*]] = mul i32 [[DUMMY27_2]], [[DUMMY27_2]] +; CHECK-NEXT: [[DUMMY29_2:%.*]] = mul i32 [[DUMMY28_2]], [[DUMMY28_2]] +; CHECK-NEXT: [[DUMMY30_2:%.*]] = mul i32 [[DUMMY29_2]], [[DUMMY29_2]] +; CHECK-NEXT: [[DUMMY31_2:%.*]] = mul i32 [[DUMMY30_2]], [[DUMMY30_2]] +; CHECK-NEXT: [[DUMMY32_2:%.*]] = mul i32 [[DUMMY31_2]], [[DUMMY31_2]] +; CHECK-NEXT: [[DUMMY33_2:%.*]] = mul i32 [[DUMMY32_2]], [[DUMMY32_2]] +; CHECK-NEXT: [[DUMMY34_2:%.*]] = mul i32 [[DUMMY33_2]], [[DUMMY33_2]] +; CHECK-NEXT: [[DUMMY35_2:%.*]] = mul i32 [[DUMMY34_2]], [[DUMMY34_2]] +; CHECK-NEXT: [[DUMMY36_2:%.*]] = mul i32 [[DUMMY35_2]], [[DUMMY35_2]] +; CHECK-NEXT: [[DUMMY37_2:%.*]] = mul i32 [[DUMMY36_2]], [[DUMMY36_2]] +; CHECK-NEXT: [[DUMMY38_2:%.*]] = mul i32 [[DUMMY37_2]], [[DUMMY37_2]] +; CHECK-NEXT: [[DUMMY39_2:%.*]] = mul i32 [[DUMMY38_2]], [[DUMMY38_2]] +; CHECK-NEXT: [[DUMMY40_2:%.*]] = mul i32 [[DUMMY39_2]], [[DUMMY39_2]] +; CHECK-NEXT: [[DUMMY41_2:%.*]] = mul i32 [[DUMMY40_2]], [[DUMMY40_2]] +; CHECK-NEXT: [[DUMMY42_2:%.*]] = mul i32 [[DUMMY41_2]], [[DUMMY41_2]] +; CHECK-NEXT: [[DUMMY43_2:%.*]] = mul i32 [[DUMMY42_2]], [[DUMMY42_2]] +; CHECK-NEXT: [[DUMMY44_2:%.*]] = mul i32 [[DUMMY43_2]], [[DUMMY43_2]] +; CHECK-NEXT: [[DUMMY45_2:%.*]] = mul i32 [[DUMMY44_2]], [[DUMMY44_2]] +; CHECK-NEXT: [[DUMMY46_2:%.*]] = mul i32 [[DUMMY45_2]], [[DUMMY45_2]] +; CHECK-NEXT: [[DUMMY47_2:%.*]] = mul i32 [[DUMMY46_2]], [[DUMMY46_2]] +; CHECK-NEXT: [[DUMMY48_2:%.*]] = mul i32 [[DUMMY47_2]], [[DUMMY47_2]] +; CHECK-NEXT: [[DUMMY49_2:%.*]] = mul i32 [[DUMMY48_2]], [[DUMMY48_2]] +; CHECK-NEXT: [[DUMMY50_2:%.*]] = mul i32 [[DUMMY49_2]], [[DUMMY49_2]] +; CHECK-NEXT: [[SUM_NEXT_2:%.*]] = add nsw i32 [[DUMMY50_2]], [[SUM_NEXT_1]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_2:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 3 +; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_2]] +; CHECK-NEXT: [[VAL_3:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4 +; CHECK-NEXT: [[DUMMY1_3:%.*]] = mul i32 [[VAL_3]], [[VAL_3]] +; CHECK-NEXT: [[DUMMY2_3:%.*]] = mul i32 [[DUMMY1_3]], [[DUMMY1_3]] +; CHECK-NEXT: [[DUMMY3_3:%.*]] = mul i32 [[DUMMY2_3]], [[DUMMY2_3]] +; CHECK-NEXT: [[DUMMY4_3:%.*]] = mul i32 [[DUMMY3_3]], [[DUMMY3_3]] +; CHECK-NEXT: [[DUMMY5_3:%.*]] = mul i32 [[DUMMY4_3]], [[DUMMY4_3]] +; CHECK-NEXT: [[DUMMY6_3:%.*]] = mul i32 [[DUMMY5_3]], [[DUMMY5_3]] +; CHECK-NEXT: [[DUMMY7_3:%.*]] = mul i32 [[DUMMY6_3]], [[DUMMY6_3]] +; CHECK-NEXT: [[DUMMY8_3:%.*]] = mul i32 [[DUMMY7_3]], [[DUMMY7_3]] +; CHECK-NEXT: [[DUMMY9_3:%.*]] = mul i32 [[DUMMY8_3]], [[DUMMY8_3]] +; CHECK-NEXT: [[DUMMY10_3:%.*]] = mul i32 [[DUMMY9_3]], [[DUMMY9_3]] +; CHECK-NEXT: [[DUMMY11_3:%.*]] = mul i32 [[DUMMY10_3]], [[DUMMY10_3]] +; CHECK-NEXT: [[DUMMY12_3:%.*]] = mul i32 [[DUMMY11_3]], [[DUMMY11_3]] +; CHECK-NEXT: [[DUMMY13_3:%.*]] = mul i32 [[DUMMY12_3]], [[DUMMY12_3]] +; CHECK-NEXT: [[DUMMY14_3:%.*]] = mul i32 [[DUMMY13_3]], [[DUMMY13_3]] +; CHECK-NEXT: [[DUMMY15_3:%.*]] = mul i32 [[DUMMY14_3]], [[DUMMY14_3]] +; CHECK-NEXT: [[DUMMY16_3:%.*]] = mul i32 [[DUMMY15_3]], [[DUMMY15_3]] +; CHECK-NEXT: [[DUMMY17_3:%.*]] = mul i32 [[DUMMY16_3]], [[DUMMY16_3]] +; CHECK-NEXT: [[DUMMY18_3:%.*]] = mul i32 [[DUMMY17_3]], [[DUMMY17_3]] +; CHECK-NEXT: [[DUMMY19_3:%.*]] = mul i32 [[DUMMY18_3]], [[DUMMY18_3]] +; CHECK-NEXT: [[DUMMY20_3:%.*]] = mul i32 [[DUMMY19_3]], [[DUMMY19_3]] +; CHECK-NEXT: [[DUMMY21_3:%.*]] = mul i32 [[DUMMY20_3]], [[DUMMY20_3]] +; CHECK-NEXT: [[DUMMY22_3:%.*]] = mul i32 [[DUMMY21_3]], [[DUMMY21_3]] +; CHECK-NEXT: [[DUMMY23_3:%.*]] = mul i32 [[DUMMY22_3]], [[DUMMY22_3]] +; CHECK-NEXT: [[DUMMY24_3:%.*]] = mul i32 [[DUMMY23_3]], [[DUMMY23_3]] +; CHECK-NEXT: [[DUMMY25_3:%.*]] = mul i32 [[DUMMY24_3]], [[DUMMY24_3]] +; CHECK-NEXT: [[DUMMY26_3:%.*]] = mul i32 [[DUMMY25_3]], [[DUMMY25_3]] +; CHECK-NEXT: [[DUMMY27_3:%.*]] = mul i32 [[DUMMY26_3]], [[DUMMY26_3]] +; CHECK-NEXT: [[DUMMY28_3:%.*]] = mul i32 [[DUMMY27_3]], [[DUMMY27_3]] +; CHECK-NEXT: [[DUMMY29_3:%.*]] = mul i32 [[DUMMY28_3]], [[DUMMY28_3]] +; CHECK-NEXT: [[DUMMY30_3:%.*]] = mul i32 [[DUMMY29_3]], [[DUMMY29_3]] +; CHECK-NEXT: [[DUMMY31_3:%.*]] = mul i32 [[DUMMY30_3]], [[DUMMY30_3]] +; CHECK-NEXT: [[DUMMY32_3:%.*]] = mul i32 [[DUMMY31_3]], [[DUMMY31_3]] +; CHECK-NEXT: [[DUMMY33_3:%.*]] = mul i32 [[DUMMY32_3]], [[DUMMY32_3]] +; CHECK-NEXT: [[DUMMY34_3:%.*]] = mul i32 [[DUMMY33_3]], [[DUMMY33_3]] +; CHECK-NEXT: [[DUMMY35_3:%.*]] = mul i32 [[DUMMY34_3]], [[DUMMY34_3]] +; CHECK-NEXT: [[DUMMY36_3:%.*]] = mul i32 [[DUMMY35_3]], [[DUMMY35_3]] +; CHECK-NEXT: [[DUMMY37_3:%.*]] = mul i32 [[DUMMY36_3]], [[DUMMY36_3]] +; CHECK-NEXT: [[DUMMY38_3:%.*]] = mul i32 [[DUMMY37_3]], [[DUMMY37_3]] +; CHECK-NEXT: [[DUMMY39_3:%.*]] = mul i32 [[DUMMY38_3]], [[DUMMY38_3]] +; CHECK-NEXT: [[DUMMY40_3:%.*]] = mul i32 [[DUMMY39_3]], [[DUMMY39_3]] +; CHECK-NEXT: [[DUMMY41_3:%.*]] = mul i32 [[DUMMY40_3]], [[DUMMY40_3]] +; CHECK-NEXT: [[DUMMY42_3:%.*]] = mul i32 [[DUMMY41_3]], [[DUMMY41_3]] +; CHECK-NEXT: [[DUMMY43_3:%.*]] = mul i32 [[DUMMY42_3]], [[DUMMY42_3]] +; CHECK-NEXT: [[DUMMY44_3:%.*]] = mul i32 [[DUMMY43_3]], [[DUMMY43_3]] +; CHECK-NEXT: [[DUMMY45_3:%.*]] = mul i32 [[DUMMY44_3]], [[DUMMY44_3]] +; CHECK-NEXT: [[DUMMY46_3:%.*]] = mul i32 [[DUMMY45_3]], [[DUMMY45_3]] +; CHECK-NEXT: [[DUMMY47_3:%.*]] = mul i32 [[DUMMY46_3]], [[DUMMY46_3]] +; CHECK-NEXT: [[DUMMY48_3:%.*]] = mul i32 [[DUMMY47_3]], [[DUMMY47_3]] +; CHECK-NEXT: [[DUMMY49_3:%.*]] = mul i32 [[DUMMY48_3]], [[DUMMY48_3]] +; CHECK-NEXT: [[DUMMY50_3:%.*]] = mul i32 [[DUMMY49_3]], [[DUMMY49_3]] +; CHECK-NEXT: [[SUM_NEXT_3:%.*]] = add nsw i32 [[DUMMY50_3]], [[SUM_NEXT_2]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_3:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 4 +; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_3]] +; CHECK-NEXT: [[VAL_4:%.*]] = load i32, ptr [[ARRAYIDX_4]], align 4 +; CHECK-NEXT: [[DUMMY1_4:%.*]] = mul i32 [[VAL_4]], [[VAL_4]] +; CHECK-NEXT: [[DUMMY2_4:%.*]] = mul i32 [[DUMMY1_4]], [[DUMMY1_4]] +; CHECK-NEXT: [[DUMMY3_4:%.*]] = mul i32 [[DUMMY2_4]], [[DUMMY2_4]] +; CHECK-NEXT: [[DUMMY4_4:%.*]] = mul i32 [[DUMMY3_4]], [[DUMMY3_4]] +; CHECK-NEXT: [[DUMMY5_4:%.*]] = mul i32 [[DUMMY4_4]], [[DUMMY4_4]] +; CHECK-NEXT: [[DUMMY6_4:%.*]] = mul i32 [[DUMMY5_4]], [[DUMMY5_4]] +; CHECK-NEXT: [[DUMMY7_4:%.*]] = mul i32 [[DUMMY6_4]], [[DUMMY6_4]] +; CHECK-NEXT: [[DUMMY8_4:%.*]] = mul i32 [[DUMMY7_4]], [[DUMMY7_4]] +; CHECK-NEXT: [[DUMMY9_4:%.*]] = mul i32 [[DUMMY8_4]], [[DUMMY8_4]] +; CHECK-NEXT: [[DUMMY10_4:%.*]] = mul i32 [[DUMMY9_4]], [[DUMMY9_4]] +; CHECK-NEXT: [[DUMMY11_4:%.*]] = mul i32 [[DUMMY10_4]], [[DUMMY10_4]] +; CHECK-NEXT: [[DUMMY12_4:%.*]] = mul i32 [[DUMMY11_4]], [[DUMMY11_4]] +; CHECK-NEXT: [[DUMMY13_4:%.*]] = mul i32 [[DUMMY12_4]], [[DUMMY12_4]] +; CHECK-NEXT: [[DUMMY14_4:%.*]] = mul i32 [[DUMMY13_4]], [[DUMMY13_4]] +; CHECK-NEXT: [[DUMMY15_4:%.*]] = mul i32 [[DUMMY14_4]], [[DUMMY14_4]] +; CHECK-NEXT: [[DUMMY16_4:%.*]] = mul i32 [[DUMMY15_4]], [[DUMMY15_4]] +; CHECK-NEXT: [[DUMMY17_4:%.*]] = mul i32 [[DUMMY16_4]], [[DUMMY16_4]] +; CHECK-NEXT: [[DUMMY18_4:%.*]] = mul i32 [[DUMMY17_4]], [[DUMMY17_4]] +; CHECK-NEXT: [[DUMMY19_4:%.*]] = mul i32 [[DUMMY18_4]], [[DUMMY18_4]] +; CHECK-NEXT: [[DUMMY20_4:%.*]] = mul i32 [[DUMMY19_4]], [[DUMMY19_4]] +; CHECK-NEXT: [[DUMMY21_4:%.*]] = mul i32 [[DUMMY20_4]], [[DUMMY20_4]] +; CHECK-NEXT: [[DUMMY22_4:%.*]] = mul i32 [[DUMMY21_4]], [[DUMMY21_4]] +; CHECK-NEXT: [[DUMMY23_4:%.*]] = mul i32 [[DUMMY22_4]], [[DUMMY22_4]] +; CHECK-NEXT: [[DUMMY24_4:%.*]] = mul i32 [[DUMMY23_4]], [[DUMMY23_4]] +; CHECK-NEXT: [[DUMMY25_4:%.*]] = mul i32 [[DUMMY24_4]], [[DUMMY24_4]] +; CHECK-NEXT: [[DUMMY26_4:%.*]] = mul i32 [[DUMMY25_4]], [[DUMMY25_4]] +; CHECK-NEXT: [[DUMMY27_4:%.*]] = mul i32 [[DUMMY26_4]], [[DUMMY26_4]] +; CHECK-NEXT: [[DUMMY28_4:%.*]] = mul i32 [[DUMMY27_4]], [[DUMMY27_4]] +; CHECK-NEXT: [[DUMMY29_4:%.*]] = mul i32 [[DUMMY28_4]], [[DUMMY28_4]] +; CHECK-NEXT: [[DUMMY30_4:%.*]] = mul i32 [[DUMMY29_4]], [[DUMMY29_4]] +; CHECK-NEXT: [[DUMMY31_4:%.*]] = mul i32 [[DUMMY30_4]], [[DUMMY30_4]] +; CHECK-NEXT: [[DUMMY32_4:%.*]] = mul i32 [[DUMMY31_4]], [[DUMMY31_4]] +; CHECK-NEXT: [[DUMMY33_4:%.*]] = mul i32 [[DUMMY32_4]], [[DUMMY32_4]] +; CHECK-NEXT: [[DUMMY34_4:%.*]] = mul i32 [[DUMMY33_4]], [[DUMMY33_4]] +; CHECK-NEXT: [[DUMMY35_4:%.*]] = mul i32 [[DUMMY34_4]], [[DUMMY34_4]] +; CHECK-NEXT: [[DUMMY36_4:%.*]] = mul i32 [[DUMMY35_4]], [[DUMMY35_4]] +; CHECK-NEXT: [[DUMMY37_4:%.*]] = mul i32 [[DUMMY36_4]], [[DUMMY36_4]] +; CHECK-NEXT: [[DUMMY38_4:%.*]] = mul i32 [[DUMMY37_4]], [[DUMMY37_4]] +; CHECK-NEXT: [[DUMMY39_4:%.*]] = mul i32 [[DUMMY38_4]], [[DUMMY38_4]] +; CHECK-NEXT: [[DUMMY40_4:%.*]] = mul i32 [[DUMMY39_4]], [[DUMMY39_4]] +; CHECK-NEXT: [[DUMMY41_4:%.*]] = mul i32 [[DUMMY40_4]], [[DUMMY40_4]] +; CHECK-NEXT: [[DUMMY42_4:%.*]] = mul i32 [[DUMMY41_4]], [[DUMMY41_4]] +; CHECK-NEXT: [[DUMMY43_4:%.*]] = mul i32 [[DUMMY42_4]], [[DUMMY42_4]] +; CHECK-NEXT: [[DUMMY44_4:%.*]] = mul i32 [[DUMMY43_4]], [[DUMMY43_4]] +; CHECK-NEXT: [[DUMMY45_4:%.*]] = mul i32 [[DUMMY44_4]], [[DUMMY44_4]] +; CHECK-NEXT: [[DUMMY46_4:%.*]] = mul i32 [[DUMMY45_4]], [[DUMMY45_4]] +; CHECK-NEXT: [[DUMMY47_4:%.*]] = mul i32 [[DUMMY46_4]], [[DUMMY46_4]] +; CHECK-NEXT: [[DUMMY48_4:%.*]] = mul i32 [[DUMMY47_4]], [[DUMMY47_4]] +; CHECK-NEXT: [[DUMMY49_4:%.*]] = mul i32 [[DUMMY48_4]], [[DUMMY48_4]] +; CHECK-NEXT: [[DUMMY50_4:%.*]] = mul i32 [[DUMMY49_4]], [[DUMMY49_4]] +; CHECK-NEXT: [[SUM_NEXT_4:%.*]] = add nsw i32 [[DUMMY50_4]], [[SUM_NEXT_3]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_4:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 5 +; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_4]] +; CHECK-NEXT: [[VAL_5:%.*]] = load i32, ptr [[ARRAYIDX_5]], align 4 +; CHECK-NEXT: [[DUMMY1_5:%.*]] = mul i32 [[VAL_5]], [[VAL_5]] +; CHECK-NEXT: [[DUMMY2_5:%.*]] = mul i32 [[DUMMY1_5]], [[DUMMY1_5]] +; CHECK-NEXT: [[DUMMY3_5:%.*]] = mul i32 [[DUMMY2_5]], [[DUMMY2_5]] +; CHECK-NEXT: [[DUMMY4_5:%.*]] = mul i32 [[DUMMY3_5]], [[DUMMY3_5]] +; CHECK-NEXT: [[DUMMY5_5:%.*]] = mul i32 [[DUMMY4_5]], [[DUMMY4_5]] +; CHECK-NEXT: [[DUMMY6_5:%.*]] = mul i32 [[DUMMY5_5]], [[DUMMY5_5]] +; CHECK-NEXT: [[DUMMY7_5:%.*]] = mul i32 [[DUMMY6_5]], [[DUMMY6_5]] +; CHECK-NEXT: [[DUMMY8_5:%.*]] = mul i32 [[DUMMY7_5]], [[DUMMY7_5]] +; CHECK-NEXT: [[DUMMY9_5:%.*]] = mul i32 [[DUMMY8_5]], [[DUMMY8_5]] +; CHECK-NEXT: [[DUMMY10_5:%.*]] = mul i32 [[DUMMY9_5]], [[DUMMY9_5]] +; CHECK-NEXT: [[DUMMY11_5:%.*]] = mul i32 [[DUMMY10_5]], [[DUMMY10_5]] +; CHECK-NEXT: [[DUMMY12_5:%.*]] = mul i32 [[DUMMY11_5]], [[DUMMY11_5]] +; CHECK-NEXT: [[DUMMY13_5:%.*]] = mul i32 [[DUMMY12_5]], [[DUMMY12_5]] +; CHECK-NEXT: [[DUMMY14_5:%.*]] = mul i32 [[DUMMY13_5]], [[DUMMY13_5]] +; CHECK-NEXT: [[DUMMY15_5:%.*]] = mul i32 [[DUMMY14_5]], [[DUMMY14_5]] +; CHECK-NEXT: [[DUMMY16_5:%.*]] = mul i32 [[DUMMY15_5]], [[DUMMY15_5]] +; CHECK-NEXT: [[DUMMY17_5:%.*]] = mul i32 [[DUMMY16_5]], [[DUMMY16_5]] +; CHECK-NEXT: [[DUMMY18_5:%.*]] = mul i32 [[DUMMY17_5]], [[DUMMY17_5]] +; CHECK-NEXT: [[DUMMY19_5:%.*]] = mul i32 [[DUMMY18_5]], [[DUMMY18_5]] +; CHECK-NEXT: [[DUMMY20_5:%.*]] = mul i32 [[DUMMY19_5]], [[DUMMY19_5]] +; CHECK-NEXT: [[DUMMY21_5:%.*]] = mul i32 [[DUMMY20_5]], [[DUMMY20_5]] +; CHECK-NEXT: [[DUMMY22_5:%.*]] = mul i32 [[DUMMY21_5]], [[DUMMY21_5]] +; CHECK-NEXT: [[DUMMY23_5:%.*]] = mul i32 [[DUMMY22_5]], [[DUMMY22_5]] +; CHECK-NEXT: [[DUMMY24_5:%.*]] = mul i32 [[DUMMY23_5]], [[DUMMY23_5]] +; CHECK-NEXT: [[DUMMY25_5:%.*]] = mul i32 [[DUMMY24_5]], [[DUMMY24_5]] +; CHECK-NEXT: [[DUMMY26_5:%.*]] = mul i32 [[DUMMY25_5]], [[DUMMY25_5]] +; CHECK-NEXT: [[DUMMY27_5:%.*]] = mul i32 [[DUMMY26_5]], [[DUMMY26_5]] +; CHECK-NEXT: [[DUMMY28_5:%.*]] = mul i32 [[DUMMY27_5]], [[DUMMY27_5]] +; CHECK-NEXT: [[DUMMY29_5:%.*]] = mul i32 [[DUMMY28_5]], [[DUMMY28_5]] +; CHECK-NEXT: [[DUMMY30_5:%.*]] = mul i32 [[DUMMY29_5]], [[DUMMY29_5]] +; CHECK-NEXT: [[DUMMY31_5:%.*]] = mul i32 [[DUMMY30_5]], [[DUMMY30_5]] +; CHECK-NEXT: [[DUMMY32_5:%.*]] = mul i32 [[DUMMY31_5]], [[DUMMY31_5]] +; CHECK-NEXT: [[DUMMY33_5:%.*]] = mul i32 [[DUMMY32_5]], [[DUMMY32_5]] +; CHECK-NEXT: [[DUMMY34_5:%.*]] = mul i32 [[DUMMY33_5]], [[DUMMY33_5]] +; CHECK-NEXT: [[DUMMY35_5:%.*]] = mul i32 [[DUMMY34_5]], [[DUMMY34_5]] +; CHECK-NEXT: [[DUMMY36_5:%.*]] = mul i32 [[DUMMY35_5]], [[DUMMY35_5]] +; CHECK-NEXT: [[DUMMY37_5:%.*]] = mul i32 [[DUMMY36_5]], [[DUMMY36_5]] +; CHECK-NEXT: [[DUMMY38_5:%.*]] = mul i32 [[DUMMY37_5]], [[DUMMY37_5]] +; CHECK-NEXT: [[DUMMY39_5:%.*]] = mul i32 [[DUMMY38_5]], [[DUMMY38_5]] +; CHECK-NEXT: [[DUMMY40_5:%.*]] = mul i32 [[DUMMY39_5]], [[DUMMY39_5]] +; CHECK-NEXT: [[DUMMY41_5:%.*]] = mul i32 [[DUMMY40_5]], [[DUMMY40_5]] +; CHECK-NEXT: [[DUMMY42_5:%.*]] = mul i32 [[DUMMY41_5]], [[DUMMY41_5]] +; CHECK-NEXT: [[DUMMY43_5:%.*]] = mul i32 [[DUMMY42_5]], [[DUMMY42_5]] +; CHECK-NEXT: [[DUMMY44_5:%.*]] = mul i32 [[DUMMY43_5]], [[DUMMY43_5]] +; CHECK-NEXT: [[DUMMY45_5:%.*]] = mul i32 [[DUMMY44_5]], [[DUMMY44_5]] +; CHECK-NEXT: [[DUMMY46_5:%.*]] = mul i32 [[DUMMY45_5]], [[DUMMY45_5]] +; CHECK-NEXT: [[DUMMY47_5:%.*]] = mul i32 [[DUMMY46_5]], [[DUMMY46_5]] +; CHECK-NEXT: [[DUMMY48_5:%.*]] = mul i32 [[DUMMY47_5]], [[DUMMY47_5]] +; CHECK-NEXT: [[DUMMY49_5:%.*]] = mul i32 [[DUMMY48_5]], [[DUMMY48_5]] +; CHECK-NEXT: [[DUMMY50_5:%.*]] = mul i32 [[DUMMY49_5]], [[DUMMY49_5]] +; CHECK-NEXT: [[SUM_NEXT_5:%.*]] = add nsw i32 [[DUMMY50_5]], [[SUM_NEXT_4]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_5:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 6 +; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_5]] +; CHECK-NEXT: [[VAL_6:%.*]] = load i32, ptr [[ARRAYIDX_6]], align 4 +; CHECK-NEXT: [[DUMMY1_6:%.*]] = mul i32 [[VAL_6]], [[VAL_6]] +; CHECK-NEXT: [[DUMMY2_6:%.*]] = mul i32 [[DUMMY1_6]], [[DUMMY1_6]] +; CHECK-NEXT: [[DUMMY3_6:%.*]] = mul i32 [[DUMMY2_6]], [[DUMMY2_6]] +; CHECK-NEXT: [[DUMMY4_6:%.*]] = mul i32 [[DUMMY3_6]], [[DUMMY3_6]] +; CHECK-NEXT: [[DUMMY5_6:%.*]] = mul i32 [[DUMMY4_6]], [[DUMMY4_6]] +; CHECK-NEXT: [[DUMMY6_6:%.*]] = mul i32 [[DUMMY5_6]], [[DUMMY5_6]] +; CHECK-NEXT: [[DUMMY7_6:%.*]] = mul i32 [[DUMMY6_6]], [[DUMMY6_6]] +; CHECK-NEXT: [[DUMMY8_6:%.*]] = mul i32 [[DUMMY7_6]], [[DUMMY7_6]] +; CHECK-NEXT: [[DUMMY9_6:%.*]] = mul i32 [[DUMMY8_6]], [[DUMMY8_6]] +; CHECK-NEXT: [[DUMMY10_6:%.*]] = mul i32 [[DUMMY9_6]], [[DUMMY9_6]] +; CHECK-NEXT: [[DUMMY11_6:%.*]] = mul i32 [[DUMMY10_6]], [[DUMMY10_6]] +; CHECK-NEXT: [[DUMMY12_6:%.*]] = mul i32 [[DUMMY11_6]], [[DUMMY11_6]] +; CHECK-NEXT: [[DUMMY13_6:%.*]] = mul i32 [[DUMMY12_6]], [[DUMMY12_6]] +; CHECK-NEXT: [[DUMMY14_6:%.*]] = mul i32 [[DUMMY13_6]], [[DUMMY13_6]] +; CHECK-NEXT: [[DUMMY15_6:%.*]] = mul i32 [[DUMMY14_6]], [[DUMMY14_6]] +; CHECK-NEXT: [[DUMMY16_6:%.*]] = mul i32 [[DUMMY15_6]], [[DUMMY15_6]] +; CHECK-NEXT: [[DUMMY17_6:%.*]] = mul i32 [[DUMMY16_6]], [[DUMMY16_6]] +; CHECK-NEXT: [[DUMMY18_6:%.*]] = mul i32 [[DUMMY17_6]], [[DUMMY17_6]] +; CHECK-NEXT: [[DUMMY19_6:%.*]] = mul i32 [[DUMMY18_6]], [[DUMMY18_6]] +; CHECK-NEXT: [[DUMMY20_6:%.*]] = mul i32 [[DUMMY19_6]], [[DUMMY19_6]] +; CHECK-NEXT: [[DUMMY21_6:%.*]] = mul i32 [[DUMMY20_6]], [[DUMMY20_6]] +; CHECK-NEXT: [[DUMMY22_6:%.*]] = mul i32 [[DUMMY21_6]], [[DUMMY21_6]] +; CHECK-NEXT: [[DUMMY23_6:%.*]] = mul i32 [[DUMMY22_6]], [[DUMMY22_6]] +; CHECK-NEXT: [[DUMMY24_6:%.*]] = mul i32 [[DUMMY23_6]], [[DUMMY23_6]] +; CHECK-NEXT: [[DUMMY25_6:%.*]] = mul i32 [[DUMMY24_6]], [[DUMMY24_6]] +; CHECK-NEXT: [[DUMMY26_6:%.*]] = mul i32 [[DUMMY25_6]], [[DUMMY25_6]] +; CHECK-NEXT: [[DUMMY27_6:%.*]] = mul i32 [[DUMMY26_6]], [[DUMMY26_6]] +; CHECK-NEXT: [[DUMMY28_6:%.*]] = mul i32 [[DUMMY27_6]], [[DUMMY27_6]] +; CHECK-NEXT: [[DUMMY29_6:%.*]] = mul i32 [[DUMMY28_6]], [[DUMMY28_6]] +; CHECK-NEXT: [[DUMMY30_6:%.*]] = mul i32 [[DUMMY29_6]], [[DUMMY29_6]] +; CHECK-NEXT: [[DUMMY31_6:%.*]] = mul i32 [[DUMMY30_6]], [[DUMMY30_6]] +; CHECK-NEXT: [[DUMMY32_6:%.*]] = mul i32 [[DUMMY31_6]], [[DUMMY31_6]] +; CHECK-NEXT: [[DUMMY33_6:%.*]] = mul i32 [[DUMMY32_6]], [[DUMMY32_6]] +; CHECK-NEXT: [[DUMMY34_6:%.*]] = mul i32 [[DUMMY33_6]], [[DUMMY33_6]] +; CHECK-NEXT: [[DUMMY35_6:%.*]] = mul i32 [[DUMMY34_6]], [[DUMMY34_6]] +; CHECK-NEXT: [[DUMMY36_6:%.*]] = mul i32 [[DUMMY35_6]], [[DUMMY35_6]] +; CHECK-NEXT: [[DUMMY37_6:%.*]] = mul i32 [[DUMMY36_6]], [[DUMMY36_6]] +; CHECK-NEXT: [[DUMMY38_6:%.*]] = mul i32 [[DUMMY37_6]], [[DUMMY37_6]] +; CHECK-NEXT: [[DUMMY39_6:%.*]] = mul i32 [[DUMMY38_6]], [[DUMMY38_6]] +; CHECK-NEXT: [[DUMMY40_6:%.*]] = mul i32 [[DUMMY39_6]], [[DUMMY39_6]] +; CHECK-NEXT: [[DUMMY41_6:%.*]] = mul i32 [[DUMMY40_6]], [[DUMMY40_6]] +; CHECK-NEXT: [[DUMMY42_6:%.*]] = mul i32 [[DUMMY41_6]], [[DUMMY41_6]] +; CHECK-NEXT: [[DUMMY43_6:%.*]] = mul i32 [[DUMMY42_6]], [[DUMMY42_6]] +; CHECK-NEXT: [[DUMMY44_6:%.*]] = mul i32 [[DUMMY43_6]], [[DUMMY43_6]] +; CHECK-NEXT: [[DUMMY45_6:%.*]] = mul i32 [[DUMMY44_6]], [[DUMMY44_6]] +; CHECK-NEXT: [[DUMMY46_6:%.*]] = mul i32 [[DUMMY45_6]], [[DUMMY45_6]] +; CHECK-NEXT: [[DUMMY47_6:%.*]] = mul i32 [[DUMMY46_6]], [[DUMMY46_6]] +; CHECK-NEXT: [[DUMMY48_6:%.*]] = mul i32 [[DUMMY47_6]], [[DUMMY47_6]] +; CHECK-NEXT: [[DUMMY49_6:%.*]] = mul i32 [[DUMMY48_6]], [[DUMMY48_6]] +; CHECK-NEXT: [[DUMMY50_6:%.*]] = mul i32 [[DUMMY49_6]], [[DUMMY49_6]] +; CHECK-NEXT: [[SUM_NEXT_6:%.*]] = add nsw i32 [[DUMMY50_6]], [[SUM_NEXT_5]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_6:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 7 +; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_6]] +; CHECK-NEXT: [[VAL_7:%.*]] = load i32, ptr [[ARRAYIDX_7]], align 4 +; CHECK-NEXT: [[DUMMY1_7:%.*]] = mul i32 [[VAL_7]], [[VAL_7]] +; CHECK-NEXT: [[DUMMY2_7:%.*]] = mul i32 [[DUMMY1_7]], [[DUMMY1_7]] +; CHECK-NEXT: [[DUMMY3_7:%.*]] = mul i32 [[DUMMY2_7]], [[DUMMY2_7]] +; CHECK-NEXT: [[DUMMY4_7:%.*]] = mul i32 [[DUMMY3_7]], [[DUMMY3_7]] +; CHECK-NEXT: [[DUMMY5_7:%.*]] = mul i32 [[DUMMY4_7]], [[DUMMY4_7]] +; CHECK-NEXT: [[DUMMY6_7:%.*]] = mul i32 [[DUMMY5_7]], [[DUMMY5_7]] +; CHECK-NEXT: [[DUMMY7_7:%.*]] = mul i32 [[DUMMY6_7]], [[DUMMY6_7]] +; CHECK-NEXT: [[DUMMY8_7:%.*]] = mul i32 [[DUMMY7_7]], [[DUMMY7_7]] +; CHECK-NEXT: [[DUMMY9_7:%.*]] = mul i32 [[DUMMY8_7]], [[DUMMY8_7]] +; CHECK-NEXT: [[DUMMY10_7:%.*]] = mul i32 [[DUMMY9_7]], [[DUMMY9_7]] +; CHECK-NEXT: [[DUMMY11_7:%.*]] = mul i32 [[DUMMY10_7]], [[DUMMY10_7]] +; CHECK-NEXT: [[DUMMY12_7:%.*]] = mul i32 [[DUMMY11_7]], [[DUMMY11_7]] +; CHECK-NEXT: [[DUMMY13_7:%.*]] = mul i32 [[DUMMY12_7]], [[DUMMY12_7]] +; CHECK-NEXT: [[DUMMY14_7:%.*]] = mul i32 [[DUMMY13_7]], [[DUMMY13_7]] +; CHECK-NEXT: [[DUMMY15_7:%.*]] = mul i32 [[DUMMY14_7]], [[DUMMY14_7]] +; CHECK-NEXT: [[DUMMY16_7:%.*]] = mul i32 [[DUMMY15_7]], [[DUMMY15_7]] +; CHECK-NEXT: [[DUMMY17_7:%.*]] = mul i32 [[DUMMY16_7]], [[DUMMY16_7]] +; CHECK-NEXT: [[DUMMY18_7:%.*]] = mul i32 [[DUMMY17_7]], [[DUMMY17_7]] +; CHECK-NEXT: [[DUMMY19_7:%.*]] = mul i32 [[DUMMY18_7]], [[DUMMY18_7]] +; CHECK-NEXT: [[DUMMY20_7:%.*]] = mul i32 [[DUMMY19_7]], [[DUMMY19_7]] +; CHECK-NEXT: [[DUMMY21_7:%.*]] = mul i32 [[DUMMY20_7]], [[DUMMY20_7]] +; CHECK-NEXT: [[DUMMY22_7:%.*]] = mul i32 [[DUMMY21_7]], [[DUMMY21_7]] +; CHECK-NEXT: [[DUMMY23_7:%.*]] = mul i32 [[DUMMY22_7]], [[DUMMY22_7]] +; CHECK-NEXT: [[DUMMY24_7:%.*]] = mul i32 [[DUMMY23_7]], [[DUMMY23_7]] +; CHECK-NEXT: [[DUMMY25_7:%.*]] = mul i32 [[DUMMY24_7]], [[DUMMY24_7]] +; CHECK-NEXT: [[DUMMY26_7:%.*]] = mul i32 [[DUMMY25_7]], [[DUMMY25_7]] +; CHECK-NEXT: [[DUMMY27_7:%.*]] = mul i32 [[DUMMY26_7]], [[DUMMY26_7]] +; CHECK-NEXT: [[DUMMY28_7:%.*]] = mul i32 [[DUMMY27_7]], [[DUMMY27_7]] +; CHECK-NEXT: [[DUMMY29_7:%.*]] = mul i32 [[DUMMY28_7]], [[DUMMY28_7]] +; CHECK-NEXT: [[DUMMY30_7:%.*]] = mul i32 [[DUMMY29_7]], [[DUMMY29_7]] +; CHECK-NEXT: [[DUMMY31_7:%.*]] = mul i32 [[DUMMY30_7]], [[DUMMY30_7]] +; CHECK-NEXT: [[DUMMY32_7:%.*]] = mul i32 [[DUMMY31_7]], [[DUMMY31_7]] +; CHECK-NEXT: [[DUMMY33_7:%.*]] = mul i32 [[DUMMY32_7]], [[DUMMY32_7]] +; CHECK-NEXT: [[DUMMY34_7:%.*]] = mul i32 [[DUMMY33_7]], [[DUMMY33_7]] +; CHECK-NEXT: [[DUMMY35_7:%.*]] = mul i32 [[DUMMY34_7]], [[DUMMY34_7]] +; CHECK-NEXT: [[DUMMY36_7:%.*]] = mul i32 [[DUMMY35_7]], [[DUMMY35_7]] +; CHECK-NEXT: [[DUMMY37_7:%.*]] = mul i32 [[DUMMY36_7]], [[DUMMY36_7]] +; CHECK-NEXT: [[DUMMY38_7:%.*]] = mul i32 [[DUMMY37_7]], [[DUMMY37_7]] +; CHECK-NEXT: [[DUMMY39_7:%.*]] = mul i32 [[DUMMY38_7]], [[DUMMY38_7]] +; CHECK-NEXT: [[DUMMY40_7:%.*]] = mul i32 [[DUMMY39_7]], [[DUMMY39_7]] +; CHECK-NEXT: [[DUMMY41_7:%.*]] = mul i32 [[DUMMY40_7]], [[DUMMY40_7]] +; CHECK-NEXT: [[DUMMY42_7:%.*]] = mul i32 [[DUMMY41_7]], [[DUMMY41_7]] +; CHECK-NEXT: [[DUMMY43_7:%.*]] = mul i32 [[DUMMY42_7]], [[DUMMY42_7]] +; CHECK-NEXT: [[DUMMY44_7:%.*]] = mul i32 [[DUMMY43_7]], [[DUMMY43_7]] +; CHECK-NEXT: [[DUMMY45_7:%.*]] = mul i32 [[DUMMY44_7]], [[DUMMY44_7]] +; CHECK-NEXT: [[DUMMY46_7:%.*]] = mul i32 [[DUMMY45_7]], [[DUMMY45_7]] +; CHECK-NEXT: [[DUMMY47_7:%.*]] = mul i32 [[DUMMY46_7]], [[DUMMY46_7]] +; CHECK-NEXT: [[DUMMY48_7:%.*]] = mul i32 [[DUMMY47_7]], [[DUMMY47_7]] +; CHECK-NEXT: [[DUMMY49_7:%.*]] = mul i32 [[DUMMY48_7]], [[DUMMY48_7]] +; CHECK-NEXT: [[DUMMY50_7:%.*]] = mul i32 [[DUMMY49_7]], [[DUMMY49_7]] +; CHECK-NEXT: [[SUM_NEXT_7]] = add nsw i32 [[DUMMY50_7]], [[SUM_NEXT_6]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_7]] = add nuw nsw i64 [[INDVARS_IV]], 8 +; CHECK-NEXT: [[NITER_NEXT_7]] = add i64 [[NITER]], 8 +; CHECK-NEXT: [[NITER_NCMP_7:%.*]] = icmp eq i64 [[NITER_NEXT_7]], [[UNROLL_ITER]] +; CHECK-NEXT: br i1 [[NITER_NCMP_7]], label [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup.unr-lcssa.loopexit: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH_PH:%.*]] = phi i32 [ [[SUM_NEXT_1]], [[FOR_BODY]] ] -; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_1]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM_UNR_PH:%.*]] = phi i32 [ [[SUM_NEXT_1]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_7]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_UNR_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] ; CHECK-NEXT: br label [[FOR_COND_CLEANUP_UNR_LCSSA]] ; CHECK: for.cond.cleanup.unr-lcssa: ; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[SUM_NEXT_LCSSA_PH_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT]] ] @@ -302,7 +1010,10 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK: for.body.epil.preheader: ; CHECK-NEXT: br label [[FOR_BODY_EPIL:%.*]] ; CHECK: for.body.epil: -; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_UNR]] +; CHECK-NEXT: [[INDVARS_IV_EPIL:%.*]] = phi i64 [ [[INDVARS_IV_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[INDVARS_IV_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] +; CHECK-NEXT: [[SUM_EPIL:%.*]] = phi i32 [ [[SUM_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[SUM_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] +; CHECK-NEXT: [[EPIL_ITER:%.*]] = phi i64 [ 0, [[FOR_BODY_EPIL_PREHEADER]] ], [ [[EPIL_ITER_NEXT:%.*]], [[FOR_BODY_EPIL]] ] +; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_EPIL]] ; CHECK-NEXT: [[VAL_EPIL:%.*]] = load i32, ptr [[ARRAYIDX_EPIL]], align 4 ; CHECK-NEXT: [[DUMMY1_EPIL:%.*]] = mul i32 [[VAL_EPIL]], [[VAL_EPIL]] ; CHECK-NEXT: [[DUMMY2_EPIL:%.*]] = mul i32 [[DUMMY1_EPIL]], [[DUMMY1_EPIL]] @@ -354,10 +1065,17 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-NEXT: [[DUMMY48_EPIL:%.*]] = mul i32 [[DUMMY47_EPIL]], [[DUMMY47_EPIL]] ; CHECK-NEXT: [[DUMMY49_EPIL:%.*]] = mul i32 [[DUMMY48_EPIL]], [[DUMMY48_EPIL]] ; CHECK-NEXT: [[DUMMY50_EPIL:%.*]] = mul i32 [[DUMMY49_EPIL]], [[DUMMY49_EPIL]] -; CHECK-NEXT: [[SUM_NEXT_EPIL:%.*]] = add nsw i32 [[DUMMY50_EPIL]], [[SUM_UNR]] +; CHECK-NEXT: [[SUM_NEXT_EPIL]] = add nsw i32 [[DUMMY50_EPIL]], [[SUM_EPIL]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_EPIL]] = add nuw nsw i64 [[INDVARS_IV_EPIL]], 1 +; CHECK-NEXT: [[EXITCOND_NOT_EPIL:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_EPIL]], [[N]] +; CHECK-NEXT: [[EPIL_ITER_NEXT]] = add i64 [[EPIL_ITER]], 1 +; CHECK-NEXT: [[EPIL_ITER_CMP:%.*]] = icmp ne i64 [[EPIL_ITER_NEXT]], [[XTRAITER]] +; CHECK-NEXT: br i1 [[EPIL_ITER_CMP]], label [[FOR_BODY_EPIL]], label [[FOR_COND_CLEANUP_EPILOG_LCSSA:%.*]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: for.cond.cleanup.epilog-lcssa: +; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH1:%.*]] = phi i32 [ [[SUM_NEXT_EPIL]], [[FOR_BODY_EPIL]] ] ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_LCSSA_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA]] ], [ [[SUM_NEXT_EPIL]], [[FOR_BODY_EPIL]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_LCSSA_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA]] ], [ [[SUM_NEXT_LCSSA_PH1]], [[FOR_COND_CLEANUP_EPILOG_LCSSA]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] ; entry: From ba2e4fe4e7f79e49fcac54ea20f5b899dc687cfc Mon Sep 17 00:00:00 2001 From: Arseniy Zaostrovnykh Date: Thu, 16 May 2024 12:14:53 +0200 Subject: [PATCH 017/576] [clang] Fix CXXNewExpr end source location for 'new struct S' (#92266) Currently, `new struct S` fails to set any valid end source location because the token corresponding to `S` is consumed in `ParseClassSpecifier` and is not accessible in the `ParseDeclarationSpecifiers` that normally sets the end source location. Fixes #35300 --- .../test/clang-tidy/checkers/modernize/make-unique.cpp | 7 ++----- clang/lib/Parse/ParseDeclCXX.cpp | 1 + clang/test/AST/ast-dump-expr.cpp | 7 +++++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp index 7934c6e93ffbd3..fe512a8f3bf321 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp @@ -606,11 +606,8 @@ void invoke_template() { template_fun(foo); } -void no_fix_for_invalid_new_loc() { - // FIXME: Although the code is valid, the end location of `new struct Base` is - // invalid. Correct it once https://bugs.llvm.org/show_bug.cgi?id=35952 is - // fixed. +void fix_for_c_style_struct() { auto T = std::unique_ptr(new struct Base); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead - // CHECK-FIXES: auto T = std::unique_ptr(new struct Base); + // CHECK-FIXES: auto T = std::make_unique(); } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 65ddebca49bc6d..32c4e923243a92 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1883,6 +1883,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); + DS.SetRangeEnd(NameLoc); if (Tok.is(tok::less) && getLangOpts().CPlusPlus) { // The name was supposed to refer to a template, but didn't. diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 4df5ba4276abd2..604868103dab8b 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -583,3 +583,10 @@ void NonADLCall3() { f(x); } } // namespace test_adl_call_three + +namespace GH35300 { +struct Sock {}; +void leakNewFn() { new struct Sock; } +// CHECK: CXXNewExpr {{.*}} 'struct Sock *' +} + From 239f8b9eb0725b4c6ff8342717b6abbfc9a7915a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 16 May 2024 12:44:47 +0200 Subject: [PATCH 018/576] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in the default mode. (#91454) By default (`shouldVisitImplicitCode()` returns `false`), RAV should not traverse AST nodes that are not spelled in the source code. Deduction guides for alias templates are always synthesized, so they should not be traversed. This is usually done by checking the implicit bit of the Decl. However, this doesn't work deduction guides that are synthesized from explicit user-defined deduction guides, as we must maintain the explicit bit to ensure correct overload resolution. --- clang/include/clang/AST/RecursiveASTVisitor.h | 28 ++++-- .../DeductionGuide.cpp | 85 +++++++++++++++++++ 2 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 782f60844506f4..f5cefedb07e0eb 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -736,13 +736,27 @@ bool RecursiveASTVisitor::TraverseDecl(Decl *D) { // As a syntax visitor, by default we want to ignore declarations for // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { - // For an implicit template type parameter, its type constraints are not - // implicit and are not represented anywhere else. We still need to visit - // them. - if (auto *TTPD = dyn_cast(D)) - return TraverseTemplateTypeParamDeclConstraints(TTPD); - return true; + if (!getDerived().shouldVisitImplicitCode()) { + if (D->isImplicit()) { + // For an implicit template type parameter, its type constraints are not + // implicit and are not represented anywhere else. We still need to visit + // them. + if (auto *TTPD = dyn_cast(D)) + return TraverseTemplateTypeParamDeclConstraints(TTPD); + return true; + } + + // Deduction guides for alias templates are always synthesized, so they + // should not be traversed unless shouldVisitImplicitCode() returns true. + // + // It's important to note that checking the implicit bit is not efficient + // for the alias case. For deduction guides synthesized from explicit + // user-defined deduction guides, we must maintain the explicit bit to + // ensure correct overload resolution. + if (auto *FTD = dyn_cast(D)) + if (llvm::isa_and_present( + FTD->getDeclName().getCXXDeductionGuideTemplate())) + return true; } switch (D->getKind()) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp new file mode 100644 index 00000000000000..274f275ea66a9d --- /dev/null +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -0,0 +1,85 @@ +//===- unittest/Tooling/RecursiveASTVisitorTests/DeductionGuide.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 "TestVisitor.h" +#include + +using namespace clang; + +namespace { + +class DeductionGuideVisitor + : public ExpectedLocationVisitor { +public: + DeductionGuideVisitor(bool ShouldVisitImplicitCode) + : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + std::string Storage; + llvm::raw_string_ostream Stream(Storage); + D->print(Stream); + Match(Stream.str(), D->getLocation()); + return true; + } + + bool shouldVisitTemplateInstantiations() const { return false; } + + bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } + bool ShouldVisitImplicitCode; +}; + +TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ false); + // Verify that the synthezied deduction guide for alias is not visited in + // RAV's implicit mode. + Visitor.ExpectMatch("Foo(T) -> Foo", 11, 1); + Visitor.DisallowMatch("Bar(type-parameter-0-0) -> Foo", 14, 1); + EXPECT_TRUE(Visitor.runOver( + R"cpp( +template +concept False = true; + +template +struct Foo { + Foo(T); +}; + +template requires False +Foo(T) -> Foo; + +template +using Bar = Foo; +Bar s(1); + )cpp", + DeductionGuideVisitor::Lang_CXX2a)); +} + +TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ true); + Visitor.ExpectMatch("Foo(T) -> Foo", 11, 1); + Visitor.ExpectMatch("Bar(type-parameter-0-0) -> Foo", 14, 1); + EXPECT_TRUE(Visitor.runOver( + R"cpp( +template +concept False = true; + +template +struct Foo { + Foo(T); +}; + +template requires False +Foo(T) -> Foo; + +template +using Bar = Foo; +Bar s(1); + )cpp", + DeductionGuideVisitor::Lang_CXX2a)); +} + +} // end anonymous namespace From a9605730a481707623358d3b12220f05cfdc50a8 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 16 May 2024 13:01:18 +0200 Subject: [PATCH 019/576] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (#89358) Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 This patch implements the "IsDeducible" constraint where the template arguments of the alias template can be deduced from the returned type of the synthesized deduction guide, per C++ [over.match.class.deduct]p4. In the implementation, we perform the deduction directly, which is more efficient than the way specified in the standard. Also update relevant CTAD tests which were incorrectly compiled due to the missing constraint. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 88 ++++++++++++++++++-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 +++++++++++++++++++ clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 ++++-- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html | 4 +- 10 files changed, 241 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d70..b5a0e9df9f7aee 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32be..66d5e2d4a4aded 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9492,6 +9492,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo &Info); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo &Info); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo &Info, diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395be..8d6794223ccaf9 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { + // The __is_deducible is an internal-only type trait. To hide it from + // external users, we define it with an empty spelling name, preventing the + // clang parser from recognizing its token kind. + // However, other components such as the AST dump still require the real + // type trait name. Therefore, we return the real name when needed. + assert(std::strlen(TypeTraitSpellings[T]) == 0); + return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c929..e4601f7d6c47d5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6143,7 +6143,15 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } - default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { + const auto *TSTToBeDeduced = cast(LhsT); + sema::TemplateDeductionInfo Info(KeyLoc); + return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: + llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not implemented"); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c7aac068e264b7..a5350ceb59cb7c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2782,17 +2782,24 @@ NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, llvm_unreachable("Unhandled template parameter types"); } -// Transform the require-clause of F if any. +// Build the associated constraints for the alias deduction guides. +// C++ [over.match.class.deduct]p3.3: +// The associated constraints ([temp.constr.decl]) are the conjunction of the +// associated constraints of g and a constraint that is satisfied if and only +// if the arguments of A are deducible (see below) from the return type. +// // The return result is expected to be the require-clause for the synthesized // alias deduction guide. -Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *F, - TypeAliasTemplateDecl *AliasTemplate, - ArrayRef DeduceResults) { +Expr * +buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, + TypeAliasTemplateDecl *AliasTemplate, + ArrayRef DeduceResults, + Expr *IsDeducible) { Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) - return nullptr; + return IsDeducible; - auto &Context = SemaRef.Context; + ASTContext &Context = SemaRef.Context; LocalInstantiationScope Scope(SemaRef); // In the clang AST, constraint nodes are deliberately not instantiated unless @@ -2903,7 +2910,68 @@ Expr *transformRequireClause(Sema &SemaRef, FunctionTemplateDecl *F, ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); if (E.isInvalid()) return nullptr; - return E.getAs(); + + auto Conjunction = + SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, + BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible); + if (Conjunction.isInvalid()) + return nullptr; + return Conjunction.getAs(); +} +// Build the is_deducible constraint for the alias deduction guides. +// [over.match.class.deduct]p3.3: +// ... and a constraint that is satisfied if and only if the arguments +// of A are deducible (see below) from the return type. +Expr *buildIsDeducibleConstraint(Sema &SemaRef, + TypeAliasTemplateDecl *AliasTemplate, + QualType ReturnType, + SmallVector TemplateParams) { + ASTContext &Context = SemaRef.Context; + // Constraint AST nodes must use uninstantiated depth. + if (auto *PrimaryTemplate = + AliasTemplate->getInstantiatedFromMemberTemplate()) { + LocalInstantiationScope Scope(SemaRef); + + // Adjust the depth for TemplateParams. + unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth(); + SmallVector TransformedTemplateArgs; + for (auto *TP : TemplateParams) { + // Rebuild any internal references to earlier parameters and reindex + // as we go. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedTemplateArgs); + NamedDecl *NewParam = transformTemplateParameter( + SemaRef, AliasTemplate->getDeclContext(), TP, Args, + /*NewIndex=*/TransformedTemplateArgs.size(), + getTemplateParameterDepth(TP) + AdjustDepth); + + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); + TransformedTemplateArgs.push_back(NewTemplateArgument); + } + // Transformed the ReturnType to restore the uninstantiated depth. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedTemplateArgs); + ReturnType = SemaRef.SubstType( + ReturnType, Args, AliasTemplate->getLocation(), + Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate)); + }; + + SmallVector IsDeducibleTypeTraitArgs = { + Context.getTrivialTypeSourceInfo( + Context.getDeducedTemplateSpecializationType( + TemplateName(AliasTemplate), /*DeducedType=*/QualType(), + /*IsDependent=*/true)), // template specialization type whose + // arguments will be deduced. + Context.getTrivialTypeSourceInfo( + ReturnType), // type from which template arguments are deduced. + }; + return TypeTraitExpr::Create( + Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), + TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs, + AliasTemplate->getLocation(), /*Value*/ false); } std::pair> @@ -3112,8 +3180,10 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, Sema::CodeSynthesisContext::BuildingDeductionGuides)) { auto *GG = cast(FPrime); - Expr *RequiresClause = - transformRequireClause(SemaRef, F, AliasTemplate, DeduceResults); + Expr *IsDeducible = buildIsDeducibleConstraint( + SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams); + Expr *RequiresClause = buildAssociatedConstraints( + SemaRef, F, AliasTemplate, DeduceResults, IsDeducible); // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index b5d405111fe4cb..4d89fcfc9b116f 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3237,6 +3237,40 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( return TemplateDeductionResult::Success; } +/// Complete template argument deduction for DeduceTemplateArgumentsFromType. +/// FIXME: this is mostly duplicated with the above two versions. Deduplicate +/// the three implementations. +static TemplateDeductionResult FinishTemplateArgumentDeduction( + Sema &S, TemplateDecl *TD, + SmallVectorImpl &Deduced, + TemplateDeductionInfo &Info) { + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::SFINAETrap Trap(S); + + Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(TD)); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + SmallVector SugaredBuilder, CanonicalBuilder; + if (auto Result = ConvertDeducedTemplateArguments( + S, TD, /*IsPartialOrdering=*/false, Deduced, Info, SugaredBuilder, + CanonicalBuilder); + Result != TemplateDeductionResult::Success) + return Result; + + if (Trap.hasErrorOccurred()) + return TemplateDeductionResult::SubstitutionFailure; + + if (auto Result = CheckDeducedArgumentConstraints(S, TD, SugaredBuilder, + CanonicalBuilder, Info); + Result != TemplateDeductionResult::Success) + return Result; + + return TemplateDeductionResult::Success; +} /// Perform template argument deduction to determine whether the given template /// arguments match the given class or variable template partial specialization @@ -3305,6 +3339,58 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, return ::DeduceTemplateArguments(*this, Partial, TemplateArgs, Info); } +TemplateDeductionResult +Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo &Info) { + if (TD->isInvalidDecl()) + return TemplateDeductionResult::Invalid; + + QualType PType; + if (const auto *CTD = dyn_cast(TD)) { + // Use the InjectedClassNameType. + PType = Context.getTypeDeclType(CTD->getTemplatedDecl()); + } else if (const auto *AliasTemplate = dyn_cast(TD)) { + PType = AliasTemplate->getTemplatedDecl() + ->getUnderlyingType() + .getCanonicalType(); + } else { + assert(false && "Expected a class or alias template"); + } + + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated( + *this, Sema::ExpressionEvaluationContext::Unevaluated); + SFINAETrap Trap(*this); + + // This deduction has no relation to any outer instantiation we might be + // performing. + LocalInstantiationScope InstantiationScope(*this); + + SmallVector Deduced( + TD->getTemplateParameters()->size()); + SmallVector PArgs = {TemplateArgument(PType)}; + SmallVector AArgs = {TemplateArgument(FromType)}; + if (auto DeducedResult = DeduceTemplateArguments( + TD->getTemplateParameters(), PArgs, AArgs, Info, Deduced, false); + DeducedResult != TemplateDeductionResult::Success) { + return DeducedResult; + } + + SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); + InstantiatingTemplate Inst(*this, Info.getLocation(), TD, DeducedArgs, Info); + if (Inst.isInvalid()) + return TemplateDeductionResult::InstantiationDepth; + + if (Trap.hasErrorOccurred()) + return TemplateDeductionResult::SubstitutionFailure; + + TemplateDeductionResult Result; + runWithSufficientStackSpace(Info.getLocation(), [&] { + Result = ::FinishTemplateArgumentDeduction(*this, TD, Deduced, Info); + }); + return Result; +} + /// Determine whether the given type T is a simple-template-id type. static bool isSimpleTemplateIdType(QualType T) { if (const TemplateSpecializationType *Spec diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 423c3454ccb73e..7fe6c05621eee1 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -24,14 +24,24 @@ Out2::AInner t(1.0); // Verify that the require-clause of alias deduction guide is transformed correctly: // - Occurrence T should be replaced with `int`; // - Occurrence V should be replaced with the Y with depth 1 +// - Depth of occurrence Y in the __is_deducible constraint should be 1 // // CHECK: | `-FunctionTemplateDecl {{.*}} // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y -// CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' -// CHECK-NEXT: | | |-TemplateArgument type 'int' -// CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int' -// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' -// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | |-BinaryOperator {{.*}} '' '&&' +// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' +// CHECK-NEXT: | | | |-TemplateArgument type 'int' +// CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int' +// CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible +// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'AInner' dependent +// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent +// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent Inner +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' +// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> Inner' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 4c5595e409f285..7c186dc379c7b1 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -109,10 +109,12 @@ struct Foo { }; template -using Bar = Foo; +using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ + // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ + // expected-note {{because '__is_deducible}} -// FIXME: we should reject this case? GCC rejects it, MSVC accepts it. -Bar s = {{1}}; + +Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }} } // namespace test9 namespace test10 { @@ -133,9 +135,13 @@ A a(2); // Foo namespace test11 { struct A {}; template struct Foo { T c; }; -template using AFoo = Foo; +template +using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ + // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \ + // expected-note {{because '__is_deducible(AFoo, Foo)' evaluated to false}} \ + // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} -AFoo s = {1}; +AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} } // namespace test11 namespace test12 { @@ -190,13 +196,16 @@ template struct Foo { Foo(T); }; template using AFoo = Foo; template concept False = false; -template using BFoo = AFoo; +// FIXME: emit a more descriptive diagnostic for "__is_deducible" constraint failure. +template +using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ + // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ + // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} int i = 0; AFoo a1(&i); // OK, deduce Foo -// FIXME: we should reject this case as the W is not deduced from the deduced -// type Foo. -BFoo b2(&i); +// the W is not deduced from the deduced type Foo. +BFoo b2(&i); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'BFoo'}} } // namespace test15 namespace test16 { diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 51e1eb49c5de75..a91ab5ec7bcc5f 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -282,12 +282,16 @@ using AFoo = Foo>; // CHECK-LABEL: Dumping // CHECK: FunctionTemplateDecl {{.*}} implicit // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U -// CHECK-NEXT: |-ParenExpr {{.*}} 'bool' -// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '==' -// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'G' -// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} -// CHECK-NEXT: | `-IntegerLiteral {{.*}} -// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' +// CHECK-NEXT: |-BinaryOperator {{.*}} '&&' +// CHECK-NEXT: | |-ParenExpr {{.*}} 'bool' +// CHECK-NEXT: | | `-BinaryOperator {{.*}} 'bool' '==' +// CHECK-NEXT: | | |-UnaryExprOrTypeTraitExpr {{.*}} 'G' +// CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} +// CHECK-NEXT: | | `-IntegerLiteral {{.*}} +// CHECK-NEXT: | `-TypeTraitExpr {{.*}} 'bool' __is_deducible +// CHECK-NEXT: | |-DeducedTemplateSpecializationType {{.*}} 'AFoo' dependent +// CHECK-NEXT: | `-TemplateSpecializationType {{.*}} 'Foo>' dependent Foo +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (G) -> Foo>' // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G' // CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (G) -> Foo>' implicit_instantiation // CHECK-NEXT: |-TemplateArgument type 'int' diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 06777eaa6df69c..6e2fd745e666cb 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -870,8 +870,8 @@

C++20 implementation status

Clang 19 (Partial) - The associated constraints (over.match.class.deduct#3.3) for the - synthesized deduction guides are not yet implemented. + This feature has been initially completed, but the feature macro + __cpp_deduction_guides has not been updated.
From 46bc54f4e688870da8356a9b85257ffb12d47e1f Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 16 May 2024 19:14:30 +0800 Subject: [PATCH 020/576] [ValueTracking] Fix assertion failure when `computeKnownFPClass` returns fcNone (#92355) Fixes https://github.com/llvm/llvm-project/pull/92084#issuecomment-2114083188. --- llvm/lib/Analysis/ValueTracking.cpp | 4 ++ .../test/Transforms/InstCombine/known-bits.ll | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index c8c527a2d4d2f7..e07d14ccbb85c4 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1126,6 +1126,10 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); FPClassTest FPClasses = Result.KnownFPClasses; + // TODO: Treat it as zero/poison if the use of I is unreachable. + if (FPClasses == fcNone) + break; + if (Result.isKnownNever(fcNormal | fcSubnormal | fcNan)) { Known.Zero.setAllBits(); Known.One.setAllBits(); diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 7a380205005179..cb404c0b7f889f 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1658,5 +1658,45 @@ define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { ret i32 %and } +; Make sure that we don't crash when the use of x is unreachable. +define i64 @pr92084(double %x) { +; CHECK-LABEL: @pr92084( +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then1: +; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE]], label [[IF_THEN2:%.*]] +; CHECK: if.then2: +; CHECK-NEXT: [[CAST:%.*]] = bitcast double [[X]] to i64 +; CHECK-NEXT: [[AND:%.*]] = and i64 [[CAST]], 1 +; CHECK-NEXT: ret i64 [[AND]] +; CHECK: if.else: +; CHECK-NEXT: ret i64 0 +; + %cmp = fcmp uno double %x, 0.000000e+00 + br i1 %cmp, label %if.then1, label %if.else + +if.then1: + br i1 %cmp, label %if.else, label %if.then2 + +if.then2: + %cast = bitcast double %x to i64 + %and = and i64 %cast, 1 + ret i64 %and + +if.else: + ret i64 0 +} + +define i32 @test_none(float nofpclass(all) %x) { +; CHECK-LABEL: @test_none( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + declare void @use(i1) declare void @sink(i8) From 0bc1ec5cda8d68a681534bda9fd121b7f58fb495 Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Thu, 16 May 2024 13:34:22 +0200 Subject: [PATCH 021/576] [GlobalISel] Reduce KnownBits usage in matcher combines (#92381) Two icmp/and combines forced computation of KnownBits on all operands everytime. We can avoid computing KnownBits on the LHS by exploiting a couple of properties: - Constants are always on the RHS for those instructions. If we have no KnownBits on the RHS, we can bail out early and avoid computing LHS knownbits. - For icmp uge/ult 0, we don't need to know the KBs of the LHS to infer the result This allows to save some KnownBits calls, which are very expensive, without affecting codegen. --- .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 102 ++++++++++++------ 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 9999776b982602..809f13abcadd1d 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -3220,8 +3220,15 @@ bool CombinerHelper::matchRedundantAnd(MachineInstr &MI, Register AndDst = MI.getOperand(0).getReg(); Register LHS = MI.getOperand(1).getReg(); Register RHS = MI.getOperand(2).getReg(); - KnownBits LHSBits = KB->getKnownBits(LHS); + + // Check the RHS (maybe a constant) first, and if we have no KnownBits there, + // we can't do anything. If we do, then it depends on whether we have + // KnownBits on the LHS. KnownBits RHSBits = KB->getKnownBits(RHS); + if (RHSBits.isUnknown()) + return false; + + KnownBits LHSBits = KB->getKnownBits(LHS); // Check that x & Mask == x. // x & 1 == x, always @@ -3260,6 +3267,7 @@ bool CombinerHelper::matchRedundantOr(MachineInstr &MI, Register &Replacement) { Register OrDst = MI.getOperand(0).getReg(); Register LHS = MI.getOperand(1).getReg(); Register RHS = MI.getOperand(2).getReg(); + KnownBits LHSBits = KB->getKnownBits(LHS); KnownBits RHSBits = KB->getKnownBits(RHS); @@ -4253,43 +4261,67 @@ bool CombinerHelper::matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo) { assert(MI.getOpcode() == TargetOpcode::G_ICMP); auto Pred = static_cast(MI.getOperand(1).getPredicate()); - auto KnownLHS = KB->getKnownBits(MI.getOperand(2).getReg()); + + // We want to avoid calling KnownBits on the LHS if possible, as this combine + // has no filter and runs on every G_ICMP instruction. We can avoid calling + // KnownBits on the LHS in two cases: + // + // - The RHS is unknown: Constants are always on RHS. If the RHS is unknown + // we cannot do any transforms so we can safely bail out early. + // - The RHS is zero: we don't need to know the LHS to do unsigned <0 and + // >=0. auto KnownRHS = KB->getKnownBits(MI.getOperand(3).getReg()); + if (KnownRHS.isUnknown()) + return false; + std::optional KnownVal; - switch (Pred) { - default: - llvm_unreachable("Unexpected G_ICMP predicate?"); - case CmpInst::ICMP_EQ: - KnownVal = KnownBits::eq(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_NE: - KnownVal = KnownBits::ne(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_SGE: - KnownVal = KnownBits::sge(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_SGT: - KnownVal = KnownBits::sgt(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_SLE: - KnownVal = KnownBits::sle(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_SLT: - KnownVal = KnownBits::slt(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_UGE: - KnownVal = KnownBits::uge(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_UGT: - KnownVal = KnownBits::ugt(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_ULE: - KnownVal = KnownBits::ule(KnownLHS, KnownRHS); - break; - case CmpInst::ICMP_ULT: - KnownVal = KnownBits::ult(KnownLHS, KnownRHS); - break; + if (KnownRHS.isZero()) { + // ? uge 0 -> always true + // ? ult 0 -> always false + if (Pred == CmpInst::ICMP_UGE) + KnownVal = true; + else if (Pred == CmpInst::ICMP_ULT) + KnownVal = false; } + + if (!KnownVal) { + auto KnownLHS = KB->getKnownBits(MI.getOperand(2).getReg()); + switch (Pred) { + default: + llvm_unreachable("Unexpected G_ICMP predicate?"); + case CmpInst::ICMP_EQ: + KnownVal = KnownBits::eq(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_NE: + KnownVal = KnownBits::ne(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_SGE: + KnownVal = KnownBits::sge(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_SGT: + KnownVal = KnownBits::sgt(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_SLE: + KnownVal = KnownBits::sle(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_SLT: + KnownVal = KnownBits::slt(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_UGE: + KnownVal = KnownBits::uge(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_UGT: + KnownVal = KnownBits::ugt(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_ULE: + KnownVal = KnownBits::ule(KnownLHS, KnownRHS); + break; + case CmpInst::ICMP_ULT: + KnownVal = KnownBits::ult(KnownLHS, KnownRHS); + break; + } + } + if (!KnownVal) return false; MatchInfo = From 7d81062352f75cf328d91d4900af52c1842b950e Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Thu, 16 May 2024 13:39:00 +0200 Subject: [PATCH 022/576] [GlobalISel] Refactor Combiner MatchData & Apply C++ Code Handling (#92239) Combiners that use C++ code in their "apply" pattern only use that. They never mix it with MIR patterns as that has little added value. This patch restricts C++ apply code so that if C++ is used, we cannot use MIR patterns or builtins with it. Adding this restriction allows us to merge calls to match and apply C++ code together, which in turns makes it so we can just have MatchData variables on the stack. So before, we would have ``` GIM_CheckCxxInsnPredicate // match GIM_CheckCxxInsnPredicate // apply GIR_Done ``` Alongside a massive C++ struct holding the MatchData of all rules possible (which was a big space/perf issue). Now we just have ``` GIR_DoneWithCustomAction ``` And the function being ran just does ``` unsigned SomeMatchData; if (match(SomeMatchData)) apply(SomeMatchData) ``` This approach solves multiple issues in one: - MatchData handling is greatly simplified and more efficient, "don't pay for what you don't use" - We reduce the size of the match table - Calling C++ code has a certain overhead (we need a switch), and this overhead is only paid once now. Handling of C++ code inside PatFrags is unchanged though, that still emits a `GIM_CheckCxxInsnPredicate`. This is completely fine as they can't use MatchDatas. --- llvm/docs/GlobalISel/MIRPatterns.rst | 28 ++- .../CodeGen/GlobalISel/GIMatchTableExecutor.h | 15 +- .../GlobalISel/GIMatchTableExecutorImpl.h | 14 +- .../include/llvm/Target/GlobalISel/Combine.td | 10 +- .../match-table-cxx.td | 143 ++++++++++++++ .../match-table-permutations.td | 104 +++------- .../match-table-variadics.td | 38 ++-- .../GlobalISelCombinerEmitter/match-table.td | 133 ++++++------- .../patfrag-errors.td | 2 +- .../pattern-errors.td | 17 +- .../pattern-parsing.td | 13 +- llvm/test/TableGen/GlobalISelEmitter.td | 2 +- .../test/TableGen/GlobalISelEmitterHwModes.td | 2 +- llvm/utils/TableGen/Common/CMakeLists.txt | 1 - .../Common/GlobalISel/CXXPredicates.cpp | 2 +- .../Common/GlobalISel/CXXPredicates.h | 10 +- .../GlobalISel/GlobalISelMatchTable.cpp | 63 +++--- .../Common/GlobalISel/GlobalISelMatchTable.h | 23 +-- .../GlobalISelMatchTableExecutorEmitter.cpp | 7 +- .../GlobalISelMatchTableExecutorEmitter.h | 4 - .../Common/GlobalISel/MatchDataInfo.cpp | 49 ----- .../Common/GlobalISel/MatchDataInfo.h | 90 --------- .../TableGen/Common/GlobalISel/Patterns.cpp | 4 +- .../TableGen/Common/GlobalISel/Patterns.h | 4 + .../TableGen/GlobalISelCombinerEmitter.cpp | 184 +++++++++++------- llvm/utils/TableGen/GlobalISelEmitter.cpp | 2 +- 26 files changed, 498 insertions(+), 466 deletions(-) create mode 100644 llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td delete mode 100644 llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp delete mode 100644 llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index d7dce1b978cd21..7e6d88683d491e 100644 --- a/llvm/docs/GlobalISel/MIRPatterns.rst +++ b/llvm/docs/GlobalISel/MIRPatterns.rst @@ -274,8 +274,32 @@ it's less verbose. Combine Rules also allow mixing C++ code with MIR patterns, so that you -may perform additional checks when matching, or run additional code after -rewriting a pattern. +may perform additional checks when matching, or run a C++ action after +matching. + +Note that C++ code in ``apply`` pattern is mutually exclusive with +other patterns. However, you can freely mix C++ code with other +types of patterns in ``match`` patterns. +C++ code in ``match`` patterns is always run last, after all other +patterns matched. + +.. code-block:: text + :caption: Apply Pattern Examples with C++ code + + // Valid + def Foo : GICombineRule< + (defs root:$root), + (match (G_ZEXT $tmp, (i32 0)), + (G_STORE $tmp, $ptr):$root, + "return myFinalCheck()"), + (apply "runMyAction(${root})")>; + + // error: 'apply' patterns cannot mix C++ code with other types of patterns + def Bar : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src), + "runMyAction(${root})")>; The following expansions are available for MIR patterns: diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 72c63ecba529f5..371c5c5a0a1e19 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -471,16 +471,11 @@ enum { /// - RendererFnID(2) - Custom renderer function to call GIR_CustomRenderer, - /// Calls a C++ function to perform an action when a match is complete. - /// The MatcherState is passed to the function to allow it to modify - /// instructions. - /// This is less constrained than a custom renderer and can update - /// instructions - /// in the state. + /// Calls a C++ function that concludes the current match. + /// The C++ function is free to return false and reject the match, or + /// return true and mutate the instruction(s) (or do nothing, even). /// - FnID(2) - The function to call. - /// TODO: Remove this at some point when combiners aren't reliant on it. It's - /// a bit of a hack. - GIR_CustomAction, + GIR_DoneWithCustomAction, /// Render operands to the specified instruction using a custom function, /// reading from a specific operand. @@ -688,7 +683,7 @@ class GIMatchTableExecutor { llvm_unreachable("Subclass does not implement testSimplePredicate!"); } - virtual void runCustomAction(unsigned, const MatcherState &State, + virtual bool runCustomAction(unsigned, const MatcherState &State, NewMIVector &OutMIs) const { llvm_unreachable("Subclass does not implement runCustomAction!"); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 4d147bf20c26a5..2ea9d11779f0a1 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -1335,13 +1335,19 @@ bool GIMatchTableExecutor::executeMatchTable( -1); // Not a source operand of the old instruction. break; } - case GIR_CustomAction: { + case GIR_DoneWithCustomAction: { uint16_t FnID = readU16(); DEBUG_WITH_TYPE(TgtExecutor::getName(), - dbgs() << CurrentIdx << ": GIR_CustomAction(FnID=" << FnID - << ")\n"); + dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID=" + << FnID << ")\n"); assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID"); - runCustomAction(FnID, State, OutMIs); + if (runCustomAction(FnID, State, OutMIs)) { + propagateFlags(); + return true; + } + + if (handleReject() == RejectAndGiveUp) + return false; break; } case GIR_CustomOperandRenderer: { diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 98d266c8c0b4f7..d61a5759d5a962 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -338,7 +338,7 @@ def bitreverse_shl : GICombineRule< // Combine bitreverse(lshr (bitreverse x), y)) -> (shl x, y) def bitreverse_lshr : GICombineRule< - (defs root:$d, build_fn_matchinfo:$matchinfo), + (defs root:$d), (match (G_BITREVERSE $rev, $val), (G_LSHR $src, $rev, $amt):$mi, (G_BITREVERSE $d, $src), @@ -1352,7 +1352,7 @@ def match_extract_of_element : GICombineRule< (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; def extract_vector_element_not_const : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx), (G_EXTRACT_VECTOR_ELT $root, $src, $idx)), (apply (GIReplaceReg $root, $value))>; @@ -1567,20 +1567,20 @@ def combine_shuffle_concat : GICombineRule< (apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>; def insert_vector_element_idx_undef : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_IMPLICIT_DEF $idx), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), (apply (G_IMPLICIT_DEF $root))>; def insert_vector_element_elt_undef : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_IMPLICIT_DEF $elt), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx), [{ return isGuaranteedNotToBePoison(${src}.getReg(), MRI); }]), (apply (GIReplaceReg $root, $src))>; def insert_vector_element_extract_vector_element : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_EXTRACT_VECTOR_ELT $elt, $src, $idx), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), (apply (GIReplaceReg $root, $src))>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td new file mode 100644 index 00000000000000..bb1acde2964298 --- /dev/null +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td @@ -0,0 +1,143 @@ +// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ +// RUN: -combiners=MyCombiner %s | \ +// RUN: FileCheck %s + +include "llvm/Target/Target.td" +include "llvm/Target/GlobalISel/Combine.td" + +def MyTargetISA : InstrInfo; +def MyTarget : Target { let InstructionSet = MyTargetISA; } + +def OneMatchOneApply : GICombineRule< + (defs root:$a), + (match (G_FABS $a, $b), "return MATCH0;"), + (apply "APPLY0")>; + +def TwoMatchTwoApply : GICombineRule< + (defs root:$a), + (match (G_FNEG $a, $b), "return MATCH0;", "return MATCH1;"), + (apply "APPLY0", "APPLY1")>; + +def TwoMatchNoApply : GICombineRule< + (defs root:$a), + (match (G_STORE $x, $y):$a, "return MATCH0;", "return MATCH1;"), + (apply (GIEraseRoot))>; + +def NoMatchTwoApply : GICombineRule< + (defs root:$a), + (match (G_SEXT $a, $y)), + (apply "APPLY0", "APPLY1")>; + +def MyCombiner: GICombiner<"GenMyCombiner", [ + OneMatchOneApply, + TwoMatchTwoApply, + TwoMatchNoApply, + NoMatchTwoApply +]>; + +// CHECK: bool GenMyCombiner::testMIPredicate_MI(unsigned PredicateID, const MachineInstr & MI, const MatcherState &State) const { +// CHECK-NEXT: switch (PredicateID) { +// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: { +// CHECK-NEXT: return MATCH0; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner1: { +// CHECK-NEXT: return MATCH1; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("Unknown predicate"); +// CHECK-NEXT: return false; +// CHECK-NEXT: } + +// CHECK: bool GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); +// CHECK-NEXT: switch(ApplyID) { +// CHECK-NEXT: case GICXXCustomAction_GICombiner0:{ +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return MATCH0;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner1:{ +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return MATCH0;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: if(![&](){return MATCH1;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: APPLY1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner2:{ +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: APPLY1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("Unknown Apply Action"); +// CHECK-NEXT: } + +// CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { +// CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(94), GIMT_Encode2(194), /*)*//*default:*//*Label 4*/ GIMT_Encode4(464), +// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(410), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(428), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_FNEG*//*Label 2*/ GIMT_Encode4(440), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_FABS*//*Label 3*/ GIMT_Encode4(452), +// CHECK-NEXT: // Label 0: @410 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(427), // Rule ID 2 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), +// CHECK-NEXT: // MIs[0] x +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] y +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), +// CHECK-NEXT: // Combiner Rule #2: TwoMatchNoApply +// CHECK-NEXT: GIR_EraseRootFromParent_Done, +// CHECK-NEXT: // Label 5: @427 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 1: @428 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(439), // Rule ID 3 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] y +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #3: NoMatchTwoApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), +// CHECK-NEXT: // Label 6: @439 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 2: @440 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(451), // Rule ID 1 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] b +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #1: TwoMatchTwoApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), +// CHECK-NEXT: // Label 7: @451 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 3: @452 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(463), // Rule ID 0 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] b +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #0: OneMatchOneApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 8: @463 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 4: @464 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: }; // Size: 465 bytes +// CHECK-NEXT: return MatchTable0; +// CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td index fda57d5b64e028..4a908e78234844 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td @@ -24,7 +24,7 @@ def Test0 : GICombineRule< (MatchFooPerms $cst1, (i32 20)):$b, (MatchFooPerms $cst2, (i32 30)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${cst0}")>; + (apply "APPLY ${cst0}")>; def MyCombiner: GICombiner<"GenMyCombiner", [ Test0 @@ -159,9 +159,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(738), +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(562), // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_AND), -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(88), // Rule ID 7 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(66), // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -187,16 +187,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner22), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner23), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/4, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 1: @88 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(175), // Rule ID 6 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 1: @66 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(131), // Rule ID 6 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -225,16 +219,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner19), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner20), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 2: @175 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(262), // Rule ID 5 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 2: @131 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(196), // Rule ID 5 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -263,16 +251,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner16), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner17), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 3: @262 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(357), // Rule ID 4 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 3: @196 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(269), // Rule ID 4 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -304,16 +286,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner13), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner14), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 4: @357 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(444), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 4: @269 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(334), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -342,16 +318,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner10), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner11), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 5: @444 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(539), // Rule ID 2 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 5: @334 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(407), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -383,16 +353,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner7), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner8), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 6: @539 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(634), // Rule ID 1 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 6: @407 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(480), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -424,16 +388,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner4), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner5), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 7: @634 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(737), // Rule ID 0 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 7: @480 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(561), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -468,18 +426,12 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner2), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/7, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 8: @737 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 8: @561 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 0: @738 +// CHECK-NEXT: // Label 0: @562 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: 739 bytes +// CHECK-NEXT: }; // Size: 563 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td index 83b77519bc73a8..35bddf912a541a 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td @@ -37,11 +37,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(69), GIMT_Encode2(73), /*)*//*default:*//*Label 2*/ GIMT_Encode4(88), +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(69), GIMT_Encode2(73), /*)*//*default:*//*Label 2*/ GIMT_Encode4(84), // CHECK-NEXT: /*TargetOpcode::G_UNMERGE_VALUES*//*Label 0*/ GIMT_Encode4(26), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_BUILD_VECTOR*//*Label 1*/ GIMT_Encode4(57), +// CHECK-NEXT: /*TargetOpcode::G_BUILD_VECTOR*//*Label 1*/ GIMT_Encode4(55), // CHECK-NEXT: // Label 0: @26 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(41), // Rule ID 2 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(40), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, // CHECK-NEXT: // MIs[0] a @@ -49,10 +49,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #2: InstTest2 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 3: @41 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(56), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 3: @40 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(54), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, // CHECK-NEXT: // MIs[0] a @@ -64,12 +63,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] d // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #3: InstTest3 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 4: @56 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 4: @54 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 1: @57 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(72), // Rule ID 1 // +// CHECK-NEXT: // Label 1: @55 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(69), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, // CHECK-NEXT: // MIs[0] a @@ -77,10 +75,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #1: InstTest1 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 5: @72 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(87), // Rule ID 0 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 5: @69 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(83), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, // CHECK-NEXT: // MIs[0] a @@ -92,12 +89,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] d // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #0: InstTest0 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 6: @87 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 6: @83 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 2: @88 +// CHECK-NEXT: // Label 2: @84 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: 89 bytes +// CHECK-NEXT: }; // Size: 85 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td index 1052e31b2d051e..513a86754d6d9b 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td @@ -41,7 +41,7 @@ def InOutInstTest0 : GICombineRule< (defs root:$root), (match (G_ZEXT $tmp, $ext), (G_STORE $tmp, $ptr):$root), - (apply (G_STORE $ext, $ptr):$root, "APPLY ${ext} ${ptr} ${root}")>; + (apply (G_STORE $ext, $ptr):$root)>; // Imm operand of G_CONSTANT should match a literal int, while the second // should match a constant. @@ -76,16 +76,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // We have at most 2 registers used by one rule at a time, so we should only have 2 registers MDInfos. -// CHECK: struct MatchInfosTy { -// CHECK-NEXT: Register MDInfo0, MDInfo1; -// CHECK-NEXT: }; - // Check predicates // CHECK: switch (PredicateID) { // CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: { -// CHECK-NEXT: return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0] -// CHECK-NEXT: } -// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner1: { // CHECK-NEXT: return matchIConstant(State.MIs[0]->getOperand(1), 0); // CHECK-NEXT: } @@ -96,8 +89,6 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: B.setInstrAndDebugLoc(I); // CHECK-NEXT: State.MIs.clear(); // CHECK-NEXT: State.MIs.push_back(&I); -// CHECK-NEXT: MatchInfos = MatchInfosTy(); -// CHECK-EMPTY: // CHECK-NEXT: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr)) // CHECK-NEXT: return true; // CHECK-NEXT: } @@ -107,43 +98,52 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // Check apply // CHECK: enum { -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner0 = GICXXCustomAction_Invalid + 1, -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner1, -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner2, +// CHECK-NEXT: GICXXCustomAction_GICombiner0 = GICXXCustomAction_Invalid + 1, +// CHECK-NEXT: GICXXCustomAction_GICombiner1, +// CHECK-NEXT: GICXXCustomAction_GICombiner2, // CHECK-NEXT: }; -// CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { + +// CHECK: bool GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); // CHECK-NEXT: switch(ApplyID) { -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner0:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); +// CHECK-NEXT: case GICXXCustomAction_GICombiner0:{ +// CHECK-NEXT: // Apply Patterns // CHECK-NEXT: APPLY -// CHECK-NEXT: return; +// CHECK-NEXT: return true; // CHECK-NEXT: } -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner1:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); -// CHECK-NEXT: APPLY MatchInfos.MDInfo0, MatchInfos.MDInfo1 -// CHECK-NEXT: return; +// CHECK-NEXT: case GICXXCustomAction_GICombiner1:{ +// CHECK-NEXT: Register GIMatchData_r0; +// CHECK-NEXT: Register GIMatchData_r1; +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY GIMatchData_r0, GIMatchData_r1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner2:{ +// CHECK-NEXT: Register GIMatchData_r0; +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0]}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY +// CHECK-NEXT: return true; // CHECK-NEXT: } -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner2:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); -// CHECK-NEXT: APPLY State.MIs[1]->getOperand(1) State.MIs[0]->getOperand(1) OutMIs[0] -// CHECK-NEXT: return; // CHECK-NEXT: } -// CHECK-NEXT: } // CHECK-NEXT: llvm_unreachable("Unknown Apply Action"); // CHECK-NEXT: } // Verify match table. // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(19), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label 6*/ GIMT_Encode4([[L677:[0-9]+]]), -// CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4([[L462:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ GIMT_Encode4([[L504:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ GIMT_Encode4([[L557:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ GIMT_Encode4([[L599:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ GIMT_Encode4([[L624:[0-9]+]]), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ GIMT_Encode4([[L637:[0-9]+]]), -// CHECK-NEXT: // Label 0: @[[L462]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4([[L491:[0-9]+]]), // Rule ID 4 // +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(19), GIMT_Encode2(133), /*)*//*default:*//*Label 6*/ GIMT_Encode4(653), +// CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4(466), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ GIMT_Encode4(502), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ GIMT_Encode4(549), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ GIMT_Encode4(583), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ GIMT_Encode4(606), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ GIMT_Encode4(618), +// CHECK-NEXT: // Label 0: @466 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(490), // Rule ID 4 // // CHECK-NEXT: GIM_CheckFeatures, GIMT_Encode2(GIFBS_HasAnswerToEverything), // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), // CHECK-NEXT: // MIs[0] a @@ -153,25 +153,22 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ZEXT), // CHECK-NEXT: // MIs[1] c // CHECK-NEXT: // No operand predicates -// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1, // CHECK-NEXT: // Combiner Rule #3: InstTest1 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 7: @[[L491]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4([[L503:[0-9]+]]), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), +// CHECK-NEXT: // Label 7: @490 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(501), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), // CHECK-NEXT: // MIs[0] a // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #2: InstTest0 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner1), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 8: @[[L503]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), +// CHECK-NEXT: // Label 8: @501 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 1: @[[L504]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4([[L556:[0-9]+]]), // Rule ID 6 // +// CHECK-NEXT: // Label 1: @502 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(548), // Rule ID 6 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule5Enabled), // CHECK-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32, // CHECK-NEXT: // MIs[0] dst @@ -188,10 +185,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // z // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 9: @[[L556]] +// CHECK-NEXT: // Label 9: @548 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 2: @[[L557]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4([[L598:[0-9]+]]), // Rule ID 5 // +// CHECK-NEXT: // Label 2: @549 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4(582), // Rule ID 5 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule4Enabled), // CHECK-NEXT: // MIs[0] tmp // CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/0, // MIs[1] @@ -206,40 +203,36 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // ext // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // ptr // CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner2), // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 10: @[[L598]] +// CHECK-NEXT: // Label 10: @582 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 3: @[[L599]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4([[L611:[0-9]+]]), // Rule ID 0 // +// CHECK-NEXT: // Label 3: @583 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4(594), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // Combiner Rule #0: WipOpcodeTest0; wip_match_opcode 'G_TRUNC' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 11: @[[L611]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4([[L623:[0-9]+]]), // Rule ID 1 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 11: @594 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4(605), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_TRUNC' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 12: @[[L623]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 12: @605 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 4: @[[L624]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4([[L636:[0-9]+]]), // Rule ID 2 // +// CHECK-NEXT: // Label 4: @606 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4(617), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_SEXT' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 13: @[[L636]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 13: @617 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 5: @[[L637]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4([[L676:[0-9]+]]), // Rule ID 7 // +// CHECK-NEXT: // Label 5: @618 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4(652), // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule6Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // MIs[0] cst // CHECK-NEXT: // No operand predicates -// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, // CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #6: PatFragTest0 @ [__PatFragTest0_match_1[0]] @@ -247,10 +240,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 14: @[[L676]] +// CHECK-NEXT: // Label 14: @652 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 6: @[[L677]] +// CHECK-NEXT: // Label 6: @653 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: {{[0-9]+}} bytes +// CHECK-NEXT: }; // Size: 654 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td index 6f5c2b93609f42..8a3c501a1b4e65 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td @@ -28,7 +28,7 @@ def too_many_perms : GICombineRule< (MatchFooPerms $cst, (i32 0)):$b, (MatchFooPerms $cst, (i32 0)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; def DummyCXXPF: GICombinePatFrag< (outs), diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td index 4b214d2ca89edf..5017672f5cbd72 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td @@ -270,6 +270,19 @@ def badflagref_in_apply : GICombineRule< (match (G_ZEXT $dst, $src):$mi), (apply (G_MUL $dst, $src, $src, (MIFlags $impostor)))>; +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'apply' patterns cannot mix C++ code with other types of patterns +def mixed_cxx_apply : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src), "APPLY")>; + +// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: GIDefMatchData can only be used if 'apply' in entirely written in C++ +def dummy_md : GIDefMatchData<"unsigned">; +def matchdata_without_cxx_apply : GICombineRule< + (defs root:$dst, dummy_md:$md), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src))>; + // CHECK: error: Failed to parse one or more rules def MyCombiner: GICombiner<"GenMyCombiner", [ @@ -311,5 +324,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ miflags_in_builtin, miflags_in_intrin, using_flagref_in_match, - badflagref_in_apply + badflagref_in_apply, + mixed_cxx_apply, + matchdata_without_cxx_apply ]>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td index c261ec45754534..85075359df7374 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td @@ -65,7 +65,7 @@ def InstTest0 : GICombineRule< // CHECK: (CombineRule name:InstTest1 id:3 root:d // CHECK-NEXT: (MatchDatas -// CHECK-NEXT: (MatchDataInfo pattern_symbol:r0 type:'Register' var_name:MDInfo0) +// CHECK-NEXT: (MatchDataDef symbol:r0 type:Register) // CHECK-NEXT: ) // CHECK-NEXT: (MatchPats // CHECK-NEXT: d:(CodeGenInstructionPattern COPY operands:[$a, i32:$b]) @@ -90,7 +90,7 @@ def InstTest1 : GICombineRule< // CHECK: (CombineRule name:InstTest2 id:4 root:d // CHECK-NEXT: (MatchDatas -// CHECK-NEXT: (MatchDataInfo pattern_symbol:r0 type:'Register' var_name:MDInfo0) +// CHECK-NEXT: (MatchDataDef symbol:r0 type:Register) // CHECK-NEXT: ) // CHECK-NEXT: (MatchPats // CHECK-NEXT: __InstTest2_match_0:(CodeGenInstructionPattern COPY operands:[$d, (i32 0):$x]) @@ -116,7 +116,6 @@ def InstTest2 : GICombineRule< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __InOutInstTest0_apply_0:(CodeGenInstructionPattern G_TRUNC operands:[$dst, $src]) -// CHECK-NEXT: __InOutInstTest0_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: dst -> __InOutInstTest0_match_0 @@ -132,7 +131,7 @@ def InOutInstTest0 : GICombineRule< (defs root:$dst), (match (COPY $dst, $tmp), (G_ZEXT $tmp, $src)), - (apply (G_TRUNC $dst, $src), "APPLY ${src}")>; + (apply (G_TRUNC $dst, $src))>; def MatchICst: GICombinePatFrag< (outs), @@ -156,7 +155,6 @@ def MatchICst: GICombinePatFrag< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __PatFragTest0_apply_0:(CodeGenInstructionPattern COPY operands:[$dst, (i32 0)]) -// CHECK-NEXT: __PatFragTest0_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: cst -> @@ -169,7 +167,7 @@ def MatchICst: GICombinePatFrag< def PatFragTest0 : GICombineRule< (defs root:$dst), (match (G_ZEXT $dst, $cst), (MatchICst $cst, (i32 0))), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; def MatchFooPerms: GICombinePatFrag< (outs), @@ -205,7 +203,6 @@ def MatchFooPerms: GICombinePatFrag< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __PatFragTest1_apply_0:(CodeGenInstructionPattern COPY operands:[$dst, (i32 0)]) -// CHECK-NEXT: __PatFragTest1_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: cst -> @@ -252,7 +249,7 @@ def PatFragTest1 : GICombineRule< (MatchFooPerms $cst, (i32 0)):$b, (MatchFooPerms $cst, (i32 0)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; // CHECK: (CombineRule name:VariadicsInTest id:8 root:dst // CHECK-NEXT: (MatchPats diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 23b3d6f59b381e..5d5bf92664a799 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -83,7 +83,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-NEXT: const uint8_t *getMatchTable() const override; // CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override; // CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override; -// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; +// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT diff --git a/llvm/test/TableGen/GlobalISelEmitterHwModes.td b/llvm/test/TableGen/GlobalISelEmitterHwModes.td index 7c8340a154e8be..9d235f5f07a74b 100644 --- a/llvm/test/TableGen/GlobalISelEmitterHwModes.td +++ b/llvm/test/TableGen/GlobalISelEmitterHwModes.td @@ -55,7 +55,7 @@ class I Pat> // CHECK-NEXT: const uint8_t *getMatchTable() const override; // CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override; // CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override; -// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; +// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt index c31ed5a1de690c..30f188ae48a2ac 100644 --- a/llvm/utils/TableGen/Common/CMakeLists.txt +++ b/llvm/utils/TableGen/Common/CMakeLists.txt @@ -16,7 +16,6 @@ add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL GlobalISel/CXXPredicates.cpp GlobalISel/GlobalISelMatchTable.cpp GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp - GlobalISel/MatchDataInfo.cpp GlobalISel/PatternParser.cpp GlobalISel/Patterns.cpp diff --git a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp index e39293ebfe7aee..cbf70278a2813b 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp @@ -45,7 +45,7 @@ CXXPredicateCode::CXXPredicateCode(std::string Code, unsigned ID) : Code(Code), ID(ID), BaseEnumName("GICombiner" + std::to_string(ID)) {} CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXMatchCode; -CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXApplyCode; +CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXCustomActionCode; } // namespace gi } // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h index 01610a13110dd2..01a4cb46a22a9a 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h +++ b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h @@ -37,7 +37,7 @@ class CXXPredicateCode { using CXXPredicateCodePool = DenseMap>; static CXXPredicateCodePool AllCXXMatchCode; - static CXXPredicateCodePool AllCXXApplyCode; + static CXXPredicateCodePool AllCXXCustomActionCode; /// Sorts a `CXXPredicateCodePool` by their IDs and returns it. static std::vector @@ -55,16 +55,16 @@ class CXXPredicateCode { return get(AllCXXMatchCode, std::move(Code)); } - static const CXXPredicateCode &getApplyCode(std::string Code) { - return get(AllCXXApplyCode, std::move(Code)); + static const CXXPredicateCode &getCustomActionCode(std::string Code) { + return get(AllCXXCustomActionCode, std::move(Code)); } static std::vector getAllMatchCode() { return getSorted(AllCXXMatchCode); } - static std::vector getAllApplyCode() { - return getSorted(AllCXXApplyCode); + static std::vector getAllCustomActionsCode() { + return getSorted(AllCXXCustomActionCode); } const std::string Code; diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index 6d03eecae672a7..e011e78c67b153 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -1034,32 +1034,47 @@ void RuleMatcher::emit(MatchTable &Table) { for (const auto &PM : EpilogueMatchers) PM->emitPredicateOpcodes(Table, *this); - // Emit all actions except the last one, then emit coverage and emit the - // final action. - // - // This is because some actions, such as GIR_EraseRootFromParent_Done, also - // double as a GIR_Done and terminate execution of the rule. - if (!Actions.empty()) { - for (const auto &MA : drop_end(Actions)) + if (!CustomCXXAction.empty()) { + /// Handle combiners relying on custom C++ code instead of actions. + assert(Table.isCombiner() && "CustomCXXAction is only for combiners!"); + // We cannot have actions other than debug comments. + assert(none_of(Actions, [](auto &A) { + return A->getKind() != MatchAction::AK_DebugComment; + })); + for (const auto &MA : Actions) MA->emitActionOpcodes(Table, *this); - } - - assert((Table.isWithCoverage() ? !Table.isCombiner() : true) && - "Combiner tables don't support coverage!"); - if (Table.isWithCoverage()) - Table << MatchTable::Opcode("GIR_Coverage") - << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak; - else if (!Table.isCombiner()) - Table << MatchTable::Comment(("GIR_Coverage, " + Twine(RuleID) + ",").str()) + Table << MatchTable::Opcode("GIR_DoneWithCustomAction", -1) + << MatchTable::Comment("Fn") + << MatchTable::NamedValue(2, CustomCXXAction) << MatchTable::LineBreak; + } else { + // Emit all actions except the last one, then emit coverage and emit the + // final action. + // + // This is because some actions, such as GIR_EraseRootFromParent_Done, also + // double as a GIR_Done and terminate execution of the rule. + if (!Actions.empty()) { + for (const auto &MA : drop_end(Actions)) + MA->emitActionOpcodes(Table, *this); + } + + assert((Table.isWithCoverage() ? !Table.isCombiner() : true) && + "Combiner tables don't support coverage!"); + if (Table.isWithCoverage()) + Table << MatchTable::Opcode("GIR_Coverage") + << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak; + else if (!Table.isCombiner()) + Table << MatchTable::Comment( + ("GIR_Coverage, " + Twine(RuleID) + ",").str()) + << MatchTable::LineBreak; - if (Actions.empty() || - !Actions.back()->emitActionOpcodesAndDone(Table, *this)) { - Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak; + if (Actions.empty() || + !Actions.back()->emitActionOpcodesAndDone(Table, *this)) { + Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak; + } } Table << MatchTable::Label(LabelID); - ++NumPatternEmitted; } @@ -2108,14 +2123,6 @@ void CustomOperandRenderer::emitRenderOpcodes(MatchTable &Table, << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; } -//===- CustomCXXAction ----------------------------------------------------===// - -void CustomCXXAction::emitActionOpcodes(MatchTable &Table, - RuleMatcher &Rule) const { - Table << MatchTable::Opcode("GIR_CustomAction") - << MatchTable::NamedValue(2, FnEnumName) << MatchTable::LineBreak; -} - //===- BuildMIAction ------------------------------------------------------===// bool BuildMIAction::canMutate(RuleMatcher &Rule, diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index 30301c28ce6c4d..5fe3f9a32c0164 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -473,6 +473,10 @@ class RuleMatcher : public Matcher { /// have succeeded. ActionList Actions; + /// Combiners can sometimes just run C++ code to finish matching a rule & + /// mutate instructions instead of relying on MatchActions. Empty if unused. + std::string CustomCXXAction; + using DefinedInsnVariablesMap = std::map; /// A map of instruction matchers to the local variables @@ -563,6 +567,10 @@ class RuleMatcher : public Matcher { /// should NOT be emitted. bool tryEraseInsnID(unsigned ID) { return ErasedInsnIDs.insert(ID).second; } + void setCustomCXXAction(StringRef FnEnumName) { + CustomCXXAction = FnEnumName.str(); + } + // Emplaces an action of the specified Kind at the end of the action list. // // Returns a reference to the newly created action. @@ -2206,7 +2214,6 @@ class MatchAction { public: enum ActionKind { AK_DebugComment, - AK_CustomCXX, AK_BuildMI, AK_BuildConstantMI, AK_EraseInst, @@ -2261,20 +2268,6 @@ class DebugCommentAction : public MatchAction { } }; -class CustomCXXAction : public MatchAction { - std::string FnEnumName; - -public: - CustomCXXAction(StringRef FnEnumName) - : MatchAction(AK_CustomCXX), FnEnumName(FnEnumName.str()) {} - - static bool classof(const MatchAction *A) { - return A->getKind() == AK_CustomCXX; - } - - void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; -}; - /// Generates code to build an instruction or mutate an existing instruction /// into the desired instruction when this is possible. class BuildMIAction : public MatchAction { diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp index 5697899a915a03..331da97a6f7c6c 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp @@ -236,11 +236,10 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( ", const MatcherState &State) " "const override;\n" << " bool testSimplePredicate(unsigned PredicateID) const override;\n" - << " void runCustomAction(unsigned FnID, const MatcherState &State, " + << " bool runCustomAction(unsigned FnID, const MatcherState &State, " "NewMIVector &OutMIs) " - "const override;\n"; - emitAdditionalTemporariesDecl(OS, " "); - OS << "#endif // ifdef " << IfDefName << "\n\n"; + "const override;\n" + << "#endif // ifdef " << IfDefName << "\n\n"; } void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h index d2b6a74c757713..13dcfc0e55e1ea 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h @@ -182,10 +182,6 @@ class GlobalISelMatchTableExecutorEmitter { /// Emit additional content in emitExecutorImpl virtual void emitAdditionalImpl(raw_ostream &OS) {} - /// Emit additional content in emitTemporariesDecl. - virtual void emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) {} - /// Emit additional content in emitTemporariesInit. virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {} diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp deleted file mode 100644 index b5c9e4f8c24852..00000000000000 --- a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===- MatchDataInfo.cpp ----------------------------------------*- C++ -*-===// -// -// 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 "MatchDataInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { -namespace gi { - -StringMap> AllMatchDataVars; - -StringRef MatchDataInfo::getVariableName() const { - assert(hasVariableName()); - return VarName; -} - -void MatchDataInfo::print(raw_ostream &OS) const { - OS << "(MatchDataInfo pattern_symbol:" << PatternSymbol << " type:'" << Type - << "' var_name:" << (VarName.empty() ? "" : VarName) << ")"; -} - -void MatchDataInfo::dump() const { print(dbgs()); } - -void AssignMatchDataVariables(MutableArrayRef Infos) { - static unsigned NextVarID = 0; - - StringMap SeenTypes; - for (auto &Info : Infos) { - unsigned &NumSeen = SeenTypes[Info.getType()]; - auto &ExistingVars = AllMatchDataVars[Info.getType()]; - - if (NumSeen == ExistingVars.size()) - ExistingVars.push_back("MDInfo" + std::to_string(NextVarID++)); - - Info.setVariableName(ExistingVars[NumSeen++]); - } -} - -} // namespace gi -} // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h deleted file mode 100644 index abe1245bc67d09..00000000000000 --- a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h +++ /dev/null @@ -1,90 +0,0 @@ -//===- MatchDataInfo.h ------------------------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -/// \file Contains utilities related to handling "match data" for GlobalISel -/// Combiners. Match data allows for setting some arbitrary data in the "match" -/// phase and pass it down to the "apply" phase. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H -#define LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include -#include - -namespace llvm { - -class raw_ostream; - -namespace gi { - -/// Represents MatchData defined by the match stage and required by the apply -/// stage. -/// -/// This allows the plumbing of arbitrary data from C++ predicates between the -/// stages. -/// -/// When this class is initially created, it only has a pattern symbol and a -/// type. When all of the MatchDatas declarations of a given pattern have been -/// parsed, `AssignVariables` must be called to assign storage variable names to -/// each MatchDataInfo. -class MatchDataInfo { - StringRef PatternSymbol; - StringRef Type; - std::string VarName; - -public: - static constexpr StringLiteral StructTypeName = "MatchInfosTy"; - static constexpr StringLiteral StructName = "MatchInfos"; - - MatchDataInfo(StringRef PatternSymbol, StringRef Type) - : PatternSymbol(PatternSymbol), Type(Type.trim()) {} - - StringRef getPatternSymbol() const { return PatternSymbol; }; - StringRef getType() const { return Type; }; - - bool hasVariableName() const { return !VarName.empty(); } - void setVariableName(StringRef Name) { VarName = Name; } - StringRef getVariableName() const; - - std::string getQualifiedVariableName() const { - return StructName.str() + "." + getVariableName().str(); - } - - void print(raw_ostream &OS) const; - void dump() const; -}; - -/// Pool of type -> variables used to emit MatchData variables declarations. -/// -/// e.g. if the map contains "int64_t" -> ["MD0", "MD1"], then two variable -/// declarations must be emitted: `int64_t MD0` and `int64_t MD1`. -/// -/// This has a static lifetime and will outlive all the `MatchDataInfo` objects -/// by design. It needs a static lifetime so the backends can emit variable -/// declarations after processing all the inputs. -extern StringMap> AllMatchDataVars; - -/// Assign variable names to all MatchDatas used by a pattern. This must be -/// called after all MatchData decls have been parsed for a given processing -/// unit (e.g. a combine rule) -/// -/// Requires an array of MatchDataInfo so we can handle cases where a pattern -/// uses multiple instances of the same MatchData type. -/// -/// Writes to \ref AllMatchDataVars. -void AssignMatchDataVariables(MutableArrayRef Infos); - -} // namespace gi -} // end namespace llvm - -#endif // ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H diff --git a/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp index 388bf7e9e83344..28a9bcc2568c34 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp @@ -145,6 +145,8 @@ CXXPattern::CXXPattern(const StringInit &Code, StringRef Name) const CXXPredicateCode & CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef Locs, function_ref AddComment) const { + assert(!IsApply && "'apply' CXX patterns should be handled differently!"); + std::string Result; raw_string_ostream OS(Result); @@ -153,8 +155,6 @@ CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef Locs, CodeExpander Expander(RawCode, CE, Locs, /*ShowExpansions*/ false); Expander.emit(OS); - if (IsApply) - return CXXPredicateCode::getApplyCode(std::move(Result)); return CXXPredicateCode::getMatchCode(std::move(Result)); } diff --git a/llvm/utils/TableGen/Common/GlobalISel/Patterns.h b/llvm/utils/TableGen/Common/GlobalISel/Patterns.h index dac092556548d9..76d018bdbd71c4 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/Patterns.h +++ b/llvm/utils/TableGen/Common/GlobalISel/Patterns.h @@ -205,6 +205,10 @@ class CXXPattern : public Pattern { /// Expands raw code, replacing things such as `${foo}` with their /// substitution in \p CE. /// + /// Can only be used on 'match' CXX Patterns. 'apply' CXX pattern emission + /// is handled differently as we emit both the 'match' and 'apply' part + /// together in a single Custom CXX Action. + /// /// \param CE Map of Code Expansions /// \param Locs SMLocs for the Code Expander, in case it needs to emit /// diagnostics. diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index ef9e9ff04f85f7..085841ed963e4d 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -35,7 +35,6 @@ #include "Common/GlobalISel/CombinerUtils.h" #include "Common/GlobalISel/GlobalISelMatchTable.h" #include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" -#include "Common/GlobalISel/MatchDataInfo.h" #include "Common/GlobalISel/PatternParser.h" #include "Common/GlobalISel/Patterns.h" #include "Common/SubtargetFeatureInfo.h" @@ -45,6 +44,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -79,8 +79,9 @@ cl::opt DebugTypeInfer("gicombiner-debug-typeinfer", cl::desc("Print type inference debug logs"), cl::cat(GICombinerEmitterCat)); -constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply"; +constexpr StringLiteral CXXCustomActionPrefix = "GICXXCustomAction_"; constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_"; +constexpr StringLiteral MatchDataClassName = "GIDefMatchData"; //===- CodeExpansions Helpers --------------------------------------------===// @@ -605,6 +606,21 @@ CombineRuleOperandTypeChecker::getRuleEqClasses() const { return TECs; } +//===- MatchData Handling -------------------------------------------------===// +struct MatchDataDef { + MatchDataDef(StringRef Symbol, StringRef Type) : Symbol(Symbol), Type(Type) {} + + StringRef Symbol; + StringRef Type; + + /// \returns the desired variable name for this MatchData. + std::string getVarName() const { + // Add a prefix in case the symbol name is very generic and conflicts with + // something else. + return "GIMatchData_" + Symbol.str(); + } +}; + //===- CombineRuleBuilder -------------------------------------------------===// /// Parses combine rule and builds a small intermediate representation to tie @@ -671,10 +687,6 @@ class CombineRuleBuilder { void addCXXPredicate(RuleMatcher &M, const CodeExpansions &CE, const CXXPattern &P, const PatternAlternatives &Alts); - /// Adds an apply \p P to \p IM, expanding its code using \p CE. - void addCXXAction(RuleMatcher &M, const CodeExpansions &CE, - const CXXPattern &P); - bool hasOnlyCXXApplyPatterns() const; bool hasEraseRoot() const; @@ -721,6 +733,8 @@ class CombineRuleBuilder { DenseSet &SeenPats); bool emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M); + bool emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M, + ArrayRef Matchers); // Recursively visits InstructionPatterns from P to build up the // RuleMatcher actions. @@ -777,7 +791,7 @@ class CombineRuleBuilder { Pattern *MatchRoot = nullptr; SmallDenseSet ApplyRoots; - SmallVector MatchDatas; + SmallVector MatchDatas; SmallVector PermutationsToEmit; }; @@ -811,7 +825,6 @@ bool CombineRuleBuilder::emitRuleMatchers() { assert(MatchRoot); CodeExpansions CE; - declareAllMatchDatasExpansions(CE); assert(!PermutationsToEmit.empty()); for (const auto &Alts : PermutationsToEmit) { @@ -845,9 +858,8 @@ void CombineRuleBuilder::print(raw_ostream &OS) const { if (!MatchDatas.empty()) { OS << " (MatchDatas\n"; for (const auto &MD : MatchDatas) { - OS << " "; - MD.print(OS); - OS << '\n'; + OS << " (MatchDataDef symbol:" << MD.Symbol << " type:" << MD.Type + << ")\n"; } OS << " )\n"; } @@ -1008,7 +1020,7 @@ bool CombineRuleBuilder::addMatchPattern(std::unique_ptr Pat) { void CombineRuleBuilder::declareAllMatchDatasExpansions( CodeExpansions &CE) const { for (const auto &MD : MatchDatas) - CE.declare(MD.getPatternSymbol(), MD.getQualifiedVariableName()); + CE.declare(MD.Symbol, MD.getVarName()); } void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M, @@ -1030,13 +1042,6 @@ void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M, ExpandedCode.getEnumNameWithPrefix(CXXPredPrefix)); } -void CombineRuleBuilder::addCXXAction(RuleMatcher &M, const CodeExpansions &CE, - const CXXPattern &P) { - const auto &ExpandedCode = P.expandCode(CE, RuleDef.getLoc()); - M.addAction( - ExpandedCode.getEnumNameWithPrefix(CXXApplyPrefix)); -} - bool CombineRuleBuilder::hasOnlyCXXApplyPatterns() const { return all_of(ApplyPats, [&](auto &Entry) { return isa(Entry.second.get()); @@ -1175,9 +1180,20 @@ bool CombineRuleBuilder::checkSemantics() { UsesWipMatchOpcode = true; } + std::optional IsUsingCXXPatterns; for (const auto &Apply : ApplyPats) { - assert(Apply.second.get()); - const auto *IP = dyn_cast(Apply.second.get()); + Pattern *Pat = Apply.second.get(); + if (IsUsingCXXPatterns) { + if (*IsUsingCXXPatterns != isa(Pat)) { + PrintError("'apply' patterns cannot mix C++ code with other types of " + "patterns"); + return false; + } + } else + IsUsingCXXPatterns = isa(Pat); + + assert(Pat); + const auto *IP = dyn_cast(Pat); if (!IP) continue; @@ -1260,6 +1276,12 @@ bool CombineRuleBuilder::checkSemantics() { } } + if (!hasOnlyCXXApplyPatterns() && !MatchDatas.empty()) { + PrintError(MatchDataClassName + + " can only be used if 'apply' in entirely written in C++"); + return false; + } + return true; } @@ -1440,7 +1462,7 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { // data from the match stage to the apply stage, and ensure that the // generated matcher has a suitable variable for it to do so. if (Record *MatchDataRec = - getDefOfSubClass(*Def.getArg(I), "GIDefMatchData")) { + getDefOfSubClass(*Def.getArg(I), MatchDataClassName)) { MatchDatas.emplace_back(Def.getArgNameStr(I), MatchDataRec->getValueAsString("Type")); continue; @@ -1463,9 +1485,6 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { } RootName = Roots.front(); - - // Assign variables to all MatchDatas. - AssignMatchDataVariables(MatchDatas); return true; } @@ -1502,6 +1521,8 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, llvm_unreachable("Unknown kind of InstructionPattern!"); // Emit remaining patterns + const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns(); + SmallVector CXXMatchers; for (auto &Pat : values(MatchPats)) { if (SeenPats.contains(Pat.get())) continue; @@ -1523,7 +1544,11 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, cast(Pat.get())->reportUnreachable(RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXPredicate(M, CE, *cast(Pat.get()), Alts); + // Delay emission for top-level C++ matchers (which can use MatchDatas). + if (IsUsingCustomCXXAction) + CXXMatchers.push_back(cast(Pat.get())); + else + addCXXPredicate(M, CE, *cast(Pat.get()), Alts); continue; } default: @@ -1531,7 +1556,8 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, } } - return emitApplyPatterns(CE, M); + return IsUsingCustomCXXAction ? emitCXXMatchApply(CE, M, CXXMatchers) + : emitApplyPatterns(CE, M); } bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, @@ -1539,6 +1565,7 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, const AnyOpcodePattern &AOP) { auto StackTrace = PrettyStackTraceEmit(RuleDef, &AOP); + const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns(); for (const CodeGenInstruction *CGI : AOP.insts()) { auto &M = addRuleMatcher(Alts, "wip_match_opcode '" + CGI->TheDef->getName() + "'"); @@ -1552,6 +1579,7 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, IM.addPredicate(CGI); // Emit remaining patterns. + SmallVector CXXMatchers; for (auto &Pat : values(MatchPats)) { if (Pat.get() == &AOP) continue; @@ -1576,7 +1604,11 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXPredicate(M, CE, *cast(Pat.get()), Alts); + // Delay emission for top-level C++ matchers (which can use MatchDatas). + if (IsUsingCustomCXXAction) + CXXMatchers.push_back(cast(Pat.get())); + else + addCXXPredicate(M, CE, *cast(Pat.get()), Alts); break; } default: @@ -1584,7 +1616,10 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, } } - if (!emitApplyPatterns(CE, M)) + const bool Res = IsUsingCustomCXXAction + ? emitCXXMatchApply(CE, M, CXXMatchers) + : emitApplyPatterns(CE, M); + if (!Res) return false; } @@ -1727,11 +1762,7 @@ bool CombineRuleBuilder::emitPatFragMatchPattern( } bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { - if (hasOnlyCXXApplyPatterns()) { - for (auto &Pat : values(ApplyPats)) - addCXXAction(M, CE, *cast(Pat.get())); - return true; - } + assert(MatchDatas.empty()); DenseSet SeenPats; StringMap OperandToTempRegID; @@ -1764,8 +1795,8 @@ bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { cast(*Pat).reportUnreachable(RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXAction(M, CE, *cast(Pat.get())); - continue; + llvm_unreachable( + "CXX Pattern Emission should have been handled earlier!"); } default: llvm_unreachable("unknown pattern kind!"); @@ -1780,6 +1811,44 @@ bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { return true; } +bool CombineRuleBuilder::emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M, + ArrayRef Matchers) { + assert(hasOnlyCXXApplyPatterns()); + declareAllMatchDatasExpansions(CE); + + std::string CodeStr; + raw_string_ostream OS(CodeStr); + + for (auto &MD : MatchDatas) + OS << MD.Type << " " << MD.getVarName() << ";\n"; + + if (!Matchers.empty()) { + OS << "// Match Patterns\n"; + for (auto *M : Matchers) { + OS << "if(![&](){"; + CodeExpander Expander(M->getRawCode(), CE, RuleDef.getLoc(), + /*ShowExpansions=*/false); + Expander.emit(OS); + OS << "}()) {\n" + << " return false;\n}\n"; + } + } + + OS << "// Apply Patterns\n"; + ListSeparator LS("\n"); + for (auto &Pat : ApplyPats) { + auto *CXXPat = cast(Pat.second.get()); + CodeExpander Expander(CXXPat->getRawCode(), CE, RuleDef.getLoc(), + /*ShowExpansions=*/ false); + OS << LS; + Expander.emit(OS); + } + + const auto &Code = CXXPredicateCode::getCustomActionCode(CodeStr); + M.setCustomCXXAction(Code.getEnumNameWithPrefix(CXXCustomActionPrefix)); + return true; +} + bool CombineRuleBuilder::emitInstructionApplyPattern( CodeExpansions &CE, RuleMatcher &M, const InstructionPattern &P, DenseSet &SeenPats, @@ -2226,9 +2295,6 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter { void emitTestSimplePredicate(raw_ostream &OS) override; void emitRunCustomAction(raw_ostream &OS) override; - void emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) override; - const CodeGenTarget &getTarget() const override { return Target; } StringRef getClassName() const override { return Combiner->getValueAsString("Classname"); @@ -2371,8 +2437,6 @@ void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) { << " B.setInstrAndDebugLoc(I);\n" << " State.MIs.clear();\n" << " State.MIs.push_back(&I);\n" - << " " << MatchDataInfo::StructName << " = " - << MatchDataInfo::StructTypeName << "();\n\n" << " if (executeMatchTable(*this, State, ExecInfo, B" << ", getMatchTable(), *ST.getInstrInfo(), MRI, " "*MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures" @@ -2438,50 +2502,38 @@ void GICombinerEmitter::emitTestSimplePredicate(raw_ostream &OS) { } void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) { - const auto ApplyCode = CXXPredicateCode::getAllApplyCode(); + const auto CustomActionsCode = CXXPredicateCode::getAllCustomActionsCode(); - if (!ApplyCode.empty()) { + if (!CustomActionsCode.empty()) { OS << "enum {\n"; std::string EnumeratorSeparator = " = GICXXCustomAction_Invalid + 1,\n"; - for (const auto &Apply : ApplyCode) { - OS << " " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) + for (const auto &CA : CustomActionsCode) { + OS << " " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix) << EnumeratorSeparator; EnumeratorSeparator = ",\n"; } OS << "};\n"; } - OS << "void " << getClassName() + OS << "bool " << getClassName() << "::runCustomAction(unsigned ApplyID, const MatcherState &State, " "NewMIVector &OutMIs) const " - "{\n"; - if (!ApplyCode.empty()) { + "{\n Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n"; + if (!CustomActionsCode.empty()) { OS << " switch(ApplyID) {\n"; - for (const auto &Apply : ApplyCode) { - OS << " case " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) << ":{\n" - << " Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n" - << " " << join(split(Apply->Code, '\n'), "\n ") << '\n' - << " return;\n"; + for (const auto &CA : CustomActionsCode) { + OS << " case " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix) + << ":{\n" + << " " << join(split(CA->Code, '\n'), "\n ") << '\n' + << " return true;\n"; OS << " }\n"; } - OS << "}\n"; + OS << " }\n"; } OS << " llvm_unreachable(\"Unknown Apply Action\");\n" << "}\n"; } -void GICombinerEmitter::emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) { - OS << Indent << "struct " << MatchDataInfo::StructTypeName << " {\n"; - for (const auto &[Type, VarNames] : AllMatchDataVars) { - assert(!VarNames.empty() && "Cannot have no vars for this type!"); - OS << Indent << " " << Type << " " << join(VarNames, ", ") << ";\n"; - } - OS << Indent << "};\n" - << Indent << "mutable " << MatchDataInfo::StructTypeName << " " - << MatchDataInfo::StructName << ";\n\n"; -} - GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK, const CodeGenTarget &Target, StringRef Name, Record *Combiner) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index cf7e4398741ca5..9b356148cc171d 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2353,7 +2353,7 @@ void GlobalISelEmitter::emitTestSimplePredicate(raw_ostream &OS) { } void GlobalISelEmitter::emitRunCustomAction(raw_ostream &OS) { - OS << "void " << getClassName() + OS << "bool " << getClassName() << "::runCustomAction(unsigned, const MatcherState&, NewMIVector &) const " "{\n" << " llvm_unreachable(\"" + getClassName() + From cf92e51f5b66afc315f2b43c238291ca87a5602e Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Thu, 16 May 2024 11:40:02 +0000 Subject: [PATCH 023/576] [gn build] Port 7d81062352f7 --- llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn index daa3278d56d7c1..9e19ec9df4d30d 100644 --- a/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn @@ -21,7 +21,6 @@ static_library("Common") { "GlobalISel/CombinerUtils.cpp", "GlobalISel/GlobalISelMatchTable.cpp", "GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp", - "GlobalISel/MatchDataInfo.cpp", "GlobalISel/PatternParser.cpp", "GlobalISel/Patterns.cpp", "InfoByHwMode.cpp", From 311339e25cd4d431902f93b1cbc6b67ac3fd2abf Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 16 May 2024 13:05:22 +0100 Subject: [PATCH 024/576] [DAG] SimplifyDemandedBits - ISD::AND - only request DemandedElts when looking for a splat constant Limit the isConstOrConstSplat call to the vector elements we care about Noticed while investigating regressions in #92096 --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 2 +- .../Thumb2/mve-laneinterleaving-cost.ll | 138 +++++++++--------- 2 files changed, 66 insertions(+), 74 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 9ddb14e11dab2d..38583de03d9c80 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1380,7 +1380,7 @@ bool TargetLowering::SimplifyDemandedBits( // using the bits from the RHS. Below, we use knowledge about the RHS to // simplify the LHS, here we're using information from the LHS to simplify // the RHS. - if (ConstantSDNode *RHSC = isConstOrConstSplat(Op1)) { + if (ConstantSDNode *RHSC = isConstOrConstSplat(Op1, DemandedElts)) { // Do not increment Depth here; that can cause an infinite loop. KnownBits LHSKnown = TLO.DAG.computeKnownBits(Op0, DemandedElts, Depth); // If the LHS already has zeros where RHSC does, this 'and' is dead. diff --git a/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-cost.ll b/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-cost.ll index 203ce1f8811895..c2511a4992cf55 100644 --- a/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-cost.ll +++ b/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-cost.ll @@ -6,39 +6,36 @@ define arm_aapcs_vfpcc <4 x i32> @loads_i32(ptr %A, ptr %B, ptr %C) { ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: .save {r4, r5, r6, lr} ; CHECK-NEXT: push {r4, r5, r6, lr} -; CHECK-NEXT: .vsave {d8, d9} -; CHECK-NEXT: vpush {d8, d9} -; CHECK-NEXT: vldrw.u32 q1, [r1] -; CHECK-NEXT: vmov.i64 q2, #0xffffffff -; CHECK-NEXT: vmov.f32 s0, s6 -; CHECK-NEXT: vmov.f32 s2, s7 -; CHECK-NEXT: vand q0, q0, q2 -; CHECK-NEXT: vmov.f32 s6, s5 -; CHECK-NEXT: vmov r4, r5, d0 -; CHECK-NEXT: vmov r3, r1, d1 +; CHECK-NEXT: vldrw.u32 q2, [r1] +; CHECK-NEXT: vmov.i64 q1, #0xffffffff +; CHECK-NEXT: vmov.f32 s0, s10 +; CHECK-NEXT: vmov.f32 s2, s11 +; CHECK-NEXT: vand q0, q0, q1 +; CHECK-NEXT: vmov.f32 s10, s9 +; CHECK-NEXT: vmov r3, r4, d0 +; CHECK-NEXT: vand q2, q2, q1 +; CHECK-NEXT: vmov r5, r1, d1 ; CHECK-NEXT: vldrw.u32 q0, [r0] +; CHECK-NEXT: vldrw.u32 q1, [r2] +; CHECK-NEXT: vmov lr, r12, d5 ; CHECK-NEXT: vmov.f32 s12, s2 ; CHECK-NEXT: vmov.f32 s2, s3 ; CHECK-NEXT: vmov r0, s12 -; CHECK-NEXT: vand q3, q1, q2 -; CHECK-NEXT: vldrw.u32 q1, [r2] -; CHECK-NEXT: vmov lr, r12, d7 -; CHECK-NEXT: vmov.f32 s16, s6 -; CHECK-NEXT: vmov.f32 s18, s7 -; CHECK-NEXT: vand q2, q4, q2 +; CHECK-NEXT: vmov.f32 s12, s6 +; CHECK-NEXT: vmov.f32 s6, s7 ; CHECK-NEXT: asrs r2, r0, #31 -; CHECK-NEXT: adds r0, r0, r4 -; CHECK-NEXT: adcs r5, r2 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: asrl r0, r5, r2 +; CHECK-NEXT: adds r0, r0, r3 +; CHECK-NEXT: adc.w r3, r2, r4 +; CHECK-NEXT: vmov r2, s12 +; CHECK-NEXT: asrl r0, r3, r2 ; CHECK-NEXT: vmov r2, s2 ; CHECK-NEXT: vmov.f32 s2, s1 -; CHECK-NEXT: asrs r4, r2, #31 -; CHECK-NEXT: adds r2, r2, r3 -; CHECK-NEXT: adcs r1, r4 -; CHECK-NEXT: vmov r3, s10 +; CHECK-NEXT: asrs r3, r2, #31 +; CHECK-NEXT: adds r2, r2, r5 +; CHECK-NEXT: adcs r1, r3 +; CHECK-NEXT: vmov r3, s6 ; CHECK-NEXT: asrl r2, r1, r3 -; CHECK-NEXT: vmov r4, r5, d6 +; CHECK-NEXT: vmov r4, r5, d4 ; CHECK-NEXT: vmov r1, s2 ; CHECK-NEXT: vmov.f32 s2, s5 ; CHECK-NEXT: adds.w r6, r1, lr @@ -54,7 +51,6 @@ define arm_aapcs_vfpcc <4 x i32> @loads_i32(ptr %A, ptr %B, ptr %C) { ; CHECK-NEXT: asrl r4, r1, r3 ; CHECK-NEXT: vmov q0[2], q0[0], r4, r0 ; CHECK-NEXT: vmov q0[3], q0[1], r6, r2 -; CHECK-NEXT: vpop {d8, d9} ; CHECK-NEXT: pop {r4, r5, r6, pc} entry: %a = load <4 x i32>, ptr %A, align 4 @@ -138,62 +134,58 @@ entry: define arm_aapcs_vfpcc void @load_store_i32(ptr %A, ptr %B, ptr %C, ptr %D) { ; CHECK-LABEL: load_store_i32: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: .save {r4, r5, r6, r7, lr} -; CHECK-NEXT: push {r4, r5, r6, r7, lr} -; CHECK-NEXT: .pad #4 -; CHECK-NEXT: sub sp, #4 -; CHECK-NEXT: .vsave {d8, d9, d10, d11} -; CHECK-NEXT: vpush {d8, d9, d10, d11} -; CHECK-NEXT: vldrw.u32 q0, [r1] -; CHECK-NEXT: vmov.i64 q4, #0xffffffff -; CHECK-NEXT: vmov.f32 s4, s2 -; CHECK-NEXT: vmov.f32 s2, s1 -; CHECK-NEXT: vmov.f32 s6, s3 -; CHECK-NEXT: vand q2, q0, q4 +; CHECK-NEXT: .save {r4, r5, r6, r7, r8, lr} +; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, lr} +; CHECK-NEXT: .vsave {d8} +; CHECK-NEXT: vpush {d8} +; CHECK-NEXT: vldrw.u32 q2, [r1] +; CHECK-NEXT: vmov.i64 q0, #0xffffffff +; CHECK-NEXT: vmov.f32 s4, s10 +; CHECK-NEXT: vmov.f32 s6, s11 +; CHECK-NEXT: vmov.f32 s10, s9 +; CHECK-NEXT: vand q1, q1, q0 +; CHECK-NEXT: vand q2, q2, q0 ; CHECK-NEXT: vldrw.u32 q0, [r0] -; CHECK-NEXT: vand q1, q1, q4 -; CHECK-NEXT: vmov r5, r1, d3 +; CHECK-NEXT: vmov r6, r4, d3 ; CHECK-NEXT: vmov.f32 s12, s2 ; CHECK-NEXT: vmov.f32 s2, s3 -; CHECK-NEXT: vmov r0, r12, d2 +; CHECK-NEXT: vmov lr, r12, d2 ; CHECK-NEXT: vldrw.u32 q1, [r2] -; CHECK-NEXT: vmov r4, lr, d5 -; CHECK-NEXT: vmov.f32 s20, s6 -; CHECK-NEXT: vmov.f32 s6, s1 -; CHECK-NEXT: vmov.f32 s22, s7 -; CHECK-NEXT: vand q4, q5, q4 -; CHECK-NEXT: vmov r6, s2 +; CHECK-NEXT: vmov r5, r1, d5 +; CHECK-NEXT: vmov.f32 s16, s6 +; CHECK-NEXT: vmov.f32 s6, s7 +; CHECK-NEXT: vmov.f32 s10, s1 +; CHECK-NEXT: vmov r0, s2 ; CHECK-NEXT: vmov.f32 s2, s5 -; CHECK-NEXT: adds r2, r6, r5 -; CHECK-NEXT: vmov r5, s18 -; CHECK-NEXT: asr.w r7, r6, #31 -; CHECK-NEXT: adcs r1, r7 -; CHECK-NEXT: asrl r2, r1, r5 -; CHECK-NEXT: vmov r7, s2 -; CHECK-NEXT: vmov r1, s6 -; CHECK-NEXT: adds r4, r4, r1 -; CHECK-NEXT: asr.w r5, r1, #31 -; CHECK-NEXT: adc.w r1, r5, lr -; CHECK-NEXT: asrl r4, r1, r7 -; CHECK-NEXT: vmov r6, r5, d4 +; CHECK-NEXT: adds.w r8, r0, r6 +; CHECK-NEXT: asr.w r2, r0, #31 +; CHECK-NEXT: adc.w r7, r2, r4 +; CHECK-NEXT: vmov r2, s6 +; CHECK-NEXT: asrl r8, r7, r2 +; CHECK-NEXT: vmov r2, s10 +; CHECK-NEXT: asrs r4, r2, #31 +; CHECK-NEXT: adds r2, r2, r5 +; CHECK-NEXT: adcs r1, r4 +; CHECK-NEXT: vmov r4, s2 +; CHECK-NEXT: asrl r2, r1, r4 +; CHECK-NEXT: vmov r5, r7, d4 ; CHECK-NEXT: vmov r1, s12 -; CHECK-NEXT: adds r0, r0, r1 -; CHECK-NEXT: asr.w r7, r1, #31 -; CHECK-NEXT: adc.w r1, r7, r12 -; CHECK-NEXT: vmov r7, s16 -; CHECK-NEXT: asrl r0, r1, r7 +; CHECK-NEXT: adds.w r6, r1, lr +; CHECK-NEXT: asr.w r4, r1, #31 +; CHECK-NEXT: adc.w r1, r4, r12 +; CHECK-NEXT: vmov r4, s16 +; CHECK-NEXT: asrl r6, r1, r4 ; CHECK-NEXT: vmov r1, s0 -; CHECK-NEXT: adds r6, r6, r1 -; CHECK-NEXT: asr.w r7, r1, #31 -; CHECK-NEXT: adc.w r1, r7, r5 +; CHECK-NEXT: adds r0, r1, r5 +; CHECK-NEXT: asr.w r4, r1, #31 +; CHECK-NEXT: adc.w r1, r4, r7 ; CHECK-NEXT: vmov r7, s4 -; CHECK-NEXT: asrl r6, r1, r7 -; CHECK-NEXT: vmov q0[2], q0[0], r6, r0 -; CHECK-NEXT: vmov q0[3], q0[1], r4, r2 +; CHECK-NEXT: asrl r0, r1, r7 +; CHECK-NEXT: vmov q0[2], q0[0], r0, r6 +; CHECK-NEXT: vmov q0[3], q0[1], r2, r8 ; CHECK-NEXT: vstrw.32 q0, [r3] -; CHECK-NEXT: vpop {d8, d9, d10, d11} -; CHECK-NEXT: add sp, #4 -; CHECK-NEXT: pop {r4, r5, r6, r7, pc} +; CHECK-NEXT: vpop {d8} +; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, pc} entry: %a = load <4 x i32>, ptr %A, align 4 %b = load <4 x i32>, ptr %B, align 4 From fdaad738753cde2bba6480c2ee5d1e9fb45064b9 Mon Sep 17 00:00:00 2001 From: XChy Date: Thu, 16 May 2024 20:13:39 +0800 Subject: [PATCH 025/576] [Reg2Mem] Handle CallBr instructions (#90953) Fixes #90900 --- .../lib/Transforms/Utils/DemoteRegToStack.cpp | 18 +++++++++-- llvm/test/Transforms/Reg2Mem/callbr-crash.ll | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/Reg2Mem/callbr-crash.ll diff --git a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp index b2a88eadd3dee8..f03de2f25a4163 100644 --- a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +++ b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -50,6 +50,15 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads, assert(BB && "Unable to split critical edge."); (void)BB; } + } else if (CallBrInst *CBI = dyn_cast(&I)) { + for (int i = 0; i < CBI->getNumSuccessors(); i++) { + auto *Succ = CBI->getSuccessor(i); + if (!Succ->getSinglePredecessor()) { + assert(isCriticalEdge(II, i) && "Expected a critical edge!"); + BasicBlock *BB = SplitCriticalEdge(II, i); + assert(BB && "Unable to split critical edge."); + } + } } // Change all of the users of the instruction to read from the stack slot. @@ -102,9 +111,14 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads, new StoreInst(&I, Slot, Handler->getFirstInsertionPt()); return Slot; } + } else if (InvokeInst *II = dyn_cast(&I)) { + InsertPt = II->getNormalDest()->getFirstInsertionPt(); + } else if (CallBrInst *CBI = dyn_cast(&I)) { + for (BasicBlock *Succ : successors(CBI)) + new StoreInst(CBI, Slot, Succ->getFirstInsertionPt()); + return Slot; } else { - InvokeInst &II = cast(I); - InsertPt = II.getNormalDest()->getFirstInsertionPt(); + llvm_unreachable("Unsupported terminator for Reg2Mem"); } new StoreInst(&I, Slot, InsertPt); diff --git a/llvm/test/Transforms/Reg2Mem/callbr-crash.ll b/llvm/test/Transforms/Reg2Mem/callbr-crash.ll new file mode 100644 index 00000000000000..2abb01b14b0e19 --- /dev/null +++ b/llvm/test/Transforms/Reg2Mem/callbr-crash.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=reg2mem -S < %s | FileCheck %s + +define void @crash() { +; CHECK-LABEL: @crash( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_REG2MEM:%.*]] = alloca i64, align 8 +; CHECK-NEXT: %"reg2mem alloca point" = bitcast i32 0 to i32 +; CHECK-NEXT: [[A:%.*]] = callbr i64 asm "", "=r,r,!i"(i64 0) +; CHECK-NEXT: to label [[THEN:%.*]] [label %entry.else_crit_edge] +; CHECK: entry.else_crit_edge: +; CHECK-NEXT: store i64 [[A]], ptr [[A_REG2MEM]], align 4 +; CHECK-NEXT: br label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: store i64 [[A]], ptr [[A_REG2MEM]], align 4 +; CHECK-NEXT: [[A_RELOAD:%.*]] = load i64, ptr [[A_REG2MEM]], align 4 +; CHECK-NEXT: [[B:%.*]] = inttoptr i64 [[A_RELOAD]] to ptr +; CHECK-NEXT: br label [[ELSE]] +; CHECK: else: +; CHECK-NEXT: ret void +; +entry: + %a = callbr i64 asm "", "=r,r,!i"(i64 0) + to label %then [label %else] + +then: + %b = inttoptr i64 %a to ptr + br label %else + +else: + ret void +} From 911207338add39b8439a09fd7f9d97bbe4a335bd Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Thu, 16 May 2024 13:16:44 +0100 Subject: [PATCH 026/576] [RemoveDIs][NFC] Fix rotten green C API test (#92362) `llvm_test_dibuilder(/*NewDebugInfoMode=*/true)` isn't currently executed in `return llvm_test_dibuilder(false) && llvm_test_dibuilder(true);` because `llvm_test_dibuilder` returns 0 for success. Split the llvm-c-test flag `--test-dibuilder` into two, one for the old and one for the new debug info format. Add another lit test for the new format. Now that the test actually runs, it crashes using the new format with `llvm/lib/IR/LLVMContextImpl.cpp:53:llvm::LLVMContextImpl::~LLVMContextImpl(): Assertion 'TrailingDbgRecords.empty() && "DbgRecords in blocks not cleaned"' failed. Aborted`. Insert terminators into the blocks so that we don't leave the debug records trailing, unattached to any instructions, which fixes that. --- llvm/test/Bindings/llvm-c/debug_info.ll | 6 +- .../Bindings/llvm-c/debug_info_new_format.ll | 66 +++++++++++++++++++ llvm/tools/llvm-c-test/debuginfo.c | 16 +++++ llvm/tools/llvm-c-test/main.c | 8 ++- 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Bindings/llvm-c/debug_info_new_format.ll diff --git a/llvm/test/Bindings/llvm-c/debug_info.ll b/llvm/test/Bindings/llvm-c/debug_info.ll index a7fcd8a999ef15..9358bac59bd21e 100644 --- a/llvm/test/Bindings/llvm-c/debug_info.ll +++ b/llvm/test/Bindings/llvm-c/debug_info.ll @@ -1,4 +1,4 @@ -; RUN: llvm-c-test --test-dibuilder | FileCheck %s +; RUN: llvm-c-test --test-dibuilder-old-debuginfo-format | FileCheck %s ; CHECK: ; ModuleID = 'debuginfo.c' ; CHECK-NEXT: source_filename = "debuginfo.c" @@ -8,8 +8,10 @@ ; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !38, metadata !DIExpression()), !dbg !43 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !39, metadata !DIExpression()), !dbg !43 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !40, metadata !DIExpression()), !dbg !43 -; CHECK: vars: ; No predecessors! +; CHECK-NEXT: br label %vars +; CHECK: vars: ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata !41, metadata !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)), !dbg !44 +; CHECK-NEXT: ret i64 0 ; CHECK-NEXT: } ; CHECK: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) diff --git a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll new file mode 100644 index 00000000000000..05b6ef4de9adbb --- /dev/null +++ b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll @@ -0,0 +1,66 @@ +; RUN: llvm-c-test --test-dibuilder-new-debuginfo-format | FileCheck %s +;; Duplicate of debug_info.ll using debug records instead of intrinsics. + +; CHECK: ; ModuleID = 'debuginfo.c' +; CHECK-NEXT: source_filename = "debuginfo.c" + +; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !31 { +; CHECK-NEXT: entry: +; CHECK-NEXT: #dbg_declare(i64 0, !38, !DIExpression(), !43) +; CHECK-NEXT: #dbg_declare(i64 0, !39, !DIExpression(), !43) +; CHECK-NEXT: #dbg_declare(i64 0, !40, !DIExpression(), !43) +; CHECK-NEXT: br label %vars +; CHECK: vars: +; CHECK-NEXT: #dbg_value(i64 0, !41, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !44) +; CHECK-NEXT: ret i64 0 +; CHECK-NEXT: } + +; CHECK: !llvm.dbg.cu = !{!0} +; CHECK-NEXT: !FooType = !{!28} +; CHECK-NEXT: !EnumTest = !{!3} + +; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "llvm-c-test", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !11, imports: !19, macros: !23, splitDebugInlining: false, sysroot: "/") +; CHECK-NEXT: !1 = !DIFile(filename: "debuginfo.c", directory: ".") +; CHECK-NEXT: !2 = !{!3} +; CHECK-NEXT: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "EnumTest", scope: !4, file: !1, baseType: !6, size: 64, elements: !7) +; CHECK-NEXT: !4 = !DINamespace(name: "NameSpace", scope: !5) +; CHECK-NEXT: !5 = !DIModule(scope: null, name: "llvm-c-test", includePath: "/test/include/llvm-c-test.h") +; CHECK-NEXT: !6 = !DIBasicType(name: "Int64", size: 64) +; CHECK-NEXT: !7 = !{!8, !9, !10} +; CHECK-NEXT: !8 = !DIEnumerator(name: "Test_A", value: 0, isUnsigned: true) +; CHECK-NEXT: !9 = !DIEnumerator(name: "Test_B", value: 1, isUnsigned: true) +; CHECK-NEXT: !10 = !DIEnumerator(name: "Test_B", value: 2, isUnsigned: true) +; CHECK-NEXT: !11 = !{!12, !16} +; CHECK-NEXT: !12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)) +; CHECK-NEXT: !13 = distinct !DIGlobalVariable(name: "globalClass", scope: !5, file: !1, line: 1, type: !14, isLocal: true, isDefinition: true) +; CHECK-NEXT: !14 = !DICompositeType(tag: DW_TAG_structure_type, name: "TestClass", scope: !1, file: !1, line: 42, size: 64, flags: DIFlagObjcClassComplete, elements: !15) +; CHECK-NEXT: !15 = !{} +; CHECK-NEXT: !16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)) +; CHECK-NEXT: !17 = distinct !DIGlobalVariable(name: "global", scope: !5, file: !1, line: 1, type: !18, isLocal: true, isDefinition: true) +; CHECK-NEXT: !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "int64_t", scope: !1, file: !1, line: 42, baseType: !6) +; CHECK-NEXT: !19 = !{!20, !22} +; CHECK-NEXT: !20 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !21, file: !1, line: 42) +; CHECK-NEXT: !21 = !DIModule(scope: null, name: "llvm-c-test-import", includePath: "/test/include/llvm-c-test-import.h") +; CHECK-NEXT: !22 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !20, file: !1, line: 42) +; CHECK-NEXT: !23 = !{!24} +; CHECK-NEXT: !24 = !DIMacroFile(file: !1, nodes: !25) +; CHECK-NEXT: !25 = !{!26, !27} +; CHECK-NEXT: !26 = !DIMacro(type: DW_MACINFO_define, name: "SIMPLE_DEFINE") +; CHECK-NEXT: !27 = !DIMacro(type: DW_MACINFO_define, name: "VALUE_DEFINE", value: "1") +; CHECK-NEXT: !28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 192, dwarfAddressSpace: 0) +; CHECK-NEXT: !29 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyStruct", scope: !4, file: !1, size: 192, elements: !30, runtimeLang: DW_LANG_C89, identifier: "MyStruct") +; CHECK-NEXT: !30 = !{!6, !6, !6} +; CHECK-NEXT: !31 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !32, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !37) +; CHECK-NEXT: !32 = !DISubroutineType(types: !33) +; CHECK-NEXT: !33 = !{!6, !6, !34} +; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !35) +; CHECK-NEXT: !35 = !{!36} +; CHECK-NEXT: !36 = !DISubrange(count: 10, lowerBound: 0) +; CHECK-NEXT: !37 = !{!38, !39, !40, !41} +; CHECK-NEXT: !38 = !DILocalVariable(name: "a", arg: 1, scope: !31, file: !1, line: 42, type: !6) +; CHECK-NEXT: !39 = !DILocalVariable(name: "b", arg: 2, scope: !31, file: !1, line: 42, type: !6) +; CHECK-NEXT: !40 = !DILocalVariable(name: "c", arg: 3, scope: !31, file: !1, line: 42, type: !34) +; CHECK-NEXT: !41 = !DILocalVariable(name: "d", scope: !42, file: !1, line: 43, type: !6) +; CHECK-NEXT: !42 = distinct !DILexicalBlock(scope: !31, file: !1, line: 42) +; CHECK-NEXT: !43 = !DILocation(line: 42, scope: !31) +; CHECK-NEXT: !44 = !DILocation(line: 43, scope: !31) diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 9b5c37b05d9027..35c65f885af329 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -215,10 +215,26 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMDIBuilderFinalize(DIB); + // Using the new debug format, debug records get attached to instructions. + // Insert a `br` and `ret` now to absorb the debug records which are + // currently "trailing", meaning that they're associated with a block + // but no particular instruction, which is only valid as a transient state. + LLVMContextRef Ctx = LLVMGetModuleContext(M); + LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx); + LLVMPositionBuilderAtEnd(Builder, FooEntryBlock); + // Build `br label %vars` in entry. + LLVMBuildBr(Builder, FooVarBlock); + // Build `ret i64 0` in vars. + LLVMPositionBuilderAtEnd(Builder, FooVarBlock); + LLVMTypeRef I64 = LLVMInt64TypeInContext(Ctx); + LLVMValueRef Zero = LLVMConstInt(I64, 0, false); + LLVMBuildRet(Builder, Zero); + char *MStr = LLVMPrintModuleToString(M); puts(MStr); LLVMDisposeMessage(MStr); + LLVMDisposeBuilder(Builder); LLVMDisposeDIBuilder(DIB); LLVMDisposeModule(M); diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c index c4748d342fba14..9db6e05d6350d3 100644 --- a/llvm/tools/llvm-c-test/main.c +++ b/llvm/tools/llvm-c-test/main.c @@ -109,8 +109,12 @@ int main(int argc, char **argv) { return llvm_echo(); } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { return llvm_test_diagnostic_handler(); - } else if (argc == 2 && !strcmp(argv[1], "--test-dibuilder")) { - return llvm_test_dibuilder(false) && llvm_test_dibuilder(true); + } else if (argc == 2 && + !strcmp(argv[1], "--test-dibuilder-old-debuginfo-format")) { + return llvm_test_dibuilder(false); + } else if (argc == 2 && + !strcmp(argv[1], "--test-dibuilder-new-debuginfo-format")) { + return llvm_test_dibuilder(true); } else { print_usage(); } From 03d8e613911bdef52fec23924a4e5b4235997bb8 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Thu, 16 May 2024 20:29:54 +0800 Subject: [PATCH 027/576] [Transforms] Fix -Wsign-compare in DemoteRegToStack.cpp (NFC) llvm-project/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:54:23: error: comparison of integers of different signs: 'int' and 'unsigned int' [-Werror,-Wsign-compare] for (int i = 0; i < CBI->getNumSuccessors(); i++) { ~ ^ ~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp index f03de2f25a4163..653ea8bbb72b97 100644 --- a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +++ b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -51,7 +51,7 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads, (void)BB; } } else if (CallBrInst *CBI = dyn_cast(&I)) { - for (int i = 0; i < CBI->getNumSuccessors(); i++) { + for (unsigned i = 0; i < CBI->getNumSuccessors(); i++) { auto *Succ = CBI->getSuccessor(i); if (!Succ->getSinglePredecessor()) { assert(isCriticalEdge(II, i) && "Expected a critical edge!"); From 99de3a685170c24208b00ef83fe0416373387acc Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 16 May 2024 13:34:04 +0100 Subject: [PATCH 028/576] [VPlan] Document current status. (#85689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update VectorizationPlan.rst to include a section about the current status of VPlan and its use in LoopVectorize, based on "VPlan: Status Update and Future Roadmap", LLVM Developers’ Meeting 2023, https://www.youtube.com/watch?v=SzGP4PgMuLE PR: https://github.com/llvm/llvm-project/pull/85689 --- llvm/docs/VectorizationPlan.rst | 63 +++++++++++++++++++++---- llvm/docs/conf.py | 1 + llvm/docs/vplan-scope.png | Bin 0 -> 679990 bytes llvm/docs/vplan-transform-pipeline.png | Bin 0 -> 555223 bytes 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 llvm/docs/vplan-scope.png create mode 100644 llvm/docs/vplan-transform-pipeline.png diff --git a/llvm/docs/VectorizationPlan.rst b/llvm/docs/VectorizationPlan.rst index 418c52eeef7f5c..6496263cf8d97d 100644 --- a/llvm/docs/VectorizationPlan.rst +++ b/llvm/docs/VectorizationPlan.rst @@ -19,6 +19,49 @@ candidates. It serves for both optimizing candidates including estimating their cost reliably, and for performing their final translation into IR. This facilitates dealing with multiple vectorization candidates. +Current Status +============== +VPlan is currently used to drive code-generation in LoopVectorize. VPlans are +constructed after all cost-based and most legality-related decisions have been +taken. As def-use chains between recipes are now fully modeled in VPlan, +VPlan-based analyses and transformations are used to simplify and modularize +the vectorization process [10]_. Those include transformations to + +1. Legalize the initial VPlan, e.g. by introducing specialized recipes for + reductions and interleave groups. + +2. Optimize the legalized VPlan, e.g. by removing redundant recipes or + introducing active-lane-masks. + +3. Apply unroll- and vectorization-factor specific optimizations, e.g. removing + the backedge to reiterate the vector loop based on VF & UF. + +Refer to :numref:`fig-vplan-transform-pipeline` for an overview of the current +transformation pipeline. + +Note that some legality checks are already done in VPlan, including checking if +all users of a fixed-order recurrence can be re-ordered. This is implemented as +a VPlan-to-VPlan transformation that either applies a valid re-ordering or +bails out marking the VPlan as invalid. + +.. _fig-vplan-transform-pipeline: +.. figure:: ./vplan-transform-pipeline.png + :width: 800 px + + VPlan Transformation Pipeline in 2024 + + +VPlan currently models the complete vector loop, as well as additional parts of +the vectorization skeleton. Refer to :numref:`fig-vplan-scope` for an overview +of the scope covered by VPlan. + +.. _fig-vplan-scope: +.. figure:: ./vplan-scope.png + :width: 800 px + + Scope modeled in VPlan in 2024 + + High-level Design ================= @@ -160,13 +203,10 @@ The low-level design of VPlan comprises of the following classes. VPValues. :VPInstruction: - A VPInstruction is both a VPRecipe and a VPUser. It models a single - VPlan-level instruction to be generated if the VPlan is executed, including - its opcode and possibly additional characteristics. It is the basis for - writing instruction-level analyses and optimizations in VPlan as creating, - replacing or moving VPInstructions record both def-use and scheduling - decisions. VPInstructions also extend LLVM IR's opcodes with idiomatic - operations that enrich the Vectorizer's semantics. + A VPInstruction is a recipe characterized by a single opcode and optional + flags, free of ingredients or other meta-data. VPInstructions also extend + LLVM IR's opcodes with idiomatic operations that enrich the Vectorizer's + semantics. :VPTransformState: Stores information used for generating output IR, passed from @@ -177,9 +217,9 @@ The Planning Process and VPlan Roadmap ====================================== Transforming the Loop Vectorizer to use VPlan follows a staged approach. First, -VPlan is used to record the final vectorization decisions, and to execute them: -the Hierarchical CFG models the planned control-flow, and Recipes capture -decisions taken inside basic-blocks. Next, VPlan will be used also as the basis +VPlan was only used to record the final vectorization decisions, and to execute +them: the Hierarchical CFG models the planned control-flow, and Recipes capture +decisions taken inside basic-blocks. Currently, VPlan is used also as the basis for taking these decisions, effectively turning them into a series of VPlan-to-VPlan algorithms. Finally, VPlan will support the planning process itself including cost-based analyses for making these decisions, to fully @@ -248,3 +288,6 @@ References .. [9] "Extending LoopVectorizer: OpenMP4.5 SIMD and Outer Loop Auto-Vectorization", Intel Vectorizer Team, LLVM Developers' Meeting 2016. + +.. [10] "VPlan: Status Update and Future Roadmap", Florian Hahn, LLVM + Developers' Meeting 2023, https://www.youtube.com/watch?v=SzGP4PgMuLE diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py index acbddc7b2f12b4..270f5b33e98552 100644 --- a/llvm/docs/conf.py +++ b/llvm/docs/conf.py @@ -222,6 +222,7 @@ # If false, no module index is generated. # latex_domain_indices = True +numfig = True # -- Options for manual page output -------------------------------------------- diff --git a/llvm/docs/vplan-scope.png b/llvm/docs/vplan-scope.png new file mode 100644 index 0000000000000000000000000000000000000000..d60b58b55b8eab8ddd9824a49f7c1ceb804d4c98 GIT binary patch literal 679990 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 z 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
  • 6zH6*2k9(c!)}9`pF=(}04GL< zpE6!MjDUD?7csLCXM+J|Vckeokl<4LW@QKUQ(#Al&`I_-BmrWj{aQ8*2^bB)OlgZ3 z$ILx@eMyB(v4-G@`}i$=YAll_4ag)rg^COqlSQFjUTeHGk+P4YSTl2I6zw1A^or$v z!(5eoL%;Z4yKcNsCeo(H^w7pOkcNaF;`JtCu90Qk{_a~`kw!8-cTTae?I%zq1Y zg$$nqzcEvhM&k1p%hw4W1jlM`ovux^?X3+1hQ0-Eq4Wxez|tk~Y_TVw!wtnZs;7W8 zjsP~UbHnP_@FNciHV^+e`9d0{!^PC+1r!1BYB5v#`=jn*PImQ=vTvOCeTEN3Gw4f+ z5#cglN=JKTi06_3gIRqGhpjE|!kTd>VmJhrNbJ3aUz*JA0$eI+`ndIFiB#Oz{Gm7t@wG!bfcc)y2?TaN zCcqCjez`OJ*7Bm9*g6ji`C_(dAQE^iZZi3{DWVy{Yg*&Lf^0OJ1~96!+Oxur3h(rwaT;D!l_AkDp}_+Dt+-SNP9)hBoV ztC&Cxi<6OHFKXdU#o~-tK;9Bt#Cn{76~bhtA8H!j&?c7=t%($((xi0-q+7|Y%`t8{S)27O-&{L zc@^A69J!eDqrK<<32-WIeD86Z>MdeW7)ihgXThbA&zxF-OTHg5>^)=_J15U-3T-Ed zsN)PiP@OJ*_>tAMK{cFFwqcfs?HVrsIUmR789%lYOF;py7AS4+ z$jyvbg%a86P=egYKL>9@hTG_=P!T>BHFT8cel5H-BilzQ@^bKzpWHV=P3rV;|)Y8fdjxp2NLzX_uR2#o)jUA68Qo*sc7Tgn$lCK$s01`1$ru_SGq2KgcI4zS>GILU zP4jve+s7Oguc@=FkIwv^nW=@*f4vA7Hb9~ppUTs=2T)J6Jm_db&eErgfjlRdv%d1w z3$-bMWtYd+&4Fi%$?G03_EBiuWicX+#pmN~Z*S2)Y{sYI!Ej>DtS~W?1TI9lKJRB4 zq2IdOsWy!BJ}dFOG5! z^Z3QN8^0?%nvtMsfY!p;bI^-by{C={KvlW-+`cb^qc*s z+s;7p@`}_{^=(IhZc{(QY@tTRwgUnV=^xvbzT5L3zJ@;{a;5_Jisx^jR2c1-cHW=# zs8C_Zi}Tjro)Z;e1Tp+=3yzADI43+gacd@*3>@AzDqg&mGp)>-+ApuXkVapZz;c62 z>gwLv{!kRowoswE^!*oeo0skpyrcv=1TjdOb#w)3q@11>YF9SDCn3MKG!9O(u>dI;76m{*Sv z`}(s^#SmDSe^6ap8zXfT(<0d!;Vdo_h;FyspL)A>P{|HdS}1#5W5E}m7pSP3nCXVX zZ)zTIPJX_Rs~aI7QyG8u7aW0;4X*%Wcg-rkg7rMXPhClwj`nt0_>P?Jv3A!`6CKLr zUSd43Fc_m1^J zUgflATBa*0;wTS8s>t$xPBbuq$n(vm3duYD(H*1+BMXY{Mp-ZBk#-_%C~%YS`>)&o z3Hh@@Q!EHi%tOtqAD*zw`|4N2kmhME?(aVskZiTXc9|4h`3t3 z+)Q)4#E!L_3k{p^GxkCBC(uHapRAK^Svf;h)-GyhhvC?szF`s{dyAN-PHL>!?xvjGC|lgM(XuHgYuH*sz=|TH)JL_AuWb?^_zXaW%X|V z6RVKnjIVtM!a=H$`c*o?+as9g-F^I)Ka&xGDh+tcJFSDajBWr2`3l`XAN&JOAV%(J z^?$|4u~8tjUbq+vdG9+{&d+BmG`P^4hxjHRSf-qB-YOLd`B2H3Sg~nTX0-AKnKF*} z-dWHx*}t|VmBTM1{u#Y{0-`Hrgvr`=Cf%B^x2lN|%q@^NsOeY>^S~N9eps_4lmd4s zuNvVpiGz-r6rNYDP5w4MlnM1d@X!Hp%pos@5C>9Sd3)d_{oa9+yFK2KF z#(AJCr6%x{sU$TUH3dw}@(kuxX=Lnn5MrK1$Avt%EaW!FA&4HSYUEl3AM%k1w2h=x zocj?taqy!PxmDp#=KeqVh?(_AUR;4Z-U7R@m*;XVsL=ZAMfC9Y=>fQ@Uy6zK?nss$ zPg?HD<>_nYqRjsxolV&(j=#P?JQQhBWGwptnhwcf>_30raf@hzJ2o9n#&SiStB`vh zq>_+6SMR~{W24pX`dv6hW2;~WU|_A?jW)=FIi=$ix6lWe-0~4iS$0n z)}AYo=fELe*e~~FT($@%ko_LACGHkj=)myc{QAaeGZP56(SicN0P zytEBjj92bPF1KGd!f$cxk_lvUHAmD%-5Ew=*)2mJXlr2}d^E4-DX74qtrb7b1A2=A zm`7q2CbQWntf}}uxt_`spCu~XWS20%02_D>0wlNbYF)rLhDYj`IR|@m))TA0N>09X zGrs=nuOYpg%}MftxlZpDet%s85tEkxMoju&Mx7o9inKK)TPA8syA zv47eBVTLc5_4lSiy8R99x(pCd)bJ3kto83T(_ukBFTR>+*Z)wrB(4H1W`!Z=XLj9| z`OvMNJZ3e<-C~b$nkNUV4*QHTG)yN|oh;_(c*K_qm^7CEBVu^_6gbGR(L-%xBzH0| zZei5U>YW~jL0~!XNfdBQ!aE80oc=1maG3rq4FflndE#O0p9YzV@WAz+7d|rYe1ww3 z*GV1_Q?MFF-O#)_UcD4KG^CU*J&d{cZEv`L8!$7D2#sB2vnKcigS>in&VqE*y3-xJ zz{8gCNHdwEqAHZb3MNnQC`&6AT-~6^V7;6hK%iv{ry^h=T1a>+YHB_1I%gE zce(1*Ypz`A+i&9Wi-u3mR*RD3Ij;MsA3`I^F7yeHRG?dYk$`{lOHc5%>~Ts9VUQwB zwoH$}#{AU8;1I7HqsDCXzfnSp2UOmz zU2~>ox>E+(CxskB*s8t?S3c(MY+G4+!-Yd6lzJ`qA@}nH0nj2XKAUS)5U$I*78Lp} znws5_u=2vwMUQi=xb=Nk()MfYA(4ND`p*Z%0ZqP1)`=8&S=r=ED8dh3SadbS$ba1S z)pma@4+!qbR68!3CHOL*O~`Y3fVjOyo<3XxG5h;O7Po+mOK>=`)Fek=y*PWUmTmLi z{R9_VVE?GEF`T>>9ZdBhn`=E9@A+%@0GaYnj9I${1G}Nq+}Hr*LzkXhMd(|AIluLz zJ1w#v8KSVsCRo0sAj0t}*nT2y63CLR|H_hknV@My=~K^tP2XUH35U_!PQK82*mxd9 zX7ChWYrd1W_9UKoXeg$4%oOizp=|p1ZpA)+<>HqZNarW26$y4ORD(@K{i*?uKIF2)|~u+wqLLQAZxE}6#s01Z*&!m7^|{k1## zo_O2GdHEcCX3}-zzPF27*yDgL|0cXtw$1l6+HwR8*kX-K1=--o`1w+6S02cU`}#JD z;?m1cVBcGGI)X$e=eUONUETTd+Xdzq6=4u&5oSQ4#M@THLS!3J043s#-d3gl1hU!- zab3KD4i_^eaf0!bV$|1Ij*xg}Q6c3{H36+lGZ;(C8qX!244H(l7<1$6&vzPZPa#1f zQh3~g$dR6?qmX`Itb19U=CEkGp zcyZG9 zr3t4Vcj3oz|Y(pFR)>-;H<4ecbx4CDdGsXp1$O!de?rJ38@_CiuZ)myz0y!YwF zvv}I`lhfo2lg{-PF5k`889k@6k3Ai}v~x@|HuohB84Cf^X*F)~O+709$8~lrXx*ay z_FiF(BsXBgMCbN?2wRI14~w&iU%UM6E7<4+HIs93^^ROa+A9w}U;;^A9bdisv3>Bp zO=)0%hr)g7mL@XXwUU7V&XwlWnIXM5e`_zI_%CNp-IAENiYQM+(*Gjh*|{9`^vkk% z;a9y69)>gGcrE^LpSU;`ZyzhdETMM|J35EKj-sFU*^UwLWNt`6p&N=gNpxByz%~P39DD4Hy>}FF;@*JUKPvt`#gx4AGgnCI;2>9HM*5Za6Da~ z_L1!MFdY|P5lzNVgL78xIb+DP@K_?e*&UCB`W`WTNqUqN$iJZ~vP;~&ul0aDEokzO z%g*&LE{V7}bWq$Mf|QiCwI$ln1Y zw!`ZVTFm!UjTIK3ydmv4V`kH;#KS(%^fi8#vy8% zLSZVIURSRQ#xq}ot@V_}SJXJY;-nK@+rU1&6~lQEjwkj{I9|~xu(jnZ%_w5u6#omM*Lb|WbJHZ;uQ9NAs2x`1a+Z>i z90RFsm&{f{Li0mk$-&&`5K4-zzLP=+Dr9XN4&lkjvG$m*dx1o){GYSt)Z~@kK3GbS z>f5?!+#Xgy*$__5v|0?Z2R+IU~DSguwM_Oaqa}Q7mq$6*b=*gsiE8AJU zWPp2LP$BccD^O)d73>%sTKu+42n%ze(2ryyT`AUve9sLz^CPqI_`LaqsxtzVoH7GB z>;0t5?nF<9R0lY2!-p6u-*bldl5=_t&_E{Q_#vB9nz5RJ|%zYy}3^5;K|SNf*}Sl)F^Ctf*8$6)NG5 z|FIsME$hn7Pg8BW-+e8SS*_I;&__t4NNbP?vO}J#?lrZrx}219Zju3*CV_NwrS(~n zrutc6%?HVyN`r-jDG9v(jdJ5kx{)&DTH9oA^3Y!>Ld(QyKwOv(6~Ht^6HY3dju4*> z-ik7D^MZS|kl<~yM}lje?(?zB#{!|q9C=|7c(6=@B3xk*-|EUts93KHWFf>95X_$A zP6@aQxC-G;j45o}xcLEmL{;>V@ywUXlDt14c=m-ANE{sb%@Q^Me#r7fkKvSj^%m}I zk27y)UF#MfNGOC}_U(qy!TET^&y4-uK3NcK*PjHoE44ug7^2v--%ictupf&JBs|_W z|6X#(?ZK(f=D6rA>zsc3l`YsT@XLD88}7H*Y;*Xxe*mLMl~b7{>4zMhk~3oE`4>G5w>Zs_EwMYR+^-DRO&19;BKNg*){TF z@jcDgROs96o-gTdWn-*QPTa=o42(QOVb*WbCXew-d}}ItDw!!9TYc+%V-cTMTnX&x z(Ow%bjsN zo1k~vp_j?bh(k}7CJv!??mlNU8smi(>>j_WpsMgAt1N9Ex*R=3 znsOr0{P&3(u)Jl@#rqAx@q2D5F|T%4{)!r?)tw z8-0Q~Rb3$;Lr;5LD%mzAPgftP3U}k*#1m>l&;+e#A70G`(BVaNZq&pae>}PBz?0RH3pyL;a& zCl#-9+r^$)WYN1NAVbc=U5O-Hdu1BFpUh92;}o4yTtmjISrF{<}-aN-l&#SRcGog#w1T?p8q zOaHJzh7z3a8B$BJ`^y{G1Jqkih{u}lFgG%>JPvaiz9K#)NwxZ>BIAT-mTAso>K3G- zQ{h?l$la{BC?}bG?_}*zH8K#a-im%fI$&q6^e7u9E}m{x*nRK*LtATaC@tbAgfUSO z%TE|lNT69RSzeQ%m~gAI@lWPsMp{u$GkdVH(^JsB?+w1ce0TBN;R5LoC)qBA)U3YN z1Z0`>=n=3k`a{|Y=QbGOZ7omz%*oRqU|;3`N`5XFgx-YU2%U~&*lpe(ZSvc5_;%GI z&P>(-SBTTP#tc3rcsTxuk$*oL%~XaH!)dL1NpMwQoln17T1_Z|wf$zddo4SqE__vV znhI0p%jrdEh9H!euLB=#0 zFvl&#)cwc!36a7rz-v@c`s#&x3KpPzTW7(ChF zn@l?rWdDJIZQgPx5C0Ha60)kBbWJi_2cATVGj*JP_1^BvH*2$Wv(osgn=YvO0IXW5J&way#Auq2A zk~mEbycU2^6^5ZJZd!(lEzcGe@DzHl$#`;7dr`sNIRe%tq+~j3TT;wLV|VUW85B#4qD-JMb|@Achc2%Wq(;R@F=V@ z_rLT`s*UnGv;-zQ>3J(mL7npX&ikoZ@9x$H8|#W^_til4N5s5TW~%rrD;h-KZ|sbk zLXO!_o4eMiSHX}H$S@^`V(i_O7*TcfGV=$eR$~9;Y!XGSSw0&r9#+hc?Ou_$XxA>b zN?tQN?9_q+1pZ??hzga?r;7*M`}S*DEPTrko)J?@H&%HX1`2w7gs! z!wc1~EY*me-r{VGe7elWe9wt7wi}b01bYtV+)>&8W6n*v`ll<{n~J}a^Zv^n$|fHl zEwh}|;85qQkHMj$iX`$OtLVj}qJ#v(LXgl``W|qqc*rla6edC$*+L=^h}sh#Lw)p5 z@H&3`9TY)4!nQwZC7pJBJX4@XGEjbBtciVp6^1D_uE-=Js=FB;_KHdOg6vJ!KS0rK z(?v@@cyE`8dW4k$SF>@^0KZ-e6k&3uF%OO2Yp@Uwu7-!KfWn-gTXgwQcoMFTkduGA zpjC)LK<@=i67SUK<$K~X{i$}hdYED`x+KPuVSfd)?0!P6y)h0Xkegu7SE{jg?0 z6`^@a-Q4=lh(0jvsfsO7VY49mBnzzNxCfF6W#5&*cWo=05OZ>F)AjXwNwms^A@Oyx zG0<;7bGDt(i{PA!86c!gC}e?g=~nZSg5;KK-=UpK%fz=Z#SY>8&-p?$+>lD;<@ikn+bh3hpYlum^rwQjLcDOvF!;~%(@!PWf9#^NxX zKZ{rv{NFt52{3p0=gRwhJY3%8LL>n3`~$d58>nO5%s-6}#a2pllJ03gS5Y4T4jtGp9jMaC!IHK5ZsbU zqP(N6FL`?n?WQB1DTs@FHKUsh<9(?(T)I^0L9_M{?zIpk^Aa+*dv?6}8AkD38Nw{y z^CX@K|M-{lMAM-qMin8h_2AQ-bQ?xipD{oMM-shzjm@f8n(mIzBY#}tHA=lI?!kEL>vOBWx__B~WsQh3K? z(?!Wd>QvDjZZm)R^!;t(U*RWC^)aC%<#`Cw6i77L8VA`5@W$SHq)h2m_R_`?*9}$& zrLh=6;|4ggzGA>uLPXT9PdO)VQv^%HdK++f)+bRCvI&!?u?(mPKVsbNYpV4m-)DsX zhFonTzr{x*el`n;Fi$g|Zvtsxf?cgjBHF_uquwyF^>g;0!v!k(@1;muvzxvPlzV^r zanM`sk&mRbq;HDk8R&?$VjTL=_T6a-ppa6kWRL!{@|>N0qZ!^JIYP725`RG8{e+x+_NZmyR#JFe6>??U`Q>R*4V3Tw=f z(F;CQp^TuYHvb8uM!$Hl9kg71EH<)IL%9_@;pngjY*X6F4g=PxhC@Uc1Rh!iI5|k* zK|9hnKFVGzP!}Qyn+tV_meRQUfsmDct0Nzm3CMnni~dQFP4$&ng^aQng>Fwu{^$x} z69Wc4ACBz-BF+vJJuxQC@;c?)7nc;%qwImpM{7XH_%98)c2{s?{|I^*ZHGt4!#PW}aBHn%c=OPa5|A41|+%CWS zvbg=7ec)O$@~`#uY$i%;TxG*e(oDqOGCtPW2NR;lSERzj8X*2i-?kZ~Yku33r%9>L z8e?(7RHeWI!+A!xGLTdaQcxo)VCG$0db{E-Gw>AeY8DdU8f(`~--is0*5A^nZo6I* z31~!}U>2to>KRt0lPyAd3MV;Gk>k7B{MQ`fr0ZoLQ2Sd*YIEDR8HZ5c1BM(ZJ##29ii|F;r#*rFA9aINhoF@cR-N2bii_U7px$Dw?cf~6beSbm!{ zS591AyC4$yhzPmzJtJG+EWWNE9nVvC%1CD8NB4SEg&||TKv8M@S$n(x=yipa)m^J$Z}8jv`S@pQ z+48u`fUt-D_laJ=Bfa~YbdZr&RbQR<)F@t%xh%0PKQ{I^4ME{$=60R?RiT&3jfv7` z-jE9BOQ(Gpp0;h4OT9MU0RC8XF@Lae+QOfqB+$+4=GmVO+9c&fqlcp6Aj@{2z@&h z^}DTabvv2k`s%|}orv=^%!YIAh*j?+S_%RI($p%M6tR4QH=@If$;}p%fjKxco{c3k z2L6Ma3fCcibCu11Vi$kKa}|7-xYgGzC(48Pse%a;Qk+3zLv|Lm?~j05$joT!AoV{( zzfSCJveU@t?dVsWRm~fF<4IXjvCheID0b^C&7Oy>dG`zCL+uByZYSu`k46q`(Ek!X zxcwvQ2TP4j_Z=(l(s_T6Uu6_A&M$9b2IAkFn(0-3!CLd;^UpX#4xX9DyYUxLk~?v| zxMKCO^}&*1*M#vg#l0J}!D?43R38=R`1%<5z_cpU!Ds$MaYG8`x4y%&3O&bU6dR2^ zogXI(`yhtwyEp6nVrT@P5{6%%8)1vR?ErmlhOl8HLU$c52kvM<%$iqL~y7EmoaI( zzu8mo)2h~-wTr)EPbyu{pOFiMmf>oN2C?}@33JhsWUq9oRz@mT9vrExdT5RsJAtj% z@(9tJ09OuJ_PF=na+r8J|FmSna*?OriYD9Y*O38^zWEN}Bta$KICyh&XB%O*= zrT}GS^fzo5&?$yJ+Dj5za4u`X2sK7F4h#l3E{JX1StgsrAz5X1f@e-QsP}(&w1i~zW4n4etDhk zxi0YD>t1urF~=OEd{QrZ+R}ZLtQIxHOlZ8^%2`suiIp5Xf5?)5Q5sCtXT?cqfG?~DT_n+ba?tNgNU3CctXQ@n&H$Ezusse;qf^x63{)qE z;;Z(6-5p=Gf`hDWSL}iNwI+(FWOTg}#xc==Clwzl8%Z6C1E<{mjB@wa$h$1jQU*6# zhN3l`BnfuBA4MuyLf*y0(I!J6)|mzbY*Gnb6Rs0O!~G-nqBuIQ2plj_zu|>RRFl_~ zs^>B21>)#b>jWZbB1Qx@35zc=<_IQyH-!`jv7DS&Y1O!YNdKT9Vu_{jrAmL*RR2`! z$4;c9h_8AW4=K5uBn3jj28bJ`5e$3JRic%Dm6xGktAR0rbDC3KY*`DYpApMBwuqru zHU-C({wq3lDC^(Omw?ioPgmN!>AN6d_LuapRC8=|Y z?#g`$m0yl+UhOw;}0a8k4?~H+?A%489(S`f8-2OL%oy zQX52)(?z*s_E3Ia{U#8}Z%&xl!;Ac@~j1Skb6gzjg-_I4iRhVZ)&!Macx&bd$d$TiG^fhj-uoI5P zA#@#w6bsT0Sh|1qsjM%G9n@+cs_bWzl+Wlj_JM>*gg?`0P^o(}D$ymF5b4PI!s52_ zu_O~>)p*X@Wv?ZFI11LWvCKn*;f43Tj_rvyAKACyVIvVr^U1n^@evJh^l=1U z;M*y+-F?SoyY{C}ARbl1b&|@uBPlKELol$V$qD4jMJDyhH5TF3Be>l7gl z5?}d3+GpS7n|5?1@{C`a75k9kba!^tqXjxfieNSz>dVKtT0ISo#fw%)Qc53E{=PYD3i{>-< zirJI**!!UU{0h(E&B6nyQ8ngE6VG8jfAQ}IZkzUpKt;G)RcLD$IpvvQ5Ki>$Xk48% znivH8=|{aVuHLuP5e@|-?uqQ-fTbhN>GBVjYDuejv~mhj)I_MqGA~xc(CPieUp+v2 zb6j|O)k_3)#&Jyx97VJDG%qGE)TP+L0nDqGkHTh(@}?Q z70z8wYay%85{^$sIG&E|iLZN9Hz&7BI((p3C)i-Z2uf2#oJ4a^wmpHP&fO1&*NXu^ z;`>e{nzCT`X9vVL22St#Ik#JdRtbdVRd^d5w`fq5g=RR&q_%!9eElJ$oAy>Z^f;hE zCNg786X$mIT(vo|W8T$-oH(R~?s_Cln2Fe$38Y)-K)-$r{wT`va`tegt;b@Pc7~4C z7Tyx>u*U>GI_V2i?fJ$W49 z3>tN)d~X1)!t}+`iku=t_FjUmsRlv!wPWLEX8RA?1sr_hrArW^q2OEFQE058dvg3N zJJZEmoA@f~&iA0lNAM@wL1w^BtK_(!QSF9ATXveq(i62oNDp!7VwY*Ymab%>0~3T- zj7GILj*l{I?k($8)4_a-WOr-XM2!n+P{#6%fcT@s#`d(e#dEdEX6pW%YX{-JeL(;I;;Elp_BbW3^OF7 z{0BS;*tm~3HBhOtQhoU(9hhe(yM3u=I=Gh0UBAgP!p?cPI8-Lxf{3pgoqXsG0#q}F zo&p?jzL|14t7%lG>=43YOlBE5T`VGskr{>P&M2p%g_u{zz~bYyl}7eQ3H;aeJz1mb z0T&Ze*XxTTUh9Em=X;NQ_D#BCCx+gjQ|XDm<-z5MN9S{A2jO8IM17L+9hJ|A-lS6M zsQkc8l$7fwt^P6J=r9?=YTHZ3I7^KlIuv_khEe*KK%*cE{yVOd#v?J?uz=%nc}l~# zC~A7msBc!NK39YhL~Bymc=d5hUdm6(q8zF*g3|}41 zRC&;xs!_}39BIO4s3Xsx8wfmp*hTahi6$Iw<3nrA<+_R3AR2m?lAIp~vuV&$nP|M1&0D?eMt+%y;15>^n|saCnddG@~;y1YGl*M zhqE}9$F=)rPs#*?o#QvOmLSg|IZ-U63QDtIaany3Ft*|{v2`!#FTM%eJRcF;7;c8WX&7eh?k zjlF2m<=2PoYJ37=;QJ=0`Ic@#;3So>llZkb<5g15xGzOH|H5B|^X!1XraoHW#cMx*A5YlRG= zY<8<^T7_1V=*oR3R%628r@@C;5B*OE3A|>^%jMkcE9zSuMp{>{>ZV63(z2%Z3#HRj zT#4?#;(ULk(ljt^(lFF*{QGcPMoLuoHyO-QvMjckflnX_5)^ePrzX$Qtq~pEadDuv7(|3Z#;42w+Ju zf6#tUS&XqwG0Oq%ZGS&vT_4&*NbyU+mv8NPOI0hXsg;Txw55&73(m3}N0~+UVzbN` zgy7R`ZH*VT3afKIC8?r0`!O%QK9rHB39O50a7{nIb)05y{ZaqP`VfSONrNQ-ZpJ#% zTfhx(gFWC>54#a)LBJ(~4cTxHSv&>_rIaCXOS;)_QYbf!bPP{1KqSg$)~z(K4L!z$ z*l+0r0C+uNfENa~17w#2P7-om=iXQ#;j1z6uqc5rDNo*j3-^!C9cXHFLsvhyrPCPI z^`a!-k<@a!KE#l%1`cbe?O=}0EM%C#K^c6_^%d+U_-BKRMqEhxk?pvz+{t_Gww$M~ zIN(Byz1Ou-S6u*QAKydl#X*MeuGQmv@~ zeP+yh9ntcr=^L&Xl7Q>ffcop3Md`?ApMRgH=OOx@RA$42hkh1FmZ1{2VJ+oGd!jlA zvDTGAh7^^PbTP3n1|GzfTEADr)qVSVG=H_9yFzhy%{kLfS7IScg-qlEiS6an1?B|~ z=cSny9af|l?O(`ChMiWT46VS8Gt!dfr03`R3HHMzs&S)Fn~8U?tRh8bVV@M>h0v_6 zMasGmPzZUw5Z1wHr)qYg#!LLXy-H5tL=yn-aU_HTgJ8jG?b-QW<_#z0K)S;-oW&zQ zdI&ZSaml~rkP+g+^gWM+$Qu*-{Ua>;RjNaUk)aLk{2VcS;PK1ROxUA+72scOT?%I16vm1;C})iDTd-3Bn4FLkPI=eIYq zLK@)Z13p%gYSDb&NcdJQb9o{@>`%AGBvC{_yZi=q#f*uEKwu@ypy&!A3~MS_0;-8J zk(%Xf#V{jC{{uMGB)oN=FN|ei>>>Mh0nXX3U)bK`-VqR$yfa=9&8JZuri7=H@)(#R zmnvm2Z^v3`R0_L)gIgcXGw%c0#4lj>oad{1>b$w**ZYKSb~#_V!PE1GAkohB+%J$j z?fj3<)9?4Ah5;+^#NlXhNs$adiD_oAtT4db5~*WKHu`nkaf_%^>P#BA&y4r0$Hf*_ zm^xUH+OiRk9M$@&f;@!cLmnWMuoF7+W-@Na@@7t{7B2ezc+%sxDE@0?;`#b^qvm!0 z*}Lg&Ey+@&98uo&SC+W~*UL9{+eh!U99GfoWM0-a#A&SRogw8Z(yEXB&{y|cnsLW~ zaU5B$8`-)POWePIITj?#M>V~zw+7!wPQfP<_DI6ZnR)w^C70RA$~U|39DcfQT6Gq# z(ue}4Lj|NLeTu)Iq5yg0S^leG9nc)VvU4^=x=+CKImHAag!y3eeY?NF8zlH`mGN7Z zOgv`qR;k{etD^;E=_r)-OTQVu(|-H8nLltlk$&s&ts^uj_K{GEL0W36l>3V)#P<2y zn{)H9V?{^D%4-}NRgiJN4T6@^6tfJhTo_TWzV(^n%H<+;o+Grb7-c zFc)0K>1ugu*=!CoHqJ_q;UlvIIiJPA02nVFnyy=8k_F2Ye99CfAlFOA^i;BrCEfJN zAbq3XiS45-0?T1jpRcl@E6B}doJ%ye#2VrfsWS2CCHe{WQa>@bdhaQLjk2*S#0s3X z55A3m3Jk@l=(`wDV8W;$GtBg`6v#C#|KmX@Rn3w6+PYkm@-RYXFeDUl3%E1Hs@Rw~ zn$YI61w_iWJsI@2{7%X$(cSmw@JOuvA+-Y3NZ@Pn6h@SFN?uTnUqtgheZ?^DS3;nj zz`(|q=IuN*7QmFj_s(9wQ#+Rw9>X?mI-1TR4Gxh}+= z-2L6C5yEbXSRFlK08bi}eg@&JK?L_%Fg8MJSB8y?o*=KlVl9opWL79^xh~6KvRIMe z3d9E8O!#^vgNg$d%wEbqHn^+x?y1-z2b+DQv*mK(t8&&M=ki6Tq6^9;8M6 z1S`%;S_u^2zrd3gg9VmjNW^^>sYIcq=_A14OMslc0dFBa8=zdOw^6E>LW5|FBc;-Wi8VzP%enV>*G=c2Uya7$HHp~z8!_g?1&u)W==}bwm1M-5I&TjO1 zE>-U%vv;nhSqD8a1UewG%c}0lM-UX;Xwi-G=o(lQ6)&|v+XcVzXJ&(#eApF~TBw=R z8*pdU`}yGGof&-@5CTnt2)#;5)GsX?*-rM~yCVI0`)G=WFlj;vARI%`@+j&(aNVf| zUj5XZXG*uk!e6=V7tF_GHl-r!0^SP*J5v>Di=zVr`9QEb27cVSN83%zALzSR?fDFL ze_+GQR>$}NkQ4roAZI{UqV+3#GvURLOl9VJX_r@fi_&n8%OGEDLgW@ex`}toK~03YhyaOq0CP)oZlZ43qwtLyu6`r;_?o z$ddsarr{c6?tSpemw}bX-R;kbr~VPciH12a31tabHCtqe3ML$(oKi{`qV^?Z(g=}A z);I(0%{T}js>D8Z(b7s4{RmQgGA#sWscd0MdFob6p{d9N+MEnCFUQdWF|{xUusO@S z30V!2B@Es)07H@q5Kr`)5q|zVNJ*YanodkX3gu*)k!WE^|1QeRt;#u(m}P)yNw{C7 z!EZA}7$%j@ovakk%)u<0YD}Bu0IVo=N|cD?r`bS`Og6tuWm)@C-+i<-X&a_Z0Pysq zc8=~76*p;|Wa`TBH&d38gOY}7u;C-&9kFqQ?VTd0u7e4TgL(2`3Y zb#4EEQT@TCe|KJp7eZ)%*TLWAP=X(~830bSq0Toye|iaRhOzx=vwlM-YwEu!d_%U? zM{-oW2rVbLx-|?6ya^FBs?vMGmvJ(W5f%)Ovd%|cvdOTbd7WMqk1v@P+!Jfub*%l4 zyp;%l=E&uJi5Jy$k5Sw+%vME|h`GWhU@4%*{`PDo;&o2@;ef~0&zwnb#X@2`fQ{t- z`M`O#icn(ti@A@xTCpd$*493m<7@e1Ajf;=c_r8n=oAxK6Zu4`-(8v7pRSBOYMzul zaj#GJYgh)%x9@8C?zT++VEJR-Q2N6n@cJtvS*ilOdksMezB#?8``Rc&EfNUKHGPN5)2TV2+PSHhAR!L3VbcbMtn=PB7uk2^I-01wf`wmMo14e!ia7!Sp)MF zk-mu}70W!Sf+l6aVQ4NLiO_E3J+rY4x#SD5LRt)hZ+9-Mz4MhoJ~s0sM}WeoN|f*2 z80@`_;iIZb=P+MN>L{70bg40Eu?Kyma0=x6K=?0?Y+~#>2A};!uZu$qaao4swfN$O zwKZ#@=OHf<5QWxP;y7MJJbZtvnkV)(X>Rt7g|ra}NHKo_T%yN;X!a*(`Tg(Ya}RMP z$L&G)rc)?`_9%}4+-OM;L|#0{BrV(wN5tqG2BE!M7GK}{Fg89iWBYTYW*bKLECEFV z4GHKdO`U_em&p~|oP*7YwBnH6cRS^ZM%j5OQS9d)G>SL4Y;;$)R`Sit;N+*dPN1MB=(ayY7B+}U0 z9xDhp&r3jcuNJ`PGpOr}PHeb=)gItIdfFp?dqHdZbXxbS&JWePG~vDgel+n={#&GJ z`i9dV^Jz-~C#sKpK^@krL${LP3`bW4iLR$xkIy5s48k$N8f_tCUVzr9)6&tgKUe17 zh9J4+Fvw_;hq+amVL@zQ%CgTYcQGEgW)jVs{Pts1*_;+(!kBY2Rr*Q5JXw)yzeB?; zg+_Mm!de9?;AW<{pt+4Z3zDHfo;ax_1;)=OJvw`7{zltU6;xt-;GpEc1pM6<@tr^` zM%V3L8*U%t!TbNySvkjtuiK}{P(IQxQmn|0!p*gRJ{lH$_i)M{$xjZ?!Tb6J^@ju5 zw~VsNYlVKsN)eIsxerKrtDiCN;WG=*^D$PX6eWInMPBgrOM|(&_ZKH{m(+j#e~%7B zzd>}$Q=>}nv{-!+%vD4y$QJnce*@||kzeHf5Cf`?kpklU2*|Nx7`F`Hd?HE=QsRZ2 z-9hl}Wt3~nI&qj%^t|ItwW7v&xmHOm1+x6l^mIbuCu`9Z#LkR((R}v5fbE$qXtt7; z62PEM`DxOu*)vs~ZfqTX3jZzYif?eT=tb+imRJy77@@Ny%XGo(y7+RY*1R^VBIoLK z_tP$FCCQLMogDS|fM?^f_Y|iIN}hy4!Tvp6JclhGeliP)!;;;Zt<5v*1el3#&=$1h z{x28mv{*Zz-gO}2j8$mgaxXWJNRlIt%aiUz`NwK@%JmxJIjKPfB|#b)18)82=erPe z1pwHAbz=41#wqW#6;_nA8w|%dPq)6C7@c z{qEiVx@Z3L4+%@!zp7MB0>e8o5r~A}Mrx~}Otx@B8X7uZjD4A!^~B6+tU{WcQ?ME% z(^OAaDLb27M&*Ww?rHtO#MYo$MY?~_EB-uvVS!;oeG^s^`{nqoT4>>{T+SPH!bk&v z$aN2FYYf-F|DhG?q^M?AjjDH(i1tl5Ks7~@&tD!0n>vLLUgq_5{2rtLV}x$roB!x( zS^w#g7{lig1pnk@1t(O-9h*(Rh8)ZdlYdMR7sgbB8Opf*3D};I16D_8Rm^N`s>1Sj z0PHr}d?K!p8v{YCt;$S`5?r13Kn_RC^wz)-Sep$f)W8|`Zb5P6-KQ-01s%gbTiStd z@F(pB$)r>X;+_^tJ=~PoXOt%c;PJX*zZiM|Sf11#QmZupKh#0od@;Crq*G&R+Ruy} zm)csmVm`RZSHmB5l(QFbgSN~NKXZx;x-K72Qh=<3Q~xt8hzLD#-y z+}6=S&Q0N-NE6}p;J%55d4oRPdMBF$NP)5Lvx8-I^+%_K!+GL)5-SonAeOG=L*TE} z6wEM8(A-n$rZej*aeQe;#Fqe6ku~nZ0%$(08b2hRkqf#@h$qgdeR{!mGk^zkD9H=H zo!333GBq$gX%_HEBEyo22izFmPN)(V1e@vui6V(Y5;w4lu(8tn7|1e>k6YrN6ebvY z)Cd~i)M_h+SQV(CX6n#2`p*XjcuqR408AU3t$umuRtEYCZSWK5g^+JFp6`-vekqSF zT%l>_1Jf%Nt~6V)pQ=Q}tV4xs4m_QOyKby_O*TnbJZfLQ)+mr_bed&HP*f#_C<)4& z2OLF`I{}*%DOhMP#8E<{UGupUq7oO#6xWpuGF~&Rw~jFXA$;| zr=GBSX<3$4;WKA&#lH9_xHbc!i_w=#u2F`%jkco9KO1oAuf~XJ7=wz9aMdx4unW4X zT?4VeNWtp}t7r4|HV$c2M9zfR!*vXEV7fw@P=)A72&4a=?o16neflYrgE1LBz6aBa z+BTBR3i>q&tZ6s^`p{dk9PH>cdTncc;Vq!iuLVr2ejPVcxF|5l)6;xm;qF@tgvk_k z;Dn>~DhN*Sw9LVyA@4}Z#qri{z(5&TjU6>8*%RBBF0sUmH9&kqJU~6q1?9mFEOfE8 zR24i8fAb zD+F33WVU;FfK8#DI+!}!{|aOr%}_Vj2{oSSBlm{Un_{DDSi<^=Od#`0YtUe)q%uyO<|z)dBD$s2&vEqT#@C^h*;2{c66*>pRgSZlgqFR-5)3eYUZ0Hab^-c-WL`=a!qv{ge zpTnB){ZzhzphS92>*^!-7$WCC0IhmzrK;W$gonV%yUhXT!xgML*Lh$x z;(r#%fBhFO`d?o<+O%1sIwsNxOU^6DsZrW=`_vK|th2PV?}-_{-fQ9oa)|V>?|X8{ zOGz2?P7KX^UHN$ImpD-a^6lS@X3>^aG3Huj((Ju5OZq)D-H&c6WzUR^IKGioyv_R5 z1io*hf07!Ig}(d9p>%InsXp;%0MPLxl&GPUs<<4mZGu zea||9F*C$NM1X%RYJIx9qeQ#W3UlQ}M8V7lGoc=GBKLq#Z12XRD1%6FDVSjn!>J07 zGeb6Dyn+Gwo%x2c_*=lQRe^P3?fUlnA`w|~@6`3~Lt z!3)TNT8&6A>F+8PO@Q<-l>?O;)vE3P3(R!@p8e1C1=?LkWAQ#$1ZP}!`b6XPbHiBP zb>_GZq{aqPnP6ukM=`9C%0ZX1uzfg_Babef*Lf~kOG^tjb({F^ z4~A_ZShCVyfRTL%@eNr+ij`U==%LUQ(77RGp*2To@p@>{>O^XI zgTA!HpJ)h~6mgBL%oYsPK$DQ$4xIB-$s=}Adk7nsRWJP|g&w1x%eOpPr`w>KBNq=c z!Pf?`EpKlr)LtK?*dREd%nkzLX&YR5quwo*a7-AX(G||XsLczQsZ?|~F9AJE4)~5e z0#lnke&0BARR69%{9nH@{VqxW4N_Ln;aTIKf|(O2aIfr7ccw-2DD~~4?sr41asIlS z2F=_AeRy%1jA-snH?uyBQ=oG3CGxepifa?`lUX=ZEvDq+T_nSkE2iej=BIBR*Xa}6A(nQ|9tab z{O+3~<(I>EK`@8#G|cOG1Yd^-z%hE0C@@fA`AT{vBOg=BQHA0{WUCePYuvTNso-p& zKs-7jd(X7E45*@gLc$U#NbN+xgp;xBy*4z5*!2(ToA~c59SMzE@n|991|cQesD!-In_l*$nGs-PNWlFc5< zTticg9|#&=%7jC0|LBd5pFlOHAWK&FwS_cJ+}~WkEo08g9lq7a0KVPOE>duK%}#AB zKBnyF8~Z&`@dgNA3m~SfYVMBSYj5|Dj=l^pdIE!pDE|ZzZy}A%)Etja)GY2K;)=|P zOU7wUlMH)$+%*2@9Rq_xWH(+2KY(|Y{3raa5Q(fZkjL&{0-j(g7(3~S^B;)*`qA)n z&MIlU6Z8*7;0oUDZ|jCYl_8vU44Zj-Kod5mt^TOQ=O;jEC4jeA&?=xH>HqtAljqU6 zlKrlnZz2C?OkLy!Q~wuihYCu3`wKgAjo{~++J9%)Xyre=u( z6PGEY5TNPNEXGz^!AB}xp?LV4`xifwZDd`O{hE0*5zyB|4{?O8-yAXqv^m~Q8uVygkkNU}) z$2Ly{!9T}0N#coF;W_cWqT_q(XoeTk0u&{D%9GNiab-v;hd)zIOhz=VX~ zDKv#uCl^Yo7?uEf)5_Ov3G4`91X2L9{Y-0rg5?ul$0;WN%^V+l7~9~hq=f$61XN+& z>V-7E@6p#_l0P$fgiY(tPTkRy4fT5qvjw*qN-wzY)|LX)4nG7o{+j zemW;({QV)=bS(t!-%SoDUk=W1_b-}Yj1l3+JHTi>8ZTS#N&xf0uk$oauC z$0*Rt5gko&xGD!wg=`Yn)E3Id4eer#66*ye?X~!QkGy9O2BBh2WF>~uyqiTrUY}mS z>v`*8A_9A!VSiO9--(CpJzNMj%xf>eRG1$hOobUWrprFwF8E(yDz~@;`9A_E-*F@pmpyL zxt?k_|f13uipzi$ON!Il^c z8h7yMCkWI5KjtJ2qB~y0m|d^_2R;||m%$?% zHdWkpaG!xi$@(1tR0BdRME8=6<2^y=P^gw8tO*>cf!H%PjQqv=bkr?y%nAcZwLJd2 zuisr0H`ndpY=>mQjSQx>jdg++ZqATNDZ50v~|4ph?N&Y=EEv!>IypAWv7^<5Wc zSa?uA4JJSqzau$#=lWF%us?->x=8@z1}j}?5hpG=Fp-fl&_Ucp9u+DoDJdEB3r!Ng zHK;U-_yy&8G5Bj-9srbh?Ng2_bw0-#+^VtCN#Jw^YqpPry7`C_LrJ23`LFcENH$nG z_sn5uTo~~=X%=)v${6jTJs0v}>L_{ueyt+FRU)xP(b9x>fPhK|pb>_TTy1~rbFc*e zom?W~yuLs>N(=P;PX)~aPj!J-C?n{zNW6sT-$SRP2vs#F4852dJw`<^-E@V@&?~R2 z4Y-!(3>Gg7SZ~Q>^NE*D7KGao)N_nGdVNemMpj&>E1`&KcN|^Ur=P^2bU+vOz7c=Q zo#xLgBK6D%(6I~Pz52fz(KfQ#8kb4A5sVukcdP*gW*X<3u%HyUNBjiXXHp;IULU&N zZ)GSsjmBF`SO0@D%k+;DGhIJB>#;Tmy`!gDXz~n% zExo|_jd|*sa_trR&b}%%rD^^pIm%FA?>&i186bgmpWn;m5?nsTso};OA6C%?scDnp zVC4#4E%g%vNLz1eeB2opV&eV{5Ddrw(z8*q=OPyV)%c6aFY^C>lYZd-s|Q4UALMSb zLgNmW{?HJHy_hwn*c$Wgv5fM9KuoFQ@`v_aqOZqmgVH=m@Za7VyV3s;F>QIEwnQb! z6h0vh5ShcTvpweMcW8-l(GXyvQ=FonSj=7WDSC;dR%rFZjy=Q8>8#mzI&qB=r}8lk zV?nvQgW$WOU;7{Pj?ugH+&@)MvLs6?wOwJCM#QsBjIURZf! zGkgA+mCgNLW+9dku+OepZh z+W-2j9JqEy^hVC%qlOy0w#cTkW88aa>30`+zV|NmkU0L3sJe{mENsjVgmNk&lX(h@ zcDuL3g5Gt2amWoBkC~Gr<(ELIc9a8tz-E@TFo`8nA&{KtRhuaGA`PmM4un$qvzxUU zARo;{!3E*8fswKfNXSKG$ojeT{$SG7XW0g_YAQz+^f&mpkYqSA){;uLb;O|0R=yv5 zXZcLAT{In9y;M$66&!Udq{S()w8g$l?Fr0~KGs8VmM@!1vz%0#MMQmoF=nYhqnUea3lw`!WGQrj>i} z0daoYlQcj&H+B$MMO-!>^6K?HXzVhDBio53G;ULDMcOc+0Y8fH*5 zb{O_}70lxt3EZs0C4gRa9rYTtA_UR=ozCEdMr5#lyxOUHtSAV@6STwaK4)r+uz#?g*p`w)G?-82xCi;O!3ed{~%mk%V2uWz|RWe#MuvCp+$-{F$knXL}{C3Wa{giwKDE zTv@xCDd$2u3`FI_2%PvKma1&8Ngh>wD4Kmmw6aVL^+~pYipu9VmgYX{yLD0$>Ql3w zE0{hS2-*{-Ig|?pJ}_5u1X#@GWk%)YCo$yJ zE3Y^}zxtLkKl!gkfp6>0r8-XWfoQUC2Gwr#BFLtO9r^lrI)24VT+_Ha_8YAz%7MZQutBn+h%Q`!x z{@ovjd!DndFXkqZ@x|uiR$Z~Y67i`qc}=E71hRZe!Nfz^ZoDDOt^({?O~mMyV7*0- z*=YA!CcyUpdP=88lN|gSRZ3F_4MQWfj1{srSU} zSID{oWOWOUX}q*}gMEiN425T;>5&`}yit11lC7#SM=sspu+ivXyT3LjU6^e1^Mpyu zUKfTxSIrg8@<07i^6RiF;;$yHN?PAou^KOyF9d;@%@X+0VGDR2c2l0xUIRUAPmR?H z?Tp|EJ^s~*$Xk*qiL)$zm+V*gG^uX^>;JPmNnER*3emBYkI-fD=oj|FWxtwm;8kN= zVig+S{qpjcE?Z*-5xoySgJ3D{#j)V0x4QmBB@gZ=V!mf)tFdDxL&(r;fFA{D@GE)s zgR1(endBi7uj4f|X6;he2ao)xl4+b~&FUCfOgnNbWt`3ZFX_KiiBnOKtS9b=+ozp&bsJs$zTap55 zp|UhaHLWJ)N;H~&8>IF7MLBp@T^YmK*K*XI#-K9cH5a?$w+nxS&~IYhh^)tvmN}^0^_iNb8-2RUJC4)eEAG69Eb7KF!K037f~3o5!$39_nZam$W6 zH6b$El&6sBzwJ8$mf=nriyWA1ua<+p&C34&aM$ATXV&%TokJq^6z>a6Y{WJlPZQ z8s=NMb+>PRK8`Ams%w5@&{7SWhSaguH-e9{@+=dWHVbZ3^sC{ww?LDet{zVsl$RuP z!>FEDh@q76q~r|Ea+sydPat#j!2>HCLi^9&OMaV!T=`%L__&P_AET3GSN!QQp{`nm z%CGYS0lS0+F6e>eS$7jHii(h2;c*s^-2_m&u=Uj~UoV7t(aOc=KkE^EY3wbxi>JT@ zI`l%YllQAcT~Tp-h(96>)0Qq23|~_mXKP;1;>h2D5jDw^i-Q%D>@Ou+DtTf#txxwD zuBfkQoI$SDPk|6L|YiV>Z059qilX+jjwUCU@X={@*0@9%5{m?@-R7D@y-|YCg zsSAIcx@0&;7>5~8#^6*2tr8C{!d4kXchfDf$<E*c5~GvFrRd=o()@u&>;-HcnfBU%YIECU3D06Yrq>T zD{!}b=kPA9S=HS4J2IK5?;9nlrXEkb-l2?ib3EG~zTy1&BGodiR)M5!P2jfToKn=c z$?3(GX@SYT#3yv-{jQ_rWjLsRPi)F?gdQdNs%ZCC`fX`R=4#4hD@`{po5alcw2|#E z1qg4<(zZ3K-aym!wJ^5s2C_`b{2bgd+r+w(|J*s{0( zOV7};>oKg<)Hf%<)7htbQvl&BkD7Ljw?7f1#m$2dvcHI1x_Zl$@tWky=TlvG*3|1G z3*lq)wdE6<$QQ3X*tJ}uty_GJ)fXEG6s?<`<)|PCG2h6^6ag#Vi}kzf(G~cQg|CkL zNPh|#qubb;)}Q%+*uP;IZlG7QTrFKTynI>w)UiJBBRKL0VVjT6O<20aSHqxuGwcQzjW2e?}cO)SGNxukt&WCn3W4@1268>`mA%U=YxXeK!n zft=F;V9+3o9SQtCFDVrU8*6AuS+2iQDn*!3Ha{-*0!#p)bDFUpJ%6Sm$!qVYt9+%& zlqOh5%w{wO^v{o#VjZ3h&zFM!U}AhBoocOsvQDlz@i{1U@$;0QiP_$H6Yeaw0KwTn z1u2nJ$bg-chl23W1wy!f^W+-$nuN1O&(ZP2@7)QKnqN_=t)_=`cN&LU%|X)??*II$ zC(Hp&ac!WLCYmDX!h%e|75WtA)mX21Y+XwWKR+$$Kzy@$7nfr7HbXR@SobfaK2?t4 za)a>OWtssDFkkl=V+QquLGdXGWjqSEEYOw3OJ0fP@=-k@!y2XKQ5+yi+9Vzzr20XE z710Vvm_Cx8UtAJ!o2XWIU_%Uo{>(Q@6UCAY62e(^1XL;sVGwQUo{d7_BtFP(Z5by{ zCA%UfAvDn=do@(t@$70^-#mkk>=aj7RW$?Y9T1{)7wTv>*o)T`0lLO0X%shNEPW^= zJe9S8F#4P#c~fFan@*!0Zpi{Ej0!G;A%2;vD|`xJnwJG}{=sO@N^cyhj8%2tsgG6J z{nJhHTsGgn=B7LB8~MD^U(ozxq(ZPZh>P~uA_oJ0ph_b*2JwjObb*`|)kFsu8{VFb zW2p`)c%J|jD<4Uc5^a!E<+ATCFXn#{DV5mz@%k69fAKEYQ1l!31n}aJ?flP+qXu3a zdD%BDa5t2y`EB}Rnrkt(W|7Pb2Q2F(UamZn%tSRT+D5{zAij* zvaMp~ghOw8mFx4a2mjJlw0Y45MJEjIVgD|F_MrTksQsb5h5vJjWr+$m!On}OO~fyp zA+rlcol5-t4+ywb)XismFI1VMT}Sx1yMiDssyot3fKVh|k`1Y{(KmgnJHUOsG0Z|F#SDqEDktdR+%Ocn zlWzJ3xU@5t6W~N&3Rb4U@|09*4YvDGXE1bb7$xRQa`0 zQ)(0lk0mUA1$3;H_WfVfkuDdGBcR*_-e+8WVi|z1*YP@p3Iu3YqfBP zVv-C6U3`D$IKIOCXdX62me?7ib@7fbmZ$Q6huTBtXWNr!m)rE=opUw;w_`ZTvJ+Zi z@fj)0y&H3gWdieInz|V14%0*qr|?6{7v=X@`7~9msBK8vhbvqCP^Ub(=4IqA@ep5?9$NjY z&iII)BPl=IXi2}mJA?&iOiQg9qNkR0Jd3N{qovCfGOmVG&xftP!H zxKs&I9ZH05gD@30lz7LisP_O7SHEB);x$=qw{CT)BVFHYkreeIsU&{)dy*iZH(Us2 ze;d7+ov~>SF&lHeE0tNLozSVspv!$7GvR;dz5gXpuX3D;X87&tw&iVyI2I)rf-O>C zphg6l>E7p~;|3q~@rx+hs!G_v=+Cf*D#eB3^VK&%&-x8M!Z6v-0n$T0}y~*8{~rdxVhpXd+pTvfE4C!Kd0EzR*C} zdZ^d(mbi9va4Abo8;!MI@~7L26ZJ|6GShMbTrYh*Dium6 z_rxf=lmcm&?^>UP)HYKz-vuP3o^t0dS%=46`}wOzFn}hARYygxkS&*tzEaB-R&;-Y zdZ~Jf#f)ySel%5~of!L~CtIIkd$SjaLLpkj8Mu7b_-l)EyJb zG<{-L@OHyWFMw()TiC~2joec!YLa&vxpS)Ay&mL0^$**1nC zN%qF)b)t-B4;SKxTe7xKs3=7LM{EB&?C7(oI z5*CTR(_36ztijnt_9$hplP|y{Bkpwf4#aHJ;dWMIvMk;n^{e5n?>5h|8n&iW5FT)B z`0!R;Z(15COB%e^MBI@%d+v!YbpVF$KM0I^-nuR4GV4{_g|uSg>VWujkJD$=RY>R0fF3DxR?DSMxSou*jv&>5w$|tM2cSgL#g8Up z*CJe)|%M)AA?>5h>I6{&(2iD~NYClP9uZU{b*M>9WDyIi& zV|bg8z(_QWj@cu~vfh3KI#TSi%i~2e+-g3tJtk>8-m}|uZ*-4YmtUa$T{DT0u5I@5 zqN0Cr*I@M1L9m*X(fVKWPjF3a=rr~1iZvJ|%tk-)iw}7RSrmE$cN$O~QY59FWUZC7 zA;0x)spk$0FUDgAFIrP6;*wj%qYezqLZp$}z^)wkfS|LH30(utZ~5W92WxWwQmF_* zLV-HDJ;-NB^3YTNH)I{)NAUj0`1QAO2i2FH1WWkr!VYWAA}^k_D*kTCbAZ z&R@Czcm^_P&|;CzNTD(Z#3OF*(eJ;7X_f1+Ea=}^C1IV@&U`x$uBV$>D+I5;vM#!n zF>i0Shz%|Tqhs1RHGoGV+0FWajC~Wy-4X`ev!pxC zzcEf1OyXYr?) z(>ssmu(q|=e>ogkwrUAFJLwB4B1n42@Kv(5sT)*CRsn`*Ki z#BW_ePyW(K45XZ&ralJWh1iB%8@)E-Gxsee*`zE1bSzSF1A6ntN?hPm`#P$Xz>{GC zJw;jy6ryx688xfj1S+4@9@`SJ0!Hp1&U0@hMb#y%$K~oC` zsD3v^m65}Zx>4<>44y^n`sQA+6JFQJg6M&~+EZSZTZkVg=UE;D^?dS(6suHt=elcs!QN+omgwwH z?X??r3M}2nXF*XVug9w)Y7%pm=@nx)n{l$cTd?)B5CX(4t5Fhz2W?YRBqRBNxCoBE z*n)|T*w{ER@eS8faC5_&$yQ3#h_*fzK91rX<31y!_-CtihP|SMxcD%uiv_7G5LbpSvzM_8Po7v#Utn=#_a zcH(zbr1KGEGQZCXo8lrw>bB_Jz%5NpjL=BeLnDtHLvTMN+B1oh7VC(DA#6@UBE==0 z0C(L#+c@w8@(#iM5@WplQoo&dZo2nB2B|b_gx?PtF8{G=it%td=>LR|Y!UJ3+!;Ok zeTp|?rIa*~PN-^^x`9BHT}C8To7DR>mL1TA6h@`Q-r@2-zrSK{7Hfc*QNi6_W(%4N z)@*k5_tPLfR*_-1MBDfKeRvO8)Le<3Nnj;Xy>Z$y<;?EzpRSAkn+U-R7)lY*N17f#DD25Oab<9Xp^ zp*g4+Erhu6i92w)O=^J07$Wk^!XX!s_TQW?AMQ2UaxbKJw`}g=crQ#NR>aeUkT46j zo2v~-G;$9o4`@x~7M`9wV7V8#DrRf0q=om+rcmm8G(Ol5=N1G9ajE4*4Z?uxKpYVG zc6Aen?b$_LZ^PrQ4e}o{gt3r8;}=sXW3saGzYTRn9gD6mBb%`p9>@j7uTgeQyHt{8 zvY0Uk+jlhpDgYA_t%XOlPU^9VaTpopk1&c{IKriVeENM@rE+`FY!6$S6-Fv(?KdFg z{Q0}k99}wq^V6g58$4i#j#zS!u=MM`o|)BJRo4GOjPlvV;QW#`HTKFCkdcCrVJ8K!4eMraIH{mfF8B^?1jTL@~8Isws;E%J6)* z916Pk0xZ)OtP^aOeP-Db;C&$!ZT3X6zvD%g$!6!}{pN+F9G3|X3&S<5qq|8z2XJ>< zef!pEmK6FQq*f17fD~x%)+jTqP1SlY401c@1TR~<`LAt+Sypg)7*+fsDBoQaDy5>U zPXo~u=*@g!uSY^+KWfU(ufM}e8|tCD^(&L4<6I)8;9} z9C-U8ZEINJs~}*?)>@3~)zIQH8dL(M+pe@A;0!fQILR28rIw|^|1Q%DjNve%p}W3O zAYIegL+Fg4fMQyKLBBFv#Hc3cjWz2abufdXusp|k@p3cM?GPru6Y2>}fwBdH^jnDs zvl*?J&rketL7-qxj|QlRD^Pz*Vmkp|n_QJBb?tc6#65|Jkf!)!y&M7b>Q%kn5W`w` z8vj-Lu%@RhmjIl-bb>+uDt}fQO`#&n&jD(hwR^o}DQ-{GxK`*5b@UpgH0hhum!Wsi zSEZ_#3{%LVw}2Bc7|ZJ*efXs0w;N1SEWg&%ZHa44(l5r$wXIR8B#emze9}_wZ|~GE zlz0Q45aEv}L=cCpY}jW}YQr@_Auj1tR@cU7Eme@rp07Ln2tGWd4S{%g$orE8vH59+ zc)wP#kxUUdV=LpWGE=mizu-M}Ym}zEOK$=)=8O(Krm5Rqc2QwiqbaGG`#Zom5pvxF zxuBWRr-DpxI`y?7Td46D6wKNo6&dg(?*3HrsU`{pSA9yqUV6ykOW^@EqnYPb6KuA9 zt`d~$#tO)?BUP^;B@|P!o_>VOeLv&Andzo`u$yFV->MtkeQI#Z1=(e06il27n^Rcw1g2+f+AH z?>4OC3D|vz#+{9J(7{&g!H7%zQ4o$4!v$%^ZclYOI!Irn1VPDH4xob9vHy&wx`N^y%eod&rFCJGLxSnL|;3T5LSGcwWhU z)aC8=F)p|^qncTr3pAJGN=`^18(@2`j!K6&rcJ5YA6;VKTzivI{E@(V^&u_xzot71 z%=KQG?eD25!O!+oq3C>x2MU(ZY&8AwDI6ZBKMW6bbdgfkmf}3=JmKT<(HLPQP}1u- zp6iR>)%MRQ`jQkpjwo6MJ9Pt#p2fWF|3}P&By8x^s99^3QE6zR0UA%R#Og=@Y~hZv zi0y2)Ep|Hx$$|UliS!EkKR-5qQ$}ub5jN|aPDdFu-tRLbqb(c5h>)$;Iu|AiQ<>zf z^9d&vs|VG^g>wjJuOa+DW$sH%U(D&V?44lkJ0!h8O`uXb2<{~-IlU3pD2-b*ak58a8JvIukYf)(uFaZRh zRkB>Oai2o5Mj4%{iHVlFF+Lm)e5n+QMQT$%2#={@kH<{+gd&ZZuWB?5ESd-~+^&y77=Bp_(Bd?LSkS|zbJe-k+(*B} zShybNE@W=f=Wf1OhnNNT65APDg`<$?hn$`qNssWGyfqQ9D`)>s*V+IYO=)y4C5jf1qNzfH-8QGamL6D=GT10+KGxcEIN9_5-~| z9|M_CgviaH@6*G_(>6^;f0|rCkfEVke_!r-DJ%Bbs&>!yZR*=20~(8>$CUF-`o0MC ze5sz|6-d0$sT6+su0t3HUAtrC$Ggb4G8kV{{!+M0-|N5NHqhRyRMV+;LkWO^!;vV& zn8u8p4e0S*u&tj<&{f0#9Vi9eB^bsrShal13d`b4$Bb0pAB~^Mv# zSih)3-gEZnH`gIzMmt!jMzH(YxeA10y7i{TV>tK=g{w5~Mps0rq#%t+2Ja4v;?hS=}*3^dIGYM5tq!lifHrCr_u_ibG<`BNHPG4JPaNoB<80Thl_y zIz*?{{z`k#`B0h1h1tBwkjKOC)yK5x(CX+pwITlhj{res+?(3K$GG^v^AkcqUzHT& z?qY9-Lz+T}pFkeGd%QiW6!_d-LHDcSJ#E^{eNH9R#uRq18ThHZ60Pa^4-Rzcoc84i3;k`mVq#i$gHv5wUuut#L;b5RpqoOusHbRoJ;sBCQZP6Iaz^|o^P}Bs0*|j9r zuVKY;l;#_F7hmqt{)F;aF+ti&=JXy!qYJszAfIU=yNfM_s0Kvg4l=(3IRp)wDYc2j zzQtN?x~vA45hI zGyS0v$M=4xH@Gh5vAnxL$U*Lh4?IcZcBbI&IDvczi|e;>Q`m93$Q^9Nd#1RWjlUi4 z!UQ62CwrV?@q(Dm0)@=Y8{VBfLM13LLpyDRunB%1|FF>)`-MWm146dr%@=xdv?b;$ zyX|-bKPczEGAT#+1dsIn9Ri-+tDbcLj6$lKOmq=0nz+3#c>xno&<^ciLO3nNX)85V z15p#@N1dhrnTbP!Y3*R2mz(=%%wNf%SdG>r$_uBRTO|JGa_BWLBprqH@hc=7CH|O| zHT)e>*pi&E=K|$`rACCp>t1fuGtJTg?9t>aFu<{BMpTkUd;w*Ts$VJ&kdK~R)|B~n zlcYslttp7PoqE!eV)0+f{>yo*if2J!P@}+AZ>BoHm}S1xage6GFj@F!cr;hM`o zYXu4dD7&`ol)KlK(*znNEaW47Q9=h8G%~Ov`PU#jHxjO8UXxI@dol$Os3_fv;jyN@>K;a|p)hFnvV}8PVb~ zmi(-M6_eHve_%hst)bVlBq$NFR<&&mzU`G*6Y{hiyU^|-sC9FpBF3Uu3&O4hyX>r+ zAGa4EV-uXCmn`~cvC-M57+bg+apx=|Sbcu2bk|+fFBaJ#?P_IoX~if$iP4i!CKH12Puccu51+P2pHz6L;8ovGREH7E+iqDi zO1a!=?XjG-mq!=1F7#Pl)brIi~KL&NZo-)nKh1%IsGI?2$eo7r@f>f|`Ks)1t6~Qq$ zlE%%bE>h!ch35yu4O=Weh#qTf1LB@`y5FNDN{foBcr;2ooiRr7zVbXl;=Za6t93#W zK6pzPrL7a{tG!JUSvXp0j|H7^yew@)Up8d9dX%0pTLl52if+l*>tpK&J;9&nxsumz z_Xxh<7i9hPWi<5>&ys3yu&is?-A6X&jCZC`FBxh4KeUVurEKsI_TEhcQy)_mYz8i$ zb0`WSRhU})-5^S9XDy5M3J+80Yc96e->)#L z3^TjPAE|=H20~i0>Og`Bcb|EK9U;2~`V22t#EUf~JYhq$J?d1`Xu*ZLhqpMYLVL!O z=>0(b>C>m1vFJ%1T(|mUBtOFueKi9@wWj;n{wJ_`Wa2QRbm^N9HwV?DGJ!tK;spn4 z<*oaI^bun}y_m4AqYeX_l-hkCHm@X#7)+zExk&gN;yxixr+o~z(k%Rl++OPKpz!ZT zvyumKi*6@hM=9r&c0x~$T$-=Icsli9y7}W5r5ub+eDU15HkP0s_Lqd@aY_hN_8D@c zqYMn#3e~>6A$u>%AE=MG6#!cyRK|+Xo-e8#dnjtkqt{Cf+;1)=}D@JiG(f7vWBdug}Ovw=kT^ z=*(ZDTgs*Z5a=B#QwP4b3l(cjMW7VriP8|!t;t!s{OEqvsU)}pGBw4xc+!rUE|Ai* zRmMYk!f{T2z1PyuY3mF)*pfh*`mBB9cQstXzV9=T{y1Y_$!nx-2s0nvL(L7|55`{4L$jrUiAwta_ z^mt#ZYbzQ;xDkC9ibk5xs4Mh4Jbf*PQp4FE?C1>0qprzCNFoJ8V~LVclO5DR`){)W z$wmP1<%kjSzVpF8&O6UetRPwmF@;!x*co8BYhIk z3Jpxce8K0B{8!7euxDGE!|~Gb72tW1JW}Vt6G~eJU&p+0X}|a-{>`KRJq!*rJ@o5i z#dNx~^I*RWRrZ{F4${3}vr@bi%IjR zS$e@sLT&$qa~?lIS;b$ueaA9+c?LUjDkvkL60iCWVyY{-_jSs+77W{T`l{yiILXm@ z|GVkzDX$-~t^-u|#pgWjnfw1m$o+NCPKMAtM zmLt(daAoEd888J()t$33QZ1Fy^`dmeD;#dLi!sKdltNDh--K@?{bVloA}=v0l#f;h1hK07hOts zf3?I7y4APDy;f^}y~c+DnME2+hCZanpI$Utwn|AaDy`;gER&_NDjF>sEfzS(?2NGIyi79z=#wn;w>B~f^jk?|G^c9+PLZ9NbxIk0Ng9QEL>=j1rQ7@ zBrPFs8azxV@PuAuBB#&wQ^@-6;s$?YfO@9qC4oV!FunH?7w(7F)oh`l% z17bIsK-vJaad6{{rH3U!GHgSbq6$#z9;kzWAjoXYp>b*4BI?Ok-%VVfXEdA?*bh0q z5UI>BvG5p6B)`jhV7X9O8P0wCzG(vNZBTaaKT_`Im@&2@@u_Ap7_*~K2&t9mxAH78 zV!O+HW-yFO9wY-i)p~D*Yf5Z*h&ll3NJlY|_f|`zV`Jpk&!!Rdr36xVsw9XX+!`ja zsTe}M*VA)t=Bhk#lnicwOXZvgCEx) zVZ(8b4LS&ox#nM&Q&Lh6Tz#`HZD?Z&hUF)XAr&@F>I}7mV0>&o5PN*d*d+Qv9 z0cf&g-J{dQX$#YV-sMM6QZzG#0gUhCn5~gmrva9>>l2}e@LLYTBd-?w24xr4FKZWg zSCnD8gJj~R%3B-t*n8dQ8W=|EL@xAsDCcsb%cUut-I}K(L0Q6NWDbH%vf*ToU5XigLt_{x1}M#sLjYXEw0WEHzM4Jy z@oLp^zWEpb_>djnuSy~3K5%|k(5C`Kt~&zzbu z1m=HxYXh!DAb{Km=KXbKVLOz6Mu1B3j-#vGZv(}kgvlsU?Yg$RXd47zXOORfLmiR6 z^II91|J4F0D6-ZdhKakkwz7|2%bW64 zb0!IM=_ZK>tupzoo@U#voc6~a1xO{DcpS{WYw|n+IDr3xhhF2Yl|nL7Iu8gfee~X$ z6=)B20X+ou*w*)~YeB%#K&SqBn^A`bUJh-v;Vrt6JVZ{J`;#*>QM$0)pDsEHe9K*! zdzM||p%Vc#BgtK%Ao6ObnX4*%qiij-Fo9|Fi`#YW}+DHR7;j!1OG!pOy?unP#j?mQvoSdCo z^N`yRZMyG8Jr+;|ivG6T5Ec=>p_Wh0l@iFt&du<>wQK_GcrNC?37gkXayBs{JEVw} z64bBEE#kNpxNop|iu;sh-pd&v*P-N1;4s*%a?>Ca`&_VW@6wky1P+#Kv8BFkbN81) zmMS&w+D@%~3if__Rm1SrBV0u32FWxag5zY#uq)K__+j!)Ffj35m>1+U zdj*~az6ah91nCH15T5SI1PQ=f3&hM~YhLfAyj0!?pXROL=$)r(L@b0&T;6jG>!{nH z#mG}x3KJ&uMPP$6r!wf0Hpwl3RmTied4+9U`iUo?0hh5CFI{u>8qH)I02_+Dv;PD- znVJfV_qose!#J8sMB~dtH>L-PgsFNRFJ1i^EGfT;eCKwc)wG!)OV%~RWE2el$3O@# z)F{^ODT@qFy=2f1GIQVCLtv{U7?7Gr2nVHMXIDP=1lspLy*0(jKKp%U`m5+t*mmeI zt{6ehv8lQXovgNzeCfDpaKu*Fm84QL>f!LM{lZ{Rs;8?f`WzBe9=d}yYEKz=iVCcY zJ6ZZe3+i5+9i}CZn|uMBJYag~H}s3rzpf&P{vvgLbwM^?Gr}$1@g^8k4?T<*CQI+U z$7@J;iUmFbXM zab(9Op9cyZp!+-g4dFDK%=@^ltbTDCnT2_A`2K^%fQI!yo`9Z$u%b{4_n>gNh| zA{PXC-?6r1hxL$+oM~yz&|VEJ>o`HD2)IhPkwUF$lHivmlN^IEl*E<4-@NFvE3H}q z^#$T}MVb{EgL*4|M4z$0DDAvWe@HWR)Tf{MKx$S1Wg1MgVt>9pYze3}+erJpEjs)f z+^-~JevOQ1*eWO};Go)H3uO9w3f=;oW!Gz{p47<{ysVWP;Ja>e*%i?mFd$rZEX6cX zQ_EFM(WNn5Me8XH^?kzd0~AZMuN}nlr640jq^gM!P{zpxIRils6XgS>hClr5VH{WR z?fvGiXA0*ZMM^8pGE!2C(&|r%HZsW$vWfK2eV!^?K^xg%?(b}DYc)Spe=Px{VZ5g6 z?~#{fY9;N0T|M%gwvSz~Q`ztDR4zHs$2j}>))s^X5!VsaCQo9L`ieCx6k5Hm-Yt9q z=_0%V?K4Rdi!0IihQY-4$p)G}pvDaE)MsT0)v{PDfLd{jJJeEy&D!cwfo}rlP9^C# zVH`ve`+|PLn@G0Y+}w+8uN}lzWTPtOn7_XY<9ITKLKfNEc>+tzg68A4NTI3dWPB^5 z(ZWqfuL8M@p+T2|B1cV#V+YJ{m9LH)KgVx&;HmF*0&flj3xjTTYyleGiU=Dqe1d>! z!lw`pb=#Y%^?=n**ZWEo+xiuZd@q4O&pCMWvEksqQ}I6RvNVcDh3@*QxTKuvS_c~s zT#E0^DB_y4v=EI9S3gGL_iv?lT#?U5aL@=~Gm#ppQ!_Yy@Wnm#P%d@6*`_jdvKtO) z05xgY>#43P*x}nh$R`ma*bif*3QBDZbdT6uBVM&T>mo9y^@^q9heXH)Jv`ivK}RA& z1$JQcnT)BDmncu~jjSBEB=ufwCwf`#&Bj++AI!5gV*PWRDCnUS9zVTCg05G$7AvE| zo^aAf4?}@!y)~Vt-6?**IT7mS`P`Bhj~Q!LXgL8DM&a`eXjFAT!2% zLejF)iEDcWL}<%-Uqa__u6RbOB;j(6m(KZ3oc3i30mV2A>=7qe-5yJhDfzRaI`BrW zm3&`vi!2OKXUc)TnW<11YSn$Zy^Tiwopi4Z4}J$p3~POlq+=9dpw*+C>EOnTiR-BF zbk#4)oaB5@%+(BJH;FPkQY|X(7!)W7HwqC~Tn5QK`*iVp)g`}lXXY(hnm!@npH@Kr z(-*uL^{6aLqa%YIKjO?$;9r3HaUgb^GC z=NucmQE-)JC##(zj{~!mfXb< z+o#E9kA#n4z|51vc5s<37N;R3vO9bwCKac4kK&%a=uo&_zp(C7t^jv`Jv-JA)-rCE z)ECEuopMrI^Ff@Uq)e+Z5S4#ZsV^8KNXxk+@Am;`sgndQ5i^RMmh81sam`8)q|_Y ztI>5wpIEj#!Hu7u?nKpzW2C~utU45o@9og7GuB(Mjr1zxNuww(SjL%`P|=LeO!%qJ z>CW5y`u#=@xLw3{`sed3J}XW{`N1rvLOWV3{6wvsQv049ny)NLHAeJPhMl-6SM~f| z-kn4<`}!6^i|-sjHOqqN`G z6p!=p6Ay{`4(F>`P3V>X^XWu@NxMfGE*G&YnhDd1CLVN>M-O`o^*(kuD*$a%X+a?% zVk>^D+0YhoiSq+znU0!An>`u6VAJ%7gd6T6O2`f6&_X!4Y=nXl8V-pFq9v#ZdQz*< zt=Mz_=jT6Lj1^QTl|$u^sr&&xkX4)>Mb?sFoCE{UUCMJVl~A!Dt!kCL@EV{C9e&j^ zrpy-NrUaF(u)GI9y8i&5N1lMs?Mb{c8b77h5E4ltsm5h!x2FdRstc%DAtCRbjFGdr z*{^7fV6OJLb4y~^aC`!=7g)kYSI41RrPO@WXH)-Q# zu#=;~$7vjC%b}uxBuIw;*)Z#qO1rO*eI@?^yMAF>c-a*^5`DwR?fuT|>}zxxl%f{A z4((>m3S%x{IcPBp)UpdP{nEWlZj21?-g3UC#`Vf*7~jnCRIdfV2(~K;c_VR|^1d>?PjrDzeLp?J-wok;~C!H`!P}JM1rNX7yTNkg?1FG zz9Fc3yB$k9^cFAeJU48i$D)4B>St|wKat`;g_MBsD9l17C}?01G5?N}Q?rO8`@w&$ z=@oyjcNW4BHkNiG+QmXeKROLEXEnVwy-u?mIOl}nI zw#Rm4siEN}#i|IFf{nwTNlhOGBb+A=LzP8noU-^u{fOia>Gc2tADA%?F977Ic(Q+& zlO#6HWkMRJmh`vl?0ZR&=F6Y&8+}H70|&_7bw7Emni!9Kxrg~RuM4OdOEnZdO!GQw zyf~F4Rkb4EmGLZrmrMmYn0du%W;Ji>9bu&|u0H_ysJbV9n?7;n*L{oPa_n<8QK+1g zM)9r25XETNKo6YrXIM)($C6&ru?&^O_IBO7iS4UnX1j%Px1>I10oat2@V?Bfc~>h( z758>;I4Hred{Uo_cuipMs4R6tLQ1SK8mzc7+LZeg-WG4nZ8DTfrQo{GlRvkC|1pL+)# z{P>6-CQf?z_xC`0sw~}qrV)53x0OT%suH7dQVP~}fZNUj5q26$@2Q-^LMhsbj!NRc zAZe!pV7Kn04j;M)w*j}IwaM(t7~NVUMR*mvINf;%*v6mEWD z)XgV4TZ5FLD3sM#I@9mF(5NUBD5Ov2f!u4{TY$u_tw`Tl9YRKS`7xsqcd3O_fR9B# zmA)oL$Z4CK-r`h$r9rzR!u49x3XrnWoKytTH1|1=>SA^c14YA~8pI#i!=((OFJH%e zf^>GUYi!4Okhv5^LGqwQ_z~zt!p$7?NUjFBHrl*OlD>VDEzzv_TN0t6HgS18d+ZWe zteOjV22E5}`^KkaJwYH=u&&&oJ!1vSEf>{@$M0Mi1tI776*i_2MP)UJZ!Ic~o=7<9 zR>H}U0odvWnbr!z`>y^>!CYuoG3KD06Y#rgrw^x`Y^|JAxDh*gP@G9LNH_0reEO;<^10*cr5Fqv z$m@wk6Vf$BDQOM-`ju0orazrw5Y7+lRVdsIN2P4?cn@0&x7q!-Fem0a$jOr1R6c}r zjD&Skg^wr5nwe3}ad(I|A_mWxXZj@nS{bXT6{d$4k9kfeV}$)G?#~Wykl5ccB+6$C zzZDa_6po5L`jCWM^A=*`wmZ?Qf-EY15JCTT$C*|p9BqS?cYmpw^Pxkma;Q{}4euu! z*YUfebFic>FwgWzp0Bkx-_HAZaz$F0^1?Sw`O1YUH~% zIzSE~D4eIQrCy@+sxO59oHAHa__{PILaW=OJ8lVHZXRZBnGrhR5P)%&df3S2-*azR z41FChrSKpPNTZ@c2o~+Ivk4Q&B;(-RHc8#ir==t)lbVc}wiNNE64NO~Law)SWnp{~ z{!=zrd!U3vb5#cm=Tndg1A-XzOD^B#Yj+%;D*_E^hEUrT6_FJ`7ymYr*36mmLO%N9 zFVL*vbk8qjAu)u{nza&BR%C(NP>4|FkQcCHzF$nn2XM_)4m~@cB(N+cHdf{&yGfR? zJ~t3q5`+_s9C>NY4un?(#$Yk&4!tzqmX-sz0hw5b?ar75J1ZDl79mp>QcI~>Q@aBi z;4l66{4NSZUi;K67*l_=dRz3*<2;TC;kS<>57@qo`^EhU)0HMJMAl&R1J!FuWc^_E zJ{PL8TTLTb4!mf=>hVGZsanRah(T;=R0j|_8td8ebSIHnN7=7mRm!Z?#p@7pBr_`j z1D5}KHE6KtEj|6OQE9@-;HSrCecJL5NtPwwLt{v-kf#FyZo0!|UH6AW0NJ$7a?2bO zQWz&-CN=VKdR|yS;rCg|jDOO!58c@V^6A{%kC>)|iWb8uy;%eMVV8RaEmVeP1mOMA z3k-7L3KHd&l5{ZQ9Fmfv=5(EBZ%RrMiqq%&nxthc_h5wdRUY>@7n0K;p-||guKhKs z@3nB*vVAy7;u3JgD%IPysjq96YGq65#+&I^o5{PiEU#($aq$86MlVx1kPZ{GVzL~Y zz*c)I;*W2D4Jtq+Tcf{kX%Lprr)&Qb5VNfGO6cyT=osUDjQ_z0%pUfmmdg`A2fEOg z(4v$B2BTUe1#%9kYShycL5a27-56d*t5t1btMgrVjyAY`h zOZ{QzC1_l@SqdXKER-^H{5|_))HxSd3$iezbu^4nCK?jbGk)c0Ib+m6+&&ufVb~fC zbMK^yg2GpA3iW83=f+Qjk@?#jm^Caq?s$SQCtoZ3S9{9*WaNcnsgfRD03!7f?#;wq z)qB7{gV`d8OWJ0$lwN5DMKnsF0fu}K>0#T3s*db!!sU-X8=zxIP2*dCha3y}Abx7_ zO6iaM2z?#OhMo=vG?u_K4IR&>l=gDy{wRloP&$2z-QD|Vl%V*ss)^*=pF@J?#UDA8 zb_XGJA}<-lX}7Y7G=fBib?w{o<^>CbYV1(N6IN$HqldUnp*r#)88ce!+TSAY^g3jT z`_*9^3Qq>TolXJnuIdhRj&tR%2Sn?e@o$Hi(pVa!vxs$S}+uazmlSQ|R6* z{?FH9Ug)8fzXQHP&}pH-Yo9AUabQp(Tl5LU09?3O)2*f%Gs!h`UEO#WAALx4SZ5`3 zQ#f1W+-y)*GMnF{N-Lrl+8|tT^CuqpRMM%J;Ey$ad5KV3E^wOoz`lD9U1Qzc(r)Un z^!=YR`hiSIf0{tKgeChku`q-VVX81)#AkFcH*sW??h8`ZTfIjGH2#m0FXeCc`~}o^ z>)ckl30_gRA@L}**jz5EwtSWxe1p)#|6h@g7OnE9Jb3J<{7;8{mmcB5YcO~YTM1D@ zSz$Oxc<<(Y89LVzzX7&$*4RTgFzd>ouHPARr46rL5RLpWdMeluO<4v5y@BO4t zKdN^C`C|XeJxd=^PMZ8F^+Vvjcd>qJQxl04Iy3prDw|?Txm#LTXazjldUm59Fy;}T zFpjr2YaNo(H$2DQKaVK1rei`ux|3i< zQ=vy8n=*1vx%IuJq$`b1dXEeO!P8ELSB%g)qPc^Ah;dO9H<9~N`+gxeJ?k8I+_wmh z<(?&tQt+s0N6@lrPMjthD-W*zqHknMXD4{M5bjdLqyAx$@GBn_X8gOUUEmp+3C*jE zNb8HaoY@haa7vOH>cuk8@Sw^*7;Jc0sB%Rv$>fL$3k&ChXbBI0H;Yb{Ah`E>$&0@M ziY_CxCaVi>?uF&E_<%Dt!wcE}GKofQ&({F|2QbhmCsF|_l#(dlerYvP zQEp0n&_R~Hf5a%|7d@n-`gX^=>WIE*3*6y%1A@UsU=t0Z)*w-$HidesC#sIT@hZwP zDWE4mBOE)g>jp4=#sLPlygy^B^>oG&>1XDadg)6Rg26YCN<)?x{Ey08n-|${lJMMVZjkucLrp!b_ z*gyJs5>h}_F?h_&=XuKIRoLLxL|x|?DU4;OZVj( zVG--MrK=x5d;dEFcsFh^`51wD9R1C|#~itmiXfN(rAQa+GY>!5DEwE65A^3n==mP& z=5?^CFieT_pJxR0%jRQg>O}R*KWLc5j&XEnXJ-hgx6E8ZBI3qf!H82q#Gg@S@z8ib zkqSFtM)!b&PDftoH8j zSn8ziXC>Xts<%fNM^4HQmKS2ucHxdsnGsNxaIO+dwQI{8_zu5>@>Mq}d?i;A^t)tK zLDgH#?}0@~d6dSbjz;t zy$jubd5o;4LB=9pY8Zmh!!|FA*7`8Q>#|fkJ0~G&0A# z*cyvM!rM8B<0OQ1^aeK)K72BN0=&Px&uSV-tAqEwCJSwRa4!QGztV#G39xGEp+L7U zgX_xFQ0@APv6(Cc9RL-Gwo*0=BW%sjgDaBO=CI3zCr`i+y#{NV}AMLi=zD4RKjmpa1Z zJ)Uoj%<%Y&-v#wDfX<62TB`0bf+JVzoBL=Q!61SP<1*U^EDJpNKsjg?lztBIzSsU| zOUFZ$mD2GjB}LtpIMQ`w?|F`_$R zUVqYyfJvs|@B8rT*?YC6)p%PK*KMsNI-RyJ9?P^fZ*l?)oNB#d`YSG(mBcS1ze4c+>?bm2JX?=nQ0^b8x= z=PlhoFNY3d7^88?W_~xPg6)Kef9|V+0RN?{+{A%mtqb@8f37fW2em1H!Qxvf|yX@Y0=n)9Iq6+SQ*F1a3@pfa9v@ zWCkk;9!+CpXj_iAeN3xyskkQS1fYS6NR{C!2+{wNxpu*yQgCw44iPA9L102yxspX` z#nsdOo+p3L%V|wf*pDtGH>ieW33ly5YSna+zbQYxgLj1=m+FI$x1}l3g4Kb5^H~K{ zynFDQm9gx;fwIh|(svwvkb4K#f$L5ocv7%3j-U2RQAP1ah$ibpD6#+r#tG1E|{6?8=#HwLTD6Q|H! zq~2+`u4reF%4uyj6-!z}+s>uhLd(XCO4bHe{w}>+npyN}e>W2qQwK%dIeoYOVn=wy zr&7&8Kt)WviawMfl@j7mD%I4=vez;HKJ6A4sg%+wGWzxlF|CWs>o4hBlnH;}6J#~j z)a2aF+U_SLN5m5FtUvI*P(cX{;(PV|+fp-d(r_i#AQkx5uxUWQyq?x<@Y#YHHwSHI zBc3Tr8hpBv#IBz`NUoO#HaJUevpvSwP!Uui2J4ONLk+xpU;G3f4pcd2?n0-3e>Z$8 zz3GEsX`cXT0!uADC*GiDGAhI<+A&nBb}Jjm0z|5pJ4GJkIvo89v6p}H;^)r&VaF!F z{-{uqzM-zlf#D^$%?+tN|L?xn6fSlV7lPj2A4v1-f5zYc^KC~LMBq{{!>CQYZv3c% zxr1=xQqS^uVt2{1-RUtHy|W}`t2!C=P*Z~~v++>lvL15l{tJoqx0y-)iQuwX-VY;2 zWhyMAD(A4Ol3b-ED_WQ{x#>OH2syo0Gobq;0wo|z?zNmJ@J0qW_SKUf6>yTS zi1OBZz>|+8NDYp;2_Q9fDR|?!q`A)-MW`ORwJf60N{T>M>zpmv2~woOI4U7ie+c(x zVDc0c>;CsN0$D|cs{E6)M8eys>MSk(eB%Uc3UwTLO$?Z*Gu#H52!ZaUk&GN7D%t5! z^Vy@;WBn}?{XLy9EWqMgpI+1StT@9aHv8jVZM>t<6p+p#c>5@#e0y%O+?#@|BC7LRk z%RbNTqGn$|@Xkz^a#jb*oo_SVYxMo4g`k7#(In5SBVvY>u#wL3zm{*=sDupTx#C1E zJN6a}_uIX1ki_+Gft4w`XOlA@;Y06T^$6du;|F9(r$E&MW-85#A6zUOhQzEUg(`+f z8ZS%Z1V9V$Ip&d{@S|PR*O3e=u=h|iXH+Qj#B;B2m*E+ zleVXhy*N=++Uo8fZxuc2EJVlO;(tQIz-l+c+T$|*`D(+Z!~Xf*(7f_wqp>?4jURdg z3c?XKB?`95XYg(eMuH=y)KUVsppAxmao?97`61z=ZiGvcc>HrC>Hhd2KtJQcd?!^O z&Ow9sc}{_6mtqN}q-uTXR%i=b*2I%UXNrdw{3iDlREk8O`Tlyk{ZS0+oW;reDVn+nN-66h3Cc(>5lPli1`URQCugs!&=XpW%C@Szonb{qP{Tmd#|DY3x z$cS{J)kQ3P37RMBLG?R0-Qf@&-^Lb@Q5GYKBd84sj;{Mv@W*HsKsg1r=6N>=HE(B0 zFN1VaG@z$Uot$++brO^BExs}QuY0KCJ|7bc`RvVcD2HwBc_9x@Z3VwuiXs%=S|^B=)q#X1{=8-&Lz@N)X}$dzEv z%6}k~*xm0X+xyLL_Nio9@PZdyLWIw+mO$uiTENZ zXbz<3WrLIr%)FaS!9M9gHhIix(FT=UbneCfIhzm!H9n~70-T9&ibr|9&R>ZcwnP2X zV*^qD^k@qAg?}ky=_X*xi+4hRLiGRd6mbB~ImOhUh28(*Io}jY`(v*^-m+mBimzZ% zh;26WdsPeML7lshjN?<+UNq8~oB#}c$TL1Y@2ewt!YjvS@PkugCy{)@7UcNo@H%9& z@Ee>u4A)AxhX&!4hY-ZSa~E|J%f?XY^2JNI1qV3E|Hax@MpfCpeM)zCcO#8-hlKPY zC8QBly1P51MNm>&Qc6l%L>i=|OAzU<*+=nt{uA$qnR&nHS}gRO``&wB`-)$T4Kew= zfIm#7!hB1O{AmPh@I>7@pym2x)&-aokeGhiLql?tL)7&1q-2~7ai_)tYDOCyrCu^5 z`DJlomds7ED3Xg@e!Dlz6Q9SXg!Iq#mxU!HJYI+c5&jIIf95n81}6ZdQQ+Ha!pu84 zwZ!0SJw9s+S1Vh0_+nW7XqF|-OaPtFCv9IMT7be&#^pB?p!>lHWjK9!KC8n*4i&b5 zOeyPQ&=%?&RvEW?d%n;JcVRhwCm`54e`#Vg~!d}kEImz!tQ(U zat2J>;32Rr&P!BA%=xKQKMLZ+RdiRQb0N9 zUkVk3<^vw{1sU)K_}I3?h`|ksZ=TjhvZ8*o23lxat!Z+eW;5eY!wzBv`~}6rwGOIN z$C@f4_{;S2Fs?fQ@A^1rhI9z;4TJcqH4B0WjO)V%(Bys4=5g_4DJXQjt|jLx&<5xz zy8N2c|3EXjL2|w#zIkE^D4kIefhPzDA~*cTUE8R7-YIIDv<~>9FQ#0vJl< z70m}xwr{nY4717X4{+=x?@d>l2B$&HnZE=;Y5LQkhp{9;dd6y!E2|&TFIp_=Bw+ z+bcCt+OmoymhYj zGlS2ftV!!qCk!R$tHZe86Sq;fBJviEO2v-Ov_eP9gqAd#t99UFI4g+t;hL0Oz{Y@6 zq>|;1NhuGxR`1Ff71W03XOh6R`VkY3OHxL?M1E zi=SnL#YSHC_U@lJa(})4sQF2AvLdum$$!_uKmi;wWYDO5`G4D}#O#WMg8aPVvKZhn z21A(Mc$h6doizvD3@NFv1674~;uSxym%^zMotlq&y7IFc4Qhm~Ge=O&T|ER(k%W1+ zx7Vi47~B&K-uN7#0E@==PJR^h$VBSk+iGLU#3y{)4N3Yi+u`Hy+K5}DttX0CurI9%`b*>-gg;mGBu(goMX}-FT5HqQ_Qo;U;*@2l3@1 z4nd*PK|?vZ1gXJ`_su(V(p>Nyx*JxnuiI`fB_y=VUfZ`$7y5MK2t1!rh}GZkFPYCC ztv?5O6Xx@ohRD&;SL|zY7dnj7pO&Uod$^dHHUgHKFN zax(a`+#^0NGk(~;W0QYIc3$$jz)fl^z)VH|86Y}6Dii8?bP&b%MG?S|)aZBLzRH=| z_rD?Kvmw^J5AQ1ptX^V8&x9gD;V&0NJGWh?ld|>vA$qNE`u2tz!NNr_wGSQI6b?B& z1@_+Z2qG5c0DZz`i`?Oo#EUCIojBnIjhAo)b_WNOqxO$V&{E@G_{XB->ovdbxZV=h zDSb*t@X#~CIcE?-Q}KiC#OAx#FL(&-vIh!3dw)sg$eZ`|8UsG(bS3^eI)rSdw%Fl8z3pH#`ydTQ5q{w)Qn8N?6*3cC+^DntS*OCcP15(Q2Q6 zLZ`=BMHzs4RriHb2laFW#l~l`(sbu$271O&h@^4=<=2RPtQdRQ)yu9O#Gd+g@nOjm zo<8o243H##yB&Nj@OJoCeyo;tX8O^Q+-IN|>(Gk-R9*XXk$)vmnAfegUfcuobr(iD zH%@{H>Pd^5j49csox0g^cbQ^ICuwYErn_=QWkYn!Rl_0CTPRxp-KJ+LfE-bemKkdf zm@n`!Fua7G*+85#wRo4NvsCgeH$(ZN;zaoOS@=f(ac*HwaoTGKkKUp^{aNb$qhdie zhmpJkr24||@k|gXn2hVvnY6S__BE-Y2&UaTJW-EQS+N2*xoQ6oCpUX^Z%D#!%9G>k z_Hy5t?Hl~2p9f!T#)~xKN}dA1fD?J=Ck_dJfr(OGlj8AoCGPYOhZhUyxB{xGSr1}4 zJ|2xmK+Jp`vvw!SAE!|QE$NHJV61V}BL$eQ3?IhHtB)MH$2ZTP$Q9ddHv7_ylrG4mCM=U&D4krl?gM8vl6$9Wq4n?}{dfeN zVB^H<;%#pOBy=*NCNnMPvaNyAXc3-G?7-VjhgEVC-=~W-^O&n@9j)MnB?g`?)hQg? z0htv9dGJ<`p^X+}6=2}xwLla7x_@1l5$)#U>H=f?N8lwDb4>^O=&K%IB*C_Ze#*}~c z)nxY)D}^mVU{AES6rdzkiyhDVt;b=zM6g>j)1}H@eI+K@u{SoROtP360WFnH>>^); z+BW%_)=M$afR*+~UrVhDyf-E zXBS)xY=0WM&5IY4R}g|iL4nZ7qD!0s*&-*QFUoI_%4)Oo;!va_&})9qhHih*ad zKEziiQolrjhX)+RV+Uw&JO z>zcBu-3;;&`S!twQoT;grP(W8UkGbL4_qlY-DUb;V&9!d#I6iLiyxCV4t0dNHN{%Z zh~fjl9=2-C#QNXeJdp4w#N15YWLq~c$n<)ViHoW9=ppz;W zk~otkvz=bqjJWgqqXP0uK;`0L7^}B8k$WPPp5^c%197V%97RMuGSJ+{6C-Z0qNRU} z$k<;|@F0#{sJi*H(iN)wJqu3e+C@KUQ{*sfruO?fS+fm(a3VqyB@t9%W&x;_BUqW+ zQvCsmaxE9f*JJe-5vSO3%hbQvO8Xr8$b>2f_t>M zM{0A^MY>W_uxWJ}%r<#A=~B5YIzL9hrc*TLVUokARpBSbI|Zoq<;fNUcsRcnji`7m zB2Z(m>YvR&qSn{LKxJ6bLr_>)sGs*z{*Gstu6~(L6`Daf!~Wbxg7f1~9$!7v$JqE) zxDs#3u*7$W?79ttrl-H0eA;=9Yfg2QmoRe%}c8L-K1GUZ`wd5Eh|Q6K+^WAj9hGBsBWhJ)Y%Qsu@$RR~2A&Y_5|00xsp?PAMOXe5 zB$`cp3~Y9owOQvbqqvwYuR*6Ceu9blS4y{}JnVTrAWO0~`HAnLFLabV4wSV6)*k*M zXy|1tRM#;`sfva1hs4elPJJ|iQXmOl5y#|slO0Mcuz1t^1hg<{IStkbWi@}yb zI|})W>E_7G_hEq=6IE(eJ?GcAV7?e*AD7M2dqN+vVZ&?ttps3))r0N{LUP6%sfo%8 z_pVkR=YmqNsyt$q5!nL=aARbLJ{z7*$@Ui$Ubl7I8|X?O-X7sRP5sK2Yo@QD|HclS znuvRWF^_Wd)IR5rAzEmp&66}gQHOs?|7YTMSL7;2-GhkTUKJ#?lGMEQyZ&{LK>pU5 z<43~yLZ=&n^K$8vG*vmnPQ&}_)m_m0Qu+=tA1o2^d|g6TmoG%wJJIH-N42y zR#h9%?uffiuRvHpAPuNtm1NFTIk|Fec-m#k&hAcC<h*@9<7Vd+ML#u4uyLBngj7~jNuvAxpmsr7ImPo04 zD`h<=byd#W(VZ^<1f%uqgu!^*UY7&(l$1vTSy9Fn%iOwf9;$=Z4+<+0HGEzR`ny%j z*d&|Fq7^A5iu^Y)SGgFUrWTBF#7_Y?;P z7=gI`fOPTGOhVwd60N1_pe@R30iK3wkgqTv1=EER{RK=dV+ZOTjl77@TE>=VN&Fow z3BvvzeGnjOl3N=_>D9a@u(O54uiz?={2Q;ctLd^M_-i(}0y{cOPry{0tqrJ&=T>)W zKHXjb$-)IVAuY!Oe2QMjTXMjiva~i`p&L8}_08S>b`fFtI&Og;vZsa`$eu|F;Y(Xj?=|+o<3i(Pj9!%uVE?pM6@{vLA_pSEl`l5cqJjqqn zW9Mn7U-d4u%`CQ+ad!3LVi?(rY#{Q?{aGn;VmNL`q{uJ$B1N->>3p|tTpe415(=Ol zapu8rt{*8DxaKqqQ1UQc)sBwV4}F&q$u~tf(xlyu)0-CX`#8(uL5J?e6FELu0|9Gz~v` zxsaEcB772r0GzBd)~Nz5oNpm|S~x|@Z%|^PZLZJreT!Bf`K4YBW5wYc|IL;oWbVdf zQ8L5@3co)GLi{f_7DBAxnCS=(%u~?HC<$?pXYT`USX;Szc)j(HqV5KKpyB2P5AwNS zrI%^FT^Z}rWyNJ!Jy2`dZ-%@HrS^jQepmawE@0@aqa&C<4?ZM;8k%9`ZdiKG95CZ2WgM1#X+?7z440n%d-q0$NvclZm&|gd*nU&aA$8R(Vl177 zRAfm{*ygKi-ykhxbgV)YbIQnRnU^iB4j=G_j`Bv1j(NV8nlr{NDE4Pb?tm34zEZR2 zE_<}*&%$!XjorcV$Uc_t{9ll8V3d6O%5~Yusr=Q}Ru(X^cBXWsKi2KLm4??n zW6o(oI55)I7z((dtoyP6U=K#Z1dbS;YMxE3u%4fJO>rD%h4`k)Nak!nYJ+!@^D+nx z_HL~mqa@icZ0dVe9Z?JLm4Am3RH=U_45%>7gS^Kqlf(!F-5G*yrkbMvW?Xw(WuK^s zzM)jT)080KwI0kLG-|SW`><&_ip^%V?_~-pUU4&cuU!(*l1p#H;^Mn->{k6$4r`mU zv-ZW##&gD(R{W)7>2X&3SnUEahUn7bzQ^EaiQv7GA3*AjI z$Y(&2W~SWeW2!-|&C3|=6yZ=QYB8}ax7~S_>FH*4p~onkQZqoUW2V8;JU!h>|MxRR z$w6cIcIKl)x4Dz5jj!(}K0LjB^T>&ZNvq06;n&?lNVdPX#}4@&A(^pYL9L(XD(XI( zJmGhI>g+k1)Bt{MQAYAA&R4I?YY03x>#pn#2celt(MQ$|1YlDS*eV%6W6__~ULvPp za&!eV7XA(Tfy8$NQ!Vr-FWG;8f&%e>5KM{H&Gppf%Jdr(v+TLV9s*BjA~O~A{WNIf z>Mp%*7lMt_@_3j@{pRKkk|uvEIS-LiO-C-KG0qa{YbA7iHfc7P&Z}9BwL0-92RD-@7Pr?}0+f zpSQ^S@46;8CMuFw0n(Vu`YUUmiXQ4od_uxernf$cUHqvffbR2$i5n!DOQ-&tLP}Na z7*a!ufPioWaP_ZytLgsU7hNLIy$tA!c)K2o=f6Lu2pxIq7=u9LHhCPkzqm2W$@XV< zne9iG8YLLZ)t@;>W!K4X8sCocptA61-4+n+x0xxa+<%u`i!0rnjE{B8w$zPXX^AR& zMuweGslXFk@XM&a29L_*&q&VT=V#MSt7lK!Lc`e&b{-4U}%(nH@W?hAyB7@uyjREfJ{O(;rp3GdFegN;@*ti?9VB0OPsVWHJBEr;X$t1PB z{1p4)_x3lX^kpgfQ@%;!(*B`WYvIl#7XL|8Eam@=a6G!2wEqDB`}2?PwgWhFxOWS_ zqWOWISp#;9q#U`nr;m?BCP+zb}oUG&BU&uUii4h~@8&r$>eLcAv~`ZZxu48O4NXW)hB> zMK3r$S~~eM09FFY+8B(#lqLOk3(-N9(xs01HSUzWIzEGetn2NSC?`|CVB(EQS+_M z>BxKhYFtLMQ?arohvm}G4nakKwE&>qjsL?UfZLBNzW(nDWGB+xodt%Ea+*fJ_sg?? z8yW3&v`+u^=?2%x;v{**V`m=jqG}78KQ9;?oV<&$_GhE%51qTe3%UH*5lUvI`7dvOv5!mSM3@M_aP9-V4HYyzm)1-K>Fve zU)00ZmdabePjGExV+{Bl6=!F+XN3UVCp9WGZ(N?te1u=Zta!Jqg0k)9t)DWUuMigV zZI;`P=R_Bc>p9+$&ENz3gWJK#=cvo|{AicdY9@IkcjRGO6*KPFAW#xjVy^%9KIa+D zUO!vK@csI^jt$W(&QP8AhKfL8K!={JEx-v{*ZjTFppgv11^dm=83TjtM7W@^^C@2_ zG+$xLa!I5O*L4`7_m-k&{(G&}COB!{oz{2A4HE*J((c=@rQ$Iv2P~8plwp2O_-Jl#`i^>4D zi0qwar&aNIvkL16+t>0WBx~DaQH}njP8*aLC!N=ERSq@rZkdg;$dS-(7PopgGkoLm z$njqq^Y6qEoTrX(<)D9(9d7x%14S%DKmGfs*x&xWP_VyA3bPxs4oQ9kvjQ-Jk_5sN z{V$&ZK(fo?y;}s{Pi3Go2a^XnU?Y%fpzj4B!?v%VOemBr8+-43`0WoXycGZaj1HO6 zo@mfSGTc>^y?Bc?KqR^hz3dEJYOU0p1af5fDSi2~Cj%O9GNWpcoixHJGVi zvgoi3Omk6z%wWYhzYq;Fgzs*rYK?d(+}y3-uX8>lC+`PFm)PD+X(KxKIo^FXA?QWol;dob2FaqopA6;Lb7OupJ#7Qdblh|Of)Pgyw7mzo83MwY}T$Ox8 zS_FvFqEA>#9_UIx1gZ@&d`&A3z~E5O$aO;7rH8~?y;P?h;**Eiv)lIQ{rOciCqxX` zh2UshbcSK%4Lo{dbUFi?ii*JAZY12a9^f+Hfw^7j1ra{}F!0|czP*{jH`R zc8f)9B492c57d;OMU)bFU(}AN=2f)aG(l*9u7^Buc4BpH<;mO}E5!Qlu@Zaq_Vy|q z$Ra((lAzP_JC|#*2aXh;uV_H$2ElcAJ_~T6lXwbg{@mh4G053!!WWxw3|+4xN2mkd z?QwN{6U2h07-_y~M$+dE}I5K~JBGA4GME+Y?x3f|hhG3<^|I^bk zi@7VSxx*ByfB%&F{l6D2_4`0{EkVKKwg*35w}#(~iG)>kG7r7`QBE?km|xVnylm#R z5-Wf&1jJUm&~a@y0EasljiaHx*$0HaQJ~W~U|#Pgi3rtu!f5uQR&%TQ^)Uk%-NpZS zEvy;{D`os@K2)7)axLAJPG|wwf~K2Wou}nMIycmfFTHokO^4k?wS2Z#;}bBKQw6~h zg#^LV($cc@@(E(~qWznipJztv!6vt-Y!uD|+^N|6HPM$q_Eyw(y1GE0Ir(oaw38yX>za4obfV!UTwc3jb(izwD|UTi5mp~6=^n+^uY=wHkw9{=57Ya zB}jp-w#lJQT?*yJ&1Iy^pwPxJkhCV3f-8U|?3Q1L<-yZeQvFTvbp?g)60ag``2Jae zOeYOOu{|a2Udy*a1qsGvwc$GV&D>)Dw2GkHRuZ{Zm@oE)S8kMMwWGmL>lgR4?Iq@@ zG-?k{MsO@?1IeMeZ5bYDl>g7kSv%+JtuqmOcoxrH#MyDG%V0xRS60xSf#?Z0Xx1D3 zo2NJiO4eT52vVB=w6NX_?3(&bWCfQAsK)`zHi`RoO1TBD#mNi^P^t>=W!O$Zf9CRWn3j4@#yXZ)In*#;kMkAQ-L`djn(0$gK@MbJmo-b$cm(q@$Th)giX zDx`gegDUQaKncY_l}lSwTb-Sp1JT_dA$Y3UfU2hf!Yy2IUzN;X83WUOhK4`!L=qpH zS#4qX`V8I63&O9Y+)K>EGh6#UBy9d`G}{$DD*sCw#+c0&Fc+w z^009n48x_ZKODzOEsT#V$OY zEnh--V?truKZ)O(!Djio`9DSmL?+KLCfcEKxnRAOwy4? zoXimYun%{xvsBDqrtqy_(^}@w9y(awv&LX&jZ1gX9N1Swlj5NkgQjN`$(N6Q=|$fzYE6*9N6t|x5}}k4<^O0AQgTs zm8_23tOl=Y8h=)QN&hJrv_ht8X)agwZa|MwNjB!(>-2~DoFk+DcEt|ByU`*i%oie>8B6&>sKy_rv;`IzW!~@F}6jFX${2YvDqxq4V^yONG zby0x)BYuq0=y|xVuJ~%Brn=guBVIPWN3qUHTb}l=_u2p`GM8bD z_qBesu<#cv@rwnan`E+>P-N4%6M{T5y&nIc+XR;?(3W3o^9@nSXqB~vyx}X*n{O%^ zQoV3jiF}?}eKJxP+28H-C)~LI2{(jvA|%D#U%n?e(Zj=PJ(vW@(aYSErwy^Ui}qCV zCMqZLh{ws8steEmww#b*_d}uKCgv5FTQx8APu#oDcZjVOS2Xh%rJJup#!zk9mT zndv(qKZC2AzJv8peV_>BX~&x*!Nz{)mbSn~NT4=;cm#_35ch3jAh0Ybx{7X4 z20Wat`+U|3s~EZq(3NQihlfvZZ>~$&^>@za zz38bdiCH3BsqDnm+F1}V@!xs4Dv>(jvxiZ<1LgZvv|cDtA%3^AvKj@7Qrf~7S}%ZF z*3qyG76Jy<*CddXo2KaHy=t3%`tf(c8Z&#GbaWS5GU?P)TWMmyd3#=Ola9C6RP8A@ z81A1A>r&0gyv1A~;wUowXO@SH8(32@m^+K8i?RK=~a{ntk=Pm0L-`AvaDJzs3Sp z{cD_Pv1-w)1#^Iip=PyNR(z5O5W?ZCGNi)JoJ^Kr0^6^FZV@6m+i8(T&M2L}etZRM zrGA4#*o*!}5bxVIu=li#jo;|kKtb_ zUrPb#c*fy9Cm7$uo#v~O#|jJ4OX_pyt*#Dczc(5{DF8T@%dC^^2DK40lrxj${>W8~ z)z;ZOp+TBIpy(tu?oVqsm%sABov6Vtb zUtS*3_uw;=3t&@t279DKZkkDX!=v!Z4*|`z)?o?OIC;tP_|!OI0q^@CZ7;@={p5q+ z;Vl6jIk~`|`0NR$k=sKX?dNP9NGIN#k=tlCTi=k%3N20k)?*67@LpM|iox?GO0V>9 z(B?x+Hjy}g6)XjxhBdMK_0qg7oTJinVm-KrWkZaQxV8gf zMUTg|jsOH4>3;MveFWx^*lFf5zL8@$0iV;VLYuQ-KomMMt~f7wh{kQ;H}rh>1>bM( zEPZd>csdJq%JlG3^^(@UY)1@Am!ZHumCh6fis?Tg9}MT!n?HY9Fy8l5*vuJKd_ z1O3jHkUq2lJa-4{bYLBT$phkPt8i>>b_f2zo@gK>_{fwx`4f#(R|L+Mo*z66b-)Sc z4&_g1jsyQ%-Byn^;R+d+gL)ARq$3$Hs;uDICil+5ZwrAS+%TYyFT)xn$~Mzt7lEDC zl@a==?CH1ENPc5HptLVtCwWgPALK-+6rQUuQL$r~_^S|CRODig{BB(>5(NoKDrdSP z7rcoK6=+1(UL75|T!1%%vhw)3I%)SZ5`k$rxfAkz{bpIqta^@kqM!!dlnUDZWt}&F z<|->XE%X$B`q+Whbc?n2Htw>*E&E2X5jv|##p`d-4xbKIgj#ZDcj5o-{NN%7s)~(0 z?dzSOqx~j1vJlS-R<>4qdHPAxidQ8MNRA;IQCLJ)cYy| zW$$`!RGqR6@$a#JZ#n(GoniJ>V8KTQhyj(nykD4QlAs2aGy~$;rQO=)1}Qh^8&ndB zU+mki<;A>D*tIc&^^&@~)%NN3si`x=pri>oRaSx#Z?p4i%klN>V90g-&XlTaC+nnM z1V2iN9vs74Kx=>xh3|^T7sYxu6&{6F>2BMgYmg&X7+S7McBzN*xRkCv5{s1sbOmug zy#$)FlRv2wN`5T?`UL^XI>2Vj)H>;dp=62{?L3;L;X~2eoCtp4;g}7&6lwj=pA#8e zxI`{siUF)1B-SJJj1w+fF7O*t@C6xm6)g|gr_o*oGJpGEryDn`n1Z1i`q6!t@d*sm zGT;!rvV80jCRvc*!roC9GKz-AVdDvL&ZA z7sFN@h(76tYnMQBoCk%%7tiLJ^?6|(S@`d(wCv)gM-+}XxpWE6yO|%*CC6sF0aZ<9 zR(AGWfXN<)+7|%*D9CPX(lQW$6u`5K5s2Re8Vp;nkVv>mbgbNi&eb0$obTP_mG^j0=g1&UFfN{V zhy;oI0wM04+%(~ZkM8!iAWt;8jFzluJ0S(ynU9bCsdMMNzTCH>dcK3^669ebaru+i zmw2QOn7Ed36d`Smy*Cn3T5+d*j=B|iV%Z%3>dlJV-6lY^G{+C+0i*a~#~$&Ey%^-tjx4cRVo-VmAi za8tOBYizaLi?iX}N6(A%cz3e9P>~llmn+eAh-ZT(aln@GuZe_8GFOLf^>cc6$B5p3WIVt$xJ&x)2*FSpji$`}8RqcHIoNNd za+Jg2rq9lSP)?}NZO|GxI&<>2on&IMZSGKuk|g|!3Wom4KNC7!1Ob-9-*x2Yn1HcX z)2Vv?%}P2?*H2uC)=N^l8_}97#F?wrca`P=&Aqh@rukAr92D1^0otbhaU&@yhna^+ zDzd6g(7e5J@Sn(cNz9wEuSp99qi-Nz4RmG1aCK#@WW31hSoFtZ*8T{BpStNs%=h@z z04RUg3c-e7h7DBEsm9VB1|-!`BvBVbEt<)YPR;kfuX$|rJ8=xRg=a60kUsTO4sFCq z+<07oR>N1?4n-nWMe0|wX4JHjt_X2uVV+P{0iz%ZA}_YxpvbMy*ef!&dsrkq^m^*O z8>t*d{rQB9We!{E_k7mY(o#@m@=?T2rp%8(mY4BqX%VHj8YF9RUxkdjGYXVbH6sf{ zW->~By#-@?HzS$eAjeoyb~X|bce?$Yl5#jhw+!48bZ8xq%gb5rS~(ZlZPpUn$$Qoy zke-iWxdic%?)KjACOY>E#iDWIp!gT9oi2V=i2h!~K4AiQWL zM>_Ij)9gp}V)LZ6b~q+a&c(!PqGUqqM%UEHiNAV|E!jT<_L$S@P#0*Ke!EAlN_s&tS5PgM3X2z7GYdX zG}zk?y!U(2jsdoMm@Zyanwmh)OsAXF?hNc!76vlG&M0kiSck1{kz#FF7sawu3H#@i zVwZC@{V*i58GhHQD^KJv-FfOA4G@%jF+S{!6~@yp1RB~{Z<>96q9`UNMqMfyc7}!N@FNvHosnOR<6dT9{{8^(P`a(pCtNv+ z7Y|oKaZ&ENcb)Q9NIF_!3 z$T1iEYJ5jFXJu;*O(MD{X^3jG3^Ckg>rTvK(ZK{^H>pqC86oH19&xofc6UakaX0D8 z?mOZ_J&d6TTUfaXbs(?MdRZ>Xj%rO!2wHQ#A#Q?fXwj5hs9U`fjK~rmZ}*G|h=?vt z(4FuV%A~OAA9pxvh>yc9uti$@$;grvrWEymcUKg2;4_afdf&WKjK``V#KGs3s0v28}p9CPJVnGGabq*D(G8w3d7yudbqm@ z{1_RHmDtuml(`r9_P{ngg+(Oi+-;_fvs#x8idW@W&BX4Fsfc9utvOa>}0sVVTVE_+L%_Ay-vIC&Q zdlXR$>og$kR(CYY10h*TM?umo-T7XVR_&Ca7Ue`8441!@Y(L%>pi6?}hzPL9ymDnv zJG)5V6weKIWeBH)>G6)EA?eO-AFY2+=UNiEiZTh()<_K!bpGALeQRdL6<+|ILia;oR!z&z5 zBwGZBXFvjC&?IGAuo6-G(gC(*sfVn{I{wYP9i`jNE@`S>Fu{b0|24mxU-R6_&EthO z3K4f^>n{%dQXcL^_YL~i1R(hV49Jq4El0FzReU!WJ=?5i2!4WRP+|ham+b()&qVL@ z!cfC7-l#zf9a0dA`Nhv^Mz|*Ui$+ zs8DupS>NY4MYmXKg4#a>!|4`Wln>S#d<@$B*2nyoBbhEd6?c*|!J4`SXc(BF=7nww5Y_9}MB@O`fW! zr(LoCt@E=;TI4+B*vy`V!<%K`Or^)2E4*4F1e(?Zrl=j0njP z3Lx^vT6q3u&YEPsbD{4u(HFs!N}gWaAl3}+oKB+t`oai)`+%-k>w!-AE~JSXSlSBH zN%Bgp!!?sG%meF8KjG@^75_M(V9!%-C`KyVa z)5n*_(_o8SvCG~7Wyv_ekKzoxBJ2kma-9}q(Z{iq6@esk%;oh1lew>HJi>>F2#GWq zby84F#Wl0|aej89U)4BQ6FkKaAt|>t4>{?nl8t3DQ)#&LM`qKJmqvV0$>qmi#R$2^ zLG^`wGe$CItzJX;l~_*nkP9Pu|2nW{jb<`n6{Eu_{DdOro6_3S<@w5~#O47ThrnCj z1hdL}l2%rTY4o9kR%Yhewpe>MWA8pF(K{?5bOC9>Qvw$GZ?{?QVR)@7bTku^kq*F> z6(SeA;afz^04VRsmt5vo7@&!K%uGklLXhn~?-|a~un2od@?qZpNagGX4)9cg$NU}U z5Pl#(=1+|;0{ij=gZLu$Jdcpy_C-R=j>D^i2^dnBl$>T8BGvc*jKn|3+=JL%WKw$l zlKtk}IfF|&?E8>~J6Pe;CM)ilc`!7c;t2f9?b99QW!~3hgr-y9kgxXCp7#%q;C=WM z?Pd05r`BH0qCy8Cxg`7E2cyMhXZ}wBVCv+8#*-a(8o-K1qs@4wzR zQvtnC-%?pN6ILuBG%QHpD7Rt%eSLK`eQmOa{GrR1tomSOhPIs5ryvBSwUso0cOepy zVqNL8ucAfD6c2v2WHBjk6s1tb$Tq7GR%nf@U4_WX;BXR*XC(M#Axmw-4uVBgHts5z z3+pVn!d)L)FUxPYAH>~!QO6_xtyGtD4ST)_r<7!h_}49-rFvOlQx~u+?I?|OU%_wY zsJ<{=zLE<2)PK-+ee&Am7j>2%ilI$mS*h0o(6+Wsc~0@U=|F7RueSu|;pq{skzm{G zZi7+zKzV2QOa}{hdPihIU+c6BhXniENOO<2r7H}XsrQEVMPyUcpup_0)e%TR)$A%= zSfT23^dj)FyJ6^N7{4z1Rfo9(90p##d_c>)Z?VvNo!nizT$=L5vHP(fo%#C3<7_o~ z_I!~>!s_JDKuP>qDP_Rp_WZjHTtecOFPaRIPWVIQpM_4Dm%rMEN(1nPjceZrSO|Cz zk{^o~J$`R5-+uk=e1(TR1aPDV@+05%9Clz`gZvdgRS(XR-%ccNjD6j@G&?)Mmdmta z9Bv)M1@z$9!mTKn9H0ZP(UhO)ls_)5W9`eG@}u}2UbF(@JBMXMyEPY^2vPnr?`@4WHdD-8Wja#e5&mb973r^(o;hnMJEeZCBhU0AJ~}&8Iq9su9t`NfhZ5 zy7@Q|DW2@3R=6io=3rz=A?k0}Mv)+VJ*5CD1PN_ZUCt0r`Yytr9vN zOvu{Q?~B}KUvB~NZTv`upUtHwrDW+I1GMOCgKX@<2NXcUZmZO{GjPdNJXKkSvEu{giS5MlgFkhaG z_`O`E-ugXE901e}DDt%XC^BYwdF=&&(82~rmfC5lP6WK_4M=>O`7!Hc_2G#vgEt*e zn-^}lx4HTop#KM#xeN~@Kwex5QO?=bodyAn&|@=S2hduQW;wc{BS&Dh_`4_eCxA%> zeNtKh;=WP32J$)@`r^+$5i*zI+^MA7AKjXOnv2E^!e6v%(&=oXKb zG6Q+{!rX|63w;foV_jJ(cpP;J1h!H5?jQtNxnx#~WYx`DxD_>t6?7SXsFz zDe856RI+kgpE&Gq&T84nVvNOkd_W+Esk0hDH^gab?GOiG!B)%4H}&*4Tg?mDCLdWX>o3_ ztcx^8g6#$glRO&+ZXRE?8Q7gLg@gvL+Ff5nQhc6xtTygXS2{mlrY*AU+4=raaidPI zEXopjJa-=Y$2@2q%NMWc1H>S(oehCrmFz-8mV2ab*o9iApvKR874JiZrFY;|-wlb) zMt@eYZG9;Q>$tQUmo>cvPo^SL14Qh+Pk+HopuO<-9J8_1V9@8h3e}%A8AN^6byiQ8 z`I-3XrTfXx>G8Vfj|XK_@frhN!iDbTYl~`0qQjHGml${q>Zwe$0kmkD8Gol2+ameO z6NV(kkVEkWsTYb&xJBP;hEO&D>G=uuu<7$7bP-H6y!LaObBSApj*#YzpPcK*>FLB@ z^pd5r9dv7LxP@Z(3buh8E;eis#&JMSTVt^UHF^*4I$Mml_N`1fCdx$ck4M7rk#LBx zd!QLX2dT8!s=n6B+Y4|h?;>550Ap0f$+`H)IAndknvSRp$t^%)EeqQFh!SQ^K@hz1 z-}{8*!i(on7RHTQotd>W{S_FK6r892{E_ZXWw};M<$v{ZVs6Xvqkk`P3U6-zRTbhV zAM_Y7ev)7Cy`-o&!BLe?#qj7@njg%rLrCG##^SpGWOt#VhuuEtL5MSDR$nuYK*`Mg zG`mrP9m((TYv552nf(;Q{r3oL9Lu@3xBd8p+_x~OE*_Keq;oEKBZG%|7y-{pTOUGvv=UvGXl|XTcSyL9*kI5rad85|qzwYz zuVE|dAxSwIaV9t|vVrZe)-peHYwFGjYmZ?S>_#&ZD*js-Cb@wl3FYgT>J{p?(l^5g z&t~g(@X7ExCz7sFee1y*Wqd#|b)P6nnKLexollq8^9eqn?>ke^`DlnZT0y}=E|_fy zvLUYMuww&oU0PXuL5WzN+|6&_*6&eP&Ag%rKJ2Nv7b2Mq<4itjn~o-hiO4NL4mSwY zcB{|QqP0VUE*GlId%FaKyxwGZ2aO@HAeUHkJ%R1!82EVh>tIksrbs=fW0|s5L_4CG zI>KaA_wB){3cqfSt`EN>ti%u%s&{OlCtAObPB1L)L67iL(9m86%8#()W$+r~oBok= z3uft$LM}q>`t15=PT29Bd^qsTV!e6YHB zuuGz3dsCOTjxel`xs?@cjGH)L65hIsTL@A}(q-ce|M@jISe1$)c^RhAdC?a`bwN21$zAERl!xeDY& z4OaHnTJum+LbkWDJW@oQY7kotsv3LC4@(LY8z2w;v=TW;5QbNQ-dNs4EK**p82$XOuLWL%q)-AbwAAEp_iZChq&`K?v6+2^&Q^fqT^>wwJg8l5nVrvU_LmttK9O2PCzD2CIZy&O zb_o$I#QHq?;wOWS&Pou^1+VRLKG!YC@ra<3`aoOjBbN;$chqVka$1cxH-`>^%qz*b zcGbBh;!G#7=G$2Puh;JAWl`|X$T<8ZHh7)vtdxgt;4WBb{6u@0$S*G~WdG$S^zA|6G^9|g(%BgNHH z`VAZ&+EPCIqagOo3Sc{in<>}i=Xdd=FqG~?$*n2lM6JzyCYSpZ$-4MJVE>{|EXD59 zPm;(_+(ej-fYwZaxy$O05*vSWZH*u{#^&W_MJ3@UDmGRAdioY_+m^4$bL3*$>jiwJ zA*{xZ6SkeO`>#iVzF2Xyb|Hs*K%i=pOJ4SzU5(+5lBc^?FSj3h2H#}t&dkq2{KF1L>t}!fb<<=@o@~nmd-|U)w6y{ z1?crgL9iV}(2k9@P0ehR-__(u1;n#CzZN;LtD#gOniH;~VWStE+W_MYX}Mw5Mg(WJ zi2Kx9tidH10PJ>+AgJsrH9h^-n?rpX-T4-@z6ukU^WssoTVfjZjKko>$bX~&47u)6 zJKX09Pf1K!qpKk&swC%kD2XAo!o_?JT{Zam)S_w042*BGr>3HUrV8Kd$5VIt1XU9c zNw{LIJ`zpZf!Ih=8`M2x*+^4CAd+Pq7sKW4#ah=JTqxQ}Ffry;^6?Rs@`c|na=?I(-I_=jr4P?n-_!35G3Ny4;^n#bEi=T0 zT{bI=y^v^;A23y;E@h+}K{};FxF=qhQr}uQmb|w z&L9gkx_y9nrB%XZ@o5M{Ol>u5@2v66MBD(85Inf^+alJ}$VH443Y94CemxC#e+5Y`HOdO>8 z-ISyjnA_#(TF)T^Y*1dO05mwDZa2lzCM}g_8`?d{U(^UOiV>P_ydwE|Jv|+p@tu!c z$K6XlVe<9uwKp&rr1%6!)iX{<)5cdAcH#dK^<}f0t0#t5GyBb5hz#a2H&f9JqD(u^ zIk?D#>Pc_j6<7>lQQdrXNsK(K{BpCq zshOXAj26nxfD~0DkKY^ZXHW~Cv|abP@APFUH6E_p?Bz(*6BEdy8I8DFgq?zDm-4lf z1>)!w7euIl;00>bQx`g;hz6&_Z0wTw4hMSe-Hy>M&G_Rej6UaWee;MkdeRRKe?CA+ zNJy+dlYie8@JDOALpNamk&W{&h1F@mlVf%dMTYF3x6dsX_$knisdp`FBaAb zm!R_P=Li;TlJeO2dM`W=pitd9I!FrbG{|TL!_UczEC*9Lo-pvezoQ$KL0ib9I!pc( z-lE$j8vLImGgM^mr>j3RO$niN{$I`I)kJ#~Zmhq&zo7qP{IQ~X)29)jv2LL5YklMs z60|h6FhPupCSVEGJZ-=hakHxk3zpN7kbVWTrfj}=I>6|4jwVgNe-3!2PdJ-Cc$TyF{t$jxkw7h#n%bMUbvVy%OHi^!2|lN5Cn@9#X^RyWTHuwb+vSG^H7aopX+=r?{KJG-#F^bOKxm)Ku*F(P z>rL6aP*nU?#^DDHxe^l<>7qA)Sb5dyzx001MrBkYJei2pId!QK`S_7Iau#-||DV=N zr+uQ;%`pcE#JQw<4;PK9ied_7%k}$Bxh{ll`LZ_K;hE}zh9gb=E~eKQZpjsx6w9ft ztyTZ-EWaaVM8+bJiVk&~M{m4yyo#H<-^EJKKKObfA~pWu-!HnG7|}8>;~olnc_9tv z^t9N#;(xU%>Q_{9OKU1J_WVcKQIDWP`_5(cpa`)!8X22Oybm*SktmtFoLNiIo~C$OFS8JXFfzZfO0p+z^^#${#Sl(;L7c8&TK$g)KHu zK9xZKMLxHpV#lyHuWptbK8)V=I=0@bkD7+%x>(keQ`xK ziNc`J+`Y;{q8Lc%o=ZHA1~^f({37K9nt)J<2D76A8L21=Z(@O?1XZC0m)eb4rmj`APPC7@&}G!ec_=$i2atBIyc zgIQ$gqe&&1tl-0+AmQZs>Y#yK5?1_nI}Rrit+=ZneGB-5{@t>}HL)6)_nA{ya5-_*sDlu;TMOhl@!El-`ltPwO!cvNE+P*@Cg zBouW6oG>(`dt18VDKSDVe@MQ+JtXND*BmtC#49x_$Y)m*Ns>XsX=v-yvHb2j3eMh$ z=m`gtqhv^^gp5O{J2$Bc%2qHCH+)jn@Qr`)gC75u;YS#B>wLzz$PZ7z$Al27O^`TN zDGd4&3KQ+WcopYfl0j{5Q8Fo@SCd(RSEcJ!3E#De(IT8|EbILX4-SA~1BV|IGjovl z*7901@Wy|0qC_iZ3Qs%KZyVkh)=7@(qXc>3yjq?nxVp}9XQY3#Ei)ZXT>1$#IjH!v zspAcp7L#pK!m!Ey9De6EEjRMUlE(&IQ4DIE1IG^5JwRYpP2gJmEt1Aw1;SD znY^&`PTtI%kZMYMye9byeHUr&I{sttLUmE`LPG$(p=~S>xAsK8Wj6HxgrTSweRmA$ z#J7)aVe2maIw&sC)7dQz$cd+$?51Y(Kk@`0{>4EBh9aKWZ_T!XdB5WtMtQyvv77J< zTsQR2GcHdTs(HNP)_|$(ejY!60mcdy3Q~QYJPS{S+_g&v-&gE5^1(*4ef;XnKj0$n z)MDsNbU6c$!s{pN%a1*IzMQ>d;E>Ny|Fr0`b^*$6hPOBjVCTnE=D!tx21}f5@kff`(qO`en)$c8af|6}T`pkH%089ex*C3$p3E^K~RjEH@J zw|j<}o;@)x(=853)%I7HZ+t7G3>Qe8_({hv?_oLT?VkF%7sK+`-cr|x<%4l%rLyPn z6&CF7vR((;X~sE+hC6NJ)`K7J7Ux4e6T>&&sc=q{_fd}1&s)!cfK?AL9wSV@=2Y`| zo#lOyh3JPrUN3BD^~6wU2;X|_%%*`FGg8ZPu?AXXAFu9DhmC$WL4pTe1k%%JcnuM> zhlQw#qBXa)t=U$1{bKp>q8hh^ERk_zyumD@9QeNaV6uW!4Q8j^BSYsm@-Oajsuruh zB_5Mr$v3gW!wd&TzQ=DwK|Fb(qMezG2**(QQ*D=E%Nu}#@hq9B;$jmU*5#*iB9xOC zNbD|`eUU#ov4?i1rcH0i{&iLm0no_f>dwhT?8_*26vDEiGA2g#XKk z`R2zh!ls6+9w@R1mBiWG!ij-C7WKiv9bvaAiO-T-+)gvCg!~I#efO{`~aGMgM z`kidQK#xx4y~o6uns3qH=0web=XTIqxQLDc<6rcIc? zq%RafpG4`S6nD4PL6v6j9df8q;$;he=_fFiMu!9Err~$m*;mOD{nHF{*_?rI^$X#ym3a738ZhRVCnDT?D`J?F(ooncrgJkhEDm# zNCUJo$cx(qH?Q%gNoh@tQ;i=EQLd#ozN{)MH1A&(_m_Vy3cZXSSLz zdB3Y0y4`D4^Dr{ifWf;I&F{XMAaWt0%TqP^gHNh$skrif1Iay;4e*6V{v9%CtEJV5 zsC|`3vg5p^&9RqZw~cyC>+WuqHMYqgZs z?DeN~c4tnWoNzdfX9c2Cj*}>Z>RANIcEjtnVJZRpT{5Vc>n!pEFH*DK?v!3TGY-*A zVaF_$mq<7J>fJsoNlM@5IEXZNwCx%|sOqrQ6Ai5HGzs4W%vHiR_sVgBGnbP&D!-k& z*GQ%cox5-6WQsqGyd6yAV$&13mzN}B%*Lfn zZ5q^x>J>7U&SU;5FhP1B)qtJgJ90(>S+faoYI6&J?PF5*Fl$&6`|Ry&4cI=aRieRO zY<04=Od^V}0L_oj0pdMww~1@kO1JSVD;q#Fw0nP((G4|}^c`j$=)LhIu0Tsr>8|RQ zFWAZPZeS&as-_CkKU*C#;>CKj^uZF3t-lFI_kpHoX)YG(bS&e)7<-)HC(PjgXRZ+? zPXXaSH(Cf0h+h{BM@*RqDx5Cd20bPH@d^OD#lVe{eJb<0`g37<3RSyE@a8GQKWI}ldb zV^gs@l5LbYF=u_T8v;S;p(e^c-2DoFBJ=e8Nrd-@C?QTkOiuyZ<&-Syjjax&$YXT z3x|unPe(r%No{;SZlx$C1z_*bAfFWLlcw6g(?CLjVe)d{NNKH5^Ym;%Y1Xzipi5!% zCuhf>x2^y8Wf9zd)`p|~^7vtukNWM&L%i1)?=eX>sdlmwTQlu28_wBF)tUDVv|Zn= z_B%W7&1z&Bj;pivOCL#@B7l-#leLU9NWsPy8HI4&xgmq z#M+J&3)I!^vTBEOAvJ+h3QZ-2ug7zKIu;$?jSGHsWG84eKuUk7CkJ0!0%7&G$PA=~ zx9d%fi?=d?`hzPi7oVMj{M+_A)s=I8aa60w^T{l8cm$d0beAK*!S&l-Uq_|nO4{Ss zIZpJ(Vnp&JQoz=XVDJS48u=s*7^!Zn92&_K!0<_OGA%FwfeT^xvkE8hV^ zptmgm`JN(ZZA>3gK2E5^bOM;7$)Jmb>*1F5m)VeD$FT-@bTbM?(f>)yh)`hOBhVNa=F*%?*!{SPRkMP|s?9 zJg2+0^t#^J`a7DJ3tr!%O~6|$Jmcwcv$TQeb`niLvxtuApeKHj__Sdp{z*&>ODe zCxuGc*JUX|>J(RtFTRM0O?6Yt<<&nQXJSI0l49LW<23$811&Rv?T_`b*R|aaY2A#! z+kEd(5RY(y!{HoRUDq)}{I@D8t#(!;*PKJu2}5srN)%yI%P+l(KS!KQ(W}ZCc5=$e z!aoRdAqwUx4rf0aD_f25!=-B1g51j>q4plEpzN6q0Xh8CYb2ztG^e+|`5cdcxWoYI ztKS$4f|5chfsR|b3K-SbA?_ORpSj(%cY)n{DPI-Wagpayk zV?Ty1r_nZLPQb3`@~DvXyNn{LZ?o^A9f%3@WYrjC%PubxlJvyu+ovOe?mfIO@tk+; z+SJ!UzsX(u_)|V}<*MpO_kVehFPoKz<9{DgY9xD9Im!Fg(G0>Q9yL7Z`5$-|v_#LR zxE%wu{`cflp#@{)k0~UyWDV7c5ef!XBR!lHm=$6S5E%K3CGyApv*H)|*^_dwj<0^j zl$S&{=i!jC|Swy1%X0DBeFJ*UB|HV$^O` zCC_T84uW=gIe$?;eGC%tjS`Rk!2%XR*@p>Ja=O7qu?<7JfKU1%K%6>SqUL{^`|m3p z)=aTkdHb>=*grn{ND2k^u9JH`iPkVCWP^BRJaG*p80FCTduzlK0?AZ$Qxul4XQJ*g zoUrxz@}+9$eUwlQKP7gxy(sB^>ruIXST&7(;;HoY!&|f<(4}5a}4*vFypc?ksnEGdqrXBm>7$JExP@~v%Zs-0;)sU^G`>lBS-di=1 zxHt_eIC_kbAz2lO%3y>?uXgbeS^FdlKsVzYC+GI}^-Qfn$@-uMU%CdShH! zVq9bQmh!-33&GuDSjHmt@abT87V7}nPZ`+2*rp|WamqwPX1cMJnjxa|>7${7x7q%F zO#7%~eJ5K;3NRf$CMLw5*dw-&%c;fk@Ln-CucIJ{z(%F)+8KQ}%l!(gXwH&(qW68E zbs(!gXSN%c(8G!ofyofyF(TyoVkApQwovy}r>c@`P+lbehf^DO!El+{^+69h`~&(& zp-Gcc)ilnZL{KwZt2pIpCBVl>&byCEmX))olF612hshfRiz*~`wE=^zA4pk#4w&b% zL1q#D3*JfZRG@h_4+CX?fis_MUjSDm>=8Tdn@46X{f7hQusnC!Qj698(eB4ZHz2!n z9goDY%%&Uev;XVPP@MoOsidHu$eq)p@x5V7X;ye^Y!(dIKPSjuR0EnF&h1< zp~LYCZw9k3DUA~B8_)i|+S_A-e$*^o6MdY}g3doCk~bmvtX@ESzw3~sX03AU|2pj% z3H7*f0z`pY<1JaFxC4Dj5eCl-t2nY$b}?_j9>h@n#~wsuS8!kCp1MH;(# zy7AhDvWnzKTBylJ@@t^eLS2`)1^>II<+=6xCSFP^u-~2a?~T%pfCd;OeQX+3*nWzb z&~NoWM;&OdqVbyIw;z3&^JQ@uhAYl!tz=(eY+$pfZ?6O!=x!#n#&|AL+@<~g^k+c& z#nJCBP4Db7-3MhKTywAIFM=I~Qy(kd!w%zcsC zNCa)Y&5IU_ZKm0eS}J-&VSG+a!4Nc}B;sW?48hCSmat_&wqy%PTno`4gdzl%dZS3| z8TmogHft25Pm(m{D*;bBs4Yl%`{|wh=j|ECH!ho#96C~orF*+811b6?UbKVh()p-y zu2HFbggHbP!a2>d#JEoP!|tNA!e4TZs&RWNA0{jf|9)FIIj$0JGuHz!ElF=}qb9)e7 zqhIf28X~9qo;6Bnxi|Z8Y>Go4W;_}r85m$(o)qOT&{Z1mzU<;xfm41qkPP~HX3HyIFt@Mt0Q=K{uX^spZ;jv%)Q zRY=74MH!@sl^vE1f8F}c5e#wt3PWxKZbR69BBYBmYEWi6g44LV!(J?HyR{NQr;QvVe{2p~I+MNqw2cwgVU<{7^J&%NDP z(+ZUd(EHyOK#g=^X&}pKIBSaar;biV(0Nu=0~Y=5=GRF8giQ2bQlPh@=Q&6Gqew-D z3nEHME@^|ZE^*RVwj}oOQg@r}nQJvz`My=v ztSORG#>=oSL)$f~4s07Az>ol^G;bM$%DF)FB(vvSm*yWA^l%k=Zu;FnW^Ye+ey~-Q zNtcAj;ELOPsx+<7qn%CRLM+lv%GrH#i}F}vlBEkiWTMgGGDsHhv|c}z3-4q>xD zIvFlQn9KoHFX*saqD;@o09&>?;a>ae>z&6&KYF$yJ1DP>8iYLh zCcuoeTuyO+q!#`}{Et?i#7qnM02U2~Y}Ri?Wp->YRqTaTs>@2KK;0(=915KYI}L^W zI?kCzshqSWK^$b{R~8eC^$X;qnXK?$Wz^rnQRpFxBA-D62B%RK&H4cT*0WUTeQ_>C zhBck-+CdOY*!=hx!AWPyipf$qx;w2fn*+p$`Wx=3H<$L0ZT^xsQlsQ612cz3{ z4xQu1+`XU!Dx!u>7quV|y2pah2{|VwBEQ(&PqHwEp>n^B<>=mZk=R-GNO$@cs@t5cw z%pQBMJp;4ow3TFyV0ULmpprNgwxcmw_+@CrIE=pybJoQO>3vWy1e{6s=nw6WU3Eu- zfD3Rn*Z;y*93#ZgEa)^h{VY%ripU}7G21pafZ0&kgGD>W_Is=Pvl!cm!pw8-%q}Ynca{3G26^oH~=x~=kB^{$R zQ_SrQho?oR3-Vht?iPfcVClwr#+?(Lx+)Nx^9CZ-y|hiVv57`yTm{r5S$;vkSCPrk zA(_874G>7Jojuuqyhpv~Xtr!MI``S}K1l=0z&nN|D~(Frb&dy!MbXf!3WG9-QR(t3 z28U1|0ymndv2h!-FDUz)x$1(JMMLlYeyFMpQRnjTo|2&JB&0vwMR_TcC3#HqWn7>s z&s(@>GX4K>c4U~il)34%o}+(E-ol?~O-x&s2*G>Fiif->042z2z|xA%saZ?2?}V}o zsl9v6Et&QPcF)TUnZ2z>^d9FI2&n;!gSxUO?;XC6E%y(;&+$KezjQ)`E8wU?9Bwy% zfOFIxm)@ts^JV|*Ux1$)=_AoUXy4#YWLHHJ1ZBP8uDSa8BYIj0mo#Ld+jKlg_PIR<-~+e z3!NGFexr_NcAh!DDuUi02Rc#fr-88`mYvf*n_fRdIYAC=(wvp#RaRvB1t31bJf2fh zt&kt}8>yE>8x8AZz2Qf4;~`=q$*a9CL9cDd)GrG!xs=s-E);W zjs`c%q@1EIqygz^_0=^2f*DMRvyA!TJn4Z!+e%a?^gvTD}RmEVJR*jS|x4_u2eiGJJxO zxlilmqp3v#rX@`0t*#Z`cBc!OuK_Q%L@sIE zu*er(8-{G~DRF?OWq>6Lu(p|x3oe3>UpA0a)CUjLs}u4X-hZJA_>@5oIk_e&)r@36Artkep#=LZwg;;_`Nn**k=5jUoH<0!iuolO+07@2 z7_a`cQvpZ8{ByEHB8vVl*h*RW?@RepRy4P;2ngTE6|MpIBVqn8p8%s8JB`CuCdTsp z)6+~)E> zfPF)n!NNZvICb!mZ2QiPOZnoD$=`I+MDtbh^rzAa3;rIx|8M+Fh7kEwDlH{%J70Xm zVX^P`LSAu)Rz85!WFYU>QtlLs{r>^>BZOx2{{i-)`G-2!rB<9D z2CsK{$zMJn5O0$9zCYrrwVd}S%M|F5<7RD&PFXK$3%6AptU7%CPEO>TpZ>-7@8pwV zGVPAsM0b2XJ^n{UD?FMFL%3MTcP7U7zz`CiOiW@7N5TK%v-38($>TS%j5hp3yH*1M5qfVG$q?J zeXEuMQR>#|N{M>E7@q_dk5ux4JveN3ghulKL^6s>9w=*Rnuv+L9%vr#8knu(xy;Q8 z07_`_y9JFiS;Pv%StPrwfYlRZltj5#_#r(Cd-7AJ0f5b)idLB1OI)6X)+`;Y4!LFx zS2H)dVJfuU+I?d|M(S5f>CQUNdA~$CxD0bmVTCnRKeQ2M$H7z@`~|`wvS1I%$|OO@ z@H?|<_-m})45{--dfoTKD91>(^;uel+TpIdb{hiw`+X1vIkDy^xuv!hhIcVP_0QKN z6FVdDX;lp>429NN)1;9tf1-;zfR)-V=eY<`H?<*7(g!<(o9<%*xEEO6P2T~jRg_Ayg_{X(O0T5A1gMAy4Ql9_5P5) zzo1RO_^(W&7h;-A-Zf0-#;lqsWyP@g&_;>rMRju(Lg*YRH2zSaDX6q6MGSk5SI;p{ zAh@Q{Etz0cpg125zD8mQBU&rsnSMcc=py393KoYNJG~!Xjw7(SsF!vO=_Ft}xK98% zQMgr_8tEZ9<`Td^*#h56+V3sO!n_W$e5EI`lyR))JCTwCO>fMqfm&O8oT-TbEhz&i zCFE9gSV9S*dy=xmQZ_@rDlj-F;(c*BWq%6;d&t9g7x}j@2D&L(cYdAI$NP~FVy(&_ zU-g`p187RN92xzXa+p?IBAhXxv;~5<@BnTX9$Xr-PJ_EpLafE2TQ&EZ=>0gF^ z?zKn@b+pj*65Z&xaBMRE<__@bC`A{4Yu@BB(6Z)%eEbHBWD#}r<2m>a9Sb_`!Ir!@a*eN+9)n?2OsD2V@F-?dBF^`jd(I4ed)f3^Mh z*}5%E%@9Qn020SEtCo(^B~*AueYb+HUl9H!IufQr>+8zCJ7b` zwgu^AOW7fbmxQNDTh7W=E=a#j@}&aKS`%7r*%X#2`$fmHA19cARc;NXPl2$bVEUI` z2#iHPNT26~5B>qp3`fVmyo1!vyJm>XXxyT!^z0 z#tXNrblBO1r0-$@SBEMOSOf&-LH3Po;hglHFaL-}+`!~e=@qU&l;I1I;{8bq{UhhQ zID+JywZjht)k;DvWOYDTQ0vw+7<5%g4)jkba-^i;1z(9R6el_xshfMpG6mQcy=wiR z_pC5VIHv~tMDVTH6#l93aft`<3FUicwBx5?2Wi0|>+P}!qN1wmHev-RMUTL#OO)9K z4MxAwBLkFQe^LRQ*hY`dHjfl+fCCHj^nuV%L`{|B?&ZcK=vGh@Eb?@DoIKf{Zx z@JOHyWVyf(+_H}@o2x#9ZHNY)E=}SV)er9=+6ng3u|5VDPy8kUF%KbhrTeyLgNKP3 zVY6=khR<{baC)Uu#zVinq^x`C)hRdHWmhc1XQu#VGxx6Hr(QQTQ9tFac4`j4Z49&p zXsnR=SR-{PEopzX%& z<$}!PfBX|+iUn3cU+6^lvqbbqYc9p_pNd#nkY(I)+b_#^5W>TMA%sm0wc1oAFx?1` zF>z_K(`VzSJUFC6jxI3vpM;WAlR$k zwgkz1#glt_?!|hkIe~W{`xNTGG=d8mXx@4owPKt0gCOz)$%H|KKtK0x%V9jM&Si0b zyg)V-O|)H;@kxhXgtwG=jTbkWRUfmhOI9RvvYtdCWMWnN!vx|@i?}#VV+-#JPRZBK z7Lw0ypJ!VG#OM7FM>_YvauA5Hb|z8VFs<@}1mG9t{mq|$h#GYvQD95@j5oZ^HQJgk zodt_!PxE1DZKAjq9Z}yN3V_>%nTDWoOVZLk_;rmCTBWRnG%jjl(ue%XXzU1=TQzmn z_g60pAfZ+BfP#1faePpT7azz_D^qvx8rANsH#+5Pd0#FZHGabI639J%Q+XA1-;?#( zMg&N6l|O6Q*oNJ+diMKUu>${mv-jgk&8xCbJ|g@WW#{b-K2!zHX%K#lIU4&mIht=* zSSiE>`CV4|8?jE~aTPeabkpu!W6CE1Sw)MEq~17sC6F#oxax8-5k_WD4nKI)xqI|m zPcEq^{*0LnngOxSB9LH`qjrkFWuVf?>W!elLxSv#xPHC7=ASFjUl^v z-r`rfDvou(?(m&OQC$3D&47FH8`?&)rq>|bR6Wa$8DU}XyRAz=4}o6GQcAp*kR=R} zIdB`C%1@U%#72@Jh{W%yfy4*Czm#Tmv`i0RgMuJyfZ20JX|GtLQQP-WCt{xb`Jr}x zC`+Y&^4$gVnU7*8mNX6t=D6b{{`1ezlb9H3vnp-#AE#plRAzp)r(9!X_br|r2 zV@RY<3+Uuz)gE*cSQLJB@)DnEi{4@9*W0)HFe+#CU}SRTz9bWn6>xTb!=rRqe|wL$ z1ecPxU8u|g?H%{iE6oi=lw2{)gNkpikfpF6a+^PHGU`}*>VP3|o z0oa@?RT??_(NG1YEVl1_Hoe+=e2rTIejxW@JLJO|b?@_+FJaV9R`YL;chj6+_fQ*? z@I(s*n7i+>EZ}H%l8PSKjtM1In zOd5KkI`}+E8thhht<9An-!X=iV-V03-)A1fR!*7Hi4Gl1raPWQmioZ06u~newY{&=AqQ5EQ@m%&sX?I!vVitE2NO5GJD$VG_+js{G>M;We^ZC5-B>%vgp(o~Q zqR37QARa9VgxiRWyLG=JZwdZ-M{k5hw?paI3-L{TP9IU+|F*?)E&Lm%hIv~FD3CK~ z`PkhG6dUw+PAU9vPG$cYlD$2(q?-yEIlFoI<#{QzQCMuh2VL6N3Aw#o8Sz0;6oV>;gwPw1j?$$vpw>gZLVz*f z5sI-qDJU}B8GPgIb$}}@G8NLIotm4D8>mRsT}kJ%2VVSi%=)*{3W(g+&&hSl!m5$G5%MB`qp>oG7jqAf>(pP(-8}$^Ap7DO1$-TNhm5_bc zF3BzzEMJ8C9w$*um6V6^;P$Q=JVhRZA3w@|rpA7GJY%4nUVOeQnq*m#DhE;c9yxLd zW(Zwt4?^$c}2p%WMu<{{e`?MlG!l>PPDw0pd;{T(&@O`oVEZ8@#d)E6%rk)_q^y zB`_@U@r6s(WhIOJjvf5f;sdvH2-vceaaSVqB2RWqqKGj7h zDKJ;46Z3bJoj~ma1(cFY*86LL?CUxlH8fOsZ|Pz312xlVp{UOz-x6sAYIJxyF0%R)jocNPQGsRVrz*5#$kRC5*I#Si*G=&O}_`&_vzt&^MO|}Zn zc+i0%`N{l7-mB`o6P`yhEsD2Zx(ziS3P<@2{iMfMBm?>7%5Zl`9j*(%VR{Ni3o#WW zL<=eO$9WKOetF*5<}`0&m{x8}-p2*TN5#p`Wx2nw`{r+O{gIXFmk|f{y~=lLT{WEH z9(MXu6iNSws(KBn@ctIMN;xCEDjd5sm$OKfz7J$R23^hwyo=8ke)*nS2#Wf0kk@_9 zeDY7z2~(iI7D})-RsZbjP}<`@`U`;LjBF65=)m4SP$TF2$jnpxy0n!rj0v%rSsy$V zVg-S0w%LuC-y+Q+Pw%D&1bq z5tg1Eyd)W^TZM~;Ogg$FY=up>tNJD3bnQ%%AmVg$8dd4(5p&S`W^8WwGn|-p&b*IK zW6w2UuHn2I&P_nqO{D}`Sj*3;_GSy6XAw{1cB$DysJJ@=#sSmF{uWf zXRqJDz67`&CxP>N*y1{jEUb{HFta&4*>!=wp?isjpf3u zn}TA!2Kt%oBOULfK*J)YuWmCvOmt0x6-{Rd3z*u?`e1>M|zdyoWv)qD%yX zh4}9g$iJ=Sy}F0n=PDvjVd;tS{l*Z8tfd){qC?z*IMg{i9vv--)X5>;TOp$CEUIJ! zf-e{LFagF?75!`3s8IJ7{-u>s&1A$)LbVE;Rt)` zJ&1IaxAU+-=EU1&j0KQ1d5~~0HTbC?IogHcabsEN8FX9v$q%a%FWZjuCkBkEs-ZD& znESQw3WJj$sG?8Oi+@g_5-_|HN%$<&)|=5eXC;&tDAJuJ1u){*OK*&6F-PBZEO%vn zmeP8K%1aUA;($vk(4|+R`K>&y;>GfZI8^(1P!NvI_7voRyqlFKg`>xx|HyzCmEPM; zeI74BpR(gc7{v(EBuF&}8JuNDeu3_3i(|o?Drm%m&AG-Jh7i>BjvaxuI$(j052dWQ zXMH8hVGH6$-|co$AswGJdz2uuoqvrJ1P7+qRgg^ZBJQ z$kA>NQSEr|kBHi}oZ4;uz)7E0D%SFG~pL;u{RM&q!gUhc((P zT@}i>ou99BzzV7rVU|FJ8D8WIgm&tYUSU#W@;RIaoH%K`fiHd0m3F?_4q~r>8#d!G zTn~53dgj3PGgJ~5_chQ$fR+^MvI~L*SQ06i5A2guM z554*EGd%cJYK`UOkdxKyI%0&9h@oLI)Y#oK3Lwyyjl4F6iKMi1XCW{Mq;Yevy*M&W z)P)Npxvs0cCKo3%0~(0Rpo^ks)$iZ4z@^$V!mKb6IohbYs-FC*S3k-PxUvA3eyrQ? zE}fauLFl7=<^5-t;~TOl1$6wSaShyrS-Pt+<&Eedqpiqo1^it|kVUMoTIWvD?aisH zEDVcIjUoFox|s81Rs3B55Kvk2QIzRIhGOy1VG+9-O7S#sGybu{gHM)S=!Z4OsP1Js zZ7ZjAiORf29HA)7-O(gHO3<4Iko+M3oUHE+GvY%j^BQU0P3SCxG6yegrrJzr`Cc|& zEp%#>2!&|ij5*3R-`_z>Pe#3q6}5WNGwqn}PxhFKKQC^Wc49~O)xcEsBUIzvEU~E! z-_n~%oYK&2H>N0|*U3U$=RGya3->D{&$~N4{Y5EFG2gY(OofBga@w{=ZDwwa%R&k} zp7>^Fp`cJPE7|HC^mRFW>6)2TInDBVx7HW`CwEv)Bf0RWBL*pvtlFs0K(*xtw{F0+flz8E&wIAwkkbE!SZ2L8WITkjL6Gen!`dw}mwV9BFB>rbJ84AS zGRVq5;Pi0&pVT+q;!ah11<}5%fKw~I$1gwIcjG46zS>|mkap0>5+r(02Q@1km30Xo zBpA+5jxClND!RhyDfx~L*9iwrL}a2wNuYQfu^4GjI8#809BJy9PJtw1)K!KOf5`j& zXSx1njl^J^3j*B|1>5+W|0LX+Eej9u@hqj!ciP zGO$udpWSyPzan8E><%LKZ_YGWdc^x6a0Dh=!Rr$rym)whdi4;_N60eB+lcA@9c-|j z+IQMs7T$A4dg-UUw_`b?Z)ApD_!lqEND|y3E1OD8#y$pE%jgIxhQSch-!{M>qF19K zL)s(8MRUl7=>H1lAt4mxyUVGtly3O5?ZuP}U3^HHm9GZRES%w08ke~l1Do1!E#ozd z>#eHI55L4|lk(I03p>#e@@w>gN0?+BChBM^UM))z_mS7=3~pU!>AT?;N?&ZK-Y=sa z$(AZ}==ngBjHdJ{1Gxsc%5R)DJtGNd?N-%Uc`%G!W;bhu0!2=Oza|?-)bU~VU7Kww zH6E;d$Rk(kiXr3rMxIy1*90HGm+BB=V4X7=~5fr^O-*n>bbcwsOQiiu5ViN_!}*8`jQj(r?{ncdad9~{jgp2!4?)o z(95{vJpRX4c!>92_i0KSHhqMMpnId}3pf^8kRm^sS$aTC?C@#6p{cdfFe%7teQ~#N zK8XHTW$gdzK6mk*cIg=srbi$n#qpK&ZRc!Nf09TPfChW<=>s(G6vl2ucM4<2lK&LO zg!qiUM~M@HH}ez!UtUF2O)DEMvY8Vxm}y{C`R;88j)X55BVCoi`3m5 zj!84VA|?fwc8ri0c_P|6kxV;gL-hP=wg@paQJ6-OP2(afhTL*pdP#vSG05~JEcX*V zsMfltK+qgiqLu$HNA%1Ts|0L5Vm~XZKATqCOf5b{FX;f~HyNjLKzU|aVsA){&n^{M zz39B8=hB3P)YEs4vsNRg#3e8`mQsLhgp?;q@^9jbX&J|ziwMkh> zdGLlFAzKce_*{u5`s!*a7H|EBdC9e^=N3Fgv?KwfD#OvKx-#iB7Z|9}o>~mp-mGWP z904F3Yc+Rq4>9)IDo!0u+^)B~8&eMFLXH0!Ea{wP^oNT{t(X%!n(GxN87m=U^|HT< z)I_6X;cOyt=o7Iu152dEJ&d6<=~pMX9Yn~Z!vvC(xuHWh^s0apsh%dIwHDCj*HPUp zS`JIN7xjq2TaH69L+$dTX>-J%hGqOh5x^%r#eeieIu-o%43%>AE4f?lj^>!{I@kCI^ur*rXbre2Gcbz5V&pZMaUX4tc07C~jz8 zt#}IMvMdtK#bUH2wp4)`w^!t;3FqSyMA(=aALXb>pD8BLk(?Y#^Km56{XUQ4;-HK% zbvT81TWLJ3mti#-Wl|BOz8WmU|@!gJP2~DIyLj6M6F|Ak-GMZ~jQIId&m=*hT zT$3(2oy&fJC6%$#Lub3y+is_i4vswpDjyX8rq&Yp0`uUy` zM-2|^w_}yJH933h%NE5!n7uyUM00IS2H6P zFAH=(W8eeELBqNI0}exyakK@e?aO->0euBzP~ctJyg%;W?e3|XqaWnO$(C2))7muh z+vw7H`v0Nqt)r^!y02kHlopVZMvyM)E=dUisY7>5H_{yf(t>n%Nw;)&cXxvl65l@D z&-47^ecwO6G0tEN7>A3)b?v?OTyw28=f|1sZU^XCIQ}x&JDYt{jQmeJcI6 zx0&UhWr{I8HnJ@{w~Sn$I7*q2wzn4nkY6iS_#^oz_#g5werZ^^hIhqjsEl?surwv3 zH?vLQ=4WVWDYUW*v|Vujlk@hDG{N(<2&q03m@+gnrVMq`5j5buTIp^8%GT%vf7{A| zj(R|rUfAxb!G|SVdXn%P!?2UkRmj%F4?v=c<{&i5HkjsG`f)V*-&efOQxk?Rp&(k(H_;Y znm~3}oxr=&7|$~d^Qd*=1Ghw898Zgt7_~U3g}^?svQ=(JEx&7h*uaWm&*3FL*v=pQ zh9q3AzwooLIKSj}K%J>5(i^4a1S_V91#b0n?KwX+;P!cG_O5Z;#t+DIRvaMhe*Va>_p_#vz$MMf?uJNL;0!vNzG|M_9eM(_DW5SoNBTfJd$S3(6Ea2ufmL`_pqHnN1Wx>0 zp)^Sp)8~G{9(P)q+_(C+Q*?4`C-`%^bCuf8D(BvM+l~{@UZTGvnGM;t;sCRJau2~~ zuw@wZT^q&8R51M^tWz>6qcH+dY` zg4N%J&*$4__p!^n!Dfe|Lh|80u9LtuBxr-ve%LqL$g{kw{D>V%Nl;x6Wt(hr#EsRV zPq991`%Est{)FKDmw3hqVzZV!p%AL zEOGjXXcYJ{z9N_1W?)c27=m-SL*dg&^lu3a2nR&+DANE;gWsgqGm<}vFmUVuP*Hup|U^OZQKsgDM7MOL&f zAD8_OkMvQ4P?0YT<70_OF_#1Ru1Ix-U6Eeispf#62%ujA5d_AiDkJ=3^p>j(AaUXedSjTRL-x z5sxIHihrk57+Bpwz9`R5n&4V+J})(LZCuL5%9@3bzAv&Vc-G9Ls`M7LSt3v$m#qJ7 zQS$zTVa{6K)vy%n2t*4a{ksNfR}z2yS0y!MY_nk(R8nJU{;kmREQkaBUkWWdBjh|y ze{8g-N9=NwGd=jCG}`lifLu=g_k=k3_$2xyY1?#G^YZJv^eNm`JHk3EGmR5laR(*O z@vlT)-EmzfnZN!|Gx))OHDn4m&C8Pf0m3U-FD<*;P`jI9iDX)%(ODjiVFk8Of{fhO zD3{=Ny{1CyAgyJ)Qn9-?ft&?v803YVT0Y6-p(jVX4KE4PfqP}}seIJB(RS?&*1MyV z(I`u?qRC@xi4|{c;?G}RK%auNW-D_k1e7V#+jgbYP85xC9%04Fc9bsE%8I0 zHYgv06K~r+sT~FRe$az5Rwcb9-)6J(FEs=10Yt9c1nXzC?KVFl8&pF~E+?(HT(TSM zZb&xG$~+x5!?v?4w@KRr)Mu(a0mfW|zHY>E5%YO+e*~ijgg#ytp*L%kB)xwwk?kI^ zPEkfnm2^?`n^A% zE`#5}_nR`M+aQC9Ldtr9Kulvn#qKG5fDArc)*0`8`Tm|3(L;md=iI9KY6YLsc%SXa zP~MbFymJYLk3V1MT2$#LSw%&bCW=qEv*GBt%O@$xNpAGY;M5(b82Y?{7Y=kO`nw%T zz#EZAG_=RXyYwf&&Wnkz4Wd^3B;rz%%?#1M=vI|w{64wCWc!bWz0NW}clY_ahdyti zO9vjuLLCX?@N<8QEts$B5Y-fMX7w%fuXbOZzAy5wvEnFhy2cc0BrtCeQf{paFEEHZ z9cKw+`v-Z|*0~U&*YyZ|pPtZ=BT-jw6DZ7gft~KN(oz~vQWj1XUT)_NyPh-KvD$HZSBW~;Yvz2EK0MzkvvH5(`H>(0#7*d-Y%XQon3Eyc z7%7EGnP-qnqc2vSmlEj&($j}1yVEV1Z^RK{aVr?+p@C@T7r=M7CN+`!@Z{%UGr`^S z-}}G6*2~PgxWyDs3-V4gr=wcTN$|X85uNzJ>FIrfYLtv~f_wc&`*q60>lS66AqT!+ z4gsp`YpSWCN-p6V7rkfaEL_K(=Xw_DYj6Y9NtSuP{X+sX=NomB6^d*wT)IS`WPKE! zX}cT%4baaos^r)rf`fIRk83Jek8W=QDIpp&sL$>bMGYu&u;p_Yu44nis#vkWE8`=u~gVahWrbML7 zcWgD#;aM$G!vZ|k`O8bSY`s&OH$@=7dv~IxAtXD3k1);m5vI}n2c|`ipN+H0zz{0> zNL`OL1y?%fc+3)f4ZSaV%!k{A{;QuAq^n7BBf5{}4J>c%L~UW2(32sP+W=mLqXqkl z_oA-WyRNG`kd2L#~CcNz7bl||wxh?}`ZN(J)2oCG-D za5`SRb|_Zzr(n;=I@xNP?vr6Ptx?2I9It;mN%JjmePz;(V$S9aS(C>+L1KOClc?$E zOuROE)yBr{TjB?faF2yAkOl3T5_F~BXsIM$n+odFw^iTIBd!**Kik~YYB}_MYUahd zG4Vle_rxmSO8qlk5zX1nw)d0bO>oH%NkP%!aJ9p?-Ir` zffTT3Pmj`P`XeaE!p;*K+o#BKFj0yX5{^%ow(~w25ieGmpbYZRVUe*rn2Gt%UK7;F zE&Gdyk6VN)hss8%&cg z)}^ZwgZQ0UN08mE&^_V3me7Oktj=F6Q`1+$a!1RkMA?=L&2t$z-U!oES@=@e=y!}P z$G3_3YV`HvJG5M=#A(5?A^qWAG}fsuw3a;XWrj6*BTh2=at#^&R4lYZnD?KfR6n4J zmeOh`dRTrXq#cc{r94evuD7_@t!^S+80N)c-L3;2HV@(DcJ7k`*uh_lL$R}n6DQH{ zP%o{|#^&f*9Rrh)Jhto7DWLn3=zPH5pl;Jr?JftP`4M%Drz0tx;tA5j`ykm|>Eo)0no021e z4uyTpc6Hx8Yc}^yZ@e?t?hE$uG2lI@Sj?(?y43?)HZ?|?-c#dg)l|S6D}Jv(fgTB+ z4kluvLRl)!T_g(`eW?AuS+rQuvHmOK}_yLAyIp0>^bV0 zMfW-BmiWx7x>|4>iTc8i>IeAW5TZc!3(4Pz6F=7575~;GH6*c9q`b-s;p3=zchvjm z!F&6(`ym##^qx(BH(%0l6D9Kw-){bRh5uVBLZG_KQYF9V$!)70EPJgZxhrcmaw@LQ z$t;^E1J>LA4C%a({h0~Z&@Mae!=GZ@lPzCl3|+s?_x3;t3I-u`L4+h5Y3^9}J)W2m zk>!d{>N681r@`(@=!yAdSPlA@|G4UGFUak!MKr zwZyC1WZ_*NEwUAnA{XH0lrNjgA3nQzZwr=yA6+) z!7wM?Wy?p}SE<{${HRN#oXsFkIFAH-5 zMME>R++jchn^Uc$C$s9Kktr2(ylPCfZK3JsOJ7iXH7t;K79>dk^iQYdLihmX@QtjwS>~on-&}y8$EPr-sYL*|wW*9Oqj#3~$RUut; z?VLf!^Ptp`xOs@L;J+}IK$NZ4zXv}(_#4Cg-bn^a-g8xFXxB-zts~Jl3i9*M3yP_r zrs$%FE@}(F{P*`(k*IKTq|p1+1}TodyVgvjH!2LO(uQzN1F3cC zAPx&OVbzSw7U{y>R3DUSr7iQs+|3!?JJYI+tsl;hFdpoLn*@Emf8dUOj#+Mm$TQ*# z@%=jbknSjNcteU_?@;b@K^ESkt(l+y1!o#GwsjO`;~;vD&KBAsBw1@z-{%hqxp07)5Vz*#iIF zn>P_uSVtC{b!oE%0_9udH{Zpr#s55{^iPc|Quw#VF_%-YTYY4D(79LlTvL2fZX|M7 zz$^^AwX^8V@ZECYd7%pfRV-~oD=~+V!M@4Bb5v!j565S`FiDfQ#^h63VePu z)$y)8hd|Px+LJaV;#n|T67568h3CSTpkOw9QEI^=mx@nZ{Ko$D`uER%eL^$;9t5u! z_D*CQx%s15(Niw5DfsK@O@6q^H)!VU_9kX)5%1Q&qus3S4U%$I%5ne}aU1ol^uGI5 zG~_4fTSfE~xk?Hqb)QxXV%z*q;QQGdClzcIsS@+ImaFV@51AGXrcW@GbW&MH_g_-D zy$KKMjiuqUXqLNtTE2D6j&dE>Au#L-(|x~{+MM}bUp%DN#Iu9(J~S0_P8r1JCeP>j z!V3QFl*aJ7T$lh=e(aqCe{QR!GOwklg-cklz?rB19sAA9+o_2+Up*t)17&$VBWXTz z1hMgI-*))%e$PXFaPi-c+33JyB>~Oi7G^+DUdG%m0rnH=!%`vpXna@WlMFO?;Wo~m zB?TY{`fJ3qlpQw3^WMevxao4hjF{U#NHUI&y6dM4lRxFZCM^*Q(=#7AJ!GTTHlg z{jYhhG|2A2MLW&y%F*Xs*_%9l=|;OJ{mGz75mHbf3vH%G{-;S%2V?IOLIU zHr7VSn@m{FksI4V4W8*G;_qNAnf**NHBeuN!uI8eyl?iNVwJU!v>CYcRq7pVvqlE9 zy<4^J7cbNsJYfHw&#p)_Q>L~=lm%g_*G1_Y;E-deMH5~XL^sDiDY;jgMNsX!DAyY_ zRW6Dgx^Vg#)k^uBygVmOs7UBuJc1w{%n^ z9`rl$Uhjq69zQDwWlxRe7|D%33L4m4bIu~C3aTk&UtwOF_JHOBbn<@go7nu>5ZUw&)n$25+{{m3pU^J?aDqg42ZFQKjnX{o~p4{hFB=;p|scuX6dtZV%J zFE6wYxvAEM^x$r|pPvQW#e7!r(nBd!(d^%NeJ}g_fifY6DWMm)ti^>PFC{*hP3&RW z{tS~Xm431i+6_6ZN@}`?(23^@0WILRlAo`S>oGon!vH`jTTHG8k_R}*;wGxHn@@2w zQ3oE{1*bgG#RHMR8wt8vxK2E(3=-|v;d0+Ug|J0Ip4on-!lKuWTBLu`d&H!ygR7`s zFqC(F%uca*70fnB1(<+Vw9{?o-lL;VTOyZ$SZyuijF3jM^Uhm?SLP5f|3j;t|L5Uc z$BnrY4>$C|Hhuo*S!_PU&fFZsQ*med8Fpu)nKWp#2~YI=CJ+=J0{Qs^%N+B*_Hwsct!RgkF7Tde}p5)`iUvh^Wfq+ z=&J^Ym76XZqWG{DWgVL`q^(v#s3E)OWRxHa1$0b}K6^?qvkC6e|8JUX5HQzxHk zm{^oH=)&E4K6zjI?rE=Nk?BAPTkC5So7X^iMh(l{?8g;Z4^k22JUbn7jx(KWDU_mc zB~bZ5L@_myO5N)UUnoOnT}5)T8LvI|4Anl`jw2!y0i!wVXtCkTC-;BaTe_kpcSS(n z3)OZeQG$jzBRY@hB|LMqR6^Td$4OUB3hFncAi4=rmoyyJ8|*pN5@BEnTXzimF~SQO zi5KNV%1IY(`{{+=914Ijpu~?Uyr!NkUkgFELOST_`UF%q@`1XgeF(>zkZR-u~T4yshRFy4vR=kRbw ziWK4{Nf(1_hKdz*n6Ns|rSZY9!U?kz1RkV+OcmwO!=cI_Wpw6&dpdD=|2JRoO_5XV zK5d~OohFTk^FVhCf|74L&%jCTqU#we&r~1r^U~Gi9XsP*(&O`GmV=#!F*#N0BtCql zL8P^>1H|1RE8d0Y;cG7obuTF*P;tE(+YQArRq|QD!jgO*d%lr_sL^bNP0to}0*(ZE zp`!fZ@OoaNq+Wp4xV{$wJ8jh{n z1p1+uB)lXR5K~7OMpQV@NQQesf65P>F6)g5Ns08AYqO?LULHfa3NvZE=(lvlhP{cg z6a(sl<&y<)n4Hw7u!D(bES<#=q4}%8%cAENO@n$fZ8B)mgZ-e9St9zpV=}#t7vs7hLuYMU!5z(i1xd3z=&K^giVK`N980FCI zNH+~-!)?x^7O@2%0+sx}y!)20bt2|1A8w5t-Ytz4vOH6&PI4|B9gSY*H+S^XDO_zY zZ{9KC7_2gxUYw4{J2P-HZ2OS%MkxN`&EUP~y4}iBu%GxYzIUqeZJZe=X{}DDiYWqf zy)G?^3#W&vj%oL8XDZ7UO!yDN0i?|L9|)Z2qc3!9iOL6_CwUSSuIenbr5!{MGN&*N zF)itmyD$VHBqF_&)oJ$fhK=k@5>KPC9~Hpa*r+4n*kWu^-G)IU=-}0>e6UGDde`zx zkb=7VyoE_O#N6DOh|6U)gVRb4@~Wf*?*17}A4S(I+~Qi)bOwc<#ckRC9TcanLm9Hxn85g56^Ag4$}6tJL{O6z)Q`nHN9@;TcT3mX zh08$~RQp-%FY!k0&d;(L-nu;4n)1oG?$k7-Tj|~*_l&1Cr2^W-gex8|u?QjL;p)hJ zhF#}yt8q5kEj_7rw%SF;Q5_=Ib52`DB%!MqH)J>2lW_!6Xu`}m-LZ)DdB_-*u9rF8 zf18JlD<0fA9Fd!rb8BiT_xJUceqyZI5qS_zF$EPcKN&q5H#T7`6!?`Epn%r#(HrB! z#jSE8=tso*6!Ustqob|nrCpuw>&w>cC2REqmVym zZ|7ghe*rUh#lMn&XP^I44?_wV$o*0XJJ&4a5dn`2fjfcq*3m=3`~eD~G(Zz5lyPTN zoLD9fmAwO(*SV~gh?rRR`uyBUX8lVYVfj||yk%zUb(0RKa*j0aT#c1Br_i%DFUUKy z399<_a2}Wvb%ECFhe&av^uO1O;vh1DCcIHFp}E^jnOaGKW8G}I$nCn9p9}vsgGs;Z z`=#L2YaYjCm4d{Z(`9ZC;tY;a;eQqwsWp}HlwKDa) zix^RDRA;vYM>9lCfzgK}DanuaJqqyx0`||Z-GOJBS;AC+mM+Qz{pXo7??hJ9j6^AE z%+UpZc&lNeeW}8UXEP@>-s+a2Y1slZf9I1NW}1~@G@HLY*9~Lg^pMN>%}W<(Y*6g; zd7aUvns!t>z}Lo0PzP-#Fy~daorj+z``!|&X7)PVq5$jjzwuvL*r}d9MT6IXxf)`= zT=34Vz7xD1URIq*XJ1;`&^CUV`4qhKEsWabE3qUcH35S65DbY_ zPzHn*Bq@c3R>N=KLBN#B!Di!FhQqI7jSU(p3%mO_;mft%0$ZC-Ya9soXZ`X_$c_)8 zoeQ(*<}rk~aIi2zf2;XHN2OX z_Nx_9y<2P}^NNw%>*H}C$hRG@-`<_u8m(xPr zUOM6+ReoHSEm(Y#CotgULbh@=cXHaCp_t?I2e173dbH^-YhfCnRi==66D)y08(pjO zsy|N576Jl-r2V%E#X@VXxk{|#=F6ooeWVY02UPvnZ;Do_=zu)sbLeQOZ4iSUHWQHa z^nZbZmo+sS0%^aO3Eyc$H(Mb8LpYSg6%EXU3zY|Dbx~5IBlvHEfJ;$Yc=ux0Tl8{g z(2&^C7I7;P-j)cao=1SE_K_nM_US7)Y<}S5HEf}2j5Y9TN;-)%Qp;r%tHFd}=qB1w zr9=ZvHn~cK<-F}r-u%5ktwK7wbDh-x2k01=VMO-Yc56hG1*9@gm1s(VtEl{-Bqx^# z((k5VR>TaK-Ay=c{u}2WU*A?I@5lPPzom4p86^&ckqzdR(OXn!PoEZV>&`YsRv}h| zwQQhGUG*ola>9hPCWZOuD>o%^C~@K6{&0`pDP)_fQQ+cX==Zsk5*xzcg7*@%Mr(D7 ztJ_BB9o$4PzZYFe|1)}V<90Z*6X@BO_O!Uz>hDGAs6H$7L7=^ctvn+C%2~J)gZ%Y8 zOy1`S{8fM;(7iY548iJ~-%I+P$FQV=s%G+gkFCS1kr((tsU@c3E9(w279g*tNcjsFxm| zBQQFGc^YjU8JNuHPtkfXymxj?HZ67=pD;*^oUV1+-cFhQj5>7snkhrZh{M!Rxz73G z!1oEf7x-`~UJd5$d8(%q6+bOHdKdIJOxOsjUi3OamrNKQTLv(gQO0^vMx_r1RrkEE zHVNTSi4-sE?x03mQ%)2`bzqYJFhzEvOK*Kj-6|W1g%paWh!m}g-T_WE)lAqD=#K|{ zOy(A?S+GS?$|K1%@6Y6_iz_n%!@Uz#=F>@iv+D5-ni-($RtcR*saQ>^Zn;nC1Lj6< zSwQAO*+@Hk`Bh-1zg-MY_=|Q%h1DS8>fHq6l=O$YW6x?){`qRGDNe^eMgwlw3o4rl zOlnIRQZy(S!AI$s<3u0f3Vyp-zkiM!*49 zs93#5xtVd|{pYK%t#HdY>3ubJ8`jgN<9&*F4~=YnRX@!yTHen%Y@QiTzp#FrhwxhU z*(xITP^xt@!hUg55Jo(h8-L9}RA3;N2&*Cr{B%h#%uu3RyB2`6gW$ z9ZjUg<3$A1FoJ@D(tv0jEzXi8wn$gMVgwJyR32RN=Yj7`?F_D8<#h*vtZl3mtnEtcQ$3p=pmRGxq#AU( z3KVD->m4SU>sBQp?HL$*wFt82i+tNyO z3{d=XNl1!LV+iK_S-p+5zGgRP+F7n7{hDc}4ij^fv32Yzk?!B6puJh^7yRQ-0DV-I z@GCr0q2Z_cE2c@fYOpW85s0y~{;G?ZzjVG==h$iArA~CPMuWanu$Ap;@fQTL;mDz+ zs0tN$^S1~aATFj$do9Ol*4vwI7Q1;q+;N=#AdG}Afruw9y(yVeHmvv_b`&j(uMi%u z@whxL(BAdK>BY&44S$!1`{&XPunU^_dV1|9i>Dcw_{LbC4S0i2_+usmKaZw^>&zl- z^&bzqygZdsA}HhtNso!a>`d*}L&ko00&}ZwStrWH4iv@6UxgjEd1xbPB;EP!4y``>0qd6EMGne%07-Rzt3 zWk&b6*N*Q|u*G<3yhe(AlPH=zQG1u9#a%4eeinPmZ;z$Mr&;#F+tEEe!Y+V$+rpUzC1_7^=NeeRFX2ceA5W^rtxVP=HX>zIz7yDP#w*T%>MofDRy=Tl5b zJmNILNl!^|r8~ybLKXr79Eb#hg1%l;O@5Kv62>1t%+mX@MZrE^0bJyNyu1Y|b>dJv z=u)NA&O5H4zew^Ley5JTv964S&9t!THK!D;!0zYDh&E*7_k#w*hCSXF`%%;wEb7!H>Zm)Uj#k8Srgfx%i zLE7Kr7VV?@0mA1fLw;-o0no1@=ks=a4;(>8P*)-2@=$Mvk zj_cbvz;hQBd9P=K^2y}YyNVZW3h&XToF!i#zE5dQY!}TJ*(JcLWg$_}s{5GA_`$(Z zf_~h#zE`sOius%S8#w4jqzC!YScd-XYiB&;0Bmoew8fuHtoBiptD9yWu9<(KG4-GA zdisY4eQZgI`HWz9fSUU7J%sE7$>SCN=WYgxls$~mwcx;6FD$q0S7K<~_5pe~=Dv^y z*@t;0zdjY4^8)v$29S7>x!;CE87n$E8xeNam{ZmrIN?vmGDML80~yV{F)$!a{{Dry zPu*_LkC+N@N~eG#zYM_8nY8RkKi#Q|OvkbifI+HEXFXsYfx%sT{jr&^=<8~qr^aoG zfF~URe!of>bkfe?9GG-h!KZU}2K#oh9h&5rP|(GE+s%yNAH#Cr0y%fb`BujvaMPuc zxuUB9oAjG+CWWDafytlcJbALUbFy*ZT$A6>b?i}*Vv&NQD`Q}gMJgE*QV~MPsU`== zUW-AVMWa(hBwGVu0-K;||5|m((;OIFmMkdoHvoe=fEH+!^7B9w;$ zpwFOEuM@E@l$RKu)dXAgxX7CEBj5QK3ckgaf}pin7762N6Op3cRg4gIu_;04KDahK z+1_-`9t`L8JD-UQro(rsw`m=y(rO>TVLgBS|2(W;JoTX33e+#IJp9S(nkoAcUZuF6 z^Tp#1T}k?HA)4&}XNYcMuRO#SW|STEC?`3ub!HEBWo?!WMqsD)^?e$XI`~T-(k^ep zi6;`a(AM>>JIFNjMo;HyrXPhf>%|Ck~Ap_e~9!JsIGHljHcWP^Aeqd5-nnki7| z+G_@Z^fZ)3SEkBr@_;nE>?FhKc&S9XV3UyBJ`FTfD=rSB>dF8_XtLbwzW17URzgZD z6Bx0}CT``26_;&+*;++lqFnRm>Zb|*rpabs?8Qd3Y`ulC`Wr^DLtonMj*(9;fNW*b zMAj@l8YTQ?2Z*j}Xt^NmRQSPeVLM46;L&(C8wbbfgCZWu%rc8;t}(mWLVu4h+(!)K z9}+OSW)&irZ#(xC+1WliP%F1e>d^N!Cp7Fv3v7>RyRw1(IL-uuFf~^tk_(J0(RXGR zx(PsPkZU;Jm1S+(M}KoaH6;1_{xM*x!JZ^%i*{czov;oe)8D2FmPf5t-pHYc1XXf> z(g>TG6)rEVr}}5dS$`DV*J|sr%VNpRIzVs3`vCJ8w?R<-A1?s?|3Od`BQAQk(1?tN z411x4pV83}|4>s%6`Q}}VROQa`mj z=|PtEk=l555EL9Hxv!~i;IrpV z!YF|Spl1M!?ZC_rUH#Uu$xz=Bi_&oU=reT)3ougLTW)EYx3TjFC{3v~O9f&FQpWLN zfrq00<|RpRNmW(Vj!|#NgPHVcy1fJmor4UYiP|v76PTl;x93VWfV+Ikyoja9c_uA=7VdhC%LGD zHZ_nckec%4h)a|AlY#;@_Z&^!2yIb5fWwEgKgHwSn_`m?%uBReKJqrNb%quiUEMA? zOlx*@e{&O0(?5pb@&3A-dqXt3-xR&GKTN2|mhsQMT}~GEJm~GggO}|_)eXzt7wT?`IDY6r%BD&n@Li~hxPGf5910}P{$D`i#1jUo1}n#`s_Hl*{BSs}c~Eni`1*m4 z={@u&ouK}={1y34QRLgl^!0x&X#g9zpZ;_sF}gN@Nv7;Vg+{Sof~`AMxvl6##H}Y!gWCohbv6)XP1}1#_CP% z>yA+^1Hfax0;^s6=*Gd4wx|w>z{b)j^&L7NgLyx|NaU#vPotX?kZpZlsEs6Y*+6&T zEn#=I1gb)EsGfgjjVFMworAU|)a3jENFnrS?#+~w6>BxAEpq6$%R}rA=h*ZjXO=x5 zibcAEBO+89Tmadf2VArE_}Lq!R=mYCO%K|9Fpv0q@Com!eP2{MHhc8!u+266^l|tg zxbFg)VyaLUsy>a=G}X3xsT-#CDGv_jBfLFYK_8Ao9?cg4``B>e0ed~~9_?o2q?a%K zp;2N*@X503OTn{Rq!bs}pe+yaw3}q~%9TP=%Wi)T);du?MCiNHLZN2|x-nK#RK0cP ztN$5#{&{SIUjGh2tu}gBj{yi1_Nx~DQ6ByWyB4Y<^Kxso0)MUDB#FN@#<0(6Jrn(S zbO!-r{&)g>1OK-B-h54IeQGL**bAqCL@dy^A(xh;HLxm^$Po^FX;#jn8@k0AssDV&s)=z+7^-^m?0 z4Nk*8OxNqp_{nwKOpsDk8uY%ZlLDV78`!cG{5ASKgJ>QV6_xiPn!-$xAiNnG>KZH| z_WHDDKY4-($KfZgtuSS7@<>Fx%Xo!&%HgX#3(YV3`M0M(WKNqLE?G~|!Ke+lSD=!a zV;SIE&Bp%uy@fWlL++@i5{9&mEIUeS_PG(wK?D^B^yu_~468g7TBed|#A*T8WRUfnj75P{^p8egNd?yl>p_x-_G5FZ7x0dBz7t0Gs62IMWP4K#f9%Cm9Ov=LR z>sd@UFw8yuzgxsor%HK$E@JW#|JB3VNH^)ckJpDq?0N@+$0>MNBi74N1XaLJW%! zmH_9F!)&65AtZnY{}CzJ7+{Bwkd6ae+n~&@T1kRKU;o$Dy|HBh{_sF;QofJ@QsxCr zZ8DE|EX!uRGq+}PZi680cR#Q40k+taTL_kEYion8o@p^N(CaoaV~RaCMiA+(Bm=9_c!Lk!b62+TOefQ0PZ>8-PSLGh|e|eZ#X^y zdhm8%owQps=(V7CnuHQ69T`mXP{)?J7S9%o$i+WUv~NCLVumaJyBw=0AFhI90m0m| z`PxYIz>r5P1?w5Lzma`} zg?z9{QEwjPVV?Y-4;2Gmu~aKrES%uO13FTdWy7808iyY-r?pocy}Hekckx@}8J?8B`eR>rJnq2_(ojx!2PMP(Qouhb-tN-yaw41>4 zHnA^gP$yx#EBGN|PI&C5(MOa{=Zt2>mne))E-)HZ7YABg!op}m+Ajl!`TrJi%Qvfh z*-9`@3V|nbzmQjJcB@N93&gJn=QUsI;WoDvRRgD9#7`3{fXQTiQQC9|7 z8y=jM&Uj-^zHc*>M&}S1V zvU$7K;10@ET!{ad(C_1QB0ARnH{?^kt)4KMW>b`C@`GLMRff)w3pd=Escv@Y8GOa_ zRMztAt^3C%ywnu)C!kw~{~+;$7hxCeC3ZS#XVq~aL&{(Vi6#wz+NN=n8NRy5>-011~YUJk&GfC6|LVA?2RV8@oNw5r;Y7p?9PEExat zd48C9dbdNF>h`|n{)RS|K~oKV3z>lP8!4HcxYpRKsfi+01(B?tCWaMI&mzaJ?&(-d z2X<$Ge7)Tn&D@|%lu}g0Bm~qTPzuGa@(>dXcr|DYsGAGG)5}d3CW=tV$@o&1XYBv3=d zt~&Gh2tpoZ^n#xE*nON0%f`RLS(uP&{sQ@+eBi@3<`-3}Rwao(dSVH?C0t!FjNlrxY?zw2lXsHz;WI~;buciAb2D+8L!p9gwKN< zYazgb573@wc3Z!ORe(B*Qh(Vh?$hR%&AePohjXUt`w6(%c(ZIDrjcCEZNsV$G3K{k zjkprU@!_f#lFU2zmsFN=1eS?0Qcpa4iUPA3*d(Rh@ zew>fhgiADQ$$%?3gz^8Aa_Yf&sIJH4(*()=V+sawxj7JD#>OTopwYEdXG88CNh zAcci`iP(dbf3XcuO9W81o&`vMY9DGSKPqPIn%LvK3jEj7MA-TM_Hi3=c{gg|t2qUy zqq7kDR~=Cfwk6J%E~W{14BBhsve}}a_?P8?Ga{sxL}mL0A|y?xA#J&udKteNSfp2r zCeCjUr{)5hqrgD}!MqkmTrz>*yNkZ^QV(($tpo*k>zh)BF{IR+X58J%VB#3Ne=L6l#e4wFF(!*Y10g6PJHsK4G zZ;jbORm*NJMpSFr?L6$r7{ye?%AO?LV_lMf!h&mSAX=1*pj?7>7tmUqy8v4|dI}K8 z1a_)Qq@d@yiNo>VNblpOFsKPVmVoGy5wpp(y)tH_u1njiTnqP!gG?}ogU~(|F2jCzV&|Zwfufj zoz6MB1@pYE3aF>jTE%&6Cp#6v;FPyAa*>O=oO6a6EMx;dXsyP!#%xkD-}Q7&baQa+ zXzuhBolI=R?-Zkl^hJmM8Wq=Vmz}Xy>6AX>_q~55?$V!`aG-}LydsQ|27Z0>Ybkdz zB=6#1G32al%bt;9g*aIw_lLMI)B_!VgPhyCGLg$}OAZ`L3n|j!Iz5pPqk-?~Q5q&6ZKk^gh%V}ocEafbrBKk4qDRSV!$x8>klGHQ zKV8 zIZ-Z4cUPlS8KjZjl3c{~P>g@EdVyKD&(5)qcUX;~`0oE$2SXm1MW4r|kbZ+2PirU! zl3buxIUZY4AbYWN_UZ7p-__K);mQ=%BX8nGj1EOH5dp{J={ryqBP)x*eeTuz*l}R@ zbv~{TCuigW{fLm(5+xl5x@x?#hBXg+=ZhkW@TU%e>2-}@s{cVEjaG86LJe>0md zC_XsL=myxYM|dLZ0|qFB{ip|W_3EJ4Ho5-zGZ{B`;$tGeF)FT9J_Pc62YRv4h=^Pu z$B5qYT;qctTMtk4Qu=CpAkTiE1!zKiZcqQ+&b&vK=AR|8P6>I3{J11cVT?5Kd9kJ? zu3Cuuv#fv|fOrL$4VCZM_y+pM&?CMIC*%=pG)Ywe`_dE`4-6G>)6**CAlt-XCqM=o z!NF8lxM3txl)z>lXQYTnB(O|u>xbKHWiRcf-ObK(xB0 z_@dHO*F^*c!8hmw@*oY^%Ftv4iiP1(w;`%}`=da)(*{QuEwZV%q8 zip6TNHM}QY4bw}k&y8C zxS0k)I|G##ngbT*N>K+R_(v0F0Ixz0mQ05(?-p>7D*ECXQwv|FUIH&5>S3$~r{f`q z1(xNyC*D>TC_iFv!K{zH!y?0CK6~Tl6w>@pjlmMRCj4KSh@-TFS3T&?x#o*h_W# zh0#>K6f(*WY}r*2KUbN5YXPK`@+gnw=Bn?YzNx(4uc6z#ob1P`*x8GvlawwS344qF zT()tTi>>p$=^8PTHS<_!3o?>nNVW;Vb4r%zWA2XXE7PgAhoT0v5`qrT+wdo$xL5a~ zWIi2TU1Lz~Jj#zrXxsFEVYhTUpjq3I_;pI0{~8^Yj(j+eyf{%kYZcU}7TT$3A(O>cZgQ|TEMxOP@>heH{H&lSzmePLM@-+cXkbqNwj2s z_qmv1Qi0>L*8!atjf3cB{~vE}9aYuZb`J}pf{2u)NQ0#0MnJl|Q@W9qE-C45X{4k( zB%}nCP`W`vLQ;^H{@n}E=e*B(-|x?F42FlH2ln1;-Rp{Z%{i}dBHqn`-C!NTuel$$ z4bpdHg<_(n(9!j}9jHm8shF8V)#xxO2z9dbTdCM&PBG!e=8^s6Ka%PxWjnLSQ9Y7r zz^;E4_p-oN)OTvXe={eEx!eJqj_w!1qrv#ZT@hSA&88~47KUE@Zf=$n;psx z*=ct9fewVbhBIuNL`u%PI>3Ef1mzo}4guI)87Ad~%%KzIYu zS;`B?qY)V8cWdNMh+PlDgSoXW4gid_%9DWqLxf3#KWv2&E0T zw2G)W+%}7L-mF8L;Z>0H+^@0NyM(uqp{9XfqNT{(r+p}0{Xyfl2S1G*USAm{2`g{SWwK_Yr|F%=JYEA!03wT$K=R@i&dw z`T1#Hf@1Ypfgyhb@BD|^?DsBTP`X9O3eg9jnQ|EhFF5mr@26Wm&V$D~HFC=r zT#n8^4Ogykl6yS+t{bXyBbx^V3@a5{OMJ~Y~EQrrfh%X;f&-dwsm+C z2Ib7bX}q(+4set=1? zZT<8%c9y-zj<_%_%X#rOtLs5Swf%5#k^((2%8F{Z?-F+f=oCSG=Epj8{&5TMA2?B&-4R6j4BJ z)#j+%hz8_VFsxm{{~m<-cm?!qah#~vusogW6exEF!+$;-rlO}SdNEprx4$|RkRy{U za%*8h`61iG?jJMmZl=R|165!Nr=}w}{ahy#ovF)0*jT>Ycha@fC6T_gMkPIIK%!g) z!$LFFUeZyE$*LfLJY)=iH+lKPEVxs9MRASgFZP;N|N%iVh+!kx8#$VdXWzs zXm{+3fw%(ETFZ|ay~nH{L`*zzR58gf(IW3ivN-@5liVT1 z?8WrnQ6^nEV?b7XMRJIKe9o07&W*40E_9E}A?WkfZGCc?5N%XGQm?`@21D=ppI^l7 zNM%(1pO{9;V_|O?%_a&cEN2=f=o5j@(%?*^+el7PZ!M@iY`ZP!SWWxA95=sFOVpxf zZh;NbfKf>4OK&|sTybEn>@xl!qz7U_fL%mj&&KC-uRCt2+)x zcGyx?_IiG7^#kr+I@6i>Y;3?DH;IDuo0=~Y`krX$>TTr`O}{6awdn^&_F1|gU+;lC zN^3De`PNh8{Ni*M6@tXD>D2ht)zg~&##d^06lSl8jtyULSzcX|uOzyo)gMPpH}hx_ zK3u4JnT-hU;j4zqT`^_Q2oUaX_NJ>FSoN3RbWs{MT=;bW<7Ce}@xTT{09#g(QJPM+ znF`vU>pfV90W;lTff(yCjplKEsnHoPy!6ZQY+>ebc8$h7^yygZ%l84^vIyu5`>gaK^kztsp)q^R*SPU`e;re_`NeQvlq-*I zXTZRW`-y2};IB%9fI!a0h3CG#O=R8bF+4WbO3J@^I0Bm-<`3{ z?Pap3Ge$L~n=2KOBdZ>sIqPvW%5@>(RsqcNj&QW-DEtXA@aIj>%v z@NYgFY{T?2zWU4m{D}sS0L_7uo;sx!SREbC(kj*4<55V2j_$=#(JKqZVhht5WB_jL z03b@Fvgzsd+($1L$uAhzr4CmP-T?r~V6Dx<3fT6Z38aQ{fC&Deyc;YJqoSl7-4qT0 zC4VMR1#tdsQ`WPvphE$;90;@`06Ok0c{6kYuKQ|n&5T0k$Cri#CNBU|It-S2+jP=A zJp#L);_`SbB9=9a)Z}gGq=GEk;L{}Ip9I+i3^cgx#&)t=#Auw$R;|x8e)zt^0LV32 zK#F3lfs_S$94d6%^YasHw&EOxcM{ZRwjaSjPV&Wz&j5>?ZE8&DLnzSx$+pzcy~1u0 z5#(NLkvPYmLU6LQa2|b?{I+qP;9gekzRXbabH&}+DlSe7&3Jt0v%(S0rjB7=2j$vz zg~jKA{(HSf>e$rruI2N@wYciOrUsE^oHo7c62_!HSt-)@tu1k2dGuVL9K#I zj`k2oB&3O6YKeB;4ei*&0KajRHi&s!!O16E{t*-$;p4rUzoFfJ!XNrg6@gU9aHkv@ zSs`n*b*d2Xw&TRPi5f(xyN+iI^4jPMuHFYb+Mlvz5RT6AzeDT|1SNQg6SeF4HaB4f zx4H-{6@{Q#XwU)1D;e&j!9h}qiHS;}a{wlq&4y80B|^XfV?f3>8>acavX3VVj78)G z1YT>o&*ZCDQn~}U(06hNjV6rC2?>l?P;3^hu%(HgUU>99%Udfg7!`~1?qgrxRKrIr+0N9a8JVg z@p%Y@8$RFrLoSB*zEOH}vJRFyN-z1YaW*H!v~uR5gNJ5T$Rh;5 zgie>=f5h1j3LW7GsRVG*RUKGQExw7RzI7HzL_OpN66WeNP|@ar=hYu{) z@B{^C!pEkQ$i^B59(U1Z4A`T>V_iLFuLPi?)ty=09wQQgo#5!<)_R0eTTBYuDJSSd z@FRCWrC+Ab{=Zcao~a4p0(2Dq$JZ+EF$N3=L z%}4Gp`4Bkxe_}6*Rwk|t*=JI*2~*1&s#KMI4rbkjlx7?u>T0p1L#jIN!k}}G0Z0#6 z^ARUTOLzNwC++)I9FH%X2S0iHA@v{-d{>$0IxPcbUrv+zNw6uS0+MBbjY+T)e@g$2DjKZEA7U_nc`t+X z*Ezm3xnh)m9dGB_P~N_5Q{M8Hoi-)=B~+ zNh`_xtUVcND;1Z(;{3ay@85$r)fVR`zh3m6$A5SldleZGFyTB(lu0`SxoE#+T9_CG zS)${@6dN8sWf{sWlI#`3k$-E zZY3VQe={*#GVpOvz3Yo6ge+Js+Hi$>gWLE_kZv7{XiU0_l-2d&4y}BiGJVoedmvdWdp^ zSKLZwiSvi<6+k7%4a61lzb%imZAd3 z{CD>mgv6R`Qi0l1GAJlWBC+zKGZ6N^L#@^hpxslXxl>?h$_kCc*2)2yMk~;@py1^F zLuj99bo0e7* zXaG(W5410aN=3-)2;`DLvgH(j!z@KY3;%!-faoZTK>Gmjk$hD`fXRDe*N(sbm0sX< zX!LtA6ihLhu^CHqu$@= z$OqwN7#reO(UI!3fF-nl_ceTkh`*BIa*CfwInB^&Bd4>Z@+69rrO7Bfc*~ibj(^$e z^YNfjQOt0v78*-)zWhb3RcHIDAF;tk5YS0%>Q8!~t^SH4v)>-15M1ClLW@M`Rt-uI zx}X)qvc@Wf4JJYrI?1DwrKw~Z`}>$9(9tH&`_FT)M1(AL`|{oYqXB9V&>byO2kSOk zHX@mYK+JpxX2r{E<^XAhm}cg6ayE22vYl~zrj^uu*M^(<_FXgmDDOAP%$7)gG1xM_YJcXW;pquI z5+HiTF$hj5NETlkNMc_@q(*9MVEE}!_%!$46u;EmN45c0eG#rtIMG`i_Pi4;xy<>V zU(D_I?_O+#UG+S3wAUKmmlDTop&3Mf&(HNYKn)Br34lB&1WB#^qIG3*q)@3qiCRLk z^5W6%VizWV`s;DAC#5=j4sEXYtRZY)6>IO{13m|)eI%VJZ;O9a%*4(QaPIiS&31p5=HV6Zsb zb{<>b|COb$AIu6LYzGTV@ko!)o5H{xwz}}KlLcTf2u`tCN`(PR zj8c(W)aM8ySt#-%BE&A}_?L;K-Ganb;Okrr+#63WT3pQQdxQ2J|L5Dc@WrsZw(bAu zAdAze8>{6}!ReJn=vG3^RbRiWm~Z>tf1?N>Yj(3@IkAS0cBEH<>Gwmp^X*^g+Y9MZ zuD95XzoAXuH8Z?;*!27L6YT~nrzjt}InpDyr`4tMe0du1!6#W1ziN z_q_^?Euwz~v3mnZf={m#_umMIHiy72&}~^WozpuH)c5Zo?(oTF?Rs*Me*&mBitX5- zf;CI5LYnIKxk4QXfGc1zV(_E1Sy1ET*R$hv%QNjy z*clIj!@Fgh$I*%}uTEt%Sp}0-Qv^j1K8I~K#@S=G(a~lL?#CfG3^{4sZuJDo45-(W zr7v|^3|HrK8R2U^8+%RorJnP$gpfs=!~aRmvGslk8n{3F&%ix?leBUF@-{{w&?tqa zJB?vw&OhaFTB&F5vwr=SeTDPUx20*u#gb#uD{8nG8ysHs=l5@(c}r_sA*Ldk)moot zU<{a9^ufR1N2{&mCl5=&v!<#boNBbC4$(G^5%WCDIcuv;V@kh&d7`{*{ytmyCK1^G zx{JXGVAllw4DK@-scD*nxjFS%rbE))~nN=4{HDAM>y@E!4m>r4#`|mm;G1 zrs82W+XFr6XtdG5cINwoXrsUMHq8Mc(@cnqcP!k!fiXIhp*OG7y zEJ}_w00P7e(3_e}RR`wruPVKhz=|I*tDOg(ZlEv^b2Sr*zH~OO28figrd&WM8=I@e zePPm<@=mWUU?NocAkDMxs=7H6h3AGSS~n2IpmAU}_w`cmxz8d;#7%?@;v zRYFCKb_B@C;d?pIkPRpe1V;*$YjzazpP$G|N-F;76)4QM7>LpSFjHc3iL-{*EF)iM zw#`eRbr#d?sb9825KRXF-v58nAPJ?HTNT{&_3{H?qG^2_Jt z!!CSu+wTY3qxQ5hGLxDwUiXhtJsZB{xUl@~4`2LH_on|>Dzk!j%)HMu0{Xx~fT!jG zl4F(AERS-n%}PH>{ci6whmS8q)!JG^!Ar>*=bVU5&@p~zD$i*r)l5|t&Q1gdbE|7L zfZ`hLm2=?*_W&>I^}|4W$qzcupeJq>7@}_y!Je#d?;bsSuLvws?1H4!=!Sqo zOZYyE(T<_(Qk?2ATSLZpqE+?omvVyg0Z`uLdz>9lI27w+b9m;?XbT&*jieGPAJ0~} zRFa-{v8^!|0x5ztwt@Sc_nnIM@xzNxpTpXtoYf4MBCeq~PeWg(OXw{R9YAkrX5Scf zu0Q)PHaO6sOOLah09bS|^BSx zuxkVQEcYnc8%}Ngnxx3nmo%B7vC?3B47}pM z;^HC#``{O#8fYiIY0er8nHKDUbWb&)qvo4Q{+;uc(Kv1J4MEiVK<`%r*j=2d>^7~I zyKn*z+M;v}CmYRiV5Z}8fTs+&M$!O$eZu{F&PQf_YrNb?+vCV+vQANG#3ttUeFCw{ znbdb?YHA3(0AW+q*Viw31BhW*Fw03LYGCt71*B3VB{I1(sVjgJtJ1BOr%?PHW(3IV zT1utojZX}jGw*(|N;NlaXR?VTyB`$lCsr|O{IoR*Xr}#UFwjlwxsE_(uzsX^oBX_u zG#f|fRn%yy4nxQ(^V3Tn=w}8JJvr#pqv=Cw%omqU3gop)cLxHhayYa_^#ilt_6Z&Y zZofFM^A`Ts!=wTa2o*U1OiZ4ipO1~ZJ%&*#59}!*x|CA285WS*b${*74923Nk{{iF z`I53Ik;5(r<4CB`-8Ycg4)_cJP(;NMhD@)%1Gm32AXu3A1uUv^QfcP{*~aO)319`X z+AfL-3(Xe^0DaX9fV~92q>w6V{r#d(HaPDGkT3QY#1xkqgY>os)_jhStPj3Jrq^lG zq&A2`4+&$3Dt};>p<2l9Pa#7Wi{3>l#M01%%vbBF3?pL$J3{Hs&9w+xtB(jMfe(Pu z>05AA!lAwlh)Z57y#=JP0c3^-zVh;Nm8qTd6|z;=Xwm`*19+E{(@o})oP4QRTBu29 zWP~mbA_^UqJoNxv zvm--R<>sNv73XMe*LpwWusVKo?4t|REZeW0mq^P4L{pCVD{mD)S>zvA+J(QBBuKvK zYEAleftrI9Q|W%dokp~@@qk8>>j8ZSU_L?I-TG&-t@wr5?Z>mBd-n?5O)NPbHxeYD zfsItT9Cqx_!yG1V9`Y&(^|%13sMdQMCt@BRZS=kdu05mRpq?}R_Nrl4v#An#8(*BM z;X+l0B%lX*kVbDi@xiH-v;d&&o|c6ZmZeze>r-6Ec?v(I#M zoW1&T<@fVHClhEGWsKr~!XpU?kM4+5e5z1*4E;xVyk?yLg7co*3eO(<(V=+Mjqb8Z z&(bEq>mI{D^)z=N&3bTkgGk-wJ<`pq2zHG4o6`&>b7bWiLxx=8H~R1PvI|u8&BCmJ zD=3a0<$}4vTnRd`7Z$VY_8WX6RK)F<3IXEu|J~Fqe2CVsW zYrsDja^P?~DAID5bu3URmKe&F%@rjozpG~jaG zadNUL3ci14G5!jQ!Q0f19%uWika1UR9?M`E#(>E9_r2|ch#;~x=cJ<6B%F~S^v|o( z0YI5|(hH!<)r1PNjMVxM!*zFm*35F6{}?m6MlWD=_b%%#0bc+<`=fpIdvX2I zz4{PA4bL*{&p8MRLjQkY7nLW1$M5#u^Fzoo14dvNa@Kii$AAI1fpDJHE@%BKk`PEG zhZ(@K+P9FnH)fq^e{PRWK{-d;!qr`N+3>2sH-$gjx&EGL=k>yz4K#{gh{ne#`1mmlnz?{+?$D*9m$X z2m=m&`Qzgq!t@WDP0!-%0EbNreQJ?2GT=3M3Tfe!K~1M#9H_Uy5l2=;ty)3=v3Y0; z&|&PYl0!Mts}LP_Y8{Z^M8Pm!ac$e811STo&sz~NUQL1HMmO60)WHhjZRVN9X3Ezspsp;!dR!T-z9J(O*2M0;F% zn;EysXyj{aeFK6tPe0S02Qf#9il`rwWwlXBScuvXN^inhGp(%+RTq-qs9l37g9H;47cUR*c|JS;Y0J69|&_lDle7JuqDc{htcHZvs4D=nn&Xwb z+~v$CWm;w;T{ThnP^cvbnmjVblYHBP%^O(V3 zK@+nlRHSFqSEOEP3Q#VIc4E}}{STDaQSA}&y~`q3Ao4P*2?bDJb-i9*st_`v+(7tn z3`8}Ne^9rsm1}%F7*x+mL+cwKi2h6qlb^A88zIO)_V+^YixC4A;#&rpckdKqsJ}DY zAM!f~Gl3zvH!;PZdYV~`mpB3Y8qWILm^ml5fZdY$j>VG`@`iNw2OAs(z>L=@2=TE< z^p#sco?5y7-bQ8LAQVDsrd6~Os)7Z^9YvmVKH@$=2C~0+AmlO0ex|q%R8Ma}ND{T2 ztjYkAJvYM-0J&pzSOb_~ezevJD69It;BG?R0gg*)8z2R}(FR(J>U=`Iu;(0sY}bS; z(yD~J(7QySgK%p&FS$bSa7Q7=C4M0kC7f- zTaWnOclr7N>OM~6p;_=nDv8LSxr(GA1nK2V%GT8ZcG6Xgs>Obt>a!|1;We! z24NseN${BJz_m9!rg6DMgU;cNYNaVEd>!HyAQ)rrMRonbIG_W?L&VOBaP^_Ri637c zDBb_-KrJJ%2TNDpXByrKGOcfv$$lGw-S+o_{lfA#IAJjz>UgoYw5BAKyNzYPcUcAS zkp6k(21Os=oBkii=<-OhQxN;XvZ>7J1k`pP`od(yGZ;&+?R>h{U-c7Seny}o1AX73 zJ9*jPf?QV;Tx$*d^U7ifMES=^{SSx&AJ`)OG(fSD*XjreA9tezZ z*prZ#D9tP(e_VmETwOQ1(tCY&ECwtYy;FLxt8oO>49g+V&G&?dCg}L;)Jr^C(1U|)H-AV!f8zCCMiKy#@CsZ7Ty%OlQ z`&wOc9G-zut%Zp(nvtPe;O-u4d8$=Ll@i7UU2Kv-Y!aRAHp9~Gfqfz5X|am_eRJ&k zH<7|)C2Casrwf6s7uwwzmV&oolvf?<+-t8lc3pv$cV)zJyyP#b!GDtt^vxV5JU}y- z?+?T)tAmrk^N}z*^;+!{{TMC=s)68mFDKP~Iey=-9|67=OaSKc%4Ur2mJyWyyQBIW zh&sulEo&&B05`E}^^ zb>#QQ8M@5BuSoh0)Cl&SDK0Wc7mWs&!)JsaH+xbsQ2xy~0?{{oVMk7r(7-(JA5G_V zdG@zb@DfJ|6)EPg!jEZbyLVkdfJrBF|Gv3shJOs*m>Uu<#}A9h-h5%t zWAEv!t$-+XK)ZTy_|r^eYm z3LW|+>#zNn(o*QAGs7X8?`&FRD6pFNr&^vpS}sGt=b*-1+ps=o#FYtKP$yo(Ad9z4?0xufO4oM8CF% z>ingDNhpmhMQ{xZ%-R$@<2CD&XItWw%FLKtNzp*2+e`f26`No{A<7$7YF0qfX(-LxW5s=W=_7E8CTjz9Japq z3E26tLnwYd_QM08m+JbUetdCNZZbyjeb*n&gWbA&Y(1Q$ z`2@e3K`hSNbx#OlidQ~@rZ5yu6q(vC75>mOMgc{WC?eFa&y_G@Bblhteld9i7WNRB z7TN7zoA;@f*gm*Anh0!g*a{Wt3d)Mcvbol?O%UDw&cPzQ^Pc1zx(tXwlk^cdstN*h zuSYrj^&ClmvBuM5ppUebHXSe1V+FQ=noCdtjmY)Khmepz6!)?jNcQ3tEymlmz;LgD z%P>1V!So$CVu33@Vc@VLYYyvTy9AkUAcUg-8a*tp*}zYJsV$+)~qSMM%CqD6Ta zU#O4?izW2Bu5p-~lW!=Qj-KmuXt1rxklyqTzDI&#O1O%WuLz zM*tdCA+WNxx-|OihkN;Jo!EdNhg0mkIC@bkrRsuUXz;!?gd6SGO?Uu>WdXuoK@uij zm*k_Q-&7jy7r*UJzmyx;1Eq680KAcpUktbFUMK7u7+xrB%{1D@Wwks-IM|w%b((gs z!4MYn*kt!SKk|kwlxOe3H-Z2SfSAEZ62XenSdOF`S)Q|4PVRH(rqHh0XDFDn9|40i z6N5scAN;;R9o)D$znZd>6Bp#A?ZhiXv+iYhyUTcBjlROd8D8JCq9bpv(iktW6<+tf zn7Zu=qAvn;IgwgAtqm$ruAL(d5E}N~H|RfnHol`5Ca;}$Y1(y_PI53`hC*RAhs>Y< zPgs?>46D3^3DtSzktDpoT5h&m=e}9}u+@|Wh?Ct~5xcEoz>VY^#964KFq&_4_C>9K2hztR zFrHYchY$DS19DR)1HiavrBdDE7!!Uo;!8arU?8Ao*YU_{v0#1c7T|tmL3Tp-hDb>b zq$tB9(S!2=i>TXaP|Imr*r+>JepCMUWM}IT@UiVOAb-^y9~~_KNWWPc4}q0zI*2nt zt_O!Y5JLjcb~`QIlmJ@_va|w7R0z_z4)0M@%&mSg6?kBUl^c~MBCloR2|UnX!69K} zA;0auHz$DE$nnp^S<{IMBM5h@2VQ7p-d;M_iRN?ZoGv4D*U`u?-2;?C0@Q3cJA36J zy%q0{$NFo)JT@v#hm5b87zkpjHk%jkg`KidPF-sU8AVz&W;&bHicn&I z{PnQR@)B+XOkDk++6NM>$*@;!$(cdlV(LaDfYk@kmW?MV)wtXzsBY!yI!LjbCrbF_ z=y;)?s18Q%+VfO!4KHJH7}muJm1ltWUQ*wC7eql(U?zkWQ1sIcfO-TJEwc(40)8ui$J?#ZOhHXZhFs;Wr=Lf` zvvun903H2FPTHAzx%%Q)Pellc-R#R>1S=CbNP3U_WztT=zz~Hx#D_-J7lw+Y7p4{c zmZq0O9a7NVZpEiXJ00soRP%!|j`DUi?d-}Uj(?4FMTk%uN^aA{1V zzP4nnRJAX^e>fsHdO73Mr%wYQ=j0XFGAvj>Hb3?}C_#|RS-bFjyYzh`z9L>Vy9!A- znl4U3TsXrb!(+eZof2twtQ_?_Q+~sU>}XPnkPVFx3Ui}bLPD2>i$l9jKvVzG^DXh& zR(Q?VLyei~-s3tz4*l_MYx&iyGnMC)FWznLf`ut7A?ViYBZax2g`h(S<~4p{!1I7s z8JpXx#Sv)of*Tybbt>DY;5!gb2fMZ)FI5_aY(&*oQ%}M^bxQW9>7PPyOlE`Yly;zP zdH~3aO~UmEXxURV+W?z@@IP-bH2i``!DDXUc9y0f_C)Z;C7v542-L7+X3EPX2S)wy zuf2#{5VL(^}4$Ff-q6+PfMEP>a?g}&4a*qr(90r&mws7?|bHU|@VPJanD56_L4 z2EyJ{YUA+mEZEUjYaVcvZi_$D?*ZBy37x)VlOLsyr|#25T}daL7r^`wL&Z3t(w2Rw z9iJ?P0n<))YsE4Up$*ggRj(U}e!*%K9pt0VyL|=i_$>hg@t{|hbWll%rcqCajM2? z))N))NKJ1ket1pRtgN>-B+L5_oBp|>u?>YaKQR@2SR#Q6Fws}6>&aCTl<3M^hf864>7ff3sw`K#>w~A*8d%kmkmeh)~9G4xR|?$q5jbCP5Cks$6w0M^evZ?&x{Sh1k%DK7Yx(og2*L zlb$(Q9TZ1OQuM_$5S@W%wLs?}tkYq>2|cMU*U9;0+czQ~*c@<{S={oL5^gExK&$y- z$c%NbOY`d1h4RU(6eqs9rDT3w#Vx_>POkvtsLdB2=_P@8Twu_;_jvZRJ;B7?tGmxG zNUU;ZQ#9zH^31>yf9SdXKaU0?d}83`;YgBdK#H#Zb7mrY(8`iEZFja?=yRhjZok#B zv0LgE2H^g?Z1N)g1U@-SYPCG#R4$i6hLoY3>}gt_?vLUq=K+F{3}!TI@n0cEDxkd{ zrtP}Eb$RM>55Jjh^_=sM7l4|`jZ^7+g=#k+^OgD($c#n5xuD*P;^~??yK^uEr4CSb zmA6YYuZtE9Y%4Q<@itP;o%8G#1gYrWn$(735x*4KsJhC~$KZ1{Wv&!z{T?cnqHTd~ zz(Tu7*3I_c$hd{DSbKnn@@8YY6rsfl$Koza{z+B(An*8B21U>=vFL!m4UPq+{ z!O8`xPqH-ulY6qxAQ#^=!;bUSA|sTlgH7#$Km~JV>iCS;>KpqzO-%8hj0Z^_ z08U>`b(#r!+?idX{s6A#2j91(n66Al@$$>3xf31nwA2%$di4$O&>FMRusA-97&f#M zA9~9>#oufCx8&H!{}n9)VKUp%zrcZ*!+@udT+Y0Uvy?fAWhrjg(o1E+_ z@B0e-vE?D z1?vFSWnQ?w`5WEb`B$~=5)B~HsLI88x6~g01~I7$Y;SO1so5tRO@FDaQEN)VKS7?t zeY}#jH{-UI__3lwKTN%oeUe(aAeOY|?2ric^Tf__pR6e=apT9A7bk~Xr3c%~AP;4K zZ}U$Ms{(#Ad!S-W81wn5%j5&uue`f?D#qT%iwKH6k|a(Cv$8pkV}g`nz_4m{U`^XG z4T8zFeQe|eWYzG`k~Hx!^cFYsN0?yTSS~^q#r+--gAUhgtbt>t@T=hk)JQ^pkKx-! z#co@5s*kK@%Ts}=VK#%`x7NA~Aa`TxV7qglARSOzkE@d-qbk4q0a~A!X9~)eh6=SU z;9DXZxKsJus)T$5n$CV`EJPoQ!YlE-b)H8`;&ywl6U%JW-4E&J!A7dxXU$H1gaw^< z<#J`Vg)9&yB_uM3m27xW;385Sk*-g)P5$%f(CY|v3oflBeKKrEVJtp+<#qRlZYE{1 z6i5uYeiS3b$C4WPPXsrNn{BCoy42X1|B&5p3a(CHc>&aaN-fn>YJKQ z@2}AaH3M-J%w(r&m&fkF8um@)s#BbP&xazl1sKVwDLJzf^5Z$MDnJf2YEV+G0^949 z)A<69poSiZb1bp3$*V!rk{nDc=MKrfT)1D}X-@_FV5oL*OT1S`fv_Wq-9}%xzm}aX z5T-4F{;a<@1x8Er3BQP|bZa(SJZ2vLS-#;Yf6JJxb1j2dI*RAHczn5QoZ6_!jouSb zMHxkZ<&Mq9qOa|Y;Mze1y7lK+9)K=w54M6GD=$Juhjn%tttNZloju1nmdEnseXzg2 z?aNM@H`Bcn%@_y=4Dxp*pXL&H>DB{?0wT66EP7*PB@m+_!Q+yl5OO7OI&FSkOBK%+ z@AbABc>ilAK<_lwb`ep_t_Ox-D@~OQ=G4HAq~TtgH_jGTR{sS_v!dKB0oma zDcD7TOgoIA9Gp5eAzvNcoMl$FV-G~09LCsH>0|1Lc?%k!-*Wj0*6u0N#xJ}Fo}Sa>qu+ouSHkGVl8?`0C3$#D zaLnvyT$c0SPY?Pds%8oyJ#P^zT~pO6-sDx$_XLu#7vE}ayv0BFl*g(0h&qmbO_WDB zPnUqDY>{jd1xf?7_ZJz_ z)JTmt=&uoFc_8BCHk+f?geb z%-Z`>!|We4b(W=xl52hzb)IzkEk2(BXu70mo+Kh1Jxo z5iLe}|C&RP(elBgvWkCS>50^1=KFvpEF?ULcrUQlpu?m6eku}8BZ;6tl~F*;%ZzYX z`DdyK06EkN6$=s4yeiwx8~Rq-%$6EnV?8VLvLUp+sx_pSDDM^5xq;bihI{`CWx0sf ze!tT!y}fd|G1#E8_o{h0EE!V`{>dU)1djk%Q{^#-wW~HJikZrstadY3C$dzR*p{itNhpQn2ymCP0fK-hE)03Jjr*m%>l08P3Sj+Q<8Qg>>y zuKIs1zmGmiXJkeO=&?)T-wa00uc3Ihm%m4E$34oUQ);X#pt-Y&6rUY>M zj@Jp#0c~U!NDu{5py1Sj(yrMD0MDfZxn-0@JkQ&>Tkp}+PVyBSgM|t3gH4HrwQQE+ zlp;s&0vdH`prvBY3R`p&p&T{e$=GdW_&hPc%5UFt=Mo2UzT`)wT7XnC>0o?v!V*F| z`ptE{xWKx4lu4~QbRC#JqJTYjI-}|6KWBm7rC{ssy`o(X_v5PB4;5ljq{EGFP6YsK z*J?lWpil|oZ$|Jd1AsERSceL;q;7o_VOE6udhye`Vmx;uPAMNX#ZIYKi6W%Y$G2$U z{7FaCwdf3Ot-BPK^S5OsB!U$R)B#g7G2UVM;~gUMIkaw8$J+ZwC1gc|-`js}Xn7nh z{cxLEeRf8uascEWp@~b7&1#-vy51`g46%8_wtX|^_mCqVr87n=D!alny>xvwB>fcq zGr42V7Vk`r^A=|{S(9j=Z6X(G8<9Z z4~rh%EWCN=K(V>$EcRxzBX&4BH&P4}*oU^!kxhv^Nh8JvZFv9kzEMYz( z7An^-ue(`k;zCv9cZgoK2vt3K!_uVHFk4h$6%{S|y~>?5ZkB|K_+cO+AhE;l6Pzoz zPq2s10y+to#_Df(Q{9ry<4=mIPH3jnJ=Aur{|bK>%G!+ zmfTW#8iQsn<4-*YHm;{@X|{TVn|q9yH671=^4&wX-v6paF>bst;WkM?J8zq?xu~gB&K)$0!fr<|J8tjYtr%sr^>rM8dd*}zz!=Y`TcbfS%ilX;bnd5~1lo15~C_QVO zdOr#V#QIRDjHSO%PhBg1>e+T%rAs$DWMnSeU-_{3_DC?8n5d?<1`od+?x0zU!ViQY zoyMt^j;5gNhiRj`fgYe?XWuUh+xuSb(RTuEw;Qf2$Ls5Z7>?giSZT{|k2QtBmFMU* zH>Fg_zxl9PFUfIR+m-rRXyJr(1gRwg8D~0Il3JG59;p7KVSzBJ4?C=^o2=byf)7s! z!48y!pJvB_m|xQwZ{87dzX)S=r5W$M)sD|@-x`Eh=+g$jJ7zNH_2{k++0Qx8?_Lub zf_Ij@T+WYfql@I`b4#0i{jJ3D%luOatvZJRN{j`F0CTUAPXn!qdsfQCvNlm1&Ioe9 zhu$-JNoBTjY%t;hXyy}O@UzNO+IE6>;Gx!J!7=iqmeZ3gyk0$Lw@^G*F>;5fB$q8x z9L!`g1D%djW;{;IIOgGAldj;~CCTDb9bPqB@O z1*y{Kw8Mk-%}LFg$Ntzrdh`v72kaxkp9tZ&-V#4Hg-p7Ux|Mm}A&jUURSc+1fz=ZW zyo91IyW|C;=-c+RD$+iEY?iK~a_?wj)Uu-Y`pv)1j#HzpFjMP?QJUC(8!{PEIzO(D zDOM?xN5$avgapfK`$&&hKRm*w;Xj<6jgHyREaDp#dsz44l>e@8YnUSVoNFwT_7^4u zCrbM1_^ij=lz9Fw7pyOAHI&+u$W?gOhH@j!Fl(1NJq?oiE|~OodeF&M5>4K2Ym>Qx z&x`c}{jnqCz>&b_VX<+v-;v?-=lCS3Xq8oZDG18w#hdV%^bf{=5sc#n!sOPyU!1x- zeY&_OhD!Nj@`?Nx7}c9s+n;b=-Og{tpyJ?2d|yr~$KJ+b)?glr;r+_{_|g2fS-N-N z4PjxbUn?dvt{40T{1^X^uD6VfLW|nIDG8;!LAraSOS&6IQ0W{6q*1!Nq@_EC21P_c zX{1X5X_S=ieD`?te(v|f{pox;zu_F1z4uzz`d`;VvM9r+#W@Nfi-3F*x6H!xxCI-4 zf1N(NvrM-MC4#}haW}{y7X>-wk9_(k*nfx}^>#Gda1)%!M%3vM34STPy@$ehu@1Cg z4g+cf`>%)bwj05C^QG15ejW|JtIG=l8qkW3W)r2@EI+2@ZU zE_+;(KlnmVu3tT%b&8#MgfGI1`8~GH4LQq)YW#&2=YLY$B6cA3xTj9_+oRtx-WCHx zk>K@~$zm`Q_9n+oLd)@L%j>SWa>5e7?2Yem_Ud#0?~(~TQ*2*R$)n-i8i^xu-WeaF z7&Rw!(i|GiXZkBGp8wU_%uYY>&CiP>tmFU%&xkE0u55rBorVdnR6n5~fo9F0eWZPM zyzbr_C6(o8?u-;#cndbJmc}uj7ZSq=&tP?)-xI*WA9Cu6`>hTyFT(3^MCkcI@-pHq z-fDMF@&`BWasGQCo$)2wArry!#FkTK>$>gY!wT;k-fF6=7ft65KHx`Krx*m$s?FjB z$U8H2T5XYL-n;(dn39P!8_F7HH{$t?X6BxERPakOl;kx3WO*WhV)M5v{8)Rmpo?o0 zpSESc`$FjXjL_5bwwTD+3@w?&#YQ}rSfURnGq6ADVQ6F>_+PN!}QBa5IZS<`0v!`3=v+^r^#+GXH&dm zo!e+9vKz(Rd^Hr~%SIaNx{jyLS=dw7a|qwIX7)ZG!-gjue{b21U6Q;LM2U$LSP}u@ zZ7ax;ejHrr3i@@_;9~I;0$2?8o}auaZLGC$7v)hdDmwO_;bhc%_l4%G-@@u}`{k@Z ztJ4%#n+Q2aq$yk5(26BIK@rVQuy1RKJFY6baVVU%qcZoZGz!9L#3q}x;IH^t(0H1VQ-0Pn{qG%&L{P%IcO(86kcZJJ|!_c_A#IQpoIlNkzM( z|0{7umf#X9{b{+q?~dA-sU5pT?8U=NDG1(ZxAyWVhk;1nB7noZ zSz5HiEgkCgIiIlD^LIRZ>Vf;P54rcoei_!!9}#DtHPTPa7_`z&V)j9jerxADQgh zoHvYdJHLv6_y|0Rf^75cK=5IRojE^+5ZMQ{KM&cb$g3lt2xLHm9onZ2#ih4in&0c` z2WwCc^&2}W1(Cnv8fv!1){XCE)4yr2BMy7z6GcNSd)MUSOUO0gb+*qk)aLxnu$9a# zCw)nNoD732rp(RB6ofeBm z0oCTzG4qlyz065qg9A{+)ANKPJk(8{0# z=Z}DJ#>k6+(dajP<@=-GuTK|hvSuL^Rv@{+JiDpmCu$R#$jBE_GWmyh63JLQ6~xic z5e>_pUIu2GBfO^Vpr5mX+c+wd=d0T{6iqbhiZcNE=#rPJafPuG*LADO=vgmI6R~J& z%L}#Y<$ZUP7H8jL)m^x)v+Su@1HIdi3htnUyyw6Ytd1#SN|$N!W9|Nx`j>=nTURj( z1yIybE;igUuOBx$JZ$XpmY~Sm57%oR_k1pNZo{Nm=11o{1@XW#ke z4&!C$T@X908=p-J2*$Z%_;Po%uS=V;kzqdm9#nSkr=Yb@M^7A;8a?wD9x$6Wd}5+Z z!ogP;{~L{yA&{*Bz#i_@J9zUQ&AgwncYE^Hlg5YDg`yzJWV={J#j~3rR0XS3PaG8& zFk8hw5-cO<3&5IlG;NzZtsq!~91M)FnY&7lN6szjR7JdMFgSRYjU^tH-C#sLv#X>O z+&1-`bFY?Z2kU-#$BnaGNv5|a=3q9%bjJ)3*Qvh+l=l`u~s@p2%B?Yvwc!=Rm!6LCzIxc z7D1hDfaOICsbH}JXz)K3TG283e`(P6F8)#u-#DdHYLbsJAuX#!idlK57`Y?iKn4K( zzvPTb8eC1AIBGUGV=Eo8jP+kn<%pZr3`+=o7gKiAd zqQ1X`es+JetWnT_n;&3dA5XuxWaXTCysp7tkAo@ToHR*V!4m})OiFpiXV5-*QRw068n}4ZnZT0S@axK&a7p# z#GL3#j)k~({$<0!=aq7SO?}l-Wr$m9CSp}0yz*WbCw9CQ_?oaPFFN)S8+VGraGF0> zJd=b+?PYCTZgASSpBNG@i&HQBgf8 zPrg{~s)=mU-fBAdhAN5%?fAdOSaCnU2@UP_^0aPdb1s~-HLb9^=W#o zOFwPr`z?)^ZPTTHyxXXBO>ce6u-v6O+1Xb2v%uLYY!`{g=U%V&N2dC}*U^+L(x-=K z7`fQb_Or<})6x@uc6m)c(4u{solMr-)z*21)mks16Ig@>GWcZ^m7|HZ@|KHTbovC| zmu=s94`ht@akL5 zF4^sLEeIL2#4nzMq`=u)8$_)?TTxjd1`ddN=5Hohl8sIJiS3hH+tjLL2`1J~e7prRi|Sp(q6AA1G2oP2Y3abTgO_2%I- zx`RdGLSf{i+f7dWWrVi zw+`jbHuTVjV;RUwTi^ss`QN;&CV;`CAiZ>_N7$#wV5eRY$kz|!(EWaxZX$adYTH}t zP(%xKGj5djc8~a5o>&1a*cNjmQ~;m$jbMgM+bzgzEACax|1z5$ zet~l!=X)TiqbV)OflFpL{!1fD1eaNc9~HUmL6yyNYxlzQu1pXG#>m)h+U75_hp{ih zh%RvN!ZM*21*c7Kuhk+yK&IZx?7MROsHZGV|Jh)HiRZ<4@`eECc)$C`!7cdnkF>eD z9#w>#-;8ejp8F6!>rL0h7DN?tKfC&wD+`K88$njtNehJawV+O_@gF@Np9W=d^IKam z7UcTgp78W{dq8&bWQ0gXq!^bKM*eb3aN@Y^xH{V8z8YyS}UgV?kdt%Z;6~LX?0DS_q`9H;TIb7bZb0UmG~<% zY{&ndE*=c+H{F4g;*@gzmI1>ew;)t8I3^KQ-rM{>9x%2xh`Q%&7&7;whbF2qz*j`D z?eIjrq>wt9Z;^hZ6U2F2R^P;UQ5e7jUu~ZJ7FQO}Q#2;UzYqFIQNgpZ;;&v^J6i*m z9}6QPC2BOgc1p60F{e>8>G@|#yH_TR3k4u^dY$R|Eja1waC4Uk52R362I`8XtSUWR zCdu?pN~aruqviv`dW1I~?t;{n`I^;tbxRv9)~+AS;T%`WW~!#-Kp=o#NL>T;J=5LF zUd>a$P8bbGb<+tyT)0I26Zm=p1_MQBc!D+P-R6&&& z$i4+ZAQSyR6Af*<-3;OO$X%3-p@=9J&{tg-Fvf$(f{eBP6iy`sY7}4Ba0V9e&Ep7{ zS;ZC8mVODnd;X*cnfl9Y6KqX#H(#?=Kys6CNL_*2Nyak*qUdYuCpKs;*YM>D(( ztHH4~Al6VF^NeiH&dmb>or013Bx0Yfq6hdIO@DmVE{XL2Ts`|_w$)pZM#PyO+L)d# z_W>hcUD{vxP!M&JzmlCnCs%4-kCvryt{|(R${g&C=!lYgGN7j|hRQ$g0JQt}7P0=f zHVJ%7Tr{zPMM(8QZ@0DJk9rOGFMeq=89p&$odv%m9iYCn&b`^cTB4Qf<2DX9rtVGp z?l7)(qQVjubQJM6H7TipSE)7hKmlwyAvS*tP!-it%u~|M0Qv%%MBEB;5Co=M!K+M; z#+~ru)7f%##9<^8eZ(9390$1@yUS7Xhz_~1#SH$PeejD*hd<)9()i+L0Ff}mR|)h3ze z7R+CKuu zUB*JjcW`VGOr)hskT2$xza4~7+ia!glwj55=B0I$Er*hNOQa%q2pR8U#EsP}w5rx3 z%7ZK-wC!%w7Nr04gk$skdh_puTOHsRW!lbjDQlQey`Ip_{}MkAcBqcwsaFJ!#UMWI z4=bGT8h@mcb?zIp^b>77rYAdt zKyXvmngg9?5NkR#I5V%c2U>^T$s;^aA)h}UETEuhcowc3ldoDZ3emkuRAJGQI=51% zp^_~@vB&8Iiw+lset$)aL;)N-JEBnPDr~BJ#Mb$w_R3V!AOY) zm9Mh*!RmedML2pr*~MM*i^zwvK)=Se2PDf3!}I78i&$X`#Rv#uP6`HQAff7;4SyIt zQg?sev;7e{JoY>H%haJb=hD-aX}O0j$1U4RaRDmueMQ+1w}4B%B5ZFk_ucKFctunB z3Hloh;EjfkFCuX@z$05o;ag4AMadb-5u2h%SjaS$=l7}p)tTgnz=d~dk1CU%pIj5e znkNq1+_ma{^@518B0HVK>*!C2jaVBIftu|o_Hg;gWom`C!~JU3;s>Y#JHS(%&9uhG z72!-j3F1;7{ltS%AKB;no@6jcFSM^J;uGlfOibt(KS1xfwIde8?#lc&cwij@Mb*96 zZSK`(SNZt8z#YcA#V3M^3!;>Bu~fpkAd}3!5!)#c53>%33L?-$DaMO0zqR0H8Ftva zgH^;j#dXM-WL@NE@|LfTMReMSWfbq})2d8MYgHIUo__#;|_)RMf@%DD97hFRd@n|JvK(?j}Bb5qc zID;9@y*q|F#4r?sM9V)1&>~uf_Ngs$2qo8nNlC%2_}pODH!hVz9aPN`I!>JM;+^2v zWnGM;yc{w0vHri&d_|aCNwHoKQK_im_iAE(_az!XcK$ym@q#ujd%p7jX>@_gEO>Ps z@>|tI{`xmV6+%wZxvE=fSZ`P~-=yiA{E-El<&ZcYJTX<*b$Fo3iT5*82UTy-F0r+6 zu)Y2-REwYXzfRsSLH`?{;+Vh&FivBvQbx^6Zjc%-8Z_n0%_~4IrD7{LbNRgn)@cCE zzPz*6;-#L)QFt^(veM#Xy7hn>l$k4j5?F#)P&f&!Ld>JNAt^AyKnTd{Ai2#l{u(b- zhOj@Q2|ODP3l|ujnTbwq&s!#Gq+CM$Y{PdJqi`#9Z@!&POxWv9I?PVF9e*l^TFM^- zI6EET=VCF8VABD6=+V2DWj)jZDqb%()k*2z?#VUFHs$OaPpf8bp`lZ_PH{z525kV~ ztb#@SC!9swcIRt61ANC9p?2!3K;2ksAVHtnBEL@@2tiGY+X@bb745V+-c_G%2tcHq*(3(EK zRZKgJSU=Lry21w&l5kRG_#ud`6D!DU`hkOgK1=EpU_xMmeSepbe=i zvKQwI?VazpRpI5PZBo8~()m^8VpR8wk8^6>Ga`JUfl)3AI*1Z7jVxLx(&lu0-Q&C7 z%OMC-V6ceo-Ucq-elr=L9tBPozmfncZza74GVv#b7 zV_-cBddU2HIhyxDt_ro>`3CEaFQHnn3lw|@2f6rYG0JgnYqbO0ywlg;KD-`^QXK4; z=3XGcoB(by#@0i(+z{JO`t0|o&a{(0%KRIA*ZR0{A)X)^33{Z58o@T|WgBEBp_!1j zqEYc{t&!ZyYu{AW)FA~uBjQ-&CYwnu`=d@@r49J)OU`}gt)jRfnJ|LhZ1Hz1PRwF@ zplQZkL1^Z|&lUTvHIz>N5H%4PfAN^oQ#8S#bX!6&`3@9Op#QOI{#EHv?_F9Fb$)~Y z>7%E=@28Lsh!q=FxDr1?`5z~ZC{keeDbv^rFVm>Eb#_&?P`xRK2A!|&ef%AoY*e!( zj=yFbEByc0zWOsNw(Fi%eB!Ywx!rAbsfIshZ;B?Cu2}6spD4Yl(?JjN3 z=tKByW)rLo995f_i97An+C66ccgn-6+H~~Dn>%h2TP&si)1dE7-WN&ofNegw@ z6w|Ox<ndZ{|j#67A?Cg{C`+1KKhC1;Niy#?Yz5Uf@}nYe&n{ z0{yEdL!uW+yEm}h<5f>~m^A#PUPz8IKE#0e4jN7I_hlTaB&ekh{PQ726f_tfM`ziU z`6ZO=J>`d$9>KbjC*tG#vjlZvB!!LE@^#(0&=vE^+(-Nd@KI~Wk-Wf{im>|4l;Qok z4y!k;q0mCv{`RSw+|{=}=Ok(4fCb!1W61fMmj1nHA5Rg^Pu%`8V?R%TxJ>2%gf3kW zpfE5`K}p^xeBKzhSBI+z9lF$`hVK9a${U@%ox$o(N=Od0S^08LZ#x1~l(o1Nl0yIt zN!jT0kLY^>nSwkGxwgT$$;gu5H=bWJh>&#t4)9Gjns?;t=RZ_ngw5@4apy{c&E9i9 zhl7n?`^yp0YfA7XD1{DOwnUqgYPiDs;@srD1M?(YXS_y&-g0;LofZMX3uH8Fe3rM4 zbDLy5g&4qqV0K(VmN7D#Gbz<9{}dj87x8r8aqVH9VsKpDy>31Vehs*e{oY6Ql~3*y z;)Ux9pL*ysvS4y=9J-2x@xP4tHRWdvn*EfCk^8~NCKkkZw@ag1cO(0a$iD|2QS zXHtLnsHeWmBE{6n)yysvOhtc1CQbP~<$bix>zA_3=CtG!`$H_~X)xL76ndA5o`Q1;tq|O_0?0L&%az{YW*SCv&Vn|?jUCRX>P5q8ZAlAA` z0<=C-v!(Ga#6!ycP7S)Fx7Q0Rib?aAcnMkp)7!rj87G@hFgeNJThlknM3z}cr*;oo zWhs7=Oadz&tLp<+gtEpy?y>IYA(wavsa97cfT&po&d)=k**)+3Q6~zL z2zuJ*1^w=b|AK~Kw>;kg%}M8K!^+XUB9jsVSc&?Q3#A?KJ_(j|QsVyztIr(C_MEd` zuGzwKA#D~IG9it3oXjl zP%sj*DSPNFeJK|BgM28@*loEJtKr&Kzs_cE#{ID-aZvN^g3Kh(2d>8i^{eijI%Id; zvY{OnwinkJV^#9xBT_vOZdvAw)70$PLZ(Sj&?L z^rPlb;5(xFot_urM}e-87RcLbCUnQ~_V((Mmm6U{1*vxV+g%!H$G3g?l=mVaHT+A+ zD|8b06wFfrLJhA@9XWdC>E~|I<95LkXN}iV8CFvM(tM*oS;!)Jv@LutHcCkdNLIef zpq9{cb$zh6h<&jp2?kg$Ejuk+j|023>caHU%xOB0W72hhJez|2CDN-E|M~i3${=mA3pwN{#~=Mv!1~%1r`>R%gzunhzcM3;%&hDW zt%%7tel4sMuRj)!CD9?Ru-=!dWZ#8nADFfZ1!tR@eq=S(1oK`dm;}xdeC`HTnuhqJ z*>si(v-vI49HsQ0!@hrqI`RIZjsLSje!~sp!w4(7Lb(C{zkmt8!vUZF5^>Ab&}q3@ zVy~Zkj^^RWo8jWI?H6l)E>fCK+5Z)`KxTSFKLYoa`ceU~B*ha=$(-ftu=igK6$2ktrExaWDQPQAY`u;DA_V=qxc6b{Tb2ild7Cdq$3c zMK;mFv3UvI_+4D~?li6Mk41|4^Gk*G34|6z$h!^3JjG<*@@V z<(i+~Cm-+4nWjnxJz0t`rG~5fF8)Hx`Cn~f!+ptnO`Db0#)Rq=rTw+tus{<^%EeUo zD>8@rOW6nRy6!icMNtrzx^Ajnw;6i{`D0qKnEhnffI6uRMZQ=a!pOh5 zS!ocBR{jet1!pPqw+{}MQWo;Mg+FOarGz{y(id~tm$|#?MkD6N7j$r3k!Dy7+RM$d zwv!(KwC^pTpOnL1qnVwM9#AFe4q@&3b zwPGw%liF$HhgeJ#vrKND>YJrQX^hHs6+W)Lz8j!zvr4#mD$it%ST#!AhqG}(vEqGn zrt@;6D=j(5kn+}shzRZB{lCud{C@VeKNV^(7AD)nLCN#=#I?JfsoD)9vGe8+2TRij}b*Al$!s&I{e}5K5Z0 zukT&$0pW9@{m&+Dj_+J3jhm_fAHzvan-f(xH{aC!+nJiZ4#&FM-`f08s+%}=s~FNB zxk9@+yF|`y%0x6tfXov3_sLzx4Kx=1S)A5QQc(18p10Q=AKJDpL}NVp2E;_-(Zy>H znbW`i`e%~U$&6r1mZWH*$oEb@Xq(3OcxomxDD+lT2Tt}aC0~H)Egu&x2p~}fBF!j1 z`xrJg0srR*yIVDrQ6r{x91-TUV5h)`b#QeGbtts}jttu-R`tUsbDGH0>FIcA$Iv_o z1J>_HO-#*yvC$#j>9(xyPS>NEgY9Gn^yyGJ5qFlXGdIs#i zAcVf@td~s`lg_yX5()8PHUZV}!)NU9GTr3aVydvWSWR@#>9b|5`*75jNzRs>uiSR$ zlj9B8g>E>WJNo-SpDw5l?j(%;EKA8mUVO5wfi%=j{}q}o?{A(0h_2(kLy@GHN9*P` z;U~xi$i(_)&@P$~k+R|dtD-@r>JeLIcE*6_Vw|6KzoHLKUFibWa6PWh_&r3lYJ{wq zr}9EQEHL&Fu!e|-e|6i<%eGf{!WV$gbXEb&`!@hxNRyPRsv-8Z%tX zZh=EYgMFyo-v@Hj!ny(x|nTxd}rBoGgNRUjU9h{JS8$bE^4MTyEHajaA zDBfSx;2t!N-r~E|fGi@ zjvAoU--C3dx*TERkn<%NsrY5{9yU@9w;0fVcs2Yl3qZBH$nf#_662h4BqZWBK^J9B z8^!PMpMrVdRuh~_E@q);pzfoP{TSIU>khV;Zxm2PL7Wb~EnD_K?2>i|K*xs%$X4+a z$b%jM;Li@MDC~x_lC8Drm97KeIDK!wQAZ*!IXeOZ9%eh>&|otic2EQH0$Avl6KhGY zUr(woc?z$PoW}OZG~NBJfX#rHB_SPlt1A|z2`2i*sjFW z*xZgr$CX{P*sH~XX<(53w38pX9fDObK@Xf{dnq}wcR4dJ%HptD+gL0+0IuI1=a zvUgg7w6XnmRtBz;x6%`*m;VJ&a8K*8vSfhWqa>;661D5j>wu2)8er`}2vXp9QV)N$ zO4E9ut9KmF!mmcXh%SMFN2^ZKZ=~#bt5uv`Kybws#0IJYezk#t**o?J6f7b6Yh$O< zPwdH^7z0jKM=X8EzT2SJp{o*KUj{=hCA=niYDj@U=DB}92@Kl;$AQ|gF04|*(Z@=2 ztb`*=*uM;F|0S4gE{FGw9N84=&=#%{M4RIK41{~hT^=u>(?(O5EBoggT z9=YE){%AwOIqc3@77>MolF0D)Wlu~s`SPEQ3dHc`|4O|)(6MEiNai4#J{_^!Y>FYf zrs=v1@xP{}$?wiwBZ3>dYLQQ7qP~KPHkjX~nOT#@v-(fH0z_9}1!U@bJ|^Ocr;*;9 zg|a=2#pQK?P-6X;^MNmlGJ4dLSVUXt#@IJY*`03xHYd>+sN0~PMq$Ofm-<}`VywQn zySdqr#!aeSu`$J^pbUA-)~E2_lon89;Yhs@MrmHcL>HV12g4ydwI00G1LnoKXd~7& zH<@0n|7KMPI-|H9SVgt(-0(Dp#eVa|jS!$8Xs=E3554=d985j?(<;yBJjd6zV@hx; z%RB100%@4}M^6~V-6t(c@V}2*YE!aT7($I$sjoy`Pq2TgF5->!=MQ&uW>!$>!Iwhb z?tU*%#$aF%8$QpFs}v1F1I~2*$r@8>JGWwJ2d>Z4Te+xE3ylRo@YNQXC4gzS15l#Y zcqBWuo|1X|=T}ho^6R#7Qu*^IG1z~M-U?fBnlSlI))a9NsahO<)^o=qGZig?F zeHEl})oYMyE;<+ObaLF``{7^qDZq+I`PpZ8ky6sb3c&!YV?b!GG}_baw)0amXG%S% zlmt~jaukF%hfHnv3fV$~3cP^+>i_zK_Cf;29y)3`iPZ$7Ug1?=aXQ|a=6$jh>wh54hpc*3c1wlcHtdzF*5sayEgAL@{OgnC8<_rKx5W}NspV&q3 z7jK}!v!S*$&le3Go#?x_E^Bg0j@k-)VptLcPJhqZz6#%;#pqWG^G;7bgzHw;$6CF| zwBW=1!nZ2@W_Dik)N8gy?9B~cw~O|pt$s@;iEk}el+6Hc!_UbES>>fv@x@viLzpNx ze_#6;|BY4UKVzKjNEwSyXuxsF@ld00Y-3ITM+FHcWcNs`nA_hfOS|x^+f&gR2aTr- z5pt#-sik%sk(au5lUk)!rPc`D?Xe7fx}q@xsTF4{WQ>cRIDBWeATC#s|L4WbV~?-G*7y{8CjjS#9mA^vRCqY z&w9*}6T*;~lGzqJv3q*J`m4*@<6n4dYoKgY5+%lvGQz|z)n>aVQ{2vnSMy8yQF#Gc zl5s2YchTcKhA&HJsV0s(Q5YALZ|Tb2bmZQlMJrr|Kmc^4pBMTnRYJ$>t<@gR zHOXdtHS+g;P|uyyl)v3r*&C61qXnYntfL)J=|5O2R6c4bp^IBzgY37r(80F@zg6{U z4+b4xycd%0q8vIy(8eLCFp9;ZtFdU_jNf>x$zX5VAY}-`&i=9hfV5thw`NfgPr<$k z=YC<@Utry+AXXEK>~rp9WF!1@2h$!aETo1eHtM*@RhE4*=BxcL72d0!H zJ5eH^)xq%VG&B6JKt4YNGRe!9%(eF^c)Iu}StK6#lZxz`cV*^R*=Z9-rp4Xj`L?Qe<^TDiIIqII0 zjI1McLNN5@(0z#l>1U$_cV36uSTjwlN5eR#ywm`&p=$_79_3sKJGF3esTaPFM>MM1 z9Re*>i}DD3K|bR*FQIOAbkf%Cj#penZ4kw`etEmHZ_7s|amKuP_}G+@!}GF@>%7aS zBq;P^EW9vce`q=sFt=--9Y$n&hlbT~WAlh{&I0%DI23WtK`I246;F-Xsl?&kh2dON z@M_b1kNrvW;_GdX{ngBWl|MZu{@mPsI!RHunY{MZjfUV%TT{L1cQ1FB6I5B;za4)s zBHhL+<=E4l9=?AuWIy}1O1G15Z?RnPCt7OW1Z)wT!j2xj9hqxH>TD5p^GiSRD0$Xv zoN#@{TeS)?BlvrOe@sU0o*@lNJ%>XZvPobZ)1(*`L_{p=hzLFJ4vO>L@9*_QJ3q4v zrsvc!pTwz{X1K`WkY!4-qIk~jV~ z)FEFn>l9N0NnmEZ{-m5!c{iFkXxYFEh{0S-V{1V`-5lN!rNO53r1V_H>lGRb35?Q;8iE3Mwy#l9r`ApLKLZaFV2W1z+lcyJ2nlRK0=Z?Zc3`I_QP2qVSFLccAdNHBt_+Q>%Kex#E5hIq!mnzj@6UIbKlLtS8_9Qhx9oh z^pASJB=97=z&(IRZanDDJ$PyT;3tMDxN+BMa4yv+g|Df+mKKBV)ye*xL@*9!)>pee z+mVo#k#)NKDYP;E0Xy$cZQ|#&Pl4?-#7}f2j|Y{o+MGJv;O#5vIg^hos2%9EoDW%F zZzNMp>ww@s`$PsJ^e`5M6S!gQr3=Ya`@*d6DA07v^luDn!ZH(p{ZjIu{nA&1spQXz z$OxDDbcN*x`zpUV5sn2}1CsjTmZ$v@4<^JvC(_<}m^U|?g_pCxO)GXmLrjou^~i6L zjdOKF@Xwq4jsUaNc*Vm{Oj4(ERQazJV-55BHSJWn=)S?o3yYL$P3bXi#gO#OzwLQ@ zmc(j}N0YIix=I&bh=RqwQE8derKNd?3evx#Tm~OAwtaCwbiKP|$>^7cq<&JWmQ$&e z@z%uhWZ$E2rvIcp^gsSBmdb&JP}u-PO`atSQaU%>*AI|U3%U_}uK3a%46)agN7$#! z$N!b&K3Xg}Kf{wVWlc7V*h)~&&eU1jwxrAe<4h?4qJjks)xta2F;V+tD$3?&9Y1I! zx;;#xiGnarpPPzDfctekJ`(bb%@7>X5Kg@kY(VDsRZ?1%W1G4zL!%pqikEWAQdU1I zc<9wBg6yl;hX7a70*$w*?W7!4@Mb#%vZ(${T?6L11**AmptTOvx9)dSIZXQcE(6Aa zSpxQ%TFRaL8Q40cF3hKMr#$!wnIY~0n`Jxl2e*tdj$7LtZ^iPeGtQ~@_^E|Nlzp78 z%m+`E^u@a}XZ6!3@S`AQYpNb)Z>Mgx3}=w0t*5;w&V>(0vp2oPPDkGdA)4(#ddOUWT?I!R|A*)ORe=S4-@dgy4JE8 zKll?k@c3s(=^_AkN}6nvBQa7nAt!Sv=bPVpiL|C5{nirv0Y3 zYbaAHTrggDHo(<4FNN1M=Vty~_zFwIojBxk)CkxFg@?W4iG7USi6t{?Y&W}2IiCRDG11=X2Xz zl=Yqd@n!!yPJBnZM{L{GH>Ys(oBoT_P~-3GFvH9$~2rdoxpMWIrBi4v{1eDSLbH_9f*xiAuY8@4axh7Q6x z6oog=JPI>lVtqvn6M4zQLX2co=_`2(b8s;sa^Ljg5RWC}vikUJC-_P)zE9e)!&gx> zZy70AP{i<(_eqNooxPEpyUN@rgyoX&p0)Gc?x;OJ-&=QR=a$+1t$-q;Gl_K(c6N3l zk8LQ;q|-f%K|oHgVW0J_-hQhx8OHrF_ptimF4-g8$4X`+_k!2YZ-(D&gz3Z00T9L; zq6^>X>(riG_+l=d-rse(+crGx!g_c^6(1Zfb$jI+l!=s8lAnNdoCw(DN{>q8de!gB z*Vt`o2jB5wAWo;0`C$Pd;#3Cn-D4IK2 ze{bimjW#@xA>={XZomMQU74COrFiS5 zfyK!-DbHhQVxu`{F?iDhkdi9n-57N&8m+{9gx@5k)Vl8^UIBKD^W?<5Sox|6PbD8nFmrH&lMoc}A$ zNsB-K7uxd$@>%|8d~j8xUWM1Glob$L(aW7dJ-gpYWz6UR;aQMT z(F9%pGA{Cmg$_z=)=ziEG~r{D8%ix*19T+~fBBh_*Wr_Iv`RpHWvGJrNMVoN&A|5i ze(3l9|5q(6QZqUqevF*(cXPHChw12^Bo|NSHa*bls(jsm6|nu6P-8;~`C00Q8w;VI z&0^O)hd{*VdXk#Vvt!YrP!}F_50kgg@`0~q{_tho{#!sdGy*WwxQovy6F_t>v`|igy zv`m>BxY_3~xV7wfXxu3?ijD zM?u=I4x%^Ac5{=On3fL1zi0uF0G>GD8w@=}%t4@u-xs;4VHl2ruG1>vNI9%W+%2)_ zTU0WS_dcFVx^X&d ziy`N?xHVAJFGc{d+ITOAJ>f92kSyL7>a~Rjc}bL@M_^tB4@EDpXCInfn7n@2OQ{ z=%jPNH}&hQFxUATRE+gj-QtHuJK{KFJs<~hTikqyLUikDa2#1Ykr3u41baE<>-)rs zj0>8VC6LBzTCFwhh+{FRjB7bzT1>-)y2ZZrNmD|=0*AfyhjIi&`5lO~L9=yCA0pCh zM&urfrBV1VA}z$zEaEf#U zE0m@Xh~aKW>pCfEvha-RERIo@ykEZf z&=Td7v(`}aq{=jPOHP5TSS6d8hpJE|d)snica^O_x2fSV;@CkAQ|8e(Z@sJoR0K4-b#T)U znb$WCd<@@B?3MbAVx*Rm2nxo^VgGKItq2g^hwlSrfn5l5SJFUBi+0|iIG;vdvQVPl z*v;?^ex=ENH}b_^mJi8__SluO%H;-b*H?&oM{Nlr?|CA11#Q2#^wrl4by;mT$JWz2 zsaBPqM@DL2t4giYgJ;(*pLmqp&AmKN2AWs*Mc@oNl zh6|JA`M>vb`|j&l3W_X$6hsvO$(w+rg|emt5@yJ6iC1p^jCI~G#I2Hk~^>$ zyodj8Ah-!~7=4%OwG_XJX(48$wZmLT#toSFRD2GLf$?71>-alPcuZ@#!)U0zu~@ zmWV~{djnP6i~+rPzPy~uXzzA;3y`clawhH4dlNwGxn-C5u?F9o=ZYzM?%>;Fb6Vn{ z9KA<^38WoKuI|0UrJUUNU9@<p5z!MLl^ z$*o0ZZ-g6!{P!RoDx{e78!Qfm`S>d3Tc$(^iKV245JymCtmlE;6FH)`99}k#@{oiR*;P$ z?=&5r+mWqhh&0JAs(kGt7h-d#{*Pi9zR`_P?+wMvZ1jEK|0*jMn;SMVmYk+o)J>x13j@QdBIg9)#;DEvSAWj!!?H;7=8gL79K|>5o zfs1Lnfgfk+)y0A8ku4Ckz?sZ0+_B?G2qd__O&&-|3h5Mniz!WjgScg%e-d^D-8iTI znjA;Q`YwCh!`?mRXi!(kgJ8wl@TZK*M^+F8p7Ik6p!g1S@<~2n*$}8u)Xk&X)CuB^ zq`3hoLRt-X#Z@NWqZ)P&wX`7$QDp^Gsh+0A(1NFQWBLLP6v#erTo^|&sR%LNPi}oS zQ145%mn=pPjX}Ek3sA8eE7$w_YalnlJ^fw{;cqGDpMMSi0aa^swh>1bNG<|mC3d5x zJB`1mhEEj!$_gI%(ggrnflr+TwBTL5+L*97QE;pzmcujR&%A_IS5qwhNp+SF!MlTE zAer8rZq#Q9gK2K0J-9cEXi>$T$T3+jr)Vs~k+ma9J~GM<7+uL2k6suSv`zHeSbqR$ zj+N`6iIBrIU&6zGFVcqzuV>JdcTATkOXKPG(+QW-0vW^jaS~JI7=Z^oH;=)d><{!Z zYtPbad7|j?2a);r2b2dAA^Pi17#VLLTC1sDU^sd1!DrzJm9)4Bg$(s*R(Q`g^_RS5 zzCwKp^gl3nnp={C6gZWVgPO?sc3gGX4Yn4EQU~q2dCv~hwazSN^pCmU5dxMJ_;PSr zC&<)`dLsvASm?oBC*HtLkLdo>9TEZ0TX_Wm31}eA-UL;=Mux^~8*BcR%jm;Nhk{y@ z)y$jb^yagDa@%KzgHb*7-l+|NVC}WL!Re-yWO0Rz!o8bp7hLfhDPUr;eSZO+=ezi% zKZ!4Y&UxTRE3hli2c26-GFcnyH}DyZAmWICd?5(@K6C!slCWXL5yB6k_T&&`%yTr} zfRL^?Y7Xnwfz8+V!@8Oh6t7>9NGgY0OKVU|K)cX76l-M1txVll=-~2YIA7Zn#~S)S zS8WjN3WCmKYp9^u^Yq%Rwp&!raw5V~5EtQQ!T-JtC)~PRBO^Bl9g`V|>(F{;T9V-_bvZKm&6=p> z`BM#}b3R4E**LIpiFD&gq=thG_wi<3gb?P8^-vzNLI0#j!rLD2>~EKA;K6ST9rB`R zGRQz#=|wah3wV<+-@*YztkC}eh!_{Z zzy$hxp|EY-o|M3iqQTArn8Z0z=A^r)xYPGTqiqZt=D!w8cmEvA>({iRY`mj=|If>W zy}|8?X2hWob&J{m#y=h}3Vcs$AL>s7>%ljpu{}4xtAp&X)0~qB{SE!c78IfSq7sSx zPo8YIF?d7Q@AxOp2?wYVV7{eSmVnOV+8M%M=W+?Mf(LvFPu?_DuEPJ8`Vw4g8W~0K z=mc?n&adOs8k!TH7*@rGj^%&*C}-2&^ACdvlps_eykb2~zgX+-?XtAHYTb<%)5ww5 ze;&h2-+w!)WhCc<-(#1*&j^eykI`0#Qr?RJzXTQ#ebcrKbYHoEDBdM{4+3|qe&X@B z41K3%pa+$~XFKSYmL({%-59*cnB8E}3JpqOii^wa;)qE|=J$q|NcXX!J+VQWy=fea zJ<@U{FQYCH7T=7VZ}S;ai+}bii7zfS4N2(NuyeNRL%3rpa z8i??J;&$`8a-9Ct15-~*hr|G1UwbH|Ooc`1%YtbO%hiJjsw~^wv_7Ajc$R#CdXL8!v3bC0`w4jf-e0>%1@U#jaX$`kveF_mrLcS}n&PIqA^8$g0 znT5$$9uHS0hgn(3MNas|_3r!aCsnT->$hM0s+;jpt*47FcpR1Z7ZO4L>WKG;w5WgI8{M23|SkWDRDw zu0&q2cC(OIo+0(5fQ;fYI^<41R*80O@g0|GvxlV#4o1^mA?3W~O>{dfJAEi)Yv zgY`S>15>o5%E*t3puZ?sTOBmhQ`tm<|G@Wn3Rp>jxvGMEg^<+v~EZ3Oeu01LRfyS%0O} zcIG+mJRVNWGZ*1`M0q+BwNqV@(SN?bU?1>tY6#r4Uvwy2ql$mu?mzv-pEuuA^ml(W z>Qvui2cSFGp(cOa&Wx(29 zp64F52mgDJD8zZ8z2VRfGz3X{Yefex4Me74n%Te&7dH@X;IfK`h{LkQN@m6YmFegm zBeo%j@;{*#_EeBN@myjv`dz_ojZA=wadUxC33!`>VQ~YJAo)B>`V*@6AGGDq z9lQP$rIp30SOXUKA`i7%6guyZ*YukFfV)Lfb9@wB9m1HX#_iRG?iNpE^=k)TQaM{d zQ3zZ;D0TAi_N|NJf}Z5&S@}}KU(HJ3N>Tb)2g~D>mN8H{lWFLG0-3S2@lyDxR(kqn zw{vL7IrGXBaz3LZI`HfmAYkw?o+*O~(k1SA06}lH$GP)CG90Ug4biBjLr2;uo<7Gs zda|BX)VEs`M*EwMjf;ej2q$9NF%*GbN8$E(PVAq%`aeJ3>Hgj4n?kb2;Wh*I#6B8N z^)qr^?$7;F+eYJM3uz_ic(0ruQ2VXVK4$qNUdFvcB-Z9l- z0iFD*7CAKD$YrKYcyaoBFBOf%QB^meCJcTrw1ofjUVQ4k;&PYie~35FObWpY0!3ba zb+d$b=eK;m7`+aobX~<0=Y*#~6S3+XVn*N8U{WN`duHynRc{Fb3S@FpoYhy8f0qE5 zFBAZFghNka4OQsTA&oqm@HOfq5&?tDQ7ilJWr3N{7;ue|Y`Oepm}(o%1OM3YF@3-| zTmxkBS_0xx^^;zFU}*l#6aiZD$Hgh=&fiVGjyg&W{EKBWpV75_^*~{au@aoFa5aaE zguv!hXW#j|@P52GG5aMjgN80@-E8!$z7M$J&qep9lCb{oSNi|1B$l6BDp>;9`Ts4Gu6KQa z#j8QxGdy0)*{{#h)=?Uqe<+fYlA0&{o>#mx#5-xZJ{Naei;ZV~dO zX=eCmCKv(pGe>?lPQqM^oJYk3g8Js4+?D%VvFUC|9ZO0&@Q(0K{sY#V{kLZZP2~FG z;BeOAv+G@iSgWgGZ+?E4=0sRITrL7GouAfQupdmm2x2}I*S`8`YBk?f&ny4i0|CDJ z(*Kt4VMWDsuukd7Ay0>R(0Cu6b%2$#&BQtmKyV}Kak^P$1}tKvo5;&&vRP^b7+jZ=3Nm{Z112Pz{yfl*0RX)+XW&lW);EDO)B0jCrh?G7-O+=N>f zxF(CZMgcJ{g|=su9M0S0ax8zW{~)z3y|^_~`J-jgu~3mzVS zjWVkc@?wkR%@)XiNdjMJ+yg@zxW?Yc?r&|f`_2K+@`5(wG8u|dIr&Rs5m;dmy}?X7 zN0A(i*NhlD=b*~*JMWMg_VA~d1COhR8L3he-lrrt;A@1#UxpC;;gY@o-+Q8nNHtS` z55r9D^U=F+$k*I`XJ!u|GFu+Fw_5(EmzVb*0LrI zya7?l2se%^pmu$>+!3tKznK|&FB1f0&kR_AP_IJ(7$$aqb=}N~M-xZ;LWuojBY+b?aRryK=POpb0;dwE^kiFDIF;JB7`U z8lADG8J`Aff@I(EI$yzbJX+Z&B#(yR7||WHV!aAqKyBHIHw9c79^=+qE#=Yzb-*@d zbC7=_8%{@0DmuSEud*VB-LVYxVJAbvUmqwasQ1A(7y(H69V#;)ni<5KbgPUDbL2MD zq__Lc9`V!XPk>wpYT+mbcmZ}HuzJv3JCG1q?Wh9IvM-l=$~vLYJQu_GK#F}bpc6Bp zXE5-n*vrC;H3KB$rh3~NsTRQFeOHx{wwnW;LfgRk-qJL-Y-j-vGO9#Iz4C>T1M7iN z2#={sh)sWZu4}&XAYu&ZtXwx=2{;TbEVplb5Sx4 z!(Kh1^qk;a;M1diL+^Gt#WurR^kul@!<-_#rHXU#K|rZ6r_*H)j%u1XeBrK65knQC zcK~OrjH%+RHn|_covG3=!phQ%Ujus%x3^PQ()5!&mZScjSEm+;(B><+HHXhFXq+Az zOaa--K+W@OwI#tPY7aoE3r2=~a0ZbchZ|WDD7GIyAPT=+rUSE(l=AWrO~mG^M5vzs z#A~qeJOIY|j!9bJu<7fKh}0LuoYhmS`_L1aLj2`hh35{0)B@w@@BG*fo)F@`1q+{@ z=t*Yw-1(P-&*G{eFx+>AFOEsww|V*4@4-D_W_xudJQ1pCigmUHm>Vda$Xjw7Enyk0 z?N%Yy{(1xe#vp{h_uuIvzyTu00KP!$(2~^=FnD{%Pv_gXXvbSW$l+PNp~z{^R3q4- zk2-;OP=UB;TJX(C#PMf#A@~Da65wry^Bv{Qzg-Z!XK+_jI()!J2Zi*?L~RtYKV@cq zoNM#_+(|^TC@!d~6ts!=O>l8d!>S&zcaT{KD6mPihO{CVYaKAKPJT^fQ=W86w+zXnm`>MAuq)9DyfHYT5fZZfm^#NtZI^p{O+E>@3LT&i z@a^e!uk0W1%*pZ3zoG?Bd;_Lx;;oPl z#xQx8xIgzoKL?N)$-~XL-lnd71#TbxjR&P2TE#vFy-~aI3CAzn+bqhdi zc==idQ5t~cRsPP664V=U--ZF;N=ZarY5nEiZJ&`qWX-#n0jj{ z6ZviLJqmZxtX)XdBPa{uE%c$jI>Cz+90JEmOSTYR>ftD33Fz)$%K=v$i2^tY!r!lz zl;~h&P$|Ej)IZ6WdcC);ms5WBP|Ht^o6<8iYz zrvJM%=BL+6rkM?X?>_5SI`JX#GiEcDn=9cXK?s|_TNNg>ju5@*jw0#fjS)Y^I5ta3 zLCaA(A-hFySMulI;B6Ri>Hi{9<9X?3P;Ttw`h2c_4Y-sXeIDA&V$*T7vl>j|Jt#sP z{q!;$xYV&=3Y?nIKNNn?X#$BxSdHz#rWGW)MmzK<$WMCs!P;_bo_jN%bnaEnuRQeV zpS$ZZ1S-CDzyQ{ zdSTRa1MV|F4D5fdpIYk1`On{~rWX~R%ge>brgL5n@9DW`bW0`{3KlT4IS4KY?GlDSNA1&XE9~jNygAH-CMv<-*>e!LdM$!ZGx<M{7P(G^bm;KQ7!VVnSP?j!|zx_b}mumP<-L2t!L^KqSBq`l&oZ&`Cz zon+ipb4=KEOK

    zNK7VXj}wcmpoQ`6%gd+Jk|y;uV-I{cqa^5C3>r+tJ(ac*>BirIJia6BW~ zQ0)xT_-!d!rHwu5f}MYKzxR>&>jf|?qx;B%=n}w3ae9^Sd(gb?Fl6Z1WND9OXco|y zYA76X0licli|h~rT%uEeIV4*w!u%9AmDuz0$9nX*7~DF`w|k}9U@WLTRemthfiRiq?beegM7@9tJn8&jze&V9>5*QIl zhK*TUd^r{#l)BmK|GeBG8gJylPJ7Tc1Guy6Kj-Gqh4G)<)i=8-6NI+wC_|Pa*L>#e z+m2$6jDyOPyQ(yRxE>BG4&rSs0aH94r^4%lufS&Z40Oy@tszu$6>f!2PuHiKMy&ud zu&P7mmQI>;!?bfZI?Q}a*+|z zdxBQ;U0r~VygR~Gubv^SIgQoKMgHAi0jT$%qUbEn#xR;qKd!y#Zj%rQ5|{79axdk? z8*P1COrYSR--{E8?FF%K43kWd;6SS{r373RvL7tJ*Z$Bdv6^VjtR(ka6yGn2)GB5Y z4tm`mm~}#=`%vNmn-$}vzhcFD$%pD|YW9b9!%n7yuw6PK1|BTUSXw3*kQ6f+C4v?pW`1T9(^^y5kD_9T{V9=1$F8PxP~JKg~=FS|ZEx9y5_Bto*M_}j{TzZHc6KPXD0 zC2My=$7dZao}=@oc|8NJUpPxxQUlBoXOEUKkw0m2HzjkG4HA5K*J+66u7@R9eL~0o z3s}fQyV&*O810-}$d!~CvoSpRzJJ?o(ai`!SqWF(4#`xZ7@?ZV;}CBSWB@btfsk8W z@dhf8ZE?GONc4DC3b0sfNm25`&W^s1fzUULH~KE+lB_z5*ygccE0DyytS~{)p>~zT z+X}M2s%daKbLCncCU6G@q|(W^YMuTZxPH=bZiNzB4G&xkVm$vAe3)7NeDtHE&fJmK zd0`o%DynFz*v_3WH@-(&-+VJ^eSY7X2Yfu$mRMYQZo(DGz+Tf3`qJW+9=d&IhB1L% z(ILp-o%j4ku_l7WQLjLyk_kd2S)p+m43-|KR6>qSaKaPdT4D4o5|teI>G@3w*FFQ% zcXGW7^Si8*0?bwh~U76WE{g!r&pDXVX2xN3A<*)qs+#B^Heh%j8*nGjOoT6dZaq8x`LUcyy zss&wx|L%5EB?lLh|gS;&~g!=S*Xv8JqKa0cvp z6j?SM5`QbliG?iUmr6|JIBt%b-?wf?Q!+~)wteOoMKUf##{Z&t=V#StvG=26W19;A zE&(*QF+Uu!JL;m2S8ky)a= zufKv!mQ`Kx*>80V?Od~%8)h)c4hM9i)o4c5LQiDro=&C8nZ|hSNpiA%gbev(BJk&Y zTvp%dVHyA+i;JWguE(aYpK&L{_ zP@6#GO{6oWCM)Un>}_ARmh=5! z-Z~C`8(*3@F3*)zWXpal=mk*17$A$DZDbWbu1@V18}&JPIp_4{XXMZDBXI@~A3ZZ( zk=>0vm|Y09ROgVu5r&F@_q6^)!d zyfTfUKmHl1?vve=C8I_@_?F22-!1WjTWS~l(BUI3bBpR-&ArF+M4t^)*pWP@DRZ4z z?^lK~;vxCGl7#{@X@Ts;KRrG9^%>S1wl>|AUs-RLDAK~|fl zc)FjqFK+2j{VVUbTdoTW#ffUF#NC8dI2{fR;)?%gZnf>HrbWXbg06`MR9c(i*Os@8KcaV(-U6(y# zbnhe+&}?(XTdU$=vYD%m1%BKaic@6C1WWP;8EyJq+te1f7*Dx}1ZeXeT+_rno&lWK zytzWH*wqc%-~8HxaBpy=l)}s5m4NqkH_HzwEIs_w?FB91bg`Z_X>2Rp@ z(VQ^wGlx(!>z#j$H>@EaJbShuI9_6Sj4SVtJ%2JITd4U#r3X#tet)YE;$|;nnpXH% zpSADjICKQc4CsjkgXjWwEvM`6iyMaf-sa3)?}mHnSL9ZbhQD3~7AET2iR~f06v8O# z#rjv#$NCC1?`mM!6=caREg*+5`eC)#wWmy%UX^(mufg!;i@Amo!;9P5F>Iv!r&8iV z0MMJRdr3r0R5VGRA%h;hk*qzQ%bF54563Iod@!g1rnT%S@7O z1BvbtFS~8)EwFA0w2of;xg%sIMgQ!;NatcaV?cF%P2FOzhBBg@a{E4J5HWPmbU=rZ zZSA`VqjHio*e!+wO>BSeAU`D)IR>tkKWk^ccrsZ7pB6v8s$MqQ1k=I&HP(dm(U|v3 z8Qqi~Y?u`&*&hKLco>U+))+SMgW|qp5X-{A*G9jexYC^MB1$|q`CAZt({$>4XB5T= z%cjj2r*}+tZ|!ux0w@NOhBGH3!b$zNRNk40pH9Q+5}z{90(?5GKca?{EAYxkcvd7+ zqb385lpv-JZELG6jJnomD))|-!jqEM8SG{EyDtQh+2Ri>9X>A*@ z2*SZGHoSa0K7fxt$PNE!CYSHSf(6?1$AH9E{bjUtH-gVrfddXk{$}D-NI)Y!v%;}_ zEBYtEU^t%aKgY?0-VUDJKMnecH=B_&4sY{m`*Xan<@fz|Y#sD2p-DDRf&oR18RFAH zR%~>JU8eJ6d~y6u?CJJxY-muP?qx?ryI#$!kxUsDQXM4!_EhQoWp9=^{tX->I9gDu%@otH$#mC8MMzkUp5=OsR@GD53VS&S0+ z-TsjNr~MgWU|)KRnkRCHJbNjd^cl!+Mx8K)1bz`!OF`kH#9r0$%c3EN)|kZFG7e1& z0pWdJA@JYsO!^THZ1ix}1O`<`br7eR5=K#zX(eKYvG=*akuL-3P49rS(kg0iHuxCc za5Dvd!aD!}7%Ya3IA1T?5F}ePp8RUuWlBu3tV;ND%EReCr7AvBQcPGG5KADL7^`R2 z@$<8ia6O{3CIS;Dw`~*{yWj^gO_3%)Te=7#+Pr)qrFf0|hy@K1G!371PCpgyY^6nW zSh$z12%ZCo_G>VI%L4aS=+kN%VN`Tx(@$+d6Z^Wgf=|l$xp9I=EXaL01Q+X1F%x0<+6wh(X5ApIV?}Y(&og@-U8jE zc~~y@I`^x1#LZ1c%GaM4zYQJJoyro^HUu&#pK+R+V)d}wHvN2~(T}l@Tj06`*c=2} zpG-E6vF)$D&(beg^?A*KRg6H+?Snow0S;a4-AV;3_fZcr8gEDbFl{p-&Y@}8{$8Yo zV}3;^_thN&YsYi-$)`%06Kklyt~aDcu2(HIl=H9hWH1-pKh*F5?OZY`&#OJ-qvr_- z)Xsa@EolpDP86D&nppQOf=--2=>vZZ+DTX?LPh2l?wLuf2L9OQL|2-bSNIaRLApqgVBV!#0#+{}>gBh0xO{bs+Ygex*ryM=3^~k-Q}aZP`gur4#=ddbSZFSiZ8QTL8%^%uWCstrZjz2QrP5kSZwZGK%tSk2ogrcY4LHsr{sX2(AGR&mPnMfsd~4-JV>QeqXJn;v4_SToS=FY~oXm z`{}+I#Cu7mV7bk8&&*lrLsI>H(Z=DYPm(i%#P=u0@lZ>iM6rTtC)p2jJ-`45P7WXL z*Vh!Qode1XyT|F8h?vc4Wf(jpM5|aL)$Z292ir6atKm{_k5ge}7EB)$Q>?ZcAqlo1 zUc{*-y_FFFQ2+ublr%iZo$J-w36FDXH^vT#KfowX)qviTkQOeQ2g6`1q9Zmu2hMcK z0E}w;HANj{Q*ETsrBp<8Olgi{nAcJO2}`#YD}wn1M^V1Q7{gl^J5>Bf5 z>mJrS33(6~$J>mc?kb9#v>_dwo$v1t7icEtx&?GCG~trJ1an*@ntm@OVzj4r0=r); zvJAW-Hg7cD3Py8c%*y*h%e*v=V!b~32541gYh!7AXnS9Ej4RE$N;QE z2fI8lK?I?Dj-XprEu$^KJ<%-|lbGWwF2$m3GFavNWP~$mV&MI9;?TM!aMs zixGNDi3uBNHJRx*!h^Dlq48BQR8@> zb=}Em~DwRvaek zxW`#zHP?s7jE238h$7Ot$@ZmlVCsXJ%tnN`XP$%AT_lE%6I&bt>%JKR>tWPllYjsK zW!M|@1)$Sj9?D-u6Y3&qb)g+X@eac@9OogYVP4Uw!?)|9M3 z@)fXm*w*{m8DDn(8j55(+i+sKB6R*`Rw|MF9S*Bm>xGKjvlZKxG1sHd4%vFh6a4Q` zcIv-T+Fn0>QgEGl-Q7rXHm7#k7=CxxP{aaSMaM{D-lP06nho9seFY;Cel|T=CB^+G zL5f)%tXiQMRg$rulEM|HSf!-vPcLb<5FcD0F9j~KPA=;EjS|mWS8p~fo_tu~;}ra< z&?fl++(n`N)6Z&i!4g|PnIqsS4e*e6ZgfJuy&(j|0&|e<;$LftSb+N3iHV!Yx;VDI z-Pp3lQ~IsQ1&u-Jdk*qlJE$5mSx{8#EGJGh4eA*8XAy!s?EMujreT5K`p0Mhu+^DF z#9DXT?Ba2IwvNRSqI!_Yzbm!#zpnu7#C zDIxkOPVA4c7psjm>)z*BUy=>iKTz{eLhpWtPhd5w`E#CbofwYb7(SI3`_r0$AB*=O z!N2a-G;VbA@q0}Q7jInE zpNkg!%OpK(0dFP$Gc&e7J}bOIv3q#$ zp@4o)K(yyaH{x&R+}*>%iWLl0eVl#4{(649sQD&sYAZixY6E~k)6s6vZ!C|GjWC^a z6k)!EVe;9YsYLP5IiM+r+4N^;aBKpXQtbtq2BD0tKp|Fm=GF@+hzH>=9~G8I&|~%l zO((z%tTqblfy$ z$xUKp6Na83(XwtbLDQEgztADBq#g|)0(%z%IHIEnKv>%1X-_Ox;dJ&K{k3+^c9SCt zhI;R9{BVg+?OUrD-K(CLXZFOe%thWVamlFpLQu81Fi7qd6Nc|SJl>iJ1u6#OYJuVn z+jmOtp9RU2mh6hPnPFQHQur`j^GkPpWMJvXUqWXf-@-#8?KN4ig=XvhxHb9K`yC>QS`6ss&To%q=Vk%vlEjUIs0m9~(%*>QJtVbT8Yi4E#04P(L_5_kY$fdqh9+ ze0KMl3)5H#@71@kD1hiPN53%A{c`8TSmMs1uKq-vD9e0SgxFTvprydp{6}GsilmNX z@(>YcrP_e`g?o3QX`O|HWSfKdlMP&<_+8y1ID{FJZ;Vwn6PPqSoFP>}As%Y5Db;yw zR1796KVQo{7DvW!yjVUWM}r!S2$zScy{N#~q@|ujS`RjB8WY`vQO$FwdYL`n{1(>t zL_IZPuH4g4!=>%Sd4E-*P^X0Kk<&yhJQ83eUp=eo zZ4p&UNBr~zkfxN>M2UE~2Z+pWe+gc2J*UX=4SY%JPaWgKhGXA?c~pLQ=qO{~ArL4w z1Z8ur8_c?xH}fMh$F-(h(QM#nlu_GRXlV(#`ZZ&gcndQ}whE8M9Wd2G2oWo(Qn{K? z?+_a(;AN9lKQa^u;YG!U{p`&*1F3pqreW%sO%L=I1Rdwvrq(TZMc>sA^QQs+48v7J zGowoKs^_s&&U2zc8iS>Ag=Gv#aL6CXhi=R1oiirH6&cjA1MZAm&YE3PVadTI#KdAX zhlkALXc-KAE^k09^&X#I7Zkjk)&$VJi4hiTeMi>mHs@sF#M^kH|DLZNb+G0AIbW@# z(g|p96w7Cs$_8gW)VJEDKE7U%Sm}=7 zkMwbPy3lMld(1Bo)Gnxhmz?byFp3DN;w%>6fUKGvTDM9{pYgZui`>_y)g5FpA8mlE zS)n#o9+?&LHL$vPZwXuV2AM0QU&B_7mH49+zW|fSn%%B6lE?1qg6UgL<(0xgykOML zjfSs8=HqaGT)n(dB#2N4(GqbeWqOVvJPaz6tnyyan%HT3_){^2oV_GGdmViqLH|3z zVzYoqGU=1rL-hE!5DoO0MB`S|&i%FGj+c=_;fJ3AJK}*$Ipm!)cDKtu@V2GWz(X1O zSY`1!w@c|Q=MJ$($NNIF;Wsg7*=Xf69=v|N#l&~#%Y0)*1$Z!?OGKo|~UfLoVaSfBf z2=C}EzPg22kL8brTLR{3bw+NR^bkRnf<-&o=Au|>J4aMYtV=29H)7N$+^hXRK~$k4 zI%bF>RQ{e(QvyXMmIfwyTE=a2dgJL>^Z;^E;yd)X68dQV4aOnn8^_-U60^`uCf(IZ z9-&&-&6lZXp-Avzh1Nbp%-8`wMQB2S$fHxhOE6n2D(r-E`r~UH?J}deh}FD=pNZlR{`Oe*;{fYm(`JZfk1Uz(1m>151-EC z-u;VX%G2nS^hkXXKOqVfK4gVTzG(0LuYsPcMkDYLRHUj^fb5h2ek6`3dnc9~|%nR|W6nL;Q*2AW=N{bh*bE(oGZYUiX- zwCda&Q!a+brt;cMcNC9-NvlbekrqATmGMtxRQgy_En!VoN)j*|W8Scj5> zz!rocwZGswlOAN?qtY_z{&Ft;nF(*PRm86~9mEQA2H*`lPaizXFo{%qSDH*9%TJA{ zz$YE?o9!&ESSRhO`NM0FxXjZ19k3m|&!2cP{!n|m+>ES`>ru>K4NfGek=adSmV&?%7NLzw55CsRc-U=KMHh#V4!# zJR7;|j3uR-d$-h4B=I4b6fO5RleX=K)j?w z^YGc_TQWw){}se9H%z2!^r_eVGxokW{t%sx^4Wg_=3?Y@{?-!)H7?|C#X=c{19O>BAWkunTHj0Ri6U*Icn8-xr?W zO?o*hr8=9WDDK5NR5#^IkGG8Blgu!=C^rJ^65bbT6)XqR>YTS1dc8=%wVs8k@8cpR z(+(eQ`5yMk!KJmA(XJcSfzCRaylKw8_)DGFqEf06%(A+3YE1q0c92C|zO5<8q+iaf ztg?ZcsU3e)(MkSHb0EOvx<-k|6f61s*Y>>4tE&6BK!uY9&Id9QQBhHn=f}IcTbO9A z!h*>`ni}Q!&QS(ao;$PkEceI{meR|xFgWbyvAfHsTXf7|4In8cJ=>Um^7%|x2yZb4 zemEAT$X8Y719((bD94auhd1qU&xd&p>>##k3n5gLxTkgMWL`&t6nv%~@_;3lhW%@1 z8qc~=w@d|YuIL+pk+{Zh5k;81SaS;eo)h#OjxBYIB~m~p){0Zf(J+`eNUF(% zC4{#wBWhp9EGhO%Le4SXe1Elnf(~XU*fvv@$P%?ErUc0^j*ilJt!rht+W88E>H+*> zRjd=iKke&IJaGNSpoUK#f9l&i-Y!#y$w!^X;d~<38>p34U_h*PK+HaHUKZN!IJI`S z=m2z+FXzNkg|zV=&oXgDlOl8x{aix{e9p=|;L%~NIs_DSs+GrO#d2!= z)BSxU22*HU!=*3{oyiz!pP{WOJZq4_{UZ;C!05!ds)CC_>AojXh2gxJE^-Js==Kj+ zto#V=#0b^_i^Mn=rxvjZ4>h4}Z?^ea)?^ONTATPrBmWEk`$;2L9v7Z!Lq%5jmQESl z{#<(nd8rzOVm_xAfU+r~BC^e2irS@+ZC0Y^$G0LT6uq!Ct5sZKTL1d^UZH-Kj7)rNh@68M@_kqVt8h)|F7YXSW)Iqu%0LYxU_n&`lECRC~3 zHGPEJ9!V1*lPhrP(ReR^@C=`|)w&jz*}D>!jW-{9O;VK1{xq<@Volc9#z7E2*` z|A8bryb(A2vpsj!Rst0l5J%nisj{w+1apx&Q~CUOwCoJDgJO#tO-;M}k*Rvu|14=ODKlE{8?)?4Q9YXeCMzjuUh>xFUMdh{nipog^ z{dp<1=!6tbjj+;tPf?=49{Fe_pGCA)o(hy9hZE{*`A8a1A~z5`I>8d`>4Qg!R>2^- zNS6r3MS#?N{;WzXuAD*Bd0P&pkxgVf@~r=GC#JULVcfInjK$o>sLf9jGUSntl}}93 zPdsMqI9dK`VWGyF1o&f8xu}dHB2Kb@aYZc8P?XPGI?I*S_HsU4kK1l>tP5j5xtd)# z!azaFt`MGXG}yFw8$DL_BSs^@lsN0T>|mmEA%MkmRZsI|Q&DOHQKiVN>n-)eYrTX5 zy%l5{17M5%<&oUM`p}qX15)LK@^e}}!{Sx!fo4ragmcpl>_L{?>%C8Uo47g-R}x}{pI=f{KxB&#O=3~eZ(9_#qz=e z5#3qr(cZ%A{Qpa&`GQ$u^R(&AkG zLArmU5jw*XD`a~fQEsoR*c(+kUe8A02xDuli*11+I9zmk;9w)oi&smgvLdgKD8-m6 z2ZXGj5Gb9}Mdj+Fo6q+bp;_p(Io6%}^2{7(G_N0&v3~Rf%A~jGyeg@m?fS=mN)#e+ zt-N3${C))tz;Pz3!d&PEMEw#Fmub#;-l0qMplb~xNbFa1Q|eyg?xP6qaCq*N5X<{w z%VOZrT`i^DwKCEH9HFr5O&Wj{l9k>`ZJe;y(KOS^3eBmpnbG+uJYM$rF;Uh`#J*gZ zTPSBB2Ygzw1N{>evs0~Tj|Vsp@^}L0yXER`GDOkr5ZT`_KIrpuIYThNtXuEgOdhVp~mzBeXKdmq82ZU; zezndkxoyYMN|wI#kCP5TMY505Lu70K?yN|Uu*mf0?b@;WA~_5m2Ivv6`+}K>-J4tT zyzS!55;=WBW8n+`4`Xi`mF3pG@k)1hr+^^c9n$g8p-88obVvviN|%UqcSv`4NymfI zB^^@Ia29U&d-nLBFXz)9!#xmrxYxYrn)AATSK~46?A6I*N$xr!L4IqU_l7qa0&#+q z&s!zA*W2ItK8Ra2U+q%eVH#(yD%Jn zoUWPA<)Q5?&5?IFBACy23-nWbPb$+iLV1-DHMmGqRO!1(qeaR)8{J?(bh({u3|HYJ z_9WHmRmhTz@=*$T2ZIO%`yr8{9^tXbv5zQ&uhPA7H7YEySx7~|qRtXgEv#H9%ar%+ zvSuSl8)DFMwrktxOX9K!RW!r3Z5CVyD~~BP3G4Tnx1=;obPw#V41fRWE3s{)9heH^})mR_iwZW2U#$!^}*`jrn8dt%EW<$w#xsOuc~VHPNCQ_KSul zK);SLkj}#|zDe;C4Il2=s6yLZS91fN@JS%EGfUa%ZN6S?3M`+u;d~4=KRz=qz<&|m zlR<p_+Zw|>lbnNbWwyk@>_vDjX zL%IqAj)^XP8LV@0aokS-M34z7=6j-7vF}NFo}#zZ`tJ7XswbRNtJf)+z?6U|8Y#mc zhE^p6_wkS~bsMqSr}6v1IbXq7Eb=G-oRkerg%j*TJ9OQov@#`ydL7<(^C0o*49WyL zQ&UQYgZ;b*Wf>$*WZRvhQ}B`Fcg0W%Lu&c}^58qxFNE^u9bPzBbOp5j?Z@A`X3vx)N#pHtd@&5wN-9jIHPH=?d>XA$1qhq_1VBio7s4!itq9{do@?TatZ$dgz-5eT2 z0jnJk!}F64ILQ)|#b^`v2{#(m^+y5TZiUdV{TXn@lvY+BmXF|4Q$P`HK%`H$-m^{$ zGW2AMXuaK&=J_H2;-6ujAGy?jPBDs~StMrECTmJ)jSZ^zCl>7z`M2j_7}>Ko?@18! z_PfH32kbc9NU1~P$Bq@!ky14Z7@RCVJd@?IX3OChHd6&Lp?D)yOkdW`Hid5auwPFf z?j37(C$T5$tA05Z?R@p~epzMFr> zmM@WnJ`kN+xLzl0t2J2cS{CWor8V+_#xzEZAKP|$3e`Ka)r<>==lwio3mW4U5V#z7 zqB_6&z4yZ<0fi|hX;hM`0gu(lj_F!DX$h^w621rfO+5r^MnU;HIVDB;Vnmzu=lP1$V%DutVPW49sKct1Z~@Ul zcI-Wn265a0<-7E0<5CIqHPbrsu1geJBUun5$RO#@BO)aEV{*2 zL!adiB!bm`c={RJ(gudro9HoWs7Sxpl@RW`+cR$&t><9xtmQHHSVvKC!+G1}aniPO zb(1!ZEQUoI(#7u$p=}$JZ+V9yWFmH)Qd;M;ahK@OP-eVIz=p6}CrXeZ^#%;>gTn#j|-09Stt} zbbW93A?ZAFa!S2#>w+_U(=?w9rta!)asl(nLy!|Vz+eE*4{shmlB_!ghTnBe|J4z= z6#h>~;HMU#=@ioCvWT%(pci^R^ZE7cyW^ao#l3V$Iz%K*MOly)dHoH%Q>Y$XpKwV# zFh@xu=)HK6%9zK-@{S-9l2Uxdp-*VQ1T# z{aov?mf_f?Wt{;?T&Lnh4n+f=(4kKcQA2o?4A7^cI2FAPj<3lw^a7j!JwO@Uj?Mk0 zwZ*s=TOQJqf8M;owOt-<&v$~WKy>|ha%ycD*KAd0Xmj>9kVN}b2Oow|xSgc}i%Klz zBc~tJr|FXgof1w^ad5eQeZ;!}OCeU?+NI%sfgbZDZ)RMb{XWHg$UZQ(m@v+u2{ig? zv-e^z4aFqULOEjEF@4ul&j#T?zD@Av9Ifz_%Q=f+Fvu{CAah1*6r*I2-@b`s2bte{L6O* z1h%I&PO23ftU4toogp)zwV`MPZs#)-Y5nFfbSl1=y3<2lU8qJ>;r9{??)9~Hq>BV< zr3c8CBMAxyjczp9bzlMg?eHzuu1qwhLI2kFCn*_Cn~2LOQwJ-o<*_Xs*reUumJgyl~M~Et6Qf zN#hKL2y8hH-c!$4Sz)!E`)0dn&_8{t`9P^~K>E9zcg)xR6b4?%=0Or?jU@o%&Sfz3 zxHd2;@sKhoWv6X)Ek!2pFkO>GZJk1z;j1=FQJ%7?|FP?>LR1xRR~px6&3Lo^Rg<^ z2(KW^-cLy>YstkH{cXd^oKmttk@7i(cVzGoGI8RbKaqLMm1iX*C-tX9^;7(NVct%N z6;^X-BYf+AdlW>4u_;H1c-XuP$(4ZXGa@E0S*g!YeG$)Qpcv0_NkPZ1#du`bx*esG zcVb>I4X2HKFX+01|5M4d)6ZQ#Dp1di2|BbkAFf<$x1b1Mos%*Gvzx+zBGu^RB!Z!3k7MzQ_T_YF`%pelKANWV{tc4{6-hCG(1 z#N0O{!iVN($Zk%fkD-BaI1<0N$1>qkdy4Cdl|IgJ9G;z*N*N8TNwWE1@r#90jF`CgDT)#NL0B69EAnV5)(Pc zlaI@|p#&^;zvE-19)0QuI-bJ2$BaZ9uX)bK>tD82uENRVIG{&CGce&ES329IX3zS0 z;h(UzE0JCGRL--nj_CD{j@2le!dJkCWh-A=qq;UW#D=1tQLfhk3_tAAE-+V&Jug>` zb{>)>{$6Dj#s4)Zb?jV-7P^&8lEZt0)*P=cPGNbF%+E8PqPkh&(_2z)AqRAKE&|@- zBam|l`VLjSju30___yaY8!kz-V(qUCbQSFzG}<4isPJcDQ(CVlx0s424SLPmBHgye zXwK}gRmdbp5H7Q}Kd8Jr`(+vIj>WWN@>JTO8!$`@+fko22D!!QO$LSVE{3PST}6?x zj35M8u4I;`Lz;wRVq0=tu@FLmRtT7Q=q(0ffcCQ8S-c8%H zK+>*IdLmA?#Ge~_Z9bwV2Zlye?uv0Q9~$oO=OwZ|c8dmmFxHm5K`z<{n_W%u3E9f5%8_Ta z{t||gk9^!&g$c97*zt3ntVoLOg}+|+=TE+xo$J#&-Rre(60w~gReji#qgrj&g?-s? zShzQz;BL`;wYC%fdQI^`wFG(?zm$J(@7BF3DfX^=O3DffGy?rL>3jl=QjevJ9pG_s zN)8XHJs(7l)6A{Qp~p%vR!&_J{9{B$%K{?bj6X@o^Q`*>6z*DH^oMk2@*bkqyT@vY#pIJbUP%Re0_s9ibrnP1vXq=k*oEbU)YT# zfrm(4;Q2)lhKo!ET7x8>#A{nZ|=WFlTkD76PpMvjPcCd# z*;?xIM%?73b8>hlh)P=oj*~Q6q#d&+R`MJ1%XPCz|Jj(%O&46-3?6t_zNap5T_?T? zOK=kAFf=f0NWoY-0aarCTC-W|B_L29bHyMVINX_qKigBAtw&yy-tK@!TWMG!n;~QcY!K1CRl6eYR-6 zHL~sjEj-m4n|rJt+!-0K_yMapXm&!AT`{fl0UJs&L^&Viy25F2F3KEHBB57rZ&EGM zjvlu>qQyl{dwBT*#oRyai#5AldVcT>k0DQq@Qb@{ie@1xQk^M2xfsRzISRU!`+zeYKiE z(Fb;ULu_PvXokT>=0f5AQk#+B`Ul#C_5l=nd;!gl$RpGQ03JTRJ|Y+I1hA%g`?zLR z@!P2z7%@GAP(s$hVxAdvx6tw|=ZBH4GuVn|6a|nhFLWsO`xT=j_KrWGr!_~Au88$Z zZqVdv0hJoJU*ZCWQ&2Dwu!*Q<%S{4!i}rv*htTheh)^wX$~jrU=#@Ud+n|1*^$^mh1ZVi6iZ3M723*((hL#__;Vt+^Elzy=-pq4ZWT4cb>2p#9uR*~r;0#>Gc;Q!kr09P} zvZ1%b$u|r5I2)VPrCr%S{PnnRrgc?r+U|W&41iuUvNA9!_VS?P{M*X|evU6`Y+b8- z&w|i-Ly)Nl-lw2QsW1g__4+U@?A#%(`3`*kl$nKu(I@Kv;nhLQx#593YQoRmeri-$ zt7xz8O4?teZTD)qq10)lYom$bj2mRxHFXyTh=)A08U3PQWcY4tkZ{IlE1D+MAwJMu z^gx*h2NPkLaRq7PuPv{G6L;B2moi=qIZqw^uX%`<--+s>Y>mkmzU_Dii#2SAr7YYQzoqHC8(l`RW@qw=V7 z82nj(W0E}}%vpB^qCl-T?jFa#lu~OA=`HuncjYy1YA#ni1#Bv0i2e@}pHnC%4GnUt&89DjwcH;Y!i5V$Ivubv?U!oUQ5`y_BEdzl^ zBBa+YtB#&0g*=xr)TG#tzy6s^vi)l$ATx{nrXsxm!;dLD)qAGQs0{zvvNT#(=rMJz zZNTJ(p-X{zFw4?w$%b^`{?A}2(rxL*}Eh#iosLmk37xd$llszm!QJlFMKwfL;;?0-at^%(@XjqsVD?8H;wv(X zzRjRC|Gca{UO{uMhZb;!ge=DaEI;3Yh_xs(^{#`QH04m=&>17Qd`(0?2S6OO(8dLZ zpY>H0xl^NuQvDE|w)vE0=L-~_dgdD|K~y@SQ;#ne&&1dog+8aHm2SWWVUXn!&U32v zM*>3bHM3TU^=eQUV-%o)UYu)#$;(vjV`#=rmEPCK(ct|X61NBEALGMb z2jzC4S|`JHM?X<3(kOX?Lp(h02r_)xjJY_Fuac@uudxhhnAoJAQ##*0ygjl1T}3n0 zevO+)@avY$(7C;F*@YXJ+S%y$evv|bwgdtEp*JPiHYv+-$*c9#=bL$a3I=~}st^6> zTL~~XZwC0N{{u23bpD;t^v634FVnug41b?-ogSv#Ap0yVPPo;|X;>8v!c36->^k>) z{Chv&AvLy=DTdBvk4@X`a&rKc&Wak*5UegtH)^2+?2p!WUSGC!`l6mPQXmFCE0O#H zoclT~O{+mKgaf)Bk<)eq{9fS015*bl2Ru|O1^6ps6~=Jz0e1-FL(t;m@9`%)&OLWOxB zHBhj8??TV#KQwY9W_Onr^vBJehL##AosmshZ9+t$q({D2uSg8Mj~+t{BF`VJTqO-ovjZt%uo6ywes2-ZP=#ILyIBDBRT8G# zM(?IQr0XjL?kB2%9qESpNXgG{>A9*wEj>1;zBhMBWz}V8Qo$LeoX&Z=7>}hR)i`=~ z4$pSe`#3L9k1RYc6r-96RbBY*?WcQ6IKmm(mWwLlM^dKcEp-Ud61KM`Be8AJo%@Wj8>q zQjG*VZ1kuV;6E`+_KTd)dxlHko*h^`^@lynrjx^T=4+HYE}xy$+nLOd8WGwe?501( zu=w_wH`Y?F!~^6SC%T+QGgIY)K+ArYb<7vR{Mb9McM^{&59b@W>7QdLGM80?z{op} zyA?`QtqYW=Smx~jn2?I1Ak&=xX$u&j)#;ns>oX%CW}4r0pXQ&Cad-?|-(-8gi~`V% zNkGOVV}3REi^}&RhOJdP$~|XeV-Z9FWjMNKD7c({@m=S@d({wC%RQe?jo)%QVGP_2 zq5RB7G$U|z2z=ams=D;q;G*@zg5bBHv54E#sU8Qpc99$9=KOO0$dg4QkVdIfU>zxL z2j;BbR#$AHDus|9RGN9Bmilz!&cn2ytm`}mJ`8PMkUIx13~x{4F+roLZ*tO{8Y_uN zI0)-)#3;*)rd$pF%%$inKz~uj326&JVsgqCSaeKEJ7xGk8|;6(N!lavc9)lf@SMdlkU* zL8JcwPMRK$K)zq5+GLR?I$)D?y}GJ5<4GloCHO$fa^+#Q1Xgs1)p|A$c@N;L0WA^Z zVRTP6^Q8RC13ks=KMQtKLJIEKzqf%v;eW3290k@>#fxwU26No6=F;=6XKIyUw>Oqs zm4&?9pS=na{hYRwX(lJ?l0u{<>@ok0gmK^^enq{AKXHhAxrc5V3#0c7_xd6_%dNid zwd&Y6=HW;h*l}FjUv%O=TRn}(7}+0EOX>xh)-aU z3#d^g=@+jBkq~cS>f8sOybwUN;w*7O?)!+w-W(0WMx!5lxM9*f$CU>k4I=DdS?HQs za`!wDQ+@mKrm88U(qd&hI%N|qLTrICO_u+M*a8PGb*C75W{syIp}F+xire(e+I&>8 zR-d*?s!lYgosTDI9H~@Esl|LZg&Df+)A24F1C3t7@i86Usjv<(6%vrh@cQFfa{0kT&i^QM z+~O)1jZJj}X5BaNPdF6bdC3+Heu^?G_r2cduPOIuLpp!;&IbZ?w1dn2*I;yck=nXn zJBK`o0~w}=zQwBtB7nQGE0u^{Kl>Aj+?aMDNHSl9UF)SKLAcjmTznTD3c?1_u30gl zd%==)vYM*oxtn6v5d|Alm#znzESjzN$4u2L;Ay9v|K>}-&sFlx0OGOvGG;YeeZbHw z96<}RoKJRp7vPDh`&HIG3w;!SgSW)({hYy|Qe`>rFtp@0Ze+#`IbTj3>n9$QRA8m! zVR*K1Lz{mg?ImIW9$(7%Gm^Ai5Lr)_-;!#$IZ`*~!tmz%5AaM$jEY^CkRZS-6;vZ| zgDfpUlw(U#N=7Nc6S|$8kXU51l3pwmT|B?US{&MvMq@F%mK16&hCf;>TWTUj0yFF|37#5Ke2a{y*{sABy+wrCb4vjVPt=-FEw*Am2JH3a zQI!GKXLO-8A+t&FF9wk>Hvolp6&D8OAo;E+f*$i!iK90UOuasamNzDzT|Sd;Hj}78 zo)P_3=l_&M;i2Z#|LeD@pA{GY048d9oAgmsUM#}QFBF%3EyO?4d@-bk(HW+J@>Z65 zQ>_*V=>@e6o;=`Q|FlT*#DDgU@w5MT-^kfku=zMOFXrt-Wt2mf<`OV?XGY_B9AP^6 zLm)CEI`4neOF^Ld$$55_JMNwyDl%sMq-ygI} zdAQDRMer|z)EG&7ZWZ--ML4!T5w54yd zwYB$+yL%x|bxbi($08GaKFBy4m-t7@z@vv(X_iQ;>k+R2*s!?;{8Q|#vItHB&l!W? zBPZ%w)9MpofszeJj|IT=wlu4nT6AyAREAhJ@LZj7JW0&b>Bb4Mco?K^_ z7fB&xsYF?^VX}ba@tRzoi=j71%W--B9uSiBvx{~g$sKeAAZcbw-9UEU+<(MqE37q+ zLCLqowT(uy(h5lR=C@zma#w=cLY7)nwsIvPo;Y`=Qy zVDd`*3Y+P8U57h_*YGAEa+_cW@^p2JYz^LsGluXMh?F87$O(K{d(r7~Uk7Fj{xM#z^g`%fe8~AS*nm8Y`N`y9erC5&>+Q|evFlA_fEYH9z|>=tdM;vLdjK8G zD6+0^rTXQ{Nl?`Mlgbk54oHw3s1leBn8GJ1g`9%ZynYMHRHH-B>5|A0b1N-}*-kAj z=6z?%g@}SJJf^EnBU5T==VOIb zBp25H_X^DjO=`^N7-*_~#DVT;EHo&NSu{|+0nz$C9nMT#X1|peL6{WHGs>=nDf9Jt zYKpsaWo5McLCN{u4+Pk)f6?+=`t*Xxupu8L7Gx0$9_~t60Z03|VbH_7AQavb2sfB% z+8oX3eWvl)c=}+i5!APRqVjJ=2=@I`5oW&se=0&izST*}|637+1Wa=8td`gyXY5b0 z<*em3|99v5PFD^{NLNd@g^CTsrPcC%V0&=ZU>HR}a}!{r%2Vs`8-;WbKGSUbSOEtk z5{Qi+E^6}sDhIxpL2}**FKkQj`DvQ^pnsXok6|IOnRXJey$2SfR-0!PeyQR5HGqVH z-HP}8e7Pj#^p^tPClUlx1m7~MTt)cKM_MW_)Urz$&7JQ!vZB~}v`UT;&CAL6z%AzN z6@U#q(k^u3E57P*#1VW!8m70H0i>^E?_uDuaVKtqdFP`~v*muEI0c24Q8ZOC@S$>y ztiAr^vy7p9df$DJ z#0MzoB;lAk`NI=RhNAVfxj>6Cl@EZAg= zY8jpqEkKj+3LV?xm~#NW)~v5>eny8cEZ{`sinU9m1b18)M|=pGPk64Ly;LJnK`4!0 z2X;>Ct6naVq6&4F_tE9%)Mo-OlYG613}6Ox36EnielP_K7*P|YO zUky{K5R)aNCA36EH%u9+nf9%+YAz9fO*M;iLTcL<3@+yHOEhf;>U|~M8ZK6qZYt-h zyrOoTBdM@j6Z~nR=vJ=5?@a>i;T4rsbw|n5Ze14b$1-3HK;mA}%ZAWg^lY)1Xkm$` zTVsB4F2wi7KXq4H`|Xu$Ka;*bf5Z`NJD%@h((FV`f=*Grt;I&n+^>961Ytx1O* zFmF?8eeZ6Afcc;l>$bLjRN^D5C4jCoq;t)No#RKpuhhgw`w}1cU?uSS3u+4YVvS9K z_q&kIc#(QDbsa*h&Q5L>G*P+_V!SrIqzWp!p0KAmgPm&Fn|L8WaQVlB&_Duqs?I0V zC&&^djjl? z51UZ`zp)tFC4DK>+M{@q4;ikKk7dai#)>Lt!`$X)Ry?nXSe&PR3H{zK2XMk@h9_I) z?W`#kD{qmx=fmO5i2I(8+=_e6z!1yS)TmMiM&fT%2QJD;2>D|iiC$NQ4R#?iyQL%K zJShkUuS#__7_y5wwa;041+*$T=a^FOC6KSv4@VXU_AK4p+_;lpyN#-IRdLt(XdVEC zkbC6)BXreg9u2zPNo8&0wceH;(8}uZCy*CW#Y?Z5kh6`5H9y8aGK~O{Q(R+MDtN3e+G$s1nS?T3HP0 zaD0leo&{XgF<|JL8SGPkUegR%k5gb-DRULV(?~4;5{RV2*+MH5B%H%hn5a44C!k1* z8+n~+6Fios_;oLtj6Dwazlx=4;^xov0lD9nu*!Cmtw>`!Q4j9ZWZ*gD7??tvZFEKU z8ttD5FCJV4(8I#rzPDn_z^64v%=XpByie?%!HXHi?vbKGJHPQg9$?H-z+jI3Cf;$O ze;pY7Sm;H}w^c1JY-{Z8E=UQ8J@YmmNLRvNfiWjd5$}iRxn-+kf$Nj-x9&9$_PAjq z<1l_t*P1yPyip(bKJywjOP)zelE<~17OQ`VT6c>t*%h7w`Ks_!q1hL_hfTR>S+a$m z8}^g0OtA+0z2fv$_-5;sO&n^!H(u^bTHJ& zzbprXwOUjm)sn&KpG^x=R46U!!Qea4KY=wwhnyu7^pp#Nx|r*Mk4?=N7aa z-cHqKKJJV~0jQJnv8v6)*{S+6TDg`uo~x-`Q|r~u5i3EM7h8^zo!su8I`z!|ONb0Y z7I+d*tFH62FJaB3?&NDhl=x-BT~}I1jQ~kJ-7rWd-Tt_1&k_Fp`CP44nef`;gHhzx z^CL}VDVjdjeLSwUqP5`H;R|na7#ddkhECE723?QWYQu!nU%24h+tQCjMUQ{c0aWTu zJ06YC6Vu^uWeKn?t-_gV%USXu?Sy7z-~D^jXLl0P zq|%r>UEN{xSuA7vbUlMVSqf&_MmCWd$egU6yr(lt`!!!hn_+X z#Z*d;baBT|?gjBUkH3{u;Ur<3^pkp^;S@{gbchOgR=>mdSBuBUsZRGv>KfgDC8%(^ zzr19()EYroQ(gHEGEOM1UIc;xAU@yH2<~+gQ{Zs1Jcb~i6~Y+EDX3Wpi`Tw0uz&rw91S`H`W9^kRuHJn^0M3+ZC zgSRns6^QEV)qzcSP$C1M0-y_x%-IcgNlr_H1R!DQs9*3n zYU0^Gq>Ixw0^Nalmg(1Z0b5zy`=iLdI#~E6*!ycLJlm;9hi15`D&0vdQIi>ch>oOd zQarD}tI2Fj`LF_Yy>AdLbou6N#z+;c&ef%j=~`ObJ$KnZ_(uBLi!2PD^JZlNUTutO zPQg~JPFA#dO+zBcP6;itq+F)3z5m)5@y?)Z@k;ZTs`MbRR=oE{a01aNUC(4y1`VRf zAKXoPbjxv=-7KlfCD$xJ(O^Fi_<2%Kp|i?RjD)ggS{@TKOf|<2j31)1XiV7gBfmX6 zaMz5_0blsf+ZP_@90)V^DU07KZu3w<_rtq&BsW8}8ydaqfabhjMsWfK7A5q3e842h zJtRAs>WKn!7t4QExzf7=N#DrmuqIWFn7mA&)-#F*~=33~x%94-ro*mf-y%LzMJPjEGx zz4b!8Gojphb0nop((CO3P7IuM^cU6_xC8^48nl%#v<2-MHxH^f96Ia;Wt4zATYkBc zBRnDh(3;yHU-kJ3dSK3-0f&5urdxT)qV#!_EY4dAT$$UIZfa=wMrF8LfSxn>trocx z_lHxn(lCG2#&nbp2NJ^KbBe6r>oUK@f-;4&h8`(NL)*`XfGGi&_Z7kn&bXw+mb|K} z?lAX()NG-tZK1=vnZ*N7>U zWO1;@&SEL6=UTt8nzy^kTZ26VI6i* zrBtrDfu-?BEoU-Al%QgI8w&`gY@-pe$jNpf6EB>HGW0?w_ac?!KZvy zieV}~_8JO#%%D+At@a&90zMgJ@i1jya#;+Hfw_Y<@SaqsWowg*dh+Bgz^OknPsX=A zHMg)B2VBi9Q2Nwoo@YuSSeRpF>wQL%8U_joat!P2(x<&7VFWCB$PU4uVN#5{!*?qI z1N0}3c<;2*kz=?7ppq8?<1M*pNkSvL1UZa4PUlOKBHc!FiCrv9i^<4r+0S2M!-%qv zUyr4K(Mc(C)(X%dN3j~eim3jOom3tgH=#s#j5eOwawoHv=Uwvq2&ucTO4VMDkpRub zuKEC*>;oqYbzFK~<6X1Rr1{P zm9u}tW>{lNLSaGs$l>GXwMN^F;g^)kdsT_S^k46)xp2kQ8cm=99+pG^p>hFFn3|2pJIY*GZNy@^}&O(-P$oarI~^$_8L3s z8EEO?^^+9;d#Bs8w!06Q95nDbNgh_|r90E()`kXEAs^X{@{d~=^H2f| z>)M#%7$r(b9OZnkE|n=BqqGQiyjxJF(=C<5^}If{bTO$>v{}lS$x-{sZpqCh%{myD zN7YovDbMVUyP5v7!7t6Mgc@&-KR->I<(SfJz?foFnYT41d!**8+LzYt*;!R`^&o5F zy7M^RunpZQ<(+wkWkgP(37l{|yoN)19a~;Ep%wNQ7 z7Hal5H3t!1T4Tk&OY*)(gQ!Oh5?Cwt5!x8tt~6uaH6$%Al(TN?k?-xB(HeU&Xuw!~ zV3D)+1So*D42y}s8fzHI3}ftHib$(*kUV3x=obin7m^t!N`P5g>a~Z=s}H4fk8;J_5k2A*=-mo01D-LKdIIcegK^9HsPx$Ua)#&l0Qyw|yKW8(I$T}&wT6$T> z`(DpEf)-j}S>UwG{ahN)b^};CP-2}lG$0(3768HqEqX=`eQ9`N&g?TVt(A93!SLKn z1kYCXDug#B0_CZ!Z`!?AtU`%LzJX?Ah7d4v->VzPv2PS`z4*)m(my7rNZ?qr@)Pt< zNfZj>&(UnqQ? ze!4|_Yd7r4Een=77M%BVy9rT|6pw`lbE1d3#DrYNF3v{{srKjI`Tu?`E;+}anlWta z;fv&b-3vjr373uHfG&zw;v3A?Nv8=59QDwhZfMHkLp|7(QU88q$P(=e4fr9IMbv#M z?=c7d2_FX^Cbb{-qY6udGB%Np&YaH$d-osJk4mkWX;G#Uo+l=L7Th2ax>|E5SNY(Y zB+?`DMi$bYG+k#PXL0BmtU<=ZsV>+N`vW9{jMwyGIdv!P6g{nHhkcy0eQM-H3r(4n z+*Z==czK^}>m1C>o&=KGsN{-aQ1b5hbxc*fw6jW2wIgr9^dnrRJ1HryaQ(5a`YQl4 zt&lB|T$&D4H;cd{8qxRG zt}KLiAHQOQXQ~L2z$adyuMCSiGkf%VN zxpB{coY{+#Z!WY6-j9hKv8|~8j&(2n09xkKukzegU^vM2P0V-ZEs+Xl-S|Vd;u*O4 zy!b!QqA_y+@@Hcrtwy@P-;@KnyNmeUhRmze{%^SiE4=LOcSp8_7zbX#zxP8~NuIF3 z`3xXd;NOTZ`?r@{H5qymexa27Zxw=Jgb(FVSgVd5Oi)Owd84$}cJ0?d*8CK1BP3nA z(r23a>fl86)nsE$^+7s%k;mYZso&L;TgNPA%k(lg()iJ`8rC2TipP44S}0cwrRZgI zf~0W=3EOehEs0CYH`ZQA@QbTmi^cFysmjPdTq54;@VEOIA^^BMb*l4;@K1kCNv7q_uVI2RKrj6PsRZdRkiNymYtXVo5ynr zEx*^JBC`6o9=kO5oWH*WI?K9SceDmD8w_O06g+R3xGEQF<2_+|vvw1GWud6yF|vCY zX)}{`E4w(MY;2=Z`x&NCQKdTZj#hYbHQuvVn4H5`QK{Clmc%31_EWtliqsgOt|_8sf;>6)3;#vJkG9Erhb@i`=4_h z-SNbaEzjj4`2FDzGO>f>IfYsj)JZv8(dClN%(6uK?IM4l=q;hY;8PV@+klZB_#^X@ zc=Y#jf5f!`?*j4p-$eu^xZS{gK?W#Xp62Fpb-=?iAnCkvQaHeCySZXX9sjETQktv* zND8&YU8-;@HhRhIr^GGD7?G7zh2q#6w`i+)-(8(%f@Hzuwm(@je?AU**?((yuPyaE z2pfD-4KFfpzFR0ore)U>phbKOAeF0r&tzAHD*#KP5(@r$@F_8PM zf`mz4t`fh5^tGF``snsZxn!HJJL#qsb7iOL{_eU^voBIso&w?x#toC;Z|bs${Z}yJ zFCq2sNJuJxHC4$5KB-PA*XNnyL?MNle8KZL6{?mmh0v5hwb-dT{qG}QX9rmNG4y|n zI{1%YFqrZR(blgrRDj2WpX)!5#|OPN!Y82Xp=W~S5_r7zA@1K+8s8Is^-VZrC9#VY zPHCbBPEjL<)+69NSwZd<58mrYiVrAX{+2e0>c6Ahp1A}(R?1KRdjm5)MFx2aF{KR~ zq>byJlnR{V*|dtx2i|Y-&eguj2L9bikdq8Z%j(r&%v!(m0zl*nRg(FNRK(IBq?~eX zH^)jZYt%{q*0O)qFi9E!6O^P$uk(E9SJwakKKPrQjaN@(th>D|3M5aOS)<9nyZe7!^bFn@9b!J6 zQ4;#|$xBF5|I?-tjG93tm;WEa-ZCnywF?`S2FZsm;UT2EyBj3L00g8{LK+0=k`|S2 zX^@oe?v{}5lI}h?Zr$%Y&UwG{{c`LddjMss*>kJt_IJ)vCQv)KyK@(j}8Fmpj3@T%!aRrA7TDm z1Df!?UC1*+V&u}q4HeYSP)FWO@0~87U}zj|EwpkOzsZ_r`l$R*4Qz_=ingQ2Hhx|g z!Ee|6-!J1oAJ9Ftx(^Fe%aE*H9@(GwKOBN1Dl{5ycp8 z8@KXT0kCGF#ikh{`1|WX$*}0q48gmbt#QiS`jI!h*cxa)@`?W7fsS`Y^Zg;j|DT7@ zyM>MKG2QWh{aq0677m%$PWC7@_Ac@Y%mKO5#~kbVhFnYGk`8>W1RfM0?=5x!VMFpy zD_0!KFYn}_uy>DJ` zrWdD(`CDH=oX_vK+O9#FqF1hG0(O{zv6Q9GduakH^uv5c4l!^&&=x^~RwKo)t9@gC4e5}UNQbFFEo)-izg=|c+6X8&`LpCjc zJg^w;=%r$UjX{KfQ1Gt@&Mv!XRzH&;KG)J~@2H zN?Itde*gLKe~QaNLn`0bfW8=pL zmHi@_Sy>FFO28GU&oIpihVCgfwQk1b`eqMdf; zo_q#j&sZQoHNnkcFS)=LH~#&ry_*FYOkys&b5*7HwG?9;AN>C>kB#j9vHjbMfR75r zyG2MQ#o3rxc>j$#gKo=y9yT);s)_0F&?}COl==p#Zs>SHO1EWhR(Q$)@e;O^sF%|ISBKP|Rdk;}o-r?@!t z>ANQD%beGZw-N;?@Y3&H{T_6|MPPa+l1pTWQH)C=f$$q(*2KnfboJ&macWE_hc*dM@bu4&W;n0F&w#ul3Y&cf z%(>BDb%d*y*_DXrT)fT0vN*hZNb4MSf3jfO!RIp~XwxWJU$ocnN9>G&?YuW94V+>g z_b2jmLZHYSa6#OFAA!oZc65=0Y^d&6qM)d_Y>&9Sai7Zt(y|f0ekS+vB0%=4<8eQ? zEu*6tk5!c__jT6d!LfXLJ^1TQxCUqwgP=^2Z3yf#vXVK&3&y3yl!uuP|4Oy@alNGoGkTxPr8OJ&s$Ox1tfC|o7>c;rHBnsNs%yUK#)32qH+ zj6bc56rnx#?vlb^l388IlBm~{jJ$OHT#FaMok0P*!2S)|<+rayDaNUV@pwc#cHxq=wfIuhY)%17}2K8$}89I)UIL&boPANXKo;ESg3#bv;eX{B0; zUJQ%w*Pnx>K6&uzlt39C>uY+eX8T4(b7s!_vUK+Cwx4)Y$Ct&e$J?O=u|FsfP+_fq zKeeoHF3R?&Q>LTN^Bx3Pxh8va!pGM~tRPKg)Ew-y;4_wKp2QE`=L@eV+J|3;b5Ty8 zZ=AUvsD*LuES>*z!Tyz(DSHebD)Y4HR_=$Z$C2 zxNRFTGj@p#6=Z(;nh=nX$INj5ZM@@2&TVgSk>dk-=VAcU^pttGNS=h`^KWtQ8Mfh_*UG2N> z-B@m_0h_5({{W0f7Q#$dZ-bid-DpjdU9-%aytjEklzNWVLzM!Mf~0P|NJhwSM_u^3 zQRJm&jJ6$$j%_o7Ns=7aR&uFexFHAx%>s;hoVjhvVJchT7&ijwxk}d{uao4&I{2$p zU4q-$u9Zm~-`jMzqF5v*K{n!h)ATXO_V@3*uRbR1l#&SoWjTjWQ$54)HC+>MPEz5W zcQ3n?5m^1Cj!f2I+7~Mh(x`bBYlXGUCyOb-m9Io}?$3~6I+#3GY4aK=3O-Z*z-8{y zwfWSmOWyoo1w4Rz)+^oK^!Yde1pXuXpH}!Iy62`%Gi53=w<&-pXvW4Yi9rE~U!CGI z+0ehdk&Pq3`-KLo&*+V{UVAK4|$zZH_yzOG8E@tPw> z!0DIKt52Rg!*(p^K?j0VRK7i5m@VZ^fB8JHpE8a?APs~e6+*0ux{v(^jt|W89_4SQ z>@0@U{Z};xSnzK;>Ud;|XbGniN2^am$JdWHfp zk!S~GIi}kW?#KgfVLhc(fo53;6KxgGC~*^wf82|`eW%UR%rVf`aDM;QMhoja^A@T8 zu!qrPSxl%vw_X4cX?lg$Opx~UB6UVaM*3c@ir!sd-lw%!m$q`Qh@E1^r86tpWwM17 zCl2$*h^%DrSpAf7+}p-BQp9~zR|KhP)I5JWXlkCHBegE#5B%c8 z*9jpOTio5#m!aw@x4LeLRAZ!RuAKg=%YM;`y`J}I!MbN}ec{{o4|oj3=nCz$28`no z%sMq=B_Dxr+u&Yt_j!)rE}MpAi)d zpP;Tj%252GoEG?+;fbkkTY!~os~z{-pP?wKP8g%cbl5yHPi`L^*8Kx%2{f5$U?W zf^`^UZY-b6_}&oUsgYnkUYRU0{3e)=1~NERVzn1QimfGxm*y>Pa6TR{pkDA=4fG^H zgp(*>AO0}?hzV*lQx)|A*E_~T^7d-}ZUk^q@;z&Q>b`Bq#~84uakti~$6*pw`Pin*`Q5%0&&Ac~OBy zy~leJIF`j-;dGj7d~w??TX|tPm*sO?WkB#R*YyHRP8VJ*`EDgTg6P5BgxY?H&)~vP zCh217XVtpGSGU*omDTaK>CN83Rxx5f(gzm1icuC&VD;?4`)83A8L;j#T?*(tC!V@sd&>qhawNY9Z( z3JeN~9i_VDrug;2NC&FmCqXbP3Y3gB2gb1;bPSk$0;+R5a!<7I8I zRc^l3OLnujC*Bqh;^K3V`_YNHRNY3?r9X^ZqHp8TfKkzSU9qqb>Hff26HG!)jZ14E_=bB|=~{s1d4w%nbL@T*=n<`ut#vze!}v*O&H< znkmRxFasHJdCF3?$^7;-ANe2dwt`6{*DTFe3{dOn@yrniUSUm{1IbwU#fg0VT!!aF z-gCvz>Y&`Mx+A*T&8*`wJX1Y;xEl=$o{oOTkyL5>&1ki~Db2+9^e=^4PXU?f*-9S2 z{Tf{-C!OF=vl#%(J$3UCN;nT(e-Ga6)u$YHRv&<0~j~zfo&{?7tTm zxqW(lmA$6^Y;aiLn|6U;VzplsBcc90M=dH=y8FoZcqNFauNjKenm`kh3pxRdW;#BP zeVbLC;vk}kyt7QhB{)lwDqvp>ck4to2qP-#n19F%v5e$m zodB@=UN*>7XW4qMc;A!KT_ZQK6~1ppv>=74b^-L)5BsoiN#Gc_sSrL4-}6!54+; zO)l-}l{%;@;h!lyi_L(}D%=wuH*HNQT(#9Nz9#Ib3VC^G_PHV$#eJqEa^8B$E4Rbk zH%`l`jB30vQvN{j9e+_-oF*tYz4%q5#J~Y1y5&1`YZ1hl9ji<;qm9hFZ8LAR1Y8C9 zwCnbkzPYfwv`G=!dN)-8P4HzaAm=bbPVzX_bRXBfi;0Vqw>9wRui??Hq-Xd=k(m%H z(0}b7aKx~|k^yn=mGpFLMdu|{`&^ABcmqfIlj`#E@ttxyipuz&r=?q@nplU|5kq8} znDs+^9nm1nC_b5oEVLu@`7a971JFtGZdtXeR3Z8u#p=ZmvJK4=@f-S}CQTO;ekeG{ zYSTM*4cYNLRu+k6nx0Md!Cf0UMSD+p)zm^H$t}IX70XJ2ZB7T%yb79@tnF|01Bsri z3cV+T7v>l`Z`(hAD30E)TYa#LzVZ0Gmxiw=^pQ96=U1WmXPdMsBUU%o>cchm+1(!S zQc1vFA%YCp*N!NBLe9OLscNd>;)e@7)Ouybxtc!OCauZGic(0cgCQ0?Xo) zMeS)2xY*KyBE`6Mch-0}3@GluUa!cd$^W_`o*OQ>X}twW6=uNazPhIk#wFI5wnFtO z@SSWGOtz+@y`E^iT{Wvh`ZxrlE+z5kJC7hRGmOosdr&Q5@KW;d0;lZtgc~Z0vEaQ; zd0m78k%W=)@9sB9-}jD@qU7e>j+iM=hSIyp2q_k&D;b>)#M`x5dkx9$~^T9fJ*hnTbDJKoe}DACIE}{vvEc45F^B+a7+F2n=bEuAbq25W&?2E!0Qk>77f{>|)oKdwP_}a%@A7wl)}GTz%d*P4&nsaj2lLejiTvlo_9YfAwS& zCiQiwOu4lL0SPl;;M1+yIwWtA7SdGRIqmqckbR8>Zt_z}FFFVK*GXYfXvG{PFQ9QPcEc+S4Mo;Qx9 z6?pGx^%BQC@4PiQ^_m{wQM6S&xNCm5TTMGbs+cV+l}N9il|#pR8T)f90Fjg$&lS<0 zPs$SIaWlm7TkWoZv@&D!N=%}GN1e^aK;fzwL4+Cq;&End(R=nCREzl%Nw3>ptuKz` zt1$VtM^Y=|Q?_3MHbg71kFUuWorgjE%`b+ffg>f`n!s+8Dx6=JHshUQC)@L^3%9n* zO*{7t@KA`>ON%e-^C%s6g5g2_jzZaIJv3MZ{KU2N;x|S8gDbW)yeB);6G{e^aP{RR z*E@&!S%$8_1T|VUgB`4=|G)4jA??9+2tYE$K2k=;+~57t|GE1we8fsaho4*Er_s*Q zOFmKNM5|3lI2(c?7oHRKT~m(nPc&oybPpA)o@4!)3%;<^jxdrc6?lKVN^+hHE+?Em zZf+wkOibaiiq}#t?q3l-@8cZI$$^e@bu}h-(`kqWONrsbR?AFaKK3YvxKgi9W%_5A z>eMoJqW4RTBv{W4hx=W8yLlpXOH10Pl0Vh!D)%h z^ss~~s@%pMOnNKO_uP=p1m9jCsYvHFQ`+ff0y6J0@a{*P@r3#Uo9p=sGeVq&IX`a; zKA_b{=n_|fG*JrTPZz@a>OHY5C##&6b$CEXmH!g+j{l2es2=)IK|h_pq^5Li-!!F43W>^mf#zB#na8(=bPfWzHR#@ zBdWU-)!f;jX^<#yD9{^X6-WyqquEPSqU7Pu3au_}q@o-1eK1eq6}i zX*lAXzuzO5ZX@P9@W#m%aNI_WB*J|xLYZtP+B~! zKLZ!gylO+bLq)a{L=5zTmGb^q6~M_6?=x9;!1znet;VytD^jXosm#r4^>5LX7sbxK z$;bww$7@yO5&6Wp|c^pbdR78zil5bP1y)Ft+(%G&mWVPARd|YEf$75dI__MPcJT@Sdu{7H5al< zmOHS6oYLS|T0Xefm#2n}ziZj?aM>=b%##zYNtBwE;glhOPoq&gh%j!X1l#W&+j!G$ zuHjGlM>Vrcah>m^|3C(2h}qQs3N_6CZe|%_ySZct3~xGGS-)i2vkt0_Nx|`i;&+7c zDUsKG%0(kgr)u9ZkFfvlQnRDRg*ko ze#tV_rCKRlap3&`KU5}^P`q-+4mGpbaRBYq*6i^(bW3tDS@^l3Y&fYr91;ea8J`?4 zbbdjr$WT&6svPC+o2gl-(P$o7Red7(G-v?l%*61H!hZ7AyO+Aq(L+#{holK~ zzIv|xWLYp%wQ?CI4#?LqLXh8R@`kG(>Gr;s)LU#pcq2E|q0zqZ4qlgDJl2+KQ22~g zpF$fInIF35_t8rZHqnd{$I^|Kumo}N`{L#hq34ItCaM4Yc0BN7QksC zkurBpg2){pDuMgOyc`>w@5>orhWm_G?G@oRp^?$DM_iJJc38qf4*&VERf|6p&I_{XS3sXz_o@r*o+XYU!_mJt@bb$t3CC5e7w*TMj&nz(zIcP#{ zz2LJEjH1C}CoqX|Y*A7MH%7SDIX{P8;K}|eP-7T85*-vqC+zCz7(6ZP_0q! z5>>Lc+ITzFS@yXVsa$7JCkjJt@F4kRo1mjC5p*C~IHbmTPyeM5*!YLyA8Lu&JH5z0 zi8xyC&$cY8eGygbK!X(~W>9+*KFyz`#&S9NRbCxntcA*JRsK}joq?j(OQI>kf>3sG zjC~K@aZhre>mX})%e_=$Z5NzgscXGu#hNQrOZl0IlYpmUQ`TyC1X@Fb*zj^s)3N>zX{GlzgwtVkRS0tYI~ySW%7E# z`iThs7YGDC$nl)kK>wJw_(81^e#J#1`eh|w~kaNbO_=&se&3Uz=BebV_ zwh;%rCB#b9OeJgfq9p<3G*Ul)3rc~s~Dg#b#A^aWeIPt3U9=2&ht zhttUB{;b{vBB5ZjB2!O`XyjAsEz`#$5?uNWG)O|Op5lzcjBu}e9m>N};NO6#rYhRJv<75>Amx&GbhNcU%z7e|j0 zRxCvPgTk@;F!y)z!cGe})8-SedW*)IZOSo>u_=|Ic}`zpg<0hgv{HG)K4~1CPTL@1 z1+Y}FV26yN>XerF!({}LyGm^~?t9-&E_C8*LfM{gyaq1JCI)gI+`OuJF3JyoBFMp< zTUQQfO2%Mcaq`1MGgu<_KK~IH{l6z6^v`Al0ZF%e?b`{f@08Lyx96fg?o8zTXgM&-On{P33}O0 zxhn~|yCy}?)6EbNPcf#AZIrxAMYw#yH(rXvH`~H35S)}j#7jl*0e`&a#F03CGnv|{ zbVJhRkcKQJP*cv*X)gRQyg`hq^uy>;#waIl$5UJz)4{mHajgR54UY}{RLhalFWrj$ zd=?Q&$*|`8zkDAci9fPAawm+^nGKRpe5epAC;HOo)G%y7Mp9%Up{$Y*S>!eQ2b_)F+BRorjx zVUX!RJp9ie9s5w6tx6(Cy$NK>D;ZRRxl_)Axo3hxeThhGZjqDR?Tj zIKg6CKP`eJS|d&%iIR& zXpS#S^s}_;mIlPl-5|10yx0p!)I#Lykh9u@A3Vrt2QW_tw(e%Zi$VeYVGCe+kp-dI znm9{Q%Zi|?{*?v%=bu9!*kZao)~It2rYcW#+scKxk-eGcEa?DcG#T4*3~4=x`zxCE z;wGzx7*hh5ImbJFBRJ^pUEXs~#;54`g!La?e_a%UNzy``>}>vieG#MUmTPz*V1SOT zc@Svoc`?S#boDB_XESJ{;Zt@(`}(FJY9+IN_u zv2qhS6VoDZDTF_?YhfKj1356%h(_&A+#S21<6iIvbx|1<5iRErP%qrBVd$~i9te6@ zs#vzgTfGTVrD~=ehc_hNYa@2S+Zo?MyIVahIgo#}+D{-OzwcG>jgjnGUEz0%U{P*l zl8yP>o2whyU%UbzA{YXqujlXHJ}X0&l;tk_lHPGpBNTqMjU*3aB*JV47s_>fL$D=? zZIpa;efD_wG?2`VE~Xi)hg9@^9VO1@p*T}1vDe0O$xKTX1~nIRkQaOgJ}>NY8am0i z{nO<*#5e1Ay>nL_Xbm!qU*$Za{(q+%2^|dKZB`BP4i)p^BV?GvX=nyN>p=L9m0#2t_G0-`^2B>Lkz6 zJi^~%>tLNxB=>-4ov2Hq} zd25s(j-as&e(+Fk=5?7hCM1F4ya07vbZgIva9I*FSdL48A+*Qnh;~SBwlnHQ!}D;o zHy`5z#RN9mSKxFSaWvEEN$S89`*O9tvLafS4yu5%{y<)5TcQtmA8I7Me~@Da3>vP; zF6EKen1-JCVY^4%9dsIqSoI|=2sP1vP_gCb_xqe!bggRNw@`O+F%1qYvxhGg%_cWy zt&`p^tb~R=AIkzi9(>h<6x;M&f74ivj98hDq>8Pg#!nbRxZae{;)YVFK8E2-If)-X zrj6r|rpjUqR+_*>qG-mzh!hQU(HDw(Rq=*m=E!yhqQFKw5jB-|Cv{a2W#}N%mxgIV zn)>vyV*dIgziOF+R`ygIrBO*S`?VsQCHF4!!)8w>cU+>M8b$SLyQ|@a{ zJnEBhL2^q1?5JkGwqo~_lb6SPo_Evn)Dt3Wtue2|b2KAy8+7f#@9L=7p>{*ySN4v7 zB<%g2-#eA23seX6pi_91RVB$7o7t`Hgd?MmHQA8wG`KIuuY()*xMZjV)OZ^j^N==Q zVn2$O+I$U|6E%a%M{km7;_V!DD_@23T*f&j$o`g zqE-2nk|5FAQKOeL79oaeVEJ@5g7~HJHzAr7FTcMVw62LDh%M--W!tS!Mt3XO01N9+ z+NePzQVOs4`J}DKj0}ocQg=x7*M0ZcC4U^6vU;quT6pdgm3VYjTk|5<7@OJ z)oZL$#939WjhM`4ag#GjDq1d7szgPwhIoYjW-w_O zGMvnljD;L-`v>QncQT{q=Tr(|jpt!GtW~CoXwp92GSF)1NGJ(AO6hGIU>rYHQ+JpX z+^ZY)DT-)BNv^!1nXI-)dj3sY+Ejfx;}N|97{-OdzaKOrcmUQ3mB&`}Y(g@2x-kzAIOoNyDUKL)loiTw7@4$iH;WS0TL5c>lG zCsYi!oiH1LdYjzjTC7mn%J|E0wn~cE9$V52n}ddcW<2<(f?*)* z`m~5_yo)~WT1IvXS!Q~UAYSZJibn#)%-wihI z*J)AN_AH;0CX#vU!CmZ3%;y-=>iU*JwD;cMSaYtY3{8mHEK|?cI%5WXM95~ItvxI5 zPfrXy5mFIm(J*X2A_!lBHP8lVQS}oMfsb+WLFqoOE_}@b+shG{>qh)XHd0&?BvN!n zM&FdeRnZ;=62-|kF*qPg0kXQ_I@jR1c{=^eb;sKFQR3T8r&sYn=L7F85$H7vUpnL{ zL;OeG1sGx|u-$qqq5kQ$vR~2_ufB90Jx@Acf`AYZs!z<8;;tP}?*+5o=l?K5pLUz; z#-bT2=i~#GDQSsJNK6|s6Se^ik{!r|6WA^&!%b_|_z4}2)tm^kDvn~8!_#}TyD`5=zl_A7x4HxgTL*PHA=E`Hzr>TWP*JC4R!Qa8#JNb5z zpqYsu)@gKPWCP%6nV_;_e?yX*_naJD@uzU{gJW;D!1`csF>KwX`W?g10br`nb*J8b z1AOkDNW6dyIvXJpJuP9zmV8ot|0oPtQaw5nC2DorjB7X{@l>^riCbmqQY`e07sn9P zP-wY$!DQ0{Zb(v5{b~Fm7m+ci;TQCYAHibjd)0EpwuuA;tf)9Uv>y*CpM=Q4u$7OO znk`aVjE=jUZ5lRDr^Jo@s5YdvuOI0yOCKN+D_Hb}*5c6^pv!TvDL-(1yO=ILma?~a zPwH@1u_{5n0Z4kDhg6V{e(m$8>gqoxef(Vse?qqcUfHF6PpsR0)hQ(8$#|$#KtVIE zgehOp%y|Ty9b^0F1|XJsv>I*1Se7EDHd$_o&AjlGUTyhifMk5{pSr>;yxE zyHoXn%HQ6oRE*&*lb}Wo?t381J`gApiD0JO)_Y$P_ZABRzl8T^dR@Y!HGk<2RsD3M zc3c%nHHO9{&%M;Jjy}n9 zWYbS&tXwwMhq7i(+)4bFUtFKeZsoJt_(mi38AFfO2D49vUPs8V$@+1^Fvs$41*J4! zzPKS#n`f6DIiV6w7ehdG=x>c>`nop-n64sF4s%<#>wtk9=J2g;%nlrm4=TmsR&?9- zufamLma^Y)D0uH@_mR1$FJ-VsJ}S&6{D7ye&8rj@zWt}lg?tq0ZO&V5m#;{guL-wJ zv;gT-7DTv?idt0$b@>Oqxcq@Ii`~WJZq zoXM}qeCU8S82lgFV9-1GkKJ7teIcV8Q85bY!B4e5g`Eidc%Y~ zIHFkmrAvjcnk8MSVmPl;#-n{?ObOUS1Mh0fm~Xezm0}T*AVB=7nh|bp!00#AqF{~k zz%waU1jG~<-STSgp9o7h$x(7&0YSWH;dn&b4?APt^N^d2ZGk1eJ*4Ja)h+?6OM5`Aw)b zVREwz5#p~!d;yS1bJkc4u@w7AXiH0ym#>JLVU@yh?gCujk*USI0CiGvbgGu}+g(5y zNse_=%@*IS!|sfx>)o5FhY<15E4V?-{nvFaC2=gGP6Z*iIjpP@%j1)BDxQr7P+sI3 z4X?uesK=YId|r=lfxJ8504~$SnTJ!r*{a9Wtzeh1LPriO}Lr20D*}2jOd<`jw^I{AVQ}DQC7E z_HnNO0qaO*`Q{Alaf{z}PhC1RSktN`_XX(e$G)kf%6gKJ6}q2D3t-`b_?3pFikz5$Tf#lpxGoFvmW)WAk(-ptlHp0@Z~1MAaoO73N zcClg~5OOyNaWbSpn3CilalT8d>`xqWuywUxlSWL-x}@)zgoJ$2pItf8mo=NZUM`{2 z?ZJg#LcCv|yd6y=(eq1BX zm)W9W4XCMc&5B7`M0%%I+Vl?NDt@BdwV~CD&+vRz~UJ)=S_>|oNM=0WS(DP8D zz`OYlux|<+SfSWn8Y%hpFzCnZ-D{&kl;e7H`i^5>9(*=Iyu%;@&a;1uyCB1wup-zN zE#uhjcKYpzZ1l#KS@q>u#&%AEXuqH-KZTr}a4eP0N~Ttq``1O`H{VfURE>b)CNqEls?rj>y#hkXop zq$E|-{!=`AASp)+k4D08SoH38dT(raX=Xrc1+41(22sb?pN`ECAF1+U$fSmdze*L0 zZ*LIx{PKypb@R>R;yaU%sjX&$q``jC3)`r|%?r)Gt;UM+N7fx?Sl|8h)X%Mh z@1>c0iEC2=PqZ~g-QM;_%{;}~1@EQeX7&@PK|H#0AvyZP>DG`4*FTDa)M@*X5 z$zg?8`MWC=w*nhPW}G5Rlp`iNS+I1F{VnzR-PpY`3_nS3Y4Jb(g5XgdLpHbIx;xU# zqOM4$fkxMZ=+xxK$2b;djFk>3$Be$b_9O=mL$B7OwO*j$L2O+X%5pl*a-FVXnys^Hr`mIs;Lm;76O1jSKG2AlW!+K$n;L z5$fc=5#g&ZK0mzQT7(R(E;mJR?$j40m@^4NqZ5aB(5wSzu@i^IBHL|Md_KJev>ZA+ zZ2TrD$rP0~<|#gKM@r08cvuU!}zbIpd0l3rlU?`Wgk8q4`Ur?G^7EfOavlfiQ&}4u}Ib-mTUtKh7sjT>@i^wf^2131&oX$G+)e?`{luzH%)Smuec{yNk`Qo{{;Db543lZXk;y9uRC+=21z$+GYVIbCQ?lX_*eABR>C{b(1u#Jtjb^5t5> zJz7Hctuq_IlG_A^rOtUYD(iD5MI8+3P-pD3l!$dIAhdg~hD1eA=;uHPN2GQ;2|MFX z8TwRjGEmMfEl4hE?6Ell4C`O%Xm5kOraw81bdJ8MVI>BW^bZSyV9h}ML1T&jeX4SI zZ?MTgEX5^#dB4es$X9N!VuubjdCSHO==AM*_Vr2hCx{im5Iyj@@D7(t!*JP0n%~Tj z342;&xxsQwP^&)d#uG(rfIdica*Y(_oe``7cLTrM{BV_VCH~I*rp)m+?XnGNArW;2 zr7|6bQ4Z6Csq4vPM}iqF)|#kd%&j>IJ#|$-9^c3n*!A_dM$>q-DR+Hi_YC~mEHpSa zZ0}Jy579~?%tP}aUBT@;Lu3CID`HyN|JesK)Xn6XR|aR&AXFD^IVIq>6v@YB$ zM@EaS^Ic3vCsGK%?CPcO38wN{ip7U5zX*KhTi>5-xy+x$&cYo70Zlqi{?{eB_T66N z-5N0V7}FH?w4F;`-!egSM>%!S z#hp)(X1O`M@LM zO3p!n=!Jepjp7Awe@sbthCEobj*@d@+|Lpqz2{knha4QMJKO%aPZ#;TT^o$$rvw1K z0xl0ywT885B`@~J0Bgl6D~ytk2sE3XFN}&rL_~|F_>-=LrasqS5ki>Qh|yP#A;YR) zm^9NrX2h^5OL3t~HK07^Z;L0@W~thTy*%t?l{8j^FUVAkxe%5i?w(<1R%igxk6K~JO#p`>Pf$_#SkkI9ddb56bM;BqW|L_cKm<|oB=^az7 z=1Svi(avfo?0{b>F>25ZmKEJYJIo*zSBTKE2GsqqJ39viFI9gKaM*}+Gg&-g8}skU@O+S&ihbK|o(P9B$lRM){fQ!3kNz+X^e>Tf;TlKa zS{el^(|*%x*!Oh{^-~tM-e;4p!h@XK6BCGYmItJk&4kuBy0TzHP(F-u_%7s?} z5S1!{+Z>Wlq`aVDz}O`ZrLaa8$U&M%ld}oc9Dh4LDY_^qPL)iUhD^Vo9%6F|;(#f$ zEojm^pl(XQx!pzN{K3(~<%YJk?-RNi_pyar4E=PTq*3Z54~hJVJZ=Fi5jPGK(E*sl z2toBcvJoq3v44B0FYt8jtw=$?6Ao*}d>!tOX#1jCwqfe4T4tbsO{7J;{y9c>o#394 zf0SQ;@D#JbO1vikQibnMWw`6lU-EpdFRnF;L99SNjVdrgHFu-{=~%VkE8^YDig?pU zg2~dacx+zGZwDQ|-`7L@ESf9yeb2VW0yRDolswtZG3+ORH}}RBI2u<4CGOd9k?xB- zqphP3MK6=5f0HQ6K)BrO3gXVs)vdpL81uvOwj%7sw_cX6op|nBCp#*vlKSWQFZ2@( zACE6ws;s$^t-ZT<=WQDH_4XV*avQl<53?lfxB@`DD7)dV!fIBA_M9N**95tKNc;k2 zTce3lBG}@>8YXKlV4Lfwbd(tvGOz)pWbKSP!u83d&J2}yDS1ljfg0)@2c))(Gedn;aKL04aP|fF*kQdCh3J2bqfrw?@iTrdd}LNy)L{X(&4BH zguOVECU|WWTx$I?tu(g zKn(bI$K?9a|@mp5$(U z76SanAJxTrza{mlQ8pNyu@1v|p5=afZ%X~M#){;*k%|j(!oA0wUV#m*K##xY4>@LP ze=W0-i$cWe9K#OagAFFde3if%29<-??)vx1p~1Xym3D z)8#c#f&@`wNJ+wbt$Q#jz3v`nT5u&Z)?>#-HPAqw0p@i{&BKTdw_BF>?2k}8_J(aCqvVpY`l;=&VB59-kc9v#w-_!>Qpge}V6f1ihdn!NvsTxrCYcK|@XILO9T zA|e(0R+GivjFd4n;~VQzHjYWvmE*V_BIz7>T-6VgUzNm)xSzA->DHSxT}|9E@YJTi zOReOC@j*r#T3tAV}oBdYItxp{iHajCE zodxvnLdtiq^a%t!-V8PoHU;tF%ANoC?h|x6EK9zb(j#e66+{Td_0`bE;s^;NA1KDM z#Om)4+JKpn?2TnNe0Gd>a~<*MN`T@rFp1D8Bau!dO^9`RwV$GEsURYlJIr3XfE^i) zJm;60qbM2YL1Cux`Zt|tar1_JXRH4YTW=i|Rs4ScN=S-;bR!_$ozfxQ-9ryu5&{y^ zsdR^Q4lUgvokK}?ch^09zVW+v-QQoZSPPh89p2|T&))mBU#)8@$5_Yl?Vc? z)M(}80M*2b$gdDPz6GFzyUrTGHF|9zOLBe?tZ`QbN?mowR%-99VXOfQkXNlqH$wB~ zK7J^d66=|i@C*4@id0!%RfN9XSF;ds!2coMcoGJz#**LaO68@`A9#o=_L^J;YDAgM z9D0&b?dGd{nZ4&gjqM`*T@P=^XecUyE>;=OMycO~#N9%(KiZ$%p2$T5V{sTdIf9zl zH22z`dsoa(1>cG1w}fMEo#w{8%2onUQCPV}&tDR~Y=qh8p4u~wF^?0rs@Rx;L37paa4O-rV;8igMNWPfoJtl6~=|yVC`}+E+L@^0E&M4zi~q?&w4R-GZS=UYm3uIT=#fh-^1D7HZH<{YCNvB*#^`IgfNB2xv$9zxJF(39=cL%4d`8A4W~ z33u`NFd0RHiv`}R2$1#FMpEk(o`^2Pv|Ty`I_=Sr4)lPdTVr;U$GvBwSdC_}U{j)# zJ(Ed&AKLC`SN%yatcW#J8EldlTtd&sFBcfr`Q}C!Z*Nx zC)!n_W-C^p;zr^H40cg*b0WKfarS2g{T%-R{C^35eIEWDE7R~lkSqU2Y4Vh)bSEeN zbd5-a7$$M^A@Ee-F7tfJr+#bYEC6hVY^e1bU;!+4-~QWT$2Wrd%X65G5=v{=py_$x zV|tt_u$_}mDOLUcV;C11fOVBF`)K~=y@MZM^OgJF`3bjO1beQ{hlmBCs_yL&ptD*^ z*?m`8rz=d)-8UkA3qe>OC-d6?^_gPT zGEgV;zJ88<4RI_MFz#5%Sd{Vo+x{Dk(4xhD15! zD5Ki(p+-YLtganltVoYBINU-wZF`Om@?-U-&V0UB=?*XXe@0|qnBYUih0?qRP#7TZ#&5t z{N=KS*&%iWEV+uMqW070M2JuavV8BYMYfH_`b-TOg`@CBmO`na$<`WNi45S^KbzaE z^t!)x-Xi)>%w;Bzv5i)6s6EgotoM=w)O=y&K3D~WeUfZDq2EX-KE#2Ntx@QjjsSUU zoBAa>Q?z9T;8M&>(LAEnXY@#E-i{8|jN4%P9~OY3-OEUvqA`^bhBM$!oU+XFDL``L zE3W~Ejp(F_H@#H0+=o+OEhJzcfNCs8Or5EL!QDYq;!Wohfudu(US8{WY*gp6j8`#G z#yoYvHfh=G-G;}~rR&AhN~21iKA@e*7_RS`JV!%}p-AQp00$EhW}Ec*vGz|?lXN8U z_G3#|o`VJ{Ex5j;g*vqrHgaaTKswu6e=FSy6eMYKVZA&w5&^HsCierI10?bVFOfs8 z+()4=MI6$RNeYe<1?d;nG_M%5|H2Ax8ja-_c!<4;UKndD<6XK`{!*e_Dl?o~Z(I-1 ze-6-r?9@9mx<+MkK=Ei-cIB3!T>B2EB3f62BO&|FUGoD)X?V-LKZ)|%6oHXj;Y9-= zKWZXB;{ueashO6}RO$sE2?M{_oxrB&36t#*@;v#>$bp0b(fF^XQ4=T6Pxo}WE%ej9 zSv6yy)7mU8Wp%foKF5Sz8Nd#3+!NQ6uLJ0%mFcN(k7wA_Pk1=b;cH-EePK1Dj-_tnZEhh;UrEW#^&bhEgR^5N{q^s0*3tBoC~ zz+!J{G@5t@`+|o?w1;pQt1c*98*UvXRNw0Z5QkU#u)Sm`b9xWw`U&Vghs>a7e;&qj ziUA9KqWBj~0Tsy#Ja~_MwX8zJFib29x;m&xnN!wL^@ zor0uVw1Npac?6>+7GwPY=C(-#Y3?0|i{Kkcy~NG`P_M|_|9eb37qd=T@fnM`ubMN~ z*zcCR25_1#8s&JDSGdTR&k8(Cn>W94lhKy9nL&Y$tw?!c)S+*xeHPv64Rad@PZz+I z6F}Q7vK|vT1*2h$_EV6hhzC=MgsE#0`zaZtETL41cB+iZZ_-$-miWQL3`ZL2GB$ys zAA#y??rYGYdI{CUKdYN#@D5h267R16t>j9g;^a#vMfrAa=<-&sfIZ^ANKQ&_7!zk2GyOJE~(oFyXAq|6%IuW*d?9!o7ZQj{jCk82^UsT8q(06i?s7pMvyGscE5uhy>SMbaH|{?qGMRx#5}M7gNhp z`&l1Ri31b`ApJ;oH~X}pmdDX7``j4dr1a{-<%-f$+Pv8PkaUnpaHf1^bs-3G4=7B= zT4S)msC-`kBH}0!^alT@h;wFRy3wqmcX_x)z!?K6RX;=7L@G`T?J`j79-4}n}2F{17OMkVW%L1W1k=me% zq(mYEFZJG5L8mT>4PED~0w1<05y5IKyX3r4r-jP)yM;&$E8qZPoWm%J10GBEM5}u^ zko-jxq7^MY5`VzRqdbjHc#N6^GT(;j3EDr}hj| ze$^Qz;gP>=oEr!2QDKLy5@N2U+9)zHq31489ZP4fJ~>36U?;41gMHB?rJ;14b{!3$ z27W?|q&uy}o)A9bFZ-rd#i@*fNBc3|?0*9SiLiRTAW6Rm5@-bAM5S!4a&e5WXkBC< z0_4H({~hgm`^H~g=liS1FzWYCOd%l^LODI0^;T@eM7NHr`HeS&1}f}X;4A9yc28xK zNmP9YP)imD2FNV54BgDXtF)f970!7>KKihD35$gg! z`3&1fJUCwNPJA0|Bs%{9LGZFTc>FseWIs#Y41(z)RKysJOXR8qc-j`Nu=dW!%YF|F z(q;acUj5NW=>y4VVwQe}l^11_lC2K0bJSoD_i}eF#-7};r8D#K@h7KQg;TS+O(DuA!loSd0z#M9_HOR)dp!<^JGgoW< z>)Z?uoo52!o0&H-(%}EZ=E4cNc+bFaGGR(+CouX=8NYQaQO{~%^`m;L6j#FU#Y#OT zK`1Ze9NZ3`t+27vF`lYFTAb!$MMu9RHokJ4>Qhj!^cC{)qV08y4yZ_fx^b^-c0bNdbNDm=IobkIQ+7i^_uVWy z1~}6sqBSv)%=>Ba&hxSHWj(b_Ecu{P5sE_v3#0|Jx=8pR4l7hV)w(WbBz#9FK^dHM zvZiPafe+wXQt-2dc|>HS{4uc?5;%|P+_Own5V%Ih4vJ4#y2k9#2s;jNZV>!N=p7E1<>)06+~X7>|_|CBrNw0&$wQsbbyvA3 zbMa(oA2OZY{$i+bI!Zvu+d5mi;@rFILK$=SfJ;Kuy zp`B$~!?|bt@sxFOE0Q@KJ%c=PmXu_ZL|sx>n01#k%RENGjqL93Mv5BR!5Te_aau6+ z>Cc{jV2fv2XU)kkR>F>I0{8(;%D*X6F{C4;Q`=#9wiDnXy&Y`}GV0r)(Xed_xmU?q{FwY1c-SM0=|0YTb<`n`|eCyBy z%j0S~zvXJTh@X4So(?kxoy6}5KCrICP2z1z=fIrg#GHRc7!YQCnfL(yY~~#5JBzXd zL9kmBBHjspPoB0)h{4>k3kS{nx#mJWa1TcX5h-r-d6)zs`j*nG-oJjmF{jZM$XUs= zc8HebAEqoz8w;S>{1(Wt(6o zGw+JLZ1*`()RJ^-H<{Bnhr(=MZ0e`A5HhHN<|06=**@U$4niL69!$GCZ>$^XNfqJi z6Q-o3EO9Q1z+s0o_lyxzq}}cvmPvsG*9TC z!0Wrf{H0N#e=@x=p%eEcDh!L75U>!T?$h|qRS#iLyXVU$yrbTLAH2BLX5-#Je>+2# zIx6utu-uwZ)CJ$l;Oa-Ka&P(5_;Y*#=s6i&g@}l_5Znpnu`9dFtI;*`dU^t63U^&j zUN)6cm9LqdWU)dCF$Gb%!+{4AEuI&|pml@K!T|vr$wEi?mF>?>D(${crer(}mGEv@ zvy7EuOn%dO-puv{{sdr@oC(LQQ@A_y47R{L2>yM z;sHEbfrKGNO*feC+}(CPqOwN}P8#{~$PyO7e}h6F;$5Kk6pHG*&Hk=FfSB9CiX`Xe z%{A4IF88iZz*(h6Y2sl2Z-R$!X6I?)AW4?e6Hf#zEp_5;Tu~(w?=vSmnp(fJ&lcbr z1T5F`XTm-poPnmF(*yzI604GgVOLYbgvGA|fR7Ix=PvH5rQb^>bAg zxHmpowhct4k@E8Lnybz^l5!ai(swi5b7w7XJlUq zoy~_%^K$CkDoV7r$rj2|g#Ode3;GGmCNfhipOEayP^iEG@2$^+$8k5kRE?&&`O(=Q zx}7BB)p~@-rt9XJ3`VEJw+2Fqe13DG@hX7%y=n)I!H?*$b4jP?7T9eXTx{I&(Xt4? zK)QV9EVXtX&GmSlAg>KMxVJC=wMnjnHhY*+o&c{-(BEYQ!G0!A|9;~#&L@aD`G6rqz zvArALAb~UQekGr8&G-NUElztLX?27#&4=JvQE~SY*x8t`E)86z2Vd*^2@OLs@6nnll$eg&@TPGPff0=XBNZn>K1i5t!axxp*2^_q&#>8S0{r}Bz z@czFgvlT*|FXsgI)NAZ*q07(;UirWW%c)dz(+MVPyg*ld3|dK~Dss9*t5$8WNsjrP zS30z|%Yr@!c@Pw}6-?SybAa%Ud_@TA*jm)Ac(l+nxQ_A{Ak>Tl?yq9^a@~D=;el== zl2Bplaeyd!bX!)&xQ>pqpPUdq4^m(dU`i#?-f9Xdx3z{@({no24t&nZQaqu0%%P+c zgm&ChFz&+m8OLX2C;&F!IwmGq2Wn2bqBzTqd$j4sFB?TI8fB((Hz_G8?o0AzY~@X* z3luLMlY9(tiz!{efPvs4PRMPGZ!iWO8LIj;Fn$VvevEsywj`-JM-JE+pF1hMnC!7k zW-BrVyWcRll!B;rF#U|R9&Y_{hJd}5uFls$9KmN9S)iw~TDJc#d$!(yeE2o zXClut_kB%WBS^QN>RE=UKw>S=?%?21a*%-aB?O%`cZ~&I3%Y_@-FL!xaN`Sjz{7AV zHR>KS6g{2TDk-#k@8HhKJ8Hu8L~KaCc?bnPs`Q-W`q%h}$@q@kvply60%kPe3lWhb z@4j3Ytmdx(x6#JW&%C3FVwI|HG*jpd$QTtTLbYFUhap3cruH@S-rD?nWv-*28JViZ z0`I%sDtQB{QHC<5#-%Uqx`VH#t4t`B3?Suax*H)k=tRF_Q*BXOGzA5_tj8!m>ioLK zxIz0T?E1a15@63BbO$YVIonvaC8mI<()v>Y{_(&Do19|mC4qtKL~q3g98dyJ?e*k+ zrj6xFw)115MbbqphD+N;-nn{lR@0>6%;)`$T-jOPyZ~t?&uZ8vKsMC$1h#*mt4_Tg~u@FvW>T7qpU&SkdzZmHCnkyP9M|?uGKe+ zU`Q9%ikFx=Tt)%l=Ru-`L6a-8mqYMBD_CzNWVBQL&Y*~Kt4|L=Zz(-T-!k0_1Not%d3B0)LLuS4G@>Xt9A(0 z^QH4?a#+`!CHEs-Ci;VNc5S*}JQdBmQPWMgqoJUYAY?LUf{Q1f%Zz{X@67aLL2tB3 zSS?z>8xLY3P8hq}?F&+Z>u@#k7swihmw3+bQMYFHoB zDnCjL9e;<*q)$uY)vf;p&?f3y-P(I^avtrYuj?MZPI^>`NCf<&tt1fq@3T4GFzzhE z9oD=5_l)_!L#NC>mvX5g!A4zWNuTYV-Tppd9|4}aj1A)^iPEx@Ia+))7lutvujipT zTGhC!Ahb~sE}0a3`|B6Z`Z}bqdK|~57gh5{to!SVZ`R2&c4Yow2ea%`iSbp2Fys6M#^zGMRF)^T7YoB9WYD-eK3I65R8DlKvU;72mJkYx zsv-6G>7U<~ZCr;g=TxQt{@`Mi-SFCEjfp`{uWFd%mNIq%nB=qXjpLLMYyX<%X1kid zon)&3V4v{$%~y!vFBym>={oqhSO3oYJ|HqU+iRX&daQb81B|z}2EF9Zm3j@(!^9u? zXvM9ds|CpOA(gju%~(Wv>BWLKArcpZ3$IWR%}-7~&zbleUZlx}U_<`I!h+ex&W zCt2UL1N5a9iuXheFh5A(GS)&xf7a8= zcv7_#-Z@Bx!0!>|O7p|` zBy5Bm?dQJO)!sg(8Y{7cV{bV30%iy^Ic)VJAS+7wFPBT1>&dhK2X%T z*S=L28s?93vZIBQg=qIfUsD>+Wqv5BTlW>oO7daub+m@dzTWbS2jkHyj81U{Ur!&I-(0KI@{>-6_d4-nax72u$1U8D zz7NU$f!cZIyE#3C^^^I%dr-tEK`oxk#d`DkyJzEk;mYLs9>P+}GYV*O1}9Oc13M;o zj)LNbcl^d_qkoZ?#h|IDkBl!HgXoC3Ot+4HH*o3`>A!x5h1v<5*+Z>bGX2vvbdv!*%rNaj0^$=YHVtq|ZGZEP9&i;9)+ZTO{BXGnIWeA-iXI zZ~Ai!c7sgF%T;W|P85{F@wFneCz}aL>@Z3+N)l6s7bh=hJ)oinuqpMOZw-}Wmo{>} z0BO(Ki@nFQeaQMhwM`aS2@%{z~f$<{dVk323>22iB&QP~01`nl`ohh24oyxnK zMp4A+T5{bVglU6D1i8sMgVH!?s0SVnD&uhYU4RKBox)^kf?+W3lG z`AKkAf_~={+E{{?p=ZATL%GX0FN{OXe&Z9%%q)i1OVRW2Zv|E0*I6vFz0nSJk%um+ z<$y3K74@NzFpD{wC1-mNq7gZqC{`5b^2u{7VLer#z2d2N#!qf$U9={hkK(1q5MqmH@w#*emz?lDq1*n zicaDk9u&)*kfxU4&tyC22jLjJ?akutbQT#^zGYSy9N{peX@kDpY>1X2SKnJ+LG2g~ z9}Ly+N;OLR$gZ7_lt}02z2j$tfWAHfsC1?!!+8$bXEM*txT4K8py3alQ4Z|Wao&n2 z_+6MWe93GeIbCuLVK2V&4%dLXwwg#uUGn!%W5QzSjANVu&bH&UT3Uc)Uyzf8T z6QCa&jTr(aBtqj~J&MNnAhvMO*{^%ddU`bue0+R;K%*vFte~ki4XL?Z4A(~?bpCfD z7BLL5_R$kCU@=Va_xVPr4dSWH!q2JQHYM|xE{<#1Nt7n`^k#^CS++f?FmMQ`oCwr- zgO7ke!hM|ZXd*8p<1G~<4XO56BktB}s-;E^sQ5@OBT-$Pd2 zFLRX&|8^RO8otTOe1PM-_iz3Pijnw;G|<1QWzM!~AhQCuLd_bJbKA{24CoJp33%$U zzYbT~eFdUuG(YKicKxlPTyp|SJm^5AqNG1z(ePs-fyS7BYr-mw{&JO9dwPcCu@jqn z=hqKP$_;)WCed~7$DeaWqV zRFHbwc+>@wSx3D*Cm;KwA0ttOKwgv+k^dF?KnKHZm`sRf7zksNm4xt?kSev__|3=dio1`<1s(ss|d;ZO2L|L z)^ebb+2%b(6kMpcOY<~-0$h2?w|No#3(a3y&JcfRyAso(f}%p* zPWyRHD+x781D##2)wV7Nd%`m@hyHvz?`Jc0V4N=Z{z?k#W%88T+#`GEy5e(#$?&Ne zho*j1Y05WU3N6|yd-9Hw0)Xdw_9U+AUvNNzZ$T-tdX2^(>x6Rbls`YyNzvV=F+Ry2A>W`>l*mEJxX|vqI2ibD9CatEFxXj@nM=rbGqiouEBH2f{Xhf7AgvF2${z!jA3(AW2ajk_4V_bZhRQm< zhYEA?a<}tqH#dUWnF)Y!+s+%MTP(lOjw#=8YWg~jR8p>N?Hv00Jme&kIKG&e(?0-| z5uiN)%Nt)sWw9Cn3v~Su%&ge2pKR6RF=da+Fj!h7-Sj3Zj3(mAtY}3rQnWnS|tfJIoe;`CH-aX8T?`L(2*+OE>N~B0bm2s28T9HOqIfk`^OF`Z&Q4X zpDo=r5!5bJAf}Q;FXcLVcl!KMv-j26_b4vk-J-pRB=OGqwzOZGn1=-zf-o}^fPeI` z$nQq%80}{4VUY=!OoFi1IBL8980eK>ni*6__#r-iNV6!%<{X8j*_bbXb7uTV-X|%n z1I8ske*PVH1~fO)~YfEY`ElNam2Wh`8byyPWzX&O$o7xm{i%_2mYkIQIs!H z9xJew&l|s5_av%DA2>dJ9FzL63q(7q3R|-E|2UWU4%Cj@=fYpp${)rhoel#l3HKjY zz@Tt+ELxwp>`_mp)N1F8rZ}SH$Q@4 z@|m(o1l`zBcVe~$R#{RI1!+ThN567kO7g~>G6kUJ(v{8MCK~va324XMUUwsm#_K1b zX%umP@FD5rKVE0dLb|a^hbz3e3A(@9$3c1vT}H&B#!gmZ$A0fGb28r~#lnx#6gkV( zV;JWB_J*JEFAD&%{6B~5e^m>@`Im61?yh0(O+OExM{A!nBckJT9zt6$kNP{qt(U<+ zKm6xAZbL+<)_&sUs8S#?J&E_Wr(#12;IP1q`E2zaM?{d|a%;7d&#ixK)Ht;Y6_>vC zq*_VAvcLbVF4EW#pYS6l5Vktxjd{nzF&w1t@D;SWCjdbpi$7KAn~YX(mE$&zQkBT+ z3E$OB?htc{O+JMXtYP@2+f7&HsP@!XV>cpWfNPsRO#n9>dF4ZNyi*lKvm{x@&4$EJ zqGyk{09!?is>GxI{g;=g6Fv9>YbXkm&SG^DbEUVX@sNus+5D*}8A`Q1Oc2wzX;t_Sqi+NswcB}l9xnGl+}2S> z4Ke7Khim?G3kA_X?btqkk2!3tScNOkq;>&6SNBTV41lK?*53W*ik($oE$NFS5x3o| zPL|SXw8+s8h*>G^#u%<@qmfU~uDHM5)dzMxRcNB3-q(locLRJTsJH1Ii4;K3nTcrK zXP{f>wNnbQ_Xp|f!Wlr7FTOGI!P{^v!%FZd|2hQy5L!Js zj)^8RDVG!Y?aA|a-V*0yukG0C6Cw`Gr-f?;(-ADu`J8dYts3R(Y!0lutgaMybr$y=OHI&u2+y{jv5?aCBt-UDFps?bp@7R3l9gY`9d*q9YB*1@3tgQQNUmDn^>YTjB(aJfIs zr(WrV#kCqm#I1V5%~WjC%Zc~~!KdY;T&scxgHd!7wA{K?XDuqVJ@9Z|TJCF_lotO? zi4@wT{07RtP}-F6S~U_EeSBWczQ{3-2bNK78k)7UXV7R}sY>fKN{glJ0y-P=c1@JU z`~uG46oH$3p5;J<`^&8*I@1_;lxc=xGylwX^@8>cOq-`)n>A6jszJ1H)D&DfA*Y`f zcliQ1@u=$xy56=I>%tq;w$Nfg0#zy%DLhXe&%Emm-fhTew&o)GD#F`rk5)38Oum{n z`uUlet(V?gqE~%iyCzju)Vfyq>kg?dIN_*|SCfe>*6)zdHMwoMT6|_E^vuDireuNV zjN;y{-+rM(sujcQ6j+QifUY8TvjRi*7RxQ>sS_r5HwkIM*My5Hi-7*FUvubr1y&(M z0+mn)x)bwC2%DuyBm+jvB%qf1zUjHIG1xUZ5c3@zkW zbIVoA^lQoO_|#a`3PcUrFZwCx8+pKEWvHH(S&a5*R$#eNaw=6yl$UB~J~Rp5*9IO) zH{OQwt3yqyP(UevmZ%6w)$%`(XeC7HIyHMew}TknNjSqCeWJ^{xsq=w`-9W{=ml167_U;gOe_<$Bk-a5+OBOExJ< zv(7(_{%KY;~|_wq?06Z%p^?ZZRwMqL+ea^z{&858yWmt50(H50Y++y-H%;A zKQm4qeE%$;#hpROW&b!QzR1sB6Sna>HFTJX0}-yNW8zH)uWk z;q=jEZ0cnxA14cqzk_Tz+TNG5GuM#OWVyxDwF{Z1i2m|6XZT&$+m?qO({h$X-!Jn( zu@T{C855g)-OM~=_@C{flcAWDR;wNUcc?fRd4f>w%mvn$ji19H1(K!b8Pxq6KSS{vz_OEtl&(@xVtC90~~>{8%5KlbPuCZ{6~Wz%*l z7|Bqo>n)8Atf#RCwpsg6Y)**O#!qZg@SG~ueZ<|#eu_58uy@UEq(!rFjJoU-nVb5m zZ;RiHuOzkGg>%5w)xVlCm4p)Ay}-q)3gI|G=qjJ-jc_xa0v$@qlbFM*4}uwzWszP3 zvzl&O_1Dj8+j+<)vRv&+x^muCag3 zuuxo_+GAtstsVz{ZB|0CNY5Q$6LPIju0O56SSYRBGjTH5z7@XXgb3aBa$3>poBp@O zt)K_ipbH^UlkUf8GkXFum$iDUW=dn^`=Hb;YO-vetbv@mp&!avc(M7DsuACfW}j72 zv)}1sgu=jJko)pom^B9zIz$&%Un!)Z3Z}@n77_Ww=dAdBgeke{ea9_jG7gcKxIK%+ zLY_u}J6SPT-Q5$O9d{Xm7Tqs9_z`EQp~K@}JRPtm6~FW<(H}`r+sX?u&4KPW*-RAuirI4R2tajt zc*$&tq%K=2ne;n${=j9a8lq!|@+;_CwUEqL&AK(^9s7C@ZaMkKLd z6UYT2M*qzgh_UavlaEySYMB{mKL3F2Z$;8jI;GqzEq_VKd!nRKPxV5zF2w)gzYKR# z|7*A-sMNb)ywa6D|KDD@|1-?SnjyJR-eC}H6$Rg(DI>bs2~ z&B=zLv*<5ndv=lp^3lcOiwzE6Ey8S!yvszldk-N9i7iX8jCCuXI~gTL{3K6-vvI*_ zYfkX%UZH1d@pvCDjSypnj)7_d-Nx}pi)r&))7UJ#l+t6UJ|=EuP+EegVTB9kzF z_=i-sQM)g*1oFkdU4UNUFTv6foY0^85q+La5)ecS;~SUGsloq%M0=?qUG@ukxagX2 zTsMHjp}XblP2T_z%9s@&l_e0_Ffs)d`S&E+602bS-Grw$Uh4t&IH|29R4W?7xGb)| zjXLBapvlrh`Xs0)grM?SpAAORGW)x{%IHG119vE6A?j7zWMC^oEE&tu^kO9aQ}`JO zNZMxc+G7;gLu%5en;Tfo?-ilC!3T8itjoX_b8^DBEWA}+ZAH%1|G)<5HNja}IoNq* z(Qx=az&o6-18XTQxnF35G&{zihcjD4EN#Dmcw3Prh6l#sL>?m68sR3GZ0AWyI0Z!` zlOKbcBhyI4iWKNOSkuuAiHv*$>7!zap7^rQ2iwzTC5ZNlIdI*}Cr2cRAA&l1U+w2- zRyt-N=oA{Yx20Q{E&`>(SHsc4j!$W9ApT#q0F;&iz2#w5XYx)z<{;ZwX^mvmn#D_9 z@)wPgCKcEX<2-Pu3}9K$L`yD_@8U?5)uRqXlgEl6!3*obf3*#jtbQNuCVVbOy?%Hy|UN<3=eO6QV|Y|16Q<$XH&4L`-jP6%|yyl`piCX ztojUO7rwwkEXu>#!??IS$yPw2?_Ip$m?PdO(HdnTz{z?N>q*tU+)i@6H&p=h*C@KR z5IX5xKX)05r^-L;BnbUzZTL0{kDvCt3xdvMh(iu#-78RIYQbBd2VRmm(ES-BP`?eh z)6tGr9{TC2p|{OA4MMqW8tLTA?jpjt^wj51lq^jZ>SS#= zZ%e8yR$!>1!H<>SHs2U?AiTQ7F@yD;M&{ zG2JMHK8}ILgcVIkF8X=YZqslu4A#k^j7Jl3HjB$Xs&f}Z!XJB5E&d^1wBjBaJr0Q> zLJEEX;p-hgFX($}D5I)RTfVh8q1T~`4WrjH&>`5SP&PjRpLA~SY0vcYL(8CkFG%dR zeLHHe6IVf9N9e^;A&ZP0s_&SJ4B>h)vK>Uh05=j3<{8c~&pMX`YS&~g)=|sYeb!~^ zA!IqRv_iFV+4?MF#Y-Z9*|o-N!hhVn#eU?VXjb+AI=fOyWUEY7U-mTb#ZTng z%D1lkVTvLB!<>dY%(-;mr=EiSpZ<&N*#ACF|At83Am45!rMM2#k?7Rg`6xM#S@i3! zdkgSH*W4T;tF}y~&?u(M_}pJY4w%b;X*P_j$_8y6Ccs5-)Mu%ogPS!Mao+hB=qksN zIj<@V<7z^(DIe5qsHv%OQ&+WB`g~`W%F$o@ynT2|nz`|6cN#+a-ytAPVyy5Iof%gwB9h9yCl6M-b(k|RPKkqak(X&0(@)v zK_`X_kw1QVb(98n_M|caO=!8ke~~TIor0TYMT$u^jZQ!;=4VYIxBjo{^X}!8$=1}n z%up^Y;cBvF0C^=rjvs>hS}?n5_D^~kqbc`1DV+@zOyTyOHP?m5VL2d?#VAv_2Iry+ zm4!B!{eAh?msbpDr=GDD{?KwYb33qlB!Jl?hXhc?7r{v2#rn+5UB3BK)3_5u$Tg_e zAX;`ehNU#Ok;Q5P>t?m$Psn4k^(!{}Y!<6xkxane_FrgRWB=-(M!%Qmf3_&*7Vx25 zK%Jvd>(#bii2%95&Cw!{4J>D<7Kf!+*wF80kz%VC|EJolFWfUFov9E45m@`#3KAMn ztpuLFBaBG~mRke&n4;(Vf!!ay`1B)HnA)p!PNfm`;6Pys5cRU_X(; zOo0>xz}W~hW-(mm@%@AVL^aK7@P`3Y4A*@|a2S^n0v6a9_swM}wlBI@@E5Kz-JaBm zqv$-+E73Bx?i@jCC;O>YP1eO>>ZdhE?cj)yL(c9>84(#E?Jn47`-pw?=W5M@%CABBXp<^(E!|pg2jFl3EJIhh9!3D; z_ohO=OojB@NbpWgf9f&tTE^<_3r-uFBmtXW)7Rg+#asAqU7r1xMtcaaWdj{S+i{nh zPV&*6+T|FBkOC}V4Nz){uM+0pYO{31WL2F}QE+-H^ zLa}*(;L-Qh*NARk50zp2>v)*qE*0*2mkLqo&{A1 zI>F^+;KS}z+yknb{@{NWqZl0jonJdQned@E)*RUpA4J3^dwh8c%$~(1V*D zlHaIw=B2g(h#9tZEo4u?qVsL-2fgb0;rG3lJj)*474Lv9h>1U&Kjj1&?kvpAXb;Y$ zNu7STK9`ed2nX}|Eepbu+Gl#Ks#wlfo5M?5kr;Yz;h2jWlJ!@&CgF^%A#ap7ELY=b zf{K*}`|$jW)e6}=%ZPY##|TvoZ5^2bT{4vG+tN-iFLQMG{ExjXGIPgcfN#1$QBCk| z#j0G!*>{?xlK-^x834QF8K39ak2pC^t3Yu{l~&QrfOh(iba&`$kZpnMzI?4o06V~h zj(>L{D?dU0{qA76jt(~Se^>yd(w7%WG^Qic@?{V)(H=rGfvagXYe8>RYY(cGG~S^9 zhp?{zt8&}AmJl{w0)jMxfOJYpcb7C0(%qfXf`A}McS;Bnf^>sQr*wCh^uM-s?)|^} zefK#$#&bCPZ1y|XTw~5T<`|!EDbPrw1s!0{bG2(qiHu5<0{F&se9l+$TzNfv2xUdh zWx#xvE-=G}c>eA(a9cz5xPc$E1Pg>bGOgD3KG3eJ&~-qT5J=-l4_`0|c@`@v9`q;M zHWcz%`w!gPHvWPzTuLG;6skhG+D5*axd>O9|Od88V`C5zwiPU=4 z`j~4N4!rR15}LZw*FmQqGC$RFuAZ+ffN5dTjNEWb9>vW*+{g}S#LuY$32(9D3Gez} zL4jKT^N;NyJ_Us!^Ch*#hJ^39Zw(bzB#cRN(K)RqB!Tams_mE-^~*pJH@5>6<3i-^2fW9u@kUG|x`>oAiZx@;tJjE_ zI+xqqWHi@^GH+VrMvV@&o+TU&F}gABi!7rKR==tclui)8WERf0XI#@LDR>{>&vpvJxG@bIT8gAS``inY={QP{C;q2F0L5zp>*gX7VPm7`B2)5scG$nmC zajPn486WHK4=@3lrh zzR8{X6wZSVpAGil?{av8jcV?CB6un>K8>nP+upBV72W-OJ*)Yi`rdf)?A0H|y;+6o z;Trd@D|pg90CFtxdGgmuyR~a1VmHi2uWs<$ncWTtEPE|60M|9A8)HAsk7e^DBo|SE z&~?TcUx;9wK`;{sZ^*g(+qX<`WXhe}B6*~%b0IK0-giZwZH4+W*8QNEa%fVgA@SX| zCp;X${CuBJ_ERkPHhqOkAY}dmGITGl8)&J2GCtb$XIww;x^~rm7Oz|slFzv_n3-V{ zpmD^{=cjqr1U6lif!YNM9rcF2=sehdpqNH+4n6fjc@q)qgbB9TtyRnPbYnCH{rvND z20nP4SctLSUAUVz1g41mr)Hz-#=Ku&y#5-2+Ne;5!eBybYGN`}r1tpye!B7Gd-B+_ z!Mq0tuz_gN8qOL(ADP4aO(q780}AXno>L(hHqOLu<=o&1IIphZJP|`0&_> zF!$|Rc^|^oBQEia27ratui;WSh7^2>MX%MY8tYqkgcnzX%vFc>A?rF{&!hYmwCZlV=` zt_a6h3FRM^7K2cPazk>RK09wc6RVqS^!}WxhwUQBvo&4&QQ2z_Y$8{D-y1FRmTDI2 zgwFY9G5y9rLJbIC8*cgShd+zQJx^eIE>D)sXwq>cdb+t_os;|cENt}sfTpwMlXYcU zcAps&t#l)g(1sFC5xV{tva!-al^)L-<#d|V{6`wa)p#1@Pso}(i)Un$9WV+$fu7C_ z?XC{QK{Zdu^;k4bx)P%j3n#kUjp){RE+0DeuuTr$q@D*=g+_@Yl}2p{-|HN>TORZt z@?V+_<~ltThk@};iyqd4$@+5>)jK9Jul zJR)7jO}X5c4LYZ#g-JUHqENL6qKwhzW2L&<%E6D8z=}ID3}7w$^t=csj#i%a?^T-+ zLBp}Qn9+Jib=XzEA%Dn$1bZL>4UsEPI)=Z~)m#*q zT8V_xb4IgDXk2Liii;9V%X$jx^Zy|rk|9d2c-GB&oF22`^c88vkZ^o<27&)6O|prP zH*=mx&Ib?`5ZFNqOsP-HVg(O{znEbq0K;To2w=*FhjApj1Oe79uaL{1bn36{*BqHB zF@RH&bSQZ+iH)33>$LE7ZX;nQPoimb%_ZyDVP)bm;;`Hk_ls)X<1$TOnin?4L*LpM zqFDLwv1HzT9nzQhG~H*a3fk(MOr(pGTX2#$s^}e;Rjjo*HGJ!$e$?sY`-<9P?n)|? zE&sYxG`^wek#@g8T9d4m zjcbKPa>jGfm+bbsc%UZFr{g`I$X;K~lc3u~y$G~BbagaC!wD{W%Ovr*Z=;)qsBD@n zZ$N{ZV5U(&u~&TvszF(4DDjRNZs#mK-$JoALI!E}qT zeqC^#Rj(#mF&SICjEV|+H2*%|-+f0ac>hD(&|Tj`R_9A~3t7qls!6WN!|92I+G0T* z6}4aVB!5_}(1$vQ6sp*n#{P;j2tv)S@Un(-2;-LFrc*V0n9JpzX9&5%e>4}!{INc< z97$4-5#{cNhd*lze1qbvX@+BY^Ry8y}hJD@1< zn0YEM05IMb@MJ<3;cVVc4tr2NnBfkZ8CcIgue%|qUR`hBDbJI5l*OtuaHX&`0oT8S zlHl0+h7`7)Fk)2S@SC>NupHOhEB`ML5Z4*qn7{Vm^STij(P-i6)a5c?(F@CYaMVX# zlFnzYUiPCiXHti7mf#9U-a=#|1N>Z}j1Es*P3eC=T)~GRs}dun4kh4${g>>8U)mJF zcwD{xXNLUeJE5WzaT@T9>&eote7a%12~j)Q--~TAhK%4o(q5994M_gX!emc>cPhdL zSf3tIRw2X2U_wqbhD&vMlYsPE4#gYlKhGAtTB(_8l%Ru>?c(MaV`SaiDdl7$w(Kub zs)bgXE+j^cM*ZI#lW+KMnS#1Fx2rl)S55nU9OGHJskOzfJ;r)ep9YyTnP7jL zs2-*+oNi8YK;T@dh&M)kQ5(=Oc~xba-g`4OxxkHyf0}D0^vlXcbOj?Dkv-VC#o8zAvzlW$0R$^fA zKX5ozdFx4S>(!Cc?u$hiGEKn)uFJxinV8e!#wDi%q@U%m1F zK^05eTb{65EtusWlGM1JiLjjH7AS(4sCYz+V-dVEu<8t)b`d+3^T`x7pwH>o9R2U- zzYFQ+|4y7RMEC$aC!@t*&q-|&n7#dn=LCVJ!u5}T6rX(?A)C)5K@(dYM6wz@8e%Sa zYo%4YY?rwe9q{v9i3*dwvFmxIC>0nVqZrRF1fHImA==1G@(k;_#s;_IFpLr9Urt>= zzx^Q=Y-W2BRJ4|F?BU>*l=@x&7lOZc_Fgp8CtgB?zjch~4XM?1CMX_30i~}3QYLlc zc=&O{3(EQNs-_p&53_&DGeKof!bw2t#^+xRn>NfjvzoE}FR8noQnBF~GXF)B6VJlP zAxk6&S67DV?zGIDj}zJ7)NS)O{D#nUK^?I8su|!US~j-W2mWr)LOGD(&;O<&cz@+6 zKTJ#MYi!Ir@cy6vWVLBT9q9)J%Be^k<2gfbYgjV#!p~=SxbE#M9_@5dXPSKRI8a>T zYE(`qn|}nQEnIKMj!^vxY6z^TLsY!lyeQd_XLaA&e>qRc@V#+Vb=N)8BbI_%Uzdp4 z_(En$;zdF*I&|Ku{z`(8e<6ysq_G4h4J&+Q7vX4zf#M}Pal4UROePcBPrr_z-z}I$ z!R)p_PnL^(pb=ZZMs`6L+XDo0s_ovPbb!|%7Z5?;IZun z;S)o2JGVf%=wZcP{l0oE*kH@C+Q6qI7yF|iaW~sp&;n}@A8j)%uVb+^k@VNMKc^m zfx?iMF;A65(7R6G^$el@nX0Hp!Wx0UC+U~G5JhEN)xQM7zrJ?}Y%a|2Ph1*q_29k{ z*nBKi$o_JhDt_>AMD{uwi9=xx6V(I?&;9=u-2Vno*f`KPy;^@yy^I1x)l>Ihz4HGx zs_^{p`2eN7mT;$0YurNF#0mX(d_DsFzGqK)KFo!dP|!ln?sM^em8?`)TJhhh9>V>H z$`_h?q;X+=dIYcD^u*Ead*8P@(Si|{)5`tfR^VSx5||Xz56SEdp^c@3_YV|=o(5r5 zaUSwN$03dkT8RWu4~Jxmdi0Ntdj6O9P2!Jk`ZhmAB1h%zX1RC0_UR=#p@ST!wcaDV zJ?ZN#Y><0|$^HUPVLv9ZKj`vrvHn{mifrTeolm`ShdvK|yg)aYeQBwXj?*8|mMjE`E zU!Qy@_dcr$rp3kdJLv@U2+~XwUq%SWWujuN3~x1ZX6KhHNj)Jl&7a%d^hIh!H)48Jqi~egunYwosMQ*>}qaXLahNvl2Ms z%bluG&;g78P|)8jD>GgfGx+!a_5a2Dp9~|t#dnW=m(aO)pov}>?Zy59glt5X#1z}Y z#RS}UB===f0|c|kpvP3Hlk)m+c`A(z#l5s_8~sn95s&xZ-Z>e(|6?1e><5VIITb60 zm)%^~U*L|H89dFOS7QwY5dD0Y(WHMr_SLRuhX4Ly|MRzuW%A#ky+`CpHP&dcCAI}) zEp6nYSV7M>1L1EI*X*0MI^S#MAROi2-o@d;zk!1ROIP8;(cw0T9CDzFI`% zK?vQJ-uu6AHwY{vq;f;?HHqh=)cpgd_zx}}1|A=tbC&4(Jc+l+DF!ba2MbSulu!?O zD{7{RjQ0vv>3_1jew~5tpTYnHiP$*)S|_l9Nyvre1ZBt}v=ENx{)$Id=sVvTgG+v; zM=4S0iIr*>@BEv$?mdEj?()YtWjoOBSk3>P9{tEL5n#OTczM0xsj^UKlzqLP1sbb8 z+Gj(@Oz5KOf>3`fkV607U%3wF-5LL*()@X3{gp$0k4bWEV1*HMK0k$Um|rDG+f$Bg zv#rZekJMkLU|I;zCy0QC1vFloM($9<;r^+U!XZ$Agf$>FBnto%Km7j2(L& zq$P9|+O_)MqD6^pV5vg2?y^=oE(vccq@{KkeQ4mpNAnu5t5>kjJrs~Q#($!vZY(l_ zlNA;S24!J9{o#k&mJt_sFX^c_kMquV4hM261}w-(k=mKC@3u)G0F8H7~#dXzwv?oFscx8X(u)m3FCZQil{ICSv#L*yBKwFlJeRFE~yjm!|sVRNd*B^<4*Iw++uZ##t&f`8UD*q&{D>1>{!JEaz z?J6;V42+I`F;|hxJ0BbVr|CZo21K$ABHFd1{bM^mTkR(uZrSb~6-#A(gr zyfKu!&O^q4`vCSll*7>k*g}0mfOZ7@MTPI2r2v{_AtUg23oRQS#xC?6O1O_%pixc{ zNqP&T>$Y&N^Xf>b!^?@gU3A&9tRWs)o-EbA9hT>fr1s@VOmjaa@YpWzQa%5c%&F3F zaiX({?9RMEbZ&Hr-^TXb#l__YJ`A{2`Zd$a<|Q&41RUPWE?N`Y^t!nLUD!gf0dCN9 z5L3qvxCwP9W7?xtV^Tb0##+@@J!_k87C^1+HS*Wgj-Ez#kMOZZ`??lD}j*Dh!ag z6Y9AmjYXjlrQ!F5Bbi5z5&!!#{rBH6AHny2XiE|jc})A>%jySP9`nY`H5i(DZe;9R z8n!ASqrg(Z{JrSw$`E2T9K)qiX;ctSg=GrkqL;U~`DKd>36s>^MS;be?(&T5T&`tl zE%kG~8i+>Tm~CIm0(3B-U{VtH=6*uDMjMIc_g7s>Z=Q^^<}HgiyZd%Z3UUT5RtGLi=yykx z_sXP^NX^qyd_Yw2P}~ere{CiLn!)Q^g(`&(9z6VD+540YG}4pbX{ZPUw&E0U3|Qzh zMO*9^-g{gN4tk|&f7$@O13l!&Ye7)gA>~|TCz=)Tcfb=O6_2Nze9ai1P>D_02PBFC zV%O=+I7C9WFqSxt*u=y_N!BWhQC1{V|J7m>BCN3^-@Zm~CyTW{b}%Ml(v7JP5S;!4 zn{D72R>QYADj^)>c@+{RR}~O}x*Asu&jNseE@cZQKcbA2BK^D_KsNwvt~R(pv+i#g z?%xWnf?FxnS-(I}H|1|$`u}>m{e>w8&ZiIAe~da6=}=Wig}quM$qGSyp)!_NFMKK* z4uug?z<1<#17`O1Md6?`-~P*>)rT4#yNy0!Dp9{$i^4V+?4(^0(ou)6CF zw(zL06zzoLRO)mT!1<+Lv&4Yk^fl;zbhLjVi$(W8KU!6p!ukIF`YE7Mn)SS)IxXLR z_y`uP!YHP3(5aUeBkY59F6c_84A_XvgxZfl_4gh1udG-$XOwy!<=82A1~TDdEgJKR zMrE@;#%g?YKQbx$(yzCz znUl!oo0-I6iOnaP`w{WcT5T1uY_gcDX4si1Z!3N70{^eMom_8c%vLp+F(@R-5-?RJ ztp`l4yey7oxZ|!d7{#%FKIu@fFgJeFT_RcZ50r6(=5;-+$CKwj`ycGR)=jY2ZCi5-e55gpJ9xVS%0Wvn71$AO&|B=)SdPD@dscj3wNrjM z73x=(Lt+`dZr^{@m+fs;`<)?!A2Xz)qGI~Z63O^`b*2lD=syuVrsc~eivx+PFwf6J zf(MkC`x-`R>cYjeH{3BK5Lg>X^ODe1b(iBC_tfATPB-h=XdTFW(r2ha$*|&0I_HkW zQ_i)M6vw{I!fj*mkT6njQE!j4XCXk2HGtu( z0w{u^mdEXRNuyqx@*TrF-jRg&%-P6I51Ox!DT%BnKE<#mu>;xI!>06XG(K%0{ileZ zP(p^u0jnWEmd2ePxv)_I__P++C7KOMT9sx(!1diGa*IWC8*G|C>tA#0CgnL+@&KR+ z#mW|JhB*NiN%Hv*rS(@#O=NudyyNVAllA+pzT8pnX^Uaz9fvFM*tZ~P&1+zU`)+T} z1i)78`(DeZnppfm*x#RXd%A`9Eu9+jWg2FR%4>N4)<2!a1&KErR6+%{SF7xGAD(+5 zaiqWQ&1GqG3{s5M7-nj~g2yI-f@mZG#f^+V!3WsZpy=wMrth1H1TZ@Jch(U;yz3qh z|EHe+-5>Z>b5ICp7_Qv&m|y7~SqVU9sdD=fEyTqCDe5V4?Vs)rIM#pKJ5K4hiA`6+ z#Jnk4C!J=^elY9~%aUhbNsMsI^Y9;sB=ML(Gk-}fcag$ax1JSR#eccY<}^NY_D-xS zp77Nf9+RH1BI7A`#x#OMBmt_&(YKoQykwh0WifyEt&u_zATEv8o6wCnBNxSiLoj$x z+Q2Jc4&P92VEOGl9N3owxSZ3ocw?XuK1w5)8Uo%|xP~JiV2qq8zTERJ3DSraRhi5X zf(uYbrP;RJV_(0C@R z(Tme5TU>G&+!h(}@lsu+tw&>uKm%Q?)`3c`L@Ve$E9olKFver$t-8*8A3z!?05=f4 zazHHoa*`&+T^K}Ievjh}Fw72XJYRj#N;urYerLcRL*<^i$@)MhkCe60NJ##pz_VG; zsEf0`veUL}J`kz0rKDB@xAJMMnyJ~BXNWK4$cA2iP${$Fzr6VDeTlv~QBKKV>L6!U zpqL2@d_-R9-xCbk-nQb|EXWR!6y}k$b={qiO7}hB2KTo&;2TmCGiVDntN#Hb&UPJ& znlC$L3(mQ~xHMmR(m_ZVea-`}j6Izt(}W$z;KTN>`P!w(v6R(+Q1pB2ythHLh6r-|GfjtsPN zkcG(1G5^fmaxdeiNG!>CmTuunKQr326Y4ame2M|8JIa6x)aDW5Uv&h0kD;YjiF~## z{p`~1D?ElQumb!UgIcy2sPCRGi4_Al|5)1sF(SOQHM~I097sDFc&OD6hHJ3J@Q(>v z^cq|o|ExIPAs%XHVcjV=nYlO#R}4DGkK&;6s57>cityVh@2tB8D8U}AbH8~=qO`Hj z6Sply?{3yD5~oL{>z-qWZAs$3j750St>}Dv4VuXtvZwS*sDKi|4rIN)hO@4RQocrg z?=%Mn{}&+JzEf3E;r9hf*o@SpPT94NYdr7ikDrDLxz0J)To>Qz=LJO=)gz=9&GY?* zHf!Z}pdTU*^Z@cHXr3H(H7147)!SzHVpMxsp+sAemLHK|T z>dj@}BK#g3Ajvmr-GWuJOkj?~MKj~R59C~j6;I9Jgt^mv=U0$KZ>OhqOgTpr09Q9~ z33iW^>^+oOFLa)QxS#XU?SO(#d+ZoBDC@TId=856c|YFWX?t%hM%@Q=xI^~SE&xz~ zcmIaeOOF^JNd9NjD7ua2)KG$*g?~h6fXgQ^iT^WdKuA(K*~oTFkTjHk0f7w?fi_ka zv=Ws6sh=^?0niN*$#d$I0FWru?N=-GAWUOcup#R|%-?_R;o&GeR)}iUO)MIv$5DxV zA5W6ka{bY~Z7#&9NCE)e0Kvn*?NFIBZuR!0C+@|GPwXj9c88Ol$7Kgoq_|ivVP5S( z-C`~C1^4|bXan783gKQSFzU&6xgTpBji@M;56v{_q)*0zY1Oc66vv0nw6||N_)(8} zVgMsL;}$&h!q8bpu1~FqZ`AU{z32a~^ zbYk8Tg8NwfE7F0+Fj#u115mk8Dwf)UzIl#29@Kndqw@B~(lRpHKrm8j;co7c5kVPH z#=;rfqdTqN?;`ab$WQl?4#AMPrFREE9nM%Zx>09@f!M^%CZ;30@f%3Ucv_4VCyom1 z9|5zPq9aU}PvPiGMwKOH={)&IZbZ+s?R9h(fQM)ee|`qWbD#6vq-3)Tl~Nt}1>`H6z($v263-CK={c@M@J@A9n1%L}##Vt(|;L~F3DKo6}%l+<}$g?F}pqHt~ zWruG51{^C-T7Lc+8|>ces0s%G*xfcL{eJj^%KK*wqtCs&+Pw$9CEu+-^H+Vjh7maP z`8LyLrfzt9^5dv|u>hIi(iMELhSGXJ5ZI9|YdF=KC`ttbe*vyX>h3!*Ed*y`NHFkz zOlcj*=O|vlr)5Sk81~eTVF%EUbV-hGz}EW8zPhVGf$Ee z#;XPbw^k?33j|19BvuMZp+yHH)t^K~Xy1icQSq6;HO8+Mh z4QVo1=O}uSTY|UpU6obEZg>t6lehPee`Hu)tR%1BlSG+}xCf=Ozzh9Tf8ijn)S(x% zqb?A%`oX|m0n)-}{PCnLNwg1;5?sMdEA+cQHOz*99(sU4zGp{LqFWQ6QHgpmyC^18 zptki)GMvXOila`DFOpBZ5bvF){qZCn4?;~&tnPTf(CA68*BGwFAF9I6;&~cni=C067suoMS@W?fmQDJ zgBTZdVjfB3FZ*n$7^c@3XtI@N1@~&YqDcG0PaZiabv@ZJk;9Nv%1@(8P02l*+`^v-a7EQ0 z_-f=KmLn}Ue_?Ej=q>26lMS6I76OSTU)!cO$Yp!NpeCJ$_sMg+K9NDvHL_I=985LR z9s6eO2~t^)&$_gSo;w14QW}eh=1lBQlJs-;Ym0we#Cq2DzFus#LJ8<+oSJRZCn^v!k&BmL~Y8ohe6$o8Z zZXaQcQ_=KG;ABh-1id}qVGA?(#z!~&_L$w{*bJ(=Q*40-TyDQW&TueEJk!R9ZRWn0 zCwDn^Pm~+IWxWONR69R3TwfdJdb-W{ouSaMp|f zX$WY91HkV6<)I(*k2Z`sm6^JeC$saHi+avX4C{?Vs!}kB@^4VTYt*wr!S7_6!r7)aOSg#qs9d{PcX` zFa8><$K4e#$GuCEI7aK*&S4kh2@aq8-soM|)ZHx9PWJDY`CiNLmzlLje7sf{3FRQ; z=k)I)Y`i($+FLDOm1^vKH*OpKQ0N{q+Nb^n0$IfRmt@bMRN(LKNw5!$vn)DZy4Rtk zB_l)JZa&#GJD*<6HQo9h>JjXwz-*wyQ?kMDBc7juP6Lo9flZ2gA(SEbXJ-DP4e8B7 z_ty%ij&J7h!g9s4<85f>XMKDZ%c zCsIMD3Js=~5C4$RI=(z8{NK@R-2PYSD~{{WDO%vk+X0Sh@B62 zYvvN$lYre6t+1@!rvNR4DmU?jXaJ9XWj&MbZRfzY|rK}W+x*5y6D_f^}chi4j(2&QZL<#H{FaSc%R5EN%IXkLeyj4^DKB%%i$ zfZcmW$uQ2!9J%81@V-R0WD+mC4-{-q8tBZ7X9f?CS=E$54#%b+!|3U7P{n7(zAXcaPO-g88$2vFCJ@T^TCB#9>rmoH_~S zBMSE`!06jHIUL=QMXG!-P4T)HpRF9hajib8c?qdLN(?7Xndf=aSN(x)ZpQ)U0{V}bHrfG$ckQPUh=G)6XU&V3EofBGRT`GRG z{?BAtqoulCBy{yfPs+GlguBtl;2~AuW~o-OyKUpXM>x>ubBZ3k_PiLMPo(7wp`^U= zmqj0fItwL{{VHQn2UjOh<=}D7H^Lo`YMQbpeyzLVnd&-$UGn21Af7)*(`x`JZkxqp zIYz?i&3B6cEDydndt7b^4hU|3=S(=fCqEWeF!YS=W`TBI~NG*(|Z7W^7`4Xwu@9G}W#1zhR-Zals?kbX2EWdy+-7#eIuYXS~cN=6= zCW0kcGFRi-H{Fe|ARM=Tibn#mim@N@)tP?P#XnvN=2$j0F-TeeQ^m~V!{(kpsCs^% zTALqK#wQwoa)Dn@^8c0#?1kq88VjAehTj%=o%^*48zd#2>S>2tQciiGAIn#A7( zAhC-N8c9L%O;@b3^4z)ECBkcu%1svA!$$HINYz}?wXH&0sqQU1`B7|wiZ35y^fUm4 zQE?eUjHH057|site5$GoVH{_hbZ-r5?ulNb0t)|DyKbQcJa%ZGx{kIOSRu0<7`~V5 zgcM}usw|w5U}AHGFCCW3>zW5PtFHt+*I>xRVj2!4Oklzgj#ZljL$Q{KSGN=UAh3pl zO8q#F@E9!VX&&K*f_Lw-tzL2Y!|dLJBSR3p3r_{1G51Hi_I-Y$s-Uo$IJ+^KI&&>O zxw}#N z6W>bKiY91l7+!nuJfV5NMyO-EH2T9g-TUmDo3;A0XX`1$Gz%V8RelNYWc6NHrF1l1 zQ*Vh(;C-$fc0c`Kf2~bf%tB&0jn@)QjIgs2@Lc2N1Wu=K#_Sk6vyz+z*Q>ys8ayn?ctGG=d}uPAuS!qp zygko}m1pf|PPQ$bW%q(H=GnwWL%6-)w*Lvpxeo<%cgz;*FW-)7+qx^+F}0-xG8=WG z`bT#nxP5GK4ss`2DIU9I=1XselZb;MktVbIVDQ@GTzJyhc#^+Uco`XnkngBcB_@Cv zg|iH~Apu>z?BRH!23*$G1yL{tDdXDKlbQ%-rn7Yz47U~-qdfxR=Pp-mlxTrL8*W(w zZ#uHwd?xkb+%Bb4Z`s~Pm|{;`zQ+dJxJDP3peMt1hR20*w%I;syg7(AH@rJ)AH&y~ z=CMh;0UR$0_8ix~##>i!SiryPHp-6V#Ey`AEZgF>b0+K9au@$Td6afqcY7F4B!r|Vdwj%sC}vY^{d`Mdbu-UuS;~Fic&xcUT_tDLy#NsHL75<+9!R?; z&87`0FSIbjXKBHOS;$e#&b(*aHPNmMNNP$`78Lq6B<(JAmqTH$Mx3Uguy58_^P%D` z1peFgNfd&%EbK!;=vUQCLGPQ$I+tU`<0{mPG;0|YBRGTMz!^hbY)cK)U*GeuzlsTG zXh(HAEEPPfXrbPirBCyuTI(;3Zn;+Pjhg#jv$&QP&m!dqAD%8au&De_EH{G`Z|f+F zD&i|yvH$9wSEg{s3|HCWk>M}&o1?dXER7gNt~S`rXmNO1mWp4^y;qv%%quQb$t$RV zck>Dj$xl;-t5fkvhQqXJR>X9kHV7d;en&Z+@2g@Q#W8k4h>-1Oa>Hc5b-NrYiP14=@C- zm`?}4T?4gCW+MWGuJl3!-dP&-C71i_Rxz{~~?_3(i6cyM!a4HU|; z;o->sp?8AUFyornhXK2@H5=hj5}z#N+-L2~09V}-+7{5m&+I|5 z-WWmZT#8Scat$HzFsq{|I=K)36mwhCR`}f`<~;K6p1>0cjp=@SD-BU+_w7i{%*zsM zq(vYU$-UXLnHh2762yV{sB%s`IK=N!nwxN*e5wU%fB`%P%(pNL*)24u8UOpp&XT7? z#z%#H44n}i(beMufk^x80rn9*!Y@L~dEEB(YZwkX?;H81$Z(FG*1%AFlOXYVXmGWp z|SmlRY5Qh)BxSK(wOU&tQ)6HAW zb{zb%Pvak&825$YC~ZPf7HAP?m6F&$Qe^t6P`TM>gS0L%bTO0y?S>(X1`@WB#(Q`Q>L|lW`g+4bJ$TV27tfkv`60EY-Hw&tM1c@}MKQ}iQ zmgNwb+pTp(86vLCKV51Edn`({YQ~2QI-e+oP3TZ*r`Eu zAMnJ3AK^_mp~l|7&qvvx!p-)9V@w8I_8!YALQ`HG;TsGz0Q$wE2s6-(#aM# zhjL%J%Ll064}G@S5@Y$EkZI#KUTE8JhdX5(G!k_Bk$Jpt|+xH4z!-I^eyv#NnJAlo^Y~arwT8Pny zRVwipt)j-!nc5WieEzI7V-*6iIMhz+(>NDURXnmkv-@&u4#;#Jl4NG~v|qE72QXfpxDPsjs)Vk1 z^2^o*4gc7EgKr0P#e;X+T<$lv%}*SQeNB3RP&6iq8UTM^tJ-X^HOIf)0~pkOJ>RK* zIj9BqF^b&)7B#)>(_;8L^VDpFV@eeIVtagwsY;s?gpZF~Rja-)cJhxs#6wb`#k`w? zQ`Q_!BAnD`;f4hB+US`Mv5_LAMU@ezGX&G>zNH~Y_?2}Jwx+;p<{e|Tt)WA~=Ffc@5VxC}=m)Q2;W`&2=vvP|Hol!k2n{70fFKu;4iReiXk6wO!f@BK zg4xewD%uE513UAMN7Si#yA$?CY<()&?dXCNb^}6)?)l{6el6QuWlg)pM|)SAV#3VD zjI^`|=xtx%M7cI#138XVpBRj&HbR)6b!aav%~~x!GPr~O(xzT&uDVI5Au_H&BG$=> zDy`y!C#G++#@L*zn~}i9!`O0eAXT#UWL6{c)Y=b=4IVYIGxbE{<&Wy?CZ<~v5A&u^ zX^*Vr4;WB=LeL(p5)0Nn%}>b^zg6(;vM@xXXij7^k$!+%Gu4`@8P(Nh2@mV<~d^9&a#4xxh;jQo0 zwU_zGL&m<3QslDDZY|!d+I|TSL#qQ|`HTe%5V7QeNc}gWdiQ+!)tk@a9lc#7jl1-D}gt)k0ZG-RP;fpNN{p~=HseO<^iZpmeUk!ln zqbc9ukB(HyCFR%UWBo!TgH{AL4E1U=d2`y;hwvf?^}Wa3PVEh68+`2S`PDy;R(!6h zFh>a`RV`UNhH#Q?XCyCl26WK()Sd`^+mq1|`o?yqqNqZD-RBW4=uM8vem0JeVD$(o z`VRDKgcJ7UoNM#@n7Yy^*Scpl17!qSpd60Ns}r{3r!2p|=U;!lN8leEDau%17(~RC z;XcdZxtONx{v%$wkfxvau?av|iVxuf@Df_->F!>C&`8H;SU^JvK8I-VX}=Fn**ZoW z`XDY-;qA1v-V$sPZGr!NKmGu4DhJ%|vtW7o>KJ^p_h{#^eu>40O1~flFJ1~^9;?2( zEQ+C@6}J7tf3@GX0=(Bw>!&jY%JO}QkMxY*tQ~hDTUsp(yBBMIGK(>752>rRQTZIm z!OS-;f=2#wmMDtrrU`^PUhbqYpIs{9gEed*(zE;tOjF(;c)jGRQKyP{z$ITD*cGAy zsF6+6Zf!kr*5)`wqvSJtA9H49ei{m$$y-pqamF8qJQhzCD}sW}0&On8t{$LTC`_QG9?1 zX(scKepFO`V8;(e-N~ofldWG6O4pK*Y33RyNgc7jM>Te7&%K0&_XGnWsZiK{jQyN9 zj35!WgiI8E74=Ved%4#npzGvVTpRuxFf?g>FJiZJVG+rRQ0nlFztXqjK%p|$S+g5Y zEM^a0D*X>+!h{1>tFln6R}En7$@#fb8*&Ng1%|d)yz;po(wi^%5OQQbXheQl7(|Al zvd+>=0Se{%PZ6(M_!0H;tRSpjr+j1W$rSHw=M$-E1n)TkXGKJS?c(4!`?xLe z(+6=C^YhPpSlca+WM_jSP!!lOU$R@k8^lcAkSSsEWnUFtBgEvUp6TyLnTE=ePa2`s zt>NKP3dUjHo9{r@v$%rE8YEK?eAh(I6Fkx4F|(f^(u{H@2^g)rc4d{p&D#$=o==x=R~1bi9mqV39Ic>*l`UC>Q^ zz>Kk&^o9MDthnXf0b+ZQB){an$XeWhcus58K!OJuu>#3ftK`0VJ(r)v?MhOB#UW4d z;-c^a3<|x_y;i=x78J7fj(zEP#`%jNObiNQH#cZg#&D^|-yNZi-v&CSe3M7?a$*gz zH%>bRcD?tVmN53S;9x%D27KSbKf3dM54m9`8*@W&1fM#iKN=CfPW+P*N~m#wCHz_5 zV73I}(~n?d#(s;@KVwb)l9(@HOrnZ9Rz@=@V%YqFx}xJmPY})s{pB~@5k3^5$VT{Z ze<&;{N){ZLem>)D;QqJ5sl|dEUDMYP5xk#3g7@yPcEXi;08 zULC!Z%yMxnwr4m!o%8iIs!v8kZkO*wktx3IDiUnDb-Bzq-U#A&o#Jyr(CPPt#yW0o zzw_+vV|9-u!fS*w`X}+UaR~`hZQ}M!cY#Apl#bg%P-2#6SJTDj<9>E-^l>|y$be3wtX3tQ5o>CubSNthB*DUO#*leYLR=344156I|KJ8%WUln)RLK>{U8Z ze>%b?&5|STn--1nR9wRQ{^=*ZZ;0kjG#o#0-O8ych)E{*X@?0g1XAEX_bPXVh<{+d zkV9wA3d-ac&O3dS-*ZafEW?!+%fI1u*we*Bx);m9yD^*}74b{~&n4J%qa$HCCwBOi zjJ{5UgVnw#_J^(^>!~VB)A~n0#B4r2dT|)>QR6OJ=aO3SEfDF6rGr=!o#Y)b84aYD z%BOu0_ar@Qa%czvr&7~r(2|@+u;6alV@^Rc*ciokcMQ-_w|A~xqxesYfqmkD_})`2 zOXhYP%!XW)PwDm7obbuJ>j5x)sOv9Fm&%PgrPF=9XYPFmoE4@xhMH-*op)ymVdofz z^`AnRB*ap?OpjUNgrMxm$Dn3RcD+u%s{G1fIo=JJJl3M{UlN$k@MDLcws(TcrtaV# zLK%shc)$S687d@TK?=EF2y+xb7kt|*p@>*1_;)HTFfsFD@FYW4%}44r)}M155+NPu_1(dv7zczm!a?D>OZABg3lXocDEovj5A@;S!ri1sV~$vEE0K)!y`xqW+NU|V)bW%4#J_vq8{3TFV9|3qI8Gj zopyPM8>7D@wxJTd8$kZek?toezF)ntild#cf%lh>Y@l1Hc zcpw8M$Nb~!>@|LB*rCAtwb`_a`K68f{sm)#Sz57$g|9cJIT#BD%V6#z$vC53oQI5c zJ7SdPX5^6tCek8B3zotMtlsDx>GSZ&|_r=~?E_r?W-2#wlLGGCJGUR%w#sL(*S_OhG!w{_oebQPdhNFi zxW9NTBZjI+Jd-Ld5kwf15L-f0o2K6OtgLaJ7}xHJMSZG@_b9Kl*H^PeAUjNx?^KYC zY)Ma2=EdRVG?Kx-#^+#dRP82{z{ue&c!@RQ$MON)VtGq^q)9TH1P*p->JYFWRy243 z<@ULK2QI;I;dq{#&Wy^-!3cZn8-p4PjWoOKOa?%J>nUG|a3A;(ji^GjEbCrsJYOzyNFd7vhpBI`9`6xK7D=ksGBge_0a zK&}{XS3Giqt@9)yzxDC+YdYeS(>Tsl5B~5KTT7!Fqz(_#`i~}Em&>V$u~62CwdN*O zTNJ$=-^CQR$#b+A@0~)YKK`@mN@uBrd=ILD$^*_q(~JmnU+pVx;b|beY7()ioHJL zgVX-BYn9H^rSFa}ztAOkR(ceNWjYTROpqDf^vF`nIjyn8g^kepe0le*VepgM(Y0Dj zS@xo&1b@#9*#sREwWsg#u_Zci^?K-JPj`7O=J&R1=6ujs@8e26shM#}&JMVr4+i^c zrLp0kh;Wz9-5FKx6$=N^t>KTD;NtMmZQH35tyMAU+2lG-+jrsSOlRb{vmCp<=-^@248CMMk3A5T<+wXzMUlM zG=>Ks_6a2LFw5`geh#xhdpPWY`WpY}$NEr74BL;!_`X1~^AZ-s5~U{ghLYjEtX27s ztF_(24$?1SzH2bSk2PgpyLy zNH@|Q(%lV;bcZ0_jnXBElyrB!wZXdgo_Fti-#*_t|1sF>Uu&+p=9+ViG2;~_hYy}? ze6%jF*_Qi0*}K~n=?7AvIZ19z47&H(dnT1VrpFXhW)L_G21Lh=3WXd4^?T#*8dB>` zhZaU_B2VLn3w`P~L7xZh4W6Cqtpj1g5l__V1~g1k$ppw?B{LtJR?B%hf_e4r*Rgpglz!vcq z{X%9(%@Q|`aw$JP!uu!yAfKY>=n#x(6%uN@+bGYnXo12I&5YA-kl$ja?Vic`2c+q6 za+`*P)@?B-yT*nw&&TnA`)+^giHI3}i&4Bx>9D-j4waApt`5qU(%=(;k+C9hvp_9~ zF}`W$)2=dQ;)aM;lP{#U<#=)T7_p9|RbOO8f&RaOOMBHo|4KH_o zWQ5RAHz#~eaal14fXpUddNK;hiXJ-gd;62uRCY{e7^*TGHjtC}r6<2B=;++V7&u%V zl@>r0C~!2roXbB%BsF*I<<&F-WB6!iB)Ax6d^4Gd1#{vCGnwIMV<86>yB+a^t%xZX z$69;88imuoG12NIF4yF5=$DmQ#RsctgUj@R%}Qcdj^*3Tjgy2vyLd|$~e zlv44T(MJFNofvcvdNc9y!t-N4=pN+1gJLj6E$DhQr#Io-9uHE^Jhl^I6Z6HHpbVVJ z%(66bqws!8jxW4x!^c-!t1!z&E{K~f{1eW=Y!ZORqqSy6#}6B)ioP2z|mhUE~nCCSFs`WoH7s zJB`GYt9fCI6AUKp>-v2T-9mg0{my~AZJ+QK^NK_srCRo|w#VvpSVcP!HVTj=!=mDw zC#eF>GWzKmIk>Pd0WxVTFCvb=^PB+5yX_n|i;B5mK8KX`zNfTFcnO7H)qNGI>|oGP zKyzRrsTd};p3;O%rE2GQYPAmKf~O4$!H$J3rFW8vB0T+r)XX@h-SDcw4-kEn2O}-& zjkZtRAMoQEJ(+z6i+_123D)8C;|DgpgwM1m9FsO>d8f>6>hW^*%hA+asgP;k8u_foudMJoiE&t#RA} z9R$}T-Y0=>g?uBp2wJ%!X#|+M%t{{{bUgTn-ZIXrGTC^x6TiYuLL{@JuqGStdb*{A zdoK^vMU?2OotNLoSn8$wRAdU>AF|(FTu2-N3YPb{E5`K_Of02R^2xv1AecEQQn}~@ zK}S=8{X!GN2d(RkVgHf`JyC7MXhnQ(?ao&Cba`v>5;dFh8id;G?P z`Ez@pZA&+CW!tk{8CdED9irYqD4TAZ1IzT)?Y$dsOm@A^4xF1&OJ{dpS@hWNSMa}VUt)UiepgtykTI)bHKH82t&LPeB zHuQyJnh_UkV_vf-(Vi$q&zy~|?Wl^DJSw07tMcX~*Ka1&bS~9a0LI$gTES_bC*lZr zgHa6_R+^T4m;!q;A-J}3d9gUOJm`WUw=>9$YGjtPZm@o^eiGp5MQ$95$bg>{`@&c# ztD_+>=9xO*z%XR37_dJ-1N{DI0DhNuB?tcf_=DLxPov3P*9Yr+o-}UlMF3FArB9Yc z-lm|HWi97K$PiMrF6w00zw5YAY=gueqxgPGOTu&8s~8_M3Ztf#dQ{fi*)(#@&1%^J81fb&IemTYw~==LJ0_j;>LcXBJ)ID8dvVF_1?yRodZ?0Hq{ zGe>6OaaK82IOsB%vi6_UE;roEFhNRh{4{%Kzd8bIuZ6^{X7*hIBG3bzUCf=2Bxd&2>``?ehztYYzBQvU)DhRV$hxOi<+5J9hk|apLvBXv*-7Trxv%NU=5A+)&!BF+IF%#l|06@ z^C&jcP8M`_03gaO3>fKKoOqxz$tYU66`uYbVEVKicG2S@_v(T|g5h z9+eaT%B$lXLHdE#akITEKOT~F?Mogps+3{j-x_-;KiyP{dZHW@K4+gbdYA9wJK~&U z#W^=jKPP|xIqc#)rEK!ySpLR2v7MuX4>FpPXT6KcRU!l! z;j_)Yry29LW&$G=RAsK)>5pJGk*eVEN1j|>oNGTHbj%wE6)vY~p))UBi6`nsil|@U zFkku=x7wjRO-|TCIL-*>@5;NN5`qlG0Prj=kHJL$7Q)tWB>nUmtTYn?+f$NJaA$t| zM#>wKE>=Fh^o)-oFAUIkC8a-=lJ4-V6*a#|2RXvkbe}%=b!n;jCEdgITNbQlpw6A$ z+1Zn@FaJX;IO9!)LZOt<+15kx8Yc`p^){{183YpJAHC<}JFPaxCqz+$Tc106$l3zi z;}2Gf#kM_)h-FDajA%3)$U$>-0(d@Nt6ilzJtR!D7&Y6M!W$d(J(%xTmK*zoVugn6 z_>6d6y_oCY+UHsLh7hF?eki|7YWK~3CHse3e!-+0D8Gq=v^f0SkWU!ZP3MP|J^jEL zSt*`YlMIZ$v{7`3b`NK@x8OZZ_4ZrmA>BwoU^_Q86f~Z2Vij5-X1T>u2NDpGW$i^@ zCF&(K)*S5H7hP2^$({GY>@oZuE}GsT+o?Vz!T$CLtDgeEMFQf?wrl+K6-c1G4`ONM z)Adh9Qf2LMIJhx(8|X^^JKfrMs_=$zRE zSi0tJtfcA5_>o$x4tm&U9hpCi;X)iKKh9~pq4>Ih7)idU-UUP z>B*dpzB*o0xsmV&`9q>;E~sFy0(5AQ{`bdSnG=C?dFZpfwUg0ObL+8vp}mcmihkvJ zLeZts%gfzQ{G)8v7Jg(#D0W{@1X{C-b2Hj>!+IlJLLeO~=wh`s!$^J4VMR!#kPP1~ z8doo8s`K~U+!EJ##RP69e$&R5aa7;{@)GBYp}<6{nvY=$UMg-=kVC!i5CRe00Z2Jj zm|bg=vi6}TUt$I<9)Lhw>=y2{m+5Y=er`HNr4;9!7cp<2|3dd|h_J03)_hiR_3rFr zavnmXi_l(e^csZJ#R?<{S#S2n)_}$XpsPYDi{=I;0$2B_{n*9=OaJKzEehLAp~*|-@c#Hw<=z}!ye)nQsYe^Og70GtsM;=Vx9D)rbnc7b2)JETtOAFZr^WFCSlvBCRza{ZQvO`x3 zvaCzy$H%vABDec=B#yUz$#3(|j2$uDFa7ZBbhf-X*^>Zr=`8O3dYZ@X-7X^Er4|iS zF5R1pi^F z0wc!d&Q$t89_H_;Gh-;5xwsgrd>EZc;FFBEd}g6O`&X7ItBw_GFCkW-{UWRGg2Jd| z5&Yg;2eh#&{?{ZnaYQ@XOL{kC7aj>LwzIafHvGp&Mol~QB`C(Led+ zNs>;r)-Q8QU`Poo z?~)Kt)Ob`VC}{`Hd7zbh?jZ9bHe0~SishwFQ0LhL#;WW`eZ#^!gK3l3c}Z#B5TD4? z$1`h5R#kB;8Dxh1bH?5EWo1Lh{jL{tsRbqzWlvSaN}juLYD&gokF+op!b6Nk?wizg z?w2*i6EbNJC6TtfDD)!>@&;QiCB0dc^N~#HzUA}bqR4#KBe7d11Y-JvL+o<6tY{H* zk@thNzE3drB5Qdl(0;_q4T_%zVi+LBP+Or*pK~Wq1U*1RDP!6IX9C)-Mc?=hR(-0K zi>EGLMKcE9ylNY$HYUjkz3pX-!ms!FdeJWr{;(lV*T;ou6}D*2M}(%xQc>QJm8g5# zL~#@P-jJ;OU4h^Oz_HJiL@P7n`MnCp(36guBxg)b=*evXNXvOk;wBp%u!k~!C}6E^B( zSV%{cNd~TGN89SeYfhkztXNhAy^DPCoM52iEHS>#JJc2YRvu6Qw8}A)?ZfutRtwUAgv%4W7&rH0E+Jsao&FMk$ey2CGkIeUIBt`IvlJ?-Yixq;{ zqd{%7DceaCDS(@_D)8(bH4Srhx-ZXLs^4$RYqJs=Is>RE{Lvp3sVk2GbLp_}6uu41 z_AcVkD*<9&y3rBJuebWoSFq_QdAy94za!k1-Lwb5yX~Fr-G}-b7tM)yk%;~9h0H^= zf=l_yGG8PwbZwe}c!SX}++L6^%WorXa-E$^CMVIlJGMLX{Zl=?GvZ5tJm25J$zxJ7ijHIwJ~!51 zP}FwdKWDu;EugKMfH0{){4hoc4%w)ndWC_@Fz>S2G0);u=#?fqZ$2lA(G-sm=XYy% zfb9Pu0(;0e1|Uk>RB#F6OQ5XOnSJ@$SG!$VGidS>>&3|__iNXw-TqI`#HXlf@-j}B zJX0#Fjk0-?%4TNL@Tk&&6#Y7c6f4Q;VElur2?sk8IRXZ0>iuWNx{1poWg;@2msRrv$d`Ht%2Oc0HY;<}Tm4Z>p zO2pGC6nzK2-l(^DW4lYrNz}cKgH2C{HU&lO8|E-;PTqMDy7mZE@y{ScHCp+Nsycte zzD6S)vu#$(YU__tc>_?>X->X9C9c5GQ2pxNneEO!Qg%|<>(BFGP{3q%Wa`?9C1_{9 zN+SsG2mdsG>72^h;i0TNRQo){(8t1KYa5-M?K8Wbb=xEM@1CNL;9l%FB2|T`l~$H<4%X)_PRXPFW0Ys5pEex^>FT9Evcd{KsXNs%fZ z9I;%AKQdO5fi+?`ji`0DO|$uIVREihT}37(uZbAM2|?siO4=%G+={9ekJ?VsUQJ=Y z+qTgM+-jn^iHfmx&~kZgZ+WntXCYFyhcn{w?V5!t@-s8TN_*W22LM}M8U9#A)A-46 z$Km4Gf@fF!AQoagRupIuRMdvZm{>%UTtvt}!VeteHp;Sk!2@hNpQfXdOOF}}{?jS$ zHq^XM`+Fu>rKx?6)tZ(t`!pvUhr=&*{N`BU_T}eV=bsBwVU5UB-A+V zKRp!Cl)NueP{ShB!mQVBN4&k1&|NpAlvg8$pn^9HwhZ3 zc;INUlIO!m+C<1{9b$LnMc-@-+|X`q!<--km#V&%;oM#&_&auwCoQ`f2Q$4DNl92n z!gn9>x^4x`&bEH34V@ya5?m5Io{umsQMz;nEJ6AOno-ykN{wp3nn-%Fzo`A-er-Ov z=#yBhrV?qzTOq^wHsPu#?AJF1%WSJ^?#Yd*u_{eDO?XJZ^Y{pl1qD!(oa@)#H`~xi zDedP$;07NjyZyhk4l zARBQ4C!h~t?rfJ8(+;a;tIw0S^B14%Y6cm+n;dw6Y_t`9Y?mbfEK*s~!AuO3cn)jk zzB(xZZ(1$rvLrj1)=K?_kW))1Z+XQedZ%0QKG#!|OGF}Kl@Lh9r4_!pup2J(y8(IxP4t#0 z+t1gyC8C*nJ9irau?n~C5~_Grys5UWRugG2)Nds&F3#3g={yK%d9C=;h_+h;n*Fq9 zLMK0{L|Jd1lUtjNmw~l@^#GZU@pT_Cskd3WUN|Ek<=G_}?!AgBzFlG3IVmj^WX~!h zs4N(`8Ue23{hkQumLyoGsGDrDqgYeZ1=dXtOCD)8Lf53;NZJ5-bAM};>^XHPP`EbYOe#Avn)09jUI$(LT*hD}U`%L%_ zBe_lYU2qBcvD;sNbZ6nDbj}sr`^2sz~}dInO|p(JlH6Ym!(jVIb zK|sy3Q*X#t$vmc!{C(e50okwSq*`4<7jAFJV7sY(i-hRVYfdzR-OSt2pO9b@c2kK3 znm4`0@a&qa+A~78Ns^E=qIjO)>9tV1&g4xn#DD6IV%TT8!D0GBsQt;9pr%tW?(ZA2 z`w9`PNdKz?($jQ@6OY8sIOu-Cy527jA`@t&ZOw`4+yfi}`&pZRhg^Ry4l+I3H-sG2 zk5i)U1B?V!r>1%4{Ba=Fnyv&^uBE2?Z=A%+v+$yxKUE_MSTtD>de@=c{5L#WhV_+>^$1z2~`O1n}TGs`>HocLVYNVGi?Hp zY6weEeUSH-k`)kN&RiPP(o2=`U7uBoeU%d66FrGJp`4ib+V(s zE1RcN~Nj(O~jCrAj`U~kO zb5?AheOYS=w9f0-D<<`HqEp)Am2N6)up${@aDTf|xUBa$7xBw8tlc2aiH^9Esl8bhOmDMiW=gLI^rB#}@yavF&=TR{w@#A)wn}$69>|AhHN3b{ZNOm@vp9xiRue zxSJ2=ZQj@8zteg|g+2DoPVoL` zpB5};4L^q?9uU336fQe;`Eaw{%yKyaM!RDuEx4a;H~|IyQCN3YY1Iwq&Uu6b1{Yz7 zbk!o}whzg7XZQYbF9)nDIRyo33Q1a-&T_K1zS}lHyr!*I{;oo&+%6cU#BwRPH%>O5 zHz4%vW3|CWp)*@o?0g&vpKCe|N>b?_rqTrT>RN6f{X+cV}ovYik<@N1Z*Z!t`u{P{Ca|Y!-_feae^dYH*JfZAQ<`I6 z@*j|Knfhp<-e(tJ#|u(0TYHXA;tuvl(?-p=+FnPRJ)HH1m_9uwUR`X;%(1}ng4_x; zU0Nk+04c_Acx@~&WIUGd%0>2GG&Ga~#SHpw_F-tqMI<^~j9_*uRWJs`$dW3g=v>ns z48#dakd3;!x^VoFsq(f%>W$SQfFmAnx3ATFt0~xe6tivYA*Mj2)#(@JEu}e3)Q5I? zMCW7L7w;e&#R%(-lT*07Vn#>c4B_4?h~&qhRCNGUbest{%<(|){GztLJ5>&-MPx?C zmjs?g2+ssB#+D=>Oop7yk|EEEu$2M^(kFzYw}?u`MS#wb*|Ps(e?}!#Xu1Y-Q^93U zm&6r_VcIr~r3m>~0g)`2Za1a&ciVS+h7Pw*Sb+X#B%6#>Xc59_E;=2JVh9A36-qnN zUiFYy)K-}`c9Y9oypK^|X^;^d<@di!*5ZOxSHPCCji|m%;eaBmcrTCj_?XSRgXOC# z@^h3L>!bAeofLrHl373)E(S7N7&Wgcj=En~S?WF@+Tz#+`eU(n2htU%FkP+t%P5gk za-GvAJ?D^vJkK4V1(4!pd2ZvYA3tvnzz@2Co6;m@t{}x1Yka=$`#O!c#`GI+MPoF1 zTZX#Kr<`5Vmcm$OT!b*ro{D9V{6ra+E@&r?3G9VUQ7BYjPXy#@gI$j&2IB*|rs-p^ z-bo%hDdBT&HF&UUPAqqme`@x{l+GGVxjfUKLv9;!{*wL(qs^hhQkrj_BZ7TH2#`YP zcRiNAh-riPoBgg(ze-4F>jI`U=W>^%o$26F)+!*3#Bde}37j+_Ox6Ja03Qf3d*eq^ zFb@M988b3ZX|IE;lIg66F^e; z`}WP#78 z#&2YN0nt$%s7>l&>Q3dj*PnqjLps7K^1A(D?VE)v{S;jM%MRe>nE+br6ZD?bQW|%B zDuFJb3xKc(a$O2Ro{!KIY_?YEZ>um2go51IyA}z-)V73lGmS%xS2n})=~~QyRuJs3 zI}fCDBGEY;V%sTfQRQw1LirDRfjO+1)?YJo6Kzin0DtYa);88)Se4bHzk^K2*sZ+` zhd`FrI~U&{1w0Z6kL@47;Lo%&y_7w5940m&xnU2`rloi9{Wu0F!xuvlQCXim%g9IB zn?PN4J}Tx_7&vIVRA>0siabf}=fm{)Cs5MPyDycPR`S~daUJ>XbJH<-=0hJ&HBa1z z5;B$p=IuIDo2O`5FV4-j%iLW#ZP?U+7BQ;r`dX-2FPU$hFi?B`i;1w&o-xP zt;t>!7v@x4#_6YgnX8>^A6UEXy!WN+QrGOF^0~QWZbL_88Vqdho3;Cfp9|;4lIG^N zGsQ#5KA{wRdM1MYS$DCAXdwNO1a7N(KjBPa-9gS7%POM5WJUg3O?RK=4@zHu;#gW8 z-MJY6n6ca+R-{cVB{#3lX{nEj!iMgyx*2O%_=IeMJ?C6qX_Hx9QM-7YFsezHoL;f z!D{Z8sblPI6PMU~!&Y%b{Td#}SflCw>o_H9-N`mYcU(tPZFhf2^cX8(4!o2EKko^9|PUq5%Mb|(g ze0TftDd4-dS>HXD&!b_e<5-Hhs1Q96+Hy+-Jp0QBlg2W|^;y1;cBd);Aiul2u;zaL zsF8_O{lSEhhhwymacM8-i7_kV!o}giWi2Da=NQ2Jd072s({%Bc)hk8S0|%JNT1P!{ z$Jlz-H&j`#r7m_;E<1n#CG(2Nz$^TX2x0YK3|U$2it*yGL<@VrJ%0Y}myEJ!0Jg6y z<;~Bo6;!ixq@3MxX7@5GFV5!|*24|%4lUG4qN46j#!5CbUQtDaEwJdK?WYTF+(N`3 z@%Zycf7Y%kEMf8|A)#rQ<>6mJgSxV4)i4{Q+g1Bb@;e*5tKrhy>;OB8j)kPGin2Q= zA}4ki;+C5FsOg)`41!6QdGDcLM_ZZnn4jjm$^ne&~3FKn|Rp_1ZV zCCwlq6IN6sjgAW-!j^@dKY0NH@yE8ZR4uk9ns%fa+Ou&chL^4&KUcDp>lN@SNA zB8d=E=n{luMa%^;3klW_;rU2Lyxby$eIM3cp$iLlt_w80P|=yzpgVQPf0-!?*3pYLCa$3@OwjdNa%(u(v+heou&u^}S7|G)2$7 zHa8<&kC+h#)8c3MFKZ7bBtV_$(mUq>2<=2l2r;9heI3>g%z6XaR6?N?_(txERXGK6 z{px3QZ>nwA4Fl&X_Zn)}3JKb<3ed}3$BI^a2>Z&{O8a>4alWd`mkl8oqq`x(>Sf58 zRf*o*>~dg6$-u>} z69%2cKasD@dyluUN}ule@M0amL(mkvU3uj5SF-Y6&mKb?hW*}`VH`Pc+1zK@0+pK) zM&HTGF884TA|G#15rUa7RR31%CEtp>b~6LuTh-VVFZEJ@dMvnHQDO4m&`*GCS($-6O%$NLrABzVrgHVmMj#u<*M^-_Y)Jh02kt$rE-6Top$ECKXleQ-7 zvw@S~SXT|&xeObol2%p1UHYyp|6xa(>3+wU01p$|V<=qKx%rgRf#KsNYjUvAterMR zJ%C%;y@X2lXf(vp+mRV@z!=Wlc^m>MC|bmkoE^DGpozZXR+--nd$Y!p8Zjh!L+Ro6 zEBX5z00_{SFzV@XFYowehDN7q;A2l2GNY5j!-C|Su!hsxK?YtIJV0O&t_=Y8a}mj5 zJ2KwsYoAV2KCUJ0<*WfdLM`D@o5_@;8_C_8qBh2lO8g^ZK2Q}nF%4KV=_llTnYP7TM6XL*_3}6Icg|`SO^Q-`IOVEdE2y+*w1%;)ove77RV{Dat>6<`-e6Czr zuB77NB(S;;!kozqVQ0Yqq~Air<|J%HfN$}E>*jr7KXe{#QGSzuVzvh#i0s_2+y zbDPj&tTr53`Zw%;AHL0+=C{P(-qYl@i`vniXq?$CAIH?k+Mb-wSgKW6$E|%F3^owh z{-%7nn6O;3KVq>6VB=M56_chF4)!LLmZFZildA~)@gN`Ml<#JNwF8~ zi%hxX<{tuA;I4axN0?SAaCd%jBP%Q>H`Y)LZ6^!;1n`b+r==}KBz4yZmBjiyiNdeA zkYK|MF~NXTQpH_O7tjXd_D_g&IE9$D+KWIbjyEO>9nlOw`O}w6XW_Rj zcXZfFc-ff6$`eS)`at7j&<#vDyNDxl*RwEE##Md7U6V>RuAtEd!UJf=&R|f9`961? z(nGFl0lmr#J8oOaWHKWFAfNZ+4SSU^l3$7C9^$8n~%J(y%9NLEUg%7_7HbVrE?3Ffb6P9EB@?16EqG?JMq^0E; z&6Xo9q}@JR!|YbflbQW&#Rh;e+U97O$e+M5#6GkHVUtfZ=Fr+vcOP73G^YsBnpWjs|7PgWl88Jkfx9((MUuIKykcSs49s6Mm? zSRN|DZp&X@d@y7N&b_1Tp?&9ni$%MfN!!XF~)I{} z;ItxR4P0i`Xr|hM-w|nU8gcLG zsq5?D&cAC})i>DrblmblsYfK(+h^O?U;{FoQ4;cN`?bN9@hDI= zRqSW8>M~Joj_k>WpT!OZ*AIl&E;QfGylM^EU3#b!P7KsD)=K+(kohh`1W$hCdGrh= z`mes7;fpmH&Hj+Qf|Bo_o5M3ovq9Nsg1y)ZIH@|zKU_B*)Xc%T^EMHfe+ z+6Xk1%v8a|A3|daQ#;H*VSmoayXz8&Y?!Qc4{t~(qjmQ;J)u>c;>U6K2v3ihHYa-J z^)I)Iq$(}i=K-cb=s#TNld;B(yTvSb=knhTat7@fZV$9Zu~|2W$FXJe7dpkp!aYef zyy7pO*zoX;L1EJ%o`lWtJsjJ-q;`DDA!@bN-13k!V?mF!XaPL21f31~+OY2rev!Jo9l3qMoE32{jraqs?iuV44yR#!jYdDV@Q!Akm!c zt*`o7hkM6jiD=as7kWJ1avw#XYF~NLU{eilAqmGOpbf>UblJJ90gh8mFK$NH>uE(QWcVUL3z)nMfD_mlNXVYWj?+9Dr~p*H;{} zmW$ua!a;;CWhkY;eiECu^Y@6KuUpjrO*ET$O!0$@buyl%K4_d{>e^@HA-ZeDEz#%E z2X8kh|9kW!T#iF$FfLp`HvQs2sMzkiZl#u1=!V|M!;-!s1>Zz~PzO!7+$U*(HX`dst3B%GHsiPf8zo^0?%) z!_zC3j}SyCAf#JLBLlqu&o4}Ug7ow5jvC|^h6<&)T7sk?-qUrZpcNVxfK-}$j{@8D z<&~!|ICa6TA+I|3dE|mUnUPbur#`g2Jwv|%R%D13`o3Oj5#wYY@sxK5*WMtcY7!w};L_^y6+^Bi4IQ+>RWUS%w7Asi+Hp6LUq2KrPdKu(tWjgEy zpXJl#AwLYT_%qt;VW(o?{3w>jB|0#dFc_@URL?)%o=~bj$gb(+7O7R#* zBtSybh5v0=7InKJJMmA|1E`@0-$ZKAM)!iCYpHVsD*T-);G9uqa7ypn!T_)qP>qRx z>WOefG=>hUIrOjjvSydIHwiCH- z9`Qu@JM*UE90;AtbUF>^#FU!+!I~rbmQwnZnms0=-`t^483TxqwG!+4wRYA zsM}6kJU(_fv3^-*SKRBPa%KAN#1t}b?duqNQ;RYghGPG^re81K3ZXmt<&cai=~wZJ zuT>W6j4H>zR9uObFKB9IqZI|80oAL}q$_1Aa?Er#hE8?uwreGs>wnYXxfg2>YfH}5 z#n-Nu`ZUEq2xGc%0^!svXlow~_}i!q1ux6Y!>p%1X1KJBX@DI0)VS;C>zQ2_gqZl51q}F?#bY`_$~dmYX5)+O<&SG3C1OUpw~NX zWCIQG+Z8OMGi`aPnV_5l@{jc$lbbc#rQd!+V||cBdHR27K?IzU4Q8QA^w4PN}a4o@79as`Xy_oX6KZ@ zjv+&AcR-Vn3FiNfRM=L9V$3GsYEQH*RWZ|c=0TjWvClOV2?#IaAwQkm5SBaL;xS#0 zl%^yeUL4|IMtl{w4pG9i@0rmMOiw(B=U~<2mNzA;8EJ4tuNh+juPQ1H-Sv|ph!+ze z`uyG>@pE%s&*iX01MWzRKY&78Er7y7-n4j8SvrL|0AY1CxWfkd#v`m;F1} zMFA~}1u9=HZzi}s@mX6k5&rN=Y60$BKt{Be%$$ps&>5|FxkqBFtia+W^gzZ+I=hBF z*dyLUM6d1l+6_NwaLC^#h?dldI6GUAHacWK=Zuz;@#NT3(C)Ojq83487r#yM)wpHqU`T*S`K&cq1XNDLf`RH|mP&%mcQX6`>a zd;oJ?+59VX7KfZ+o}(IZPOor{@4wyD@qB<{Xsx!7j1T$=^20-HT)j%Xe}03E5E8Xx z{&ppA1h8%{)&#-h%Hn4p#3U)xhWC+8p{^ix5m`<*nOQU+99wYmi%)-H!+*b?oA9T7 zk}ey}%1AW_&dywjk@)SZ^>mO)LtWjuKDKa>;TW0jUfPAmvTe(PY?@yc2%Y}6>)+3K z1W;;sLDlS&xime`URP!%Sba%mMNEj%d@TWe7CoVk-Y;1^Y8h>~0sH)IMVglyxB!AH zsqaeCO_L?!C9yl+pzBng$9Ig6Mk3WX z6EO6gO@O(+#DRx+YxOw&J_-zzg+oV)UDxv(7RNF|4#=fGUGC%-cJ=XX&?WKOh&xWZ zhE5xvaeS19juco`$3f!=)3w5lgr=ktz)Sr5E9{3hxVsuLD1QC=BEGU=v?B*-Y;?`1 zz$$c>v_{GId(ngMM!UMr1&ALLM-}n?c5eUjkjjabwL;usddd~%?kS-&nS@H06{och_icUYq=nc{I zV-@`OMIMrcQLBc8Cx}&sOIFHoaoT&$+>*O0Of5$&SJPkyJ`;!8Q)*`YWm~_$^7?@i z$qRpE4MU_i6lb|w7DQj{nbF<2SVJ`rL?qu9=*az!y?BKw6bm8GxuT{G(`mZSpzliI z3WGN?-yh2JFKc(@k>uFjqw`5RLa`a&FKJ5dGF0XDgz+(}Fcu0`abAVjE9_TOXl8_L zB=;gEu5|t1#&!L_m#;P%3!H~Bxv`(7F@j#vOc{kPYijOH|vYOT`48f;{4RIm*WHeorL>PL^pQWKTi1HCT%c`m1y-R|{=T zNP?6=vliVHU)1sssw)jx4Vb;7f}h1li~0v}l1#-HLa@3|N( zy2;pdo|xaYyFT%MhorwA43XViAXtxitxulvZf+Ns8DFY2DsS~J0qML9F1mknV7bV0 zF{8u|x!J?bUQxg}vgWR=V6gdGBM)!H>u%f8f7%){Ts*{#LUC&N0R~U;%ckuja)x2e z-nVJF3*(3*UXoo$)H2LakL&$XPMm|`spwNp$vc=XcmB~5YT>3JKnmAIPNbI>9)IXr ziYnOkOi|L)-vhi1H{WXZ{x-s#0O7RSk zqs_X(4d8GukoW3-`-WpMMEDAlOGZ;uA!S;n5tXODEGK}QN$u_+e68n);|zb!zYsGoTm7($NEgr|U&X?Zc)kyP8(3 zhd$`wwX?LZrd9TTOe+!c+DCous*5iQ11`-zM04|&T75kzL{1apak(l8;C=Ugn!$6W zh-BuF-&wf7&34EI25V@|SyYy1bp>a+#3aK5@}tt;WPX>cx>M3~hE9p-&p6%SR@mGh z*hAewHNW8)C-{cy2T-41!TMi)J~h^p)MhdC1s@PloPH%iZ0okgAu}>n=!cN!Ad)}_ zDtC2{xD`d0_f)r=>K~>Ph{`4iKXl#nH`PsWDMk_-_8rr{i@t+64;&w~bOQ9Nm*eic`z#stz z)o|!xZ(*sbNRT&~o@CoEM%wkVH{8W4hpzf;2h`HtCq%BMGL^T^Ojb$T!0MU={`bLx z#pB-W0Ey_{d`&5tFuSTh+&qu0Yx%Vys>CT;^6*N?B2Ne_e%eK z27c^@NN*iO7Lj>5ieUv)VyfQByyda|jv&1UaR7f$eBiH=p$Q5`+&+ChNH+DzkIzfVO4N8Bf4Hb#uI8=jTz1V$_7A?ergCs;T0M{Y}#>(@JP*J9I z`4%{vo*kRT1=eKCWnOSGWfezeC`S|@Utbb_?!wR~6tAG8jp&F-fm(X%zlxZ>P{NHS zocqtSaQ=}-NMl;~w?bT88QHoMqh zap*w42&6ioE{c8tL$CbLrvGcaa31lnmy0Nd7ehStq z;3?-`LwkdviJBcvEu1Wq-%ek4(jj^Oy2$d|R-q5>)zUXS;yr_{;2{at42h|Whp#vz z##0U=Mf5{Dhz!B*;vwjG``5H$BFhaMq1O%%H8(avIP08W|met=R-oJd_eu(fK z4MP@BU0eYHXG{=Rzf~j4jhW3|u80)DuPO@nC&pTcL3ks))*=h=%+!lr(tn064ATkM zjHW3l=-xH+@91+^Aopg@BL*9p@9-Or|Kz{PXmSM3NfE_{xNUy%2idmC6|U(RoF zNZcq0i#+t`_vXqD$nZ4zhse+UJB^!7!$aTWK%Q4J2%QJx#8PI%| z&EjN#^~d97Nx)fN?Jt|`(eYcr=ugC;CxR|^8$wei@~8JjH1}ECe&26??+-d|ckL6d z2vjo@O3C#y1oVYcV)ec9V=q`2YUr-+9JSvQ8{o$41!aayPn{O zj$v3vU(V$Rk9c1YZsiq%bU3HlHN#=d;a?B4Bw?DX!z}5xHgu~B7vmy<1_i5R|J^9E z6kvjg1JJ6AuT^;$1bLi-p!O>lxs-&@PT@}c^W3EehCz(jg!0=9{QZE3?w;98+%a35 zK#U1leRCfKUIToq^Ro#Ox+8l%9>l13ud%kqwSR3m5ZOpkL_l|3XJ0Vu|Ht_|gyar; zIU-k3{pmf2nR{W0JSK=nI)xDP!gT|FUTCqeU@4_n>5aGo^SaRu-A;3+c@z)71^0vL83JKkqER%96^+{xw=zQYEH;9BnT)i${FjN}3ov zWS#4NqHlc2j2tGUGP+Az9&1R6_u98BZFt{{;`tqN%|C>8t3RgJpHO}R z^>8Lq|HBuzft#sWDQp2#m@G2`_SzEew4Gu8l>M>c%gT{XT9VAW?uNhY`G@Z#CS?W3 z$`awfcKeH#@OajSp+Sfto?0UOME1@-@!bq=@#-Yh@WQ{j6r3r$>B;sHRs z8wwPM7g{acN28XJ_~}AWPBg;;qRVwyisJvli^xbqeO^w=y)1)D7Z9(L*QSvf%E_?n zi(Pc#8VcJDw23lK)ohW0zpaEG#CCX1?3DVGfy zWEar0gEuGfMwBLg78m{)CWxEFVG^tj>9_>yl8vj>GHO;X|733NUnTBx0&WCyYxIOM z1-hJBSR_u>umGL!jz`_r*7kw_6d;qkFESE$eEE=*y7+x@pyDC)Rq8fS3>W(XrDU`n z?|~Pg&_o~6Dxzt=j;dt%p#r1dv+o)`_?4RdMhnJ&&au)i2+|oDDdXb*vDWT}6mDF) z>Mr`IJo7Dj_E8Gi7)D}fYK;AYMKssL_PpT@85W7t{rhcyJ`11IfD0$G^*CzjMC7-#O3eaZWYO z`+i^dwY;wDdc88Xf4+g2u1Fnm)1o8#xLnqE-oR^L%Mm=dKzacy`oTdiH?0N5>BP_b zuLlLeP#fge&BQP}9Br#qh>cZqUG{U7zS870Gw8GyGSZqE#OM6b0*cR*B^s)wx*WE% zg&e0&OW>bX@&N^~?ckK>Xre!Fy5w1;L0w`x`vg)?>Decg-jFN$-#$x{k7~dvzuEba zEjR7ZfA?@q!qUR;oVZUc3#SQN%n!^9#D}mDCs=KlKMZL zHsj^5DN$!_RNx%mytX`cxO8Lp*0PGI%HgdBuDm3Rk+8n9t&2@id9W@6=hKON^m_)w z$wYA1#dozg0`^yCvO+cH(CY);G)?@3+QW3)UitH({sK)TArv}wrcz+xmJ4vpj#n!J z3c~k&E?oh04PeLPRfy!V&tV#n<+IM&+!-iTfAHr0BgK>Nem^+o^k3KK@2~@KuxCkA z13eGb_%ka?c#@K)4r2`Ob{!-->z4&yctQy=~r6;<`RwsWyR%~VXS)ST>lNJ*TdvtNA6j#Yil&c zo=qh9^C={O1pFn;6bRL{cXYU96VP(IeEKZ^KYWtf)iWgqAY0m~NOF9RdgUxP;%gl* zx|gpWD^WFdaUey9(0aJMFb-GdfGhle@V))&LH^KYeryjAAXw`K{+$iW@eZ>AVJ`Ds z^{clpcSlIVC}%Qc8I*g0#a!B-h*a0oieA!e=i|})!1Ciy&;8G=HFF(!!rh_RuC#6m zMLZ)~?tAm+#CN+8yg>8Gc&axpsTs=)+z5vJN{QDT03j5pOyfB~EnE^ULf1 zJh4B1Mlzf!vG14k7w=Vc8nVKVC{Ef`}zW_^5Nrxm^N9_8I0!I%ytSz5jeZnS?j<+DD2eC@J2R zNAj3(lfZBNF)i67#qz46&O@&e^@lr<{LWgBc=CO=gH!L`|J>0AfAA&CS2afLpL5Fs ztvx}D{$)uO_Ox(Ae7y*Y7QM+hWiGB3j=;#k(F;ByTquZp95^MIK zg{5>J-#$uxsW~g}a9KwUl@fT>k+X@A@`0o(F?wuJ49)WDRn2_7*Y&^*9ZE7zIV$?h zKt&o&NiR8MIMKa`;{y`QcyF(!udvCm1p8ZBZ`j21K2#`HTS~5!>f`;G7gLw>#7ph)3 zPhW{GG7a8ds@EmBD5!7~*+6(&QBMzLnmg(>&Dhr7?rd;TG%`54;qra9Up_8;hX4vN zR^3-|`A8IJKC;4k0t%v@$Mm!6HTjRW-^UK;O$*COBJ2%<>C6lwov#01efN7v4mqs| zCo29l>m0=^!;Q&ZZg$-vDqhR(nfwTtcGk=xdlW3%^+0$U`z%7z7J{|D*nrxr3k#o0;_pG=%U-JSgb+Gxr>jW|1=Wt z$;i)CnR@GLNfrf^nF<|&c`+7csoi2~EXVu&YQ^3fKZ$J6<3Ye^01ZOhv!laY!;8?R z!D2ZM)mU{aCaRMMFy{i6b5tZoz{L3bhx?vgVOs27*ZY=wSw}-%_@mT+SSE!eOEZC# zy<(J-gF@6RjH?k_@rVcu`DlTva}n8N11Yxv$p=W6FXH;yU}XIXl5hHuT;eT$>A^{N zdT)p&jfO`z661 z3+v(jX0e;D)y_V%Z|gquQ?>v7Bb+C=`a~h3%J_ba4U9{+bh}StvMrMpVLt8%F)B?&Q96>LYckw_+A4S7v^{n>!lM zwyk^<`XiWV8c-4Kg^d4kXThCwx{x`PnKCTGDivz4Eu1aaI&8?YZ4`BF-E!)8yMHU0 z$lv|8ksK^lMulal#sD4jJ3M3wZ89AulpiSn)5}n-DMEVH3Oa9QNi_q4=*)kj@gWDKmk++LJzAKat6lnyTtDeE zW4HE_CA+@l9-ZmcvE&Cv0~NGl5kqVg;E&#V-C}q2HJ#rS9};hXY99#-Jr;R~*v2rw zpUO%GNTiNL^RI|qe-676Wh(LycYJb(74IgEel@E&LJBA-zFPW{h=Yf08Ku??s8Ix_ z*8{OirO4(GMt5P$B?H|mx7`1FWlt@W_GW5eX5u+?ztnsq?M;()k8fYh+?u{5)(c!t z5O^I`A9s1xOc~vQ+YzwCX;!+=TPzlRb^N}!c?FkaRXQC!Y&d{l6_%vlQ zIW?k0>BIyyw2t4>_W2B4I#ngv-=h+Vrven`x_JaBD%dh)d=-tG|D01xnaE_rHu@dyH5z)kQ1LTxekRQ5ZJ(ZKQK8P({C@Ba+`zxe)~ zYN>8Abov#mh&ftv$SwsVTzwaQ^sj$!!pY}|G*duIf+LL?s0VVoc7Q+zhFHush zognIZumQptb*}uzl{vYDjr*b19=_2NjIX`47n0)0;ygZ`aXxTr5x#z~G9I=zo+9(# zosOb$lGgWQ@?K4aPz`dJF7aa$n*>f{By`@k`6pDq>Z4t{caKcHvv9^{!j(c@Lza(rqs#~+?j4tUDrxDFkLGYu#m&LZ-EU02YYqYAN&D-kOhMT$MG$Cq2di8-H6?M%+)%0_e{B`0jM2>4b+V*$VddNKx@yN*|PQ%)s8upPm)4 z9@bG=9{IjHCgd=3qsOw-@xSIc6cWfgkn8QcvPmC~udIR)yYdPn)zvdt6d;iEb^dt0Iu z??vACdVhU?W4z%fj?0IJn<%sEp@V<@{sF{Lfn3gUBeDB>4D$!6UgZx*4-vJmYaS;) z-PW})e_voEOnb>0Ba;^*JQ6FadyAhxnC54Sd7(7=7jN}U@-u-eJ>%KlI2d~^61Ckj z-I`|UVz$goWb;Zy0b@ki*4i2lvh4Ytn{S3EK0BT6l*R|>z+lOe{6nWKY7v<~;`I+P z)K#S6Gm{X*7f!!k(+dVHS4y7`A4sD%ZVL%#v$b_odD`1XS8p1qXzo86Ut|4xyilAj zyEzwnTEu0`cCg^li}73gAd|$wF3J6p53t-pdW9UH>othG5j75`QW6MaZ#9tiibk@< zR-Ng6iD(9={VnqW+pN>xY$*BmA8F)R`Rmvd(=fkEu?XCGU!2_UiAMb>zJ}UAko9^( z1iwsU>iw_pE;)9PqhYo)qnV{yaZj`K(01;W=NQgAB1&OAFq6f*cGbAbEei0<2{TP@ zOB}EO=_xk@i^Mh=r7Du~e_fgTl7ukdIzgE|BkDTI5PvHHwRL}t6a;tOiByi**M zeQuEEUlYi{`$;~LAO=YzQfbQMuoM7Cp+};8CtJl+%b<#FMEC{`LO?bzepmR{v6J2mDX_V zRjtr$EY7s+uzw-4JA*OMM#6SM6-lx=uauu4#z@X1B&5wzv-@FUdRm01%)%M-Ey5)5 zmzyHFLjXZRk*Im~^zP9d>F+LuL#a!L<7!D$%8=fLD{A9Y)Jq3ec}PvPRopTePk37U zm;SvE-S1f63pt!GyN(XPf1a8m0S26(I*sS0-yfnq9psUdYb8}o0u4}Y=*7Q-$R7nF zIkH{hvXEFDk2kMk=-x9UPXT=+Pxc{F1?d_tw=p(kyR2y_S%@qnuDmg;^N$p`g!3kE zuS`e1;_F{O?%A_z;p&^@*2DJ5UJ;vE&CE-QWU$lQ8LiFfi{_0#so0k#X(p8JngCh= zR_63aFG#)>%aOOZZhYX#uUqwJ5cT-#B>a~d^=>ZzG}`aT!;0SeJ#9at9TUSHPv4GU zW7nYyx;X!Pj{mox2(Kro=~j(?6ZSzNYU1nz#-`^L6}Q|xJ}eA2F)F4$-xzGR+*;z^ zoWr_`W$@7Q(CogeYEANFuXZ4oQP`NC3Mep_8GIpWQ zj2cpgB~OO0{eEu$$cj1T2(tQogbuHq<@`irxur=lS$!E0duz(k!mVan&V8_Jtd+Ibw28!{04F=4q3+SN0 z;HY0Op!`#0HjJy)kk?GU#a`h7V<+;Ec-)yStbPA4~eqV}(8}^U{!eBMb-CrS> zmOs@61iE&cHcjx4@I8?DSKqK>P=BtsM93@Cx>VF&taoB6tz8x*J|RjfHwj=EL*BLB z*}(lDel`Z*v(1%+OI<8m?od-xear$D-{2;>|dVw(52^$Q=%%wluj<4Yc(J9b*P#Oloq zLYx?X5G-!M6}No(Mvl0wGagXf%J=Ivph$k^#BC(|S|M^hUnR(~BPFL!f>kboF8)fz z$c}fm6>+SF4S`tqZ7C>JLg!A@qKI2-uXRt{#n|mEIt(i^Nu^yYy3?02~eli@Go8b?wCba7HD z*x#o8jtSM=UfB@b*HgrD_09;MlffPkEZwUbt@bPyu=<+xRWx6DW9j?QIV@5CJlHOe zNmq&?>E8PO#P2N41R!UnhFtQy?&;~d21tbc^!&_8St$G^)zu?_b`)#D)X%2iD^+nD z{%wdSVy-q-r}xvzj6o5+YhKUM zyXjEY?~^lPbV-okKD)2N#j=<-3G8|Yl4t<2T#zboM;tcqhsShGv_+Z&E<%}Xom@TG zAfOd}vuhN~_jJb*Pq!7UX*pJpTwAJIz8Je)MhA#5!@-(t-aun}XXjhM&W;|~)H!vE z=pGqfm3XOqJhWc1h0#6khW^JJHy5YhNc)Cutyf$NHf7V%xHu}+6@B1Ae>bhknmaq+&l97TZ`Pa_Zo+X4KPNKrJ8M{-LV(sXSvtg zKfmKMHCq@c^vebufLd7qgiQ7{dOy>f71^06Q72!D`)CJ8(dv#B(*Xs{2sK|J><=$K zot|_h+E`(i4-aKLffn%uprIhU&mVD{K>wpHC4|cVI`pf4?bC`~)fb$An5-61CA0Q& zBp7_SD+npk^)u;W4U#6U)0=+%$d(A8?agm$e!ZAuWJp$_^!D_!G{vTwJNa*7Bey%) zge)*RjkMjbTF+k=69d#|h&(6v?`K2l?T2a&KLCQM@mm(Z##=QbA{4U=r<#jDWv0{a zSw>h>9@w(Ry2vI?r5_eafLg9M$-IOR(q~oPoQ3zxBF*tT+lxcfCGR}Jy_T$?A*DeV zswwiDP+eyk>yxb#8g_gky75&?Jzdd5$P59f%OWT&3P3f0V*|8`Bk|Fk1N_L4`zc{_MkJ=fw%nSx=dsH!aa zcP@J0j_o(+11^M0#sEC)q8!7I%DLfgi5NfxSI%R3>R*12=JqGhX?bdz{bbqriain) zuTM^F^P&2F5(g$x4#-=@*f$$?e{aw3%b8r~t##Dzd{gV1Vt5kUbj$996i7#nroc-~o}tLPzX>k#<(5t)r;G%d)om+4(^dp{P^GiL z<=F)^ia}dvQ~gYo4YE28zbIWm7k*6u63`V(mGfwYZt^qO+liN-!@ltNBq$X$cU#7o z{))*by#$ro!?*iJZQ-dnEuJ4t=k1~^sw9`_-dr>8ZVv&;ahwhTphAuW$ovo(!>ZrBB?;E$AI8eTkkI(r_CHJoCIjt>8-0@zQ0kjncH5Bh=}N% z=fa5;XkbK4<~O5&M4t$^1wMMHmK zHTFF$MH^J8qXg})<8?;xtKk<8#M8w>tQ;WJL_e=c7H}99EePq|Lt{f^R2GMI^-67L6$@?puI~<)BN$JT zj(=8{5@Za6l@SJJ8{klU0DMxto6q3s`^kq@Z9LIZ!$}NiD+3PLzG}}SVUtiId=;E5 zsqh?zZEOM7!3hH5p!w=gpr+;u50)x4;+WC-3IkwiVRsxDU8CmiAFncOFcC|RSPpxM?%hI ztL!yiYNqxl7l4;MIGGI!w3FNFx&b&B@hS%Tf1L}(jF5nCo-d1XM8tLJ(lSr}^R3>; z16Ogukfvh-YisLU_2tF!M)%#g61`XbX8f#9aJYX)2Op~2Yvqc!CO&A+;)HyVsKxi| zlWIvEa?a#C$^}oE!vy7*yl~ceq&Tt_#Bv?4uC8w0d;$JYIlBokMDQDBIwZCiuIRX| zHqmzEmcL*UUF*X30wQ z34+zB`r2R1XWFb2X+drbblIPn;5yid;BnpO8=#i765UsH#;1!r3V%gmDcF#vs+l+N zW#paB<6|C?D}$TO16%~RQbdl87BX1>w) zCr68Aqn#^#al$TXNi2KsmnqSFs>y@=uf*L$C5}ASM*-81DbH7W9O%R;T68CH@5NoS zwjQmm*=3Lb`Hb}OtczZE`Vt}m15a6!7=C;_bO5NZq>rt;c`W0c`~jn!HqctS0UZBZ zMiIAnVSLu#*mZ$0RC!g{kk=a$_=ZE<5e_^k+nzh63Z}mtF!R30&gJ?_?d{AR0&eP8 zwY4*Fcv|{Bzq3<5n=qyBERvl~*gS3Oc1MhnmqPUMZv5pq6Xlh8+$$O`Gr-02=%F>p z$Wp|$Jb~;?SN{`u<&A)??ffw>3iO$atH%HnI8HPTrTD$N!zcA8KOx_NrjX%-=Gr)( z#XD8ok{7-ZPMU#{tp4T5L5=b#o7+Y~)haUMk8_PE^34s-xpVn0jBqpit_3ZO){WZH zO#Rx9AM-?lI1n9dFCPR?vKW#D4N2S3r#sh?&~6DcAZlp+G9HSt zubVkqxi*3$A074&w@2SYsutH5#&IH{Bq9kwLx_&=@k`BY&9>UxH+=x-ea8!O@k{Tp zZ&E|=Tt`>VRT=_p3@;le$9CNYFD0c|=W}RKw!b%@KUq1S$NxeI{N_`Wn!2OSe2aoB zHyZ_u+!pn$zoiA)g|5$(JB_nP$d2GN{AsIm$~$d5nuNr~<=%mw^CN79Bw~5CrM!H_RdMvKO$m}E3;>GBRq&8f|mru0N>{KH1Xs0 z8qakL{%8C^z7QV$@+{U$RS=NSlcMJZFW42xA})Tbf4xB^Z zLuT;NVVvWqGsxL7%EgC@FYF0P&XF2T+{rx!^M-KcZKLq|h6h9FhdI&nwP<2o@f&|A z;NQFekEZiFdmhZY8w@UZb{u(6PDH9k0|iULg7}_RAaZ2lpM^GuegRGCGMMgEqqIjD zk4u`fCWxJrGiEM-G(!HaQ9dhBQq=RyblV-THmH~{@?P5yJ;2wC9Ft>oJR59TdRZ#PH)Y$08#{W?OXFQI+xe zDKEp9dopZE?qy5%!)>(+$#X2yTP?d*8WGV`1ItNyyy#9v;+I8_tI7+Ims6h z6c#|y#`yy#Sg%|Lq5qZSSW6gCiv(}nUjq(F$#e)2FLxjqG?Q-~5P-mWLWbMjW%*>_D%T4+(+7&KfbiJ5PfK_t8BKXiOko zbKjJd2nf%nMWPjg1a+teFo|qX=vUc2Xf~LhiLzqzMZ}7@=h2ZCb(1mq0>?55eAf8{ z?zxnGY`vPJB$tp-zbG?KLsdc1^E?($zav0IIs6_-NWbqiN-Zg)US#Fi*-fj7pK(z` zXgYJ@s)9)7o+DI-D_k;e2#Nd7txF}2?`@m$?p2M9HN22XY*D##TZgJTlw=Q(quVVF zT_Y+o@3?4Op?L6n5s<9PgiIQ*+UH z6^F}lY;4rQDiFdV6WXG)@+mWe(sQ)8(;;kCbnfvyJetM!-|xiQ4ZnT)`~;4#mb4~< zqxD{b(Df38t{Gi=34Iwv)Yk;gPu#cyy%+pi6+o8`aLF+haxex!KVu|A9}3(|3TY~} zqL4(uFrK)ct^_fJbR$3X6~?jtH61^?>lLGo$uy{4&!cIr3oJedQmz4_VB(Mcl({h^ ziY2G2AC^$=0~wg9OZ8_!b^Vc?iOIG10lvJeU(g|jmpnS0j4|c`l5po2^rdKU^YV$} z-arB~4KTjl@;y4Zw~jsoxob6Zmwr`$5=hrXOegw|oTJxWuLOGXR997QY|vu>spl1Z zsa~om-M9utW5WH!w{z<#WqQV1XtWJjL59X-mf1asuhZ37OuxhlJMYbA(CT%IuVVEb z+Ca5IP+XEhe^_jy3sVPyG+E_~sK_+>?BSv#A};8lPl+#n z2hZtqrV~(`H+Gu#k5n(<138zoJ$ka=z(x6u`TA5BKY~cV)F!GFg;#%n+I0soh7zo! zDa%Yk>{B;OUM0wR+qrS+9Rqed;!u8mevLV7?mYCY^N_0O^wm#@C!%4A-n184bTkHD zT>CYmQ3Oh|)YuSLtXDjl9pY(GV~574pHLF%N`HD2cbfm^&FJYMZ65OMR?O1wrT?&&Nl1} zK)Vi*hfwMmN(q*Yc)?9@*6g=+OmmBE2XA2xxeY6OQ8axwaV8=D`T`S=qjZZcVrzD- zmRTBPe917sH3D))J*zj`&jGRBLGhqcxS%~b4|J=KNok>G-^ywn)C^~h`r@z@{{DRE zl)IdeC%2=3>SrLyV{}T$!HW>Ic@v}qUSNR-4FS$`+5>c&yT<&*I4O0kUOxe)K(8)B zy|5i7GI3PD> zyVd?U*AlYnFk?FIk}pP7V$lV~lis2qD%x3*V`pCA2;CGE6fBm-yfp4Yumka>G0c!G zZ{Tk7T>F^x@fx6~qw#LlBL5yPHBzGjPzcH(=8ImDOaLKs`IehKfdAfROWrg$CjlDh zd{*4r;Wjj(M=i3ZoEZLu(L3bhwsd+otjx48>1&!oBtaF{D9`^qBlO+YC;7|Oa)^ek z>R#5k?hjP23#_VxYn^F7@82De__Zh|{cI$e-(uvZpN%PJ?<=>u^!-S}$Fxq=$0eF! zpxgZU40}yQ=}1&&z7wl(la;`Q?1M)F7ctBqw(cAhP}zt?|Etu5Be9I2G<*$b%Gi*9 zwV6k_KU9JREonO-bUI;_zGr4!Blure`D^EEaZey8F9|Wn-myb1e6JFk z@VbHTs$Y1(64x9Ykb~l)B5A3sdII-B7^3HY_ESq@5px$&f?<+H|BM1QMkBB@uEkTeP;~Du>NNAy z0yR^geK#BDW;#ovPz`$QGOo0vRxx>1`MqG!*6UOm#Ckz9SuS<6v?l~Bx>8T*JY-i! z{8GS*4@_s)m-GZ~QJXE#P9z|f-c&7B=Co!vOdAr4ZjETavNh=}2e6^cwj~Wj6%YDg z%}i#f(X&Hk`SD|lC zXZ@HOCXO?ZK`dY#+X3P>U#S4vNQ03fhs(0YaBv+1?hRRy-v;O~*@2;rnp`)shBodV z{UxfsJ?eu>it9S5$qL?f1+TV3H-M6A59)?MZ^G9SIe{F|9&J2;44}3?-J~2ztr^oa znxpt)sR0tE$-#Q3Utw4ZKgkUK2(!+0x`+qdl~20bWlo!K6x<)IWR-Y@E6CC&p6kuy zuJPK8NNbOh(t5zV@rA##qWk)A0wr`_g2qgxO!uRWkEYo$>QnlS5XwBYJ3s47U?~lOz~^C5Z}H`I z%{wBC+pjf2L9Z6ZZ%kh|8}HnHO$K}JJoe?fXm7j~FPCM4r-g~Hea#|~R$!w%fYJ0I zhjto`SAni>o@uT?L5443)bT;Cz%WysKx-P3BPR}UW#95#GXsu_$@gH@g0l@J>ut&QECk+*$`+Ot`tuABOdVXDHL0DNfX}NO7VRU@HZ;RzSUs4Q>qoY#P05h z4WVQ~vk&$X`E>EM257?7U*8!EMYLq21yn~f?|Yxg@V zs^9_2@1i6LHs|^x6PgV>7u-?KIkj$&Bu2|SV)gr{?T7f7|IC^H1OOsPOT-I{&Q%FN zR9RxWv!WK^tv_U|1EBu(w)aFfHzL<=^|EwbyP9}|Td#z3D|~%z&CDN@nm>Yx$LBpe z4^P~K&jPeSxOs-VK9>URDJWTN)^-8tcG$gX9z@b8-oBt*z)^lR0qC#avj?)>kKt?I zlz4--2p-b_TL2PDgqZO&4+YSL;C$+@L(g5h?Py|hC+-bEY_cpiS~D8x>~tIsdziFK zFm=&Z1bmY)oz%J*>)ZMr;H{>AbYiReiC-45HcbAM{Qj~JaOG<;bqDFK7SIVWb8czk z1Cs8EFo`45`&A)UYAJVLkW4-H9+_G8Z2)=hI!2CJ0RRBcwYhHPBH8yxQ5u11t+IRx zl)%%4zp4RPk)eQD3JEm&3=g^3hFY?bKYFs^M-1MWdFl?F;f3=n&&hZ=sYRd6=`Miu zjGKA}lhE>{=I5)U-1(1MATh(ZTF{MZl$^eiW0k4c_;Blj!6+bkmbR~$ytsco;nG!| z@t~fuSjCs?gKtejELCV}{*@Q(6I{!pnV7ozEv==Z?ZHDq3Dt>;LS4{)5q_{35K?n3 ziMGG{CQtdrewPre(K4>2zC0C+g2AgjZ}y)3&-cypgIEuw7Y081*>PX5gd$OWo@;v= z!fS2%`!e|mwe}cEkSnE+pSddU<>gg)I!~;x6D9UuO}S7VKcp4JL!mO>BrPGE>l+-+ zZAjjj(*Vuw2at%tJY%)V%2>l1UIESG7>IaKFA}q9R_x6I?kUS-37z$P-$Nz5(3RTz zw^q6W4JbgQYh2QQG3Q{M`550i{DOMIXyZTw6tzrDDrld>e!P4xKphzsMU&}%y8#M0 zPfmABdgD^5Qw_}#>B8qnFM;g3+N;=7(Cm<07PYTwyuJ7sYzqP)LdpdLbctkM@H9;B zFW1EY=KJ@>?w7=_V6!x?deF4YR=7+n0%7$obLi#!Dm;5bj*bPg#(<4Fx%}4S&w=-R z;j1%U+2wZzUchimFGF$=T9-1ie40n%3>_!234v> zx5(U?4Zj^0#=C=trhCtw#+eF^rXTmJG`P#?3~|0yCU*-BheYf;M1TFzIHFLAtRe$9 zMD~*%r2_)kyfz30_kG_>hV%%p?2FpH^8iCA&K~a|)Gk}gLd(C^e7EYA$6M&Z@5Ue` z|CR|(a_$lfs0GeD)&bli1v1pgjbr-+b^#c44C$?gG6>0R*&0AEBK{t|WlJT1_*`bw zW7=Pyp?a136EF4x1`o_k#PEUPbod)KIg+^vfeY3ED3QQSw->fB&6kMudlJD7tPN}}4c1Aqs~)KZd>4GIMXMa5SYPk|WNH_&Hu8HOKIqE~Tr*M{~^ zZnE-V0^6UPEq|Rk@+FN`Pgc<|zqphQHtSL!ANo*ORTk3q*0s)Aq(75Ith~@jXYtX7 zfd+_D1@JOZV(L~uxpwM(L6Z*UFE?2ysjDr30Jf+aVw@zKZ(41!p~gSXNC0a%ntY^3 z2(t?nQ9*%vck9Q}NR7S))IEO$(18vN6k3dRV$Z zc6FoFrtcOIx1qYBbxiTQF z_fa_)(8BCm#TLrN{R)e1ZP&r#UnE#{(TlWLX$G1XTfOOGZZz7Vcjh>C!C;R`spE4P z@C=ba9Es$k6Mc{XKprp&P68`tQ6PMD9PF-lwUP0ZOM=BqGwxeb-q5A>$E-TzO~vYN zu4nO)7*!-9@#k3D-y!)7uUeInOojVBe-J*MHCs}|u*1Gx;=50A$P?s>DpNiERh-*g z79~solloPp?C4;@Y(;ub6iTnpzeg zNNmf)AU$R;X* zG{g;oHQ{M+UHoF@R7;g6i+xymWD5IQfO9Pxjv{+dz8_Iv{mhjF?#KJl`7d z%}O9m>4FIuJlecR^_a@#4avt+cS>#`k@QB;4)<<+>liG5rEC!Ik!a2MF~V0&&x`^+8WV) zetd){q6f%Fsa6aqIMnQc0tI-&RyxZ#R({Jb=Wby8FC%#QD<$IvRvt$=dXe|I0$~tO zI`OCFrLolgrXhKmzQ=oaOlTI55uiJ)uMsFE5QuQ4Ib4~OmU2?h8A!=QEsjF>ZiqUL6n){LA!uAM8gY7Sma^e(_9%oDDpJoQ2KF0sN zl*#8c?7f&}8@s!7Do_9Ox|x^ls25|ZPmLE4S0l5w*-+6KB<+`0FTwnDC!Q?Z^<4B`Y58ZJLAP68TVI;igIbGmz{*Ccir)3V8+ZhBeWMg=xKO z<}RTEN!)sduXa-uzG+qxzzI^Y&m$edFo^^y#5-$XfK$_lj!X`qtpRF*3?eNtFis-V z7@&n&hSVMH<-o3isCIF2GN;_R@1b^E9q5D9+nfY)V{h2aTsBZ@U08JLypC&({*FO0 zi}v1pcUTREGqNV z*#S5}1b=$OKDP3UPoUuBMvhEh?P!(jNmF$8%VctH7&f325!KjQxPCHsEQW+OfB&cg zWGJ)DpF|l&q=@y~ey{ASHmP#y=h+<(ljvl&QY_;A_)9_wW;eGoY?3&Xad8Z~1FR8j z$9Cok2itA7v4>1Zl>G1oS3^6_5AJ0Ba9SV{SKbRdx^gAzMnQT%zN#YI{a)^K7ypUv zsgl)DUN<4Aoe*e?Xv#|w+n~>~E2e%QYaYWD9KPbpD>&ci>H+ekHbQby3Z1+QE%-)X~Y);pkiv0uw|b%&7w&zy>}>!=tcvE29qifj4Ic_-@D8v7kbXteJ%^A zqt}6{y|bNoz*~BLsV{gm8Zg@RbegH+BX(#h*(SaYrR@xZdF5m5zeQfI?#SuE%raJO$UzS? zXtRr5oI8ViaPi*u_IXy9rjz(YtvqW`T)_?%u<(84-qMZv#Hh4mmL*D>to5aJ{@m(eGUu0 z7zhY81joD+A z4PH`h6xrJY9h*Y{&X!_(%t6pIPhN)`8@Fu2_Co<}xPZv82>{RR%-*clG+$R0+k8uh zo*k{L6IMFL!mQ{FRN>yd=cp#daAaDO$>&%1Y@u0<4Ji4h|G~~KX6h9`AKtv@|71a{ zsLE3>z{kWFDS8L2gVj}xqME+S5#U0+5##rql*W0KaWj4=?T~*=!%8|4Z0awCpRdts z{n6#aYu|T)_t?ARQIUt6lJ23Yls&87pFEQ&F@_dIxnMG1ki0-3nU8$oH{%qtc~ zYD8{!+u>il-u6kUUbFG7{?Uwb6&M4S^#th+=z~c6wv>ZGw@xO8=ZNBU{Q_CSha&Dv z=NRe)CnRd8B&LK!cY%js21i={Rna*O_IIkO+=|fn*0h@4h*W7|k;xv?@ zCn@aV#%k#{HG*6adn?0486-64m_&61!f6aPJk!Kj1`#zVaqr4F&#BmkoM!Jk5hlt& zzjM-`-aZ_-5}NFOv~F=4kcje|n*9ulD2D_#IC9IG-=zMxU7%W`YtYz3$wKw z!kLqx^Bk2d6@VHyI^=x-(8;;!GOwojV(T=O|FV~4AnB0F|M)&C&e!z^nd=o{w7YTV zo9U%55eD1zSEJ0zY{w~)psA^#KOQP4cS)j|vS77UAsPC2S`B`B)p&bYNuL?=c z&WdTWRWC>&5unr2kzFa=n}98G+UPg-<>u1P6F{)t2HjR^L^+0uYGD%0+)^zTHf33n zJ8s?d^MAMyvR=wsE-vec@y9_e&OF?ZHQag@=54r`E;VmX10l0=U~Z6UWUYgq8W?j1 zbF1%b)`*V9`P`Qb@PoVupu1u5E)$IZ;x#vj9qd&CK>vTGex&MU=?gGV7~60Ku1DW7 z3fjL|v*hG0=-ZeWZL0+A{>k(i5NT;Kn`nK5w9cRulY@E{v;$|sMR@vr2?rTulP^qo z>Ro*`*sN~{N*8QESFO-0P>T5&;7{R{Y_im|tNG;sTfYwSFRFnuZ)vIDuEse&7gn0b z0qkS{XMH)=5`c2Z*>6y=?x3IS`1$ep`Y0%X*t|R-hPTD0Hyt#NWfx^$Tsq$Cuajn$ zLu6r|y&y4OU_EDOyp1=iAt7#orCxXtN&1F^<_oGlsK>!-%lk+1V@a+2-J+)c?PnKP zy3b^ogp`heIJvGX}I>w4W~HQLm0-RgiXlP-YH1i!S%*2=vO z=DaRKYVjla3zOfBu6ifT!_$v)iD(zkxPa046joS{m83#92B0OK{WuZ`RDSwPybOZy zn~?)Lr5mz%Z3;9mKU&a0=LGQ*i^-mQ-V>lF6#?)+eBIvFue501zPKzBVbUdWysL_r zN+uIafF*a+WJrdU4wE%XdxdR1j~Sh($nXB}rjimJr1^UD*PWM@pue{qqb#VZ0V!ke)%jae2M4IZQwfDmIYDeic!fr+NNA%l4!vM9_~oo<&4{_#Ne= zz#+mV+=gY61s@Vs&bt4kMOZdf$S$dB*s3=hGXFc#had6JJ`cX=29y;642$7VPc?*u z;m3#Yqd_@)kH~33l?1(BaGHOC{`9t*sqsadgOp&N2w?1Dz1Q(sZELmX`n^1j;ZFcG zzgyx?laV6!0uOPh1T#!qzt{#C2ywI@FjCScrrT$2sT%_Q)k@r15kc++7J%^%EQm<& zOZhYO*Imh>4F)(C^vgF#c>$U3SQ2l=Du4nguI)f|IyyUV6lIZw3VbzR24i`O=lOw< zpVby8HA8Jte)f+N{Avjp9(xc1S`R3HP1#Jgd z08-;<@{#!k%*zosA5Ovy2BisF<^)n|I%h0XI(Vu&4baJN#zsOHhA7ca=dqb@j(9$Z zJsUuf6%7%G!8w%?IfGyiWF_Tt4|D}}$2I#22sEv?GU)Wexbn(BEtIxdS9~D@>C5`0 zP-@Iogu_Gop}9&N{VRQ)Zo4X-E?zuVH}cKMqC_s|ry>|Km;ket7a@W)+P#l@GapRB z?>mk1ZIteVL_B{GuIaSjx6%!!7S9r6z|i*0QHE+F50ttn27u!1bI;reOJfw936{n?PRBm-1TG=t?^r+Ts1tr_1>ZO4UkTx!G(EWzSw{Qv89!ax7uXXF6*`2kg2kYO6Y99 zR9VWj0)nk#@#By*g5xaDo`Fu~lPs%l4iJ`{R(^)}c%28O8l2>|iumrt<@u?pDHQ8# zpxXIOG+#!G6!n7|z1t#j^l0l946GE*0zaKR9a2l8?|M9w8uolkt1=QQcrDMJMNAb+ z{jCmmm{D^iZIdUaGCQB?Po4u-`6gIOg|b1q{plQCu5R&%R_8K0Xdb5D5TZ2;H*?gj za84Ip{Y*7A8bsoT-oEZF1_%6bwu41iJgEAu4~MXIP6$kY#}%dM0ZUKk;XC#j?IBEJ zIBUW6r#DVQK*WCu0a^9o^cs`j^fl5SKZ);e?QGkhd_!N%e)YY6``$*D`b5D-01>3W z7woUt^r5fyWoyS|2QXgTV%&VS5Ki|WdCqSH36xe(It7aZP`D7cmRuE!B#UUuObn9^ zCuuq91Xx^1s6m)-1InQw^mDZWE^hpm+AcD(O__P>|9R8%tEEKpuK{ZWnUyGfhOAB2$N8HvTd$Dq5Dl1Pb85tB4c8kp8NK5LV^w-#4YUQy=yF|Hk&YS_=Py8I3vX*%`yo`>VXdy5su zbAngD@mWDS%ex@-KvWrex4EimMC|IatlBTr)D|_t)7=?(;w@no5m8uNwo?AWY&?SV z<;4FVUw-7mbKCI#ABoPHn!M!$(wb-6Bi@NGH`NW!`{cYyreaB|{O~k2{Q;?3kY8gR zf$7F+6)sv9>Z|chva(N-S-n(nvIHWe6By%W71l9(kT7k59!aT zth`$^tp~kQyKIhCqgz7`LO*JuZew}s4--9)CCv$x=3d1Ux?fg4SatqP4<>O*Af4VS zx|+Tzlp)SQn{sf)F*x~r{y?=~^_0L}L8&iqIW{c$>^o0y51*b#eYdGNCY#TkfT5AU zC-pK~!i2O~`ryGJt9R(!rK-bO-y9Cnh+0|jne;q4O>yvGE&Vs+nb0jV89EFEY9i+| z>hC4dep(yQ6F(Bj5JH%9V)KJMxALvXvdL>9r{`k4^s3&h3OL z4`yrfd1lt2dW~J$Ojxa!oZ{Y_Jk0Ue=?oXq>lq5_pI;*{y~lk-aR4g+$468l#m{2Y3XMCZ9AS7XJmsQp<+*YBWy?le<&kd( z<^FE(M<{!-NX17N$WJ4S$MBH7MJtXO$~unc!W3NTPXZg?)lHb;&mPCOX&T~N2;IKz z`1t)*5d@mtQgZVf9P0ULd_eGX<1Ox!exCdMdIW59NZrt@=(vz;j>04EOE2vD4nKl1 zRi}4OKCcLlJ`x$wBXM5aS|1bZW)#P7irVvv#xG$8;0;*-A7Q?uJ^IzH{YO1pUqauK zIYe6`r=bdImX=JmsQYzDsTRfZzdv>e{^~)+=*d$u5l!AnIMm^lEob=@I2;tlj<&#(oE|fz9-lM^c^r5Ap=9m*dOY5#B%~+`2u%H6JrHe&t})iDp4sni z0aL(t_2`eWNUFek=6|LN7)R!RFi?efBMejs^ThfN1Jy2|PWPRl-}el=?Cadxo*_b9 zlt20w-D>TZZL*}|RC_LJSQBGD2v4LfiLyz|_6<|Vwh{Qlgrz<#g|k_VgY8rBWCRI8 z{iPHGdHNdx$omvBqj%AD>e$ky7A$}BRO3~6fxhbS`aa=LMPMfxY|D^=5gRk;IhG_< z@S25j;(PPofqC^R;6hiB*CuDSHxT&8l=im zl_56~s*l45Ka@rxt9i@Q~3m`M8- z7KZuc-`uAffvt*I9`rL>?6y!0B```c*m{qajNoifmJcqWKJJ9$j`@zPkmuDK63-1EG0938b!oZWZKiKsw(bfS( z0^J%wCz!0z;^E;j10}|JnBc)~!S{_N?j4aqV)lLvGAETyTeW_(ONOfOL(CX%l*M`eEgZ_V-Hv$xOwu1*hMshJKa2u;sfMxtAxh>BH{nugmj}Bx}R6szk5eu-;j@le^_BC(3Gvw2k0^HJta1DC^7lvfOPeA zyv0)9~Pt+0VnWMTiM)Y#fo{PBkE|v!7iW@_}k9GI!_Vu*=efI#JN8zx^TYy zuJB8@k>*cYQxSI($5zpI#D9O1>xZweCASdPSs@nt9B4L>w-vYl? z1q5V$JY+;I(k1-p?1O4%6^f>NK=*(+4MyDATf6b|^BQ%q>$GL$4vAC+1JDJzwcR;t zGaQAy-BrxlC6VsBSmazFKm1eTpZroy|KOK0{r!0yh`}X~2He#fpiI|7WS?q8G zW;nMwB)Dr@r(ShJFzsnDZBU%{f#b3C2jkvwsiaia+Z^JTKT4MI{S8IHt?iAkk;H|5 zm;Yv3;v$jMf*>Ek?G~ALxxZRuXg&ewfPo|8!wDpVs<e)sFT!xjYai1GE$-#_;Q++FRFjCeDAn>Jn?nahv3S}v7B;~7vx zh~|14fUWhdQ}Nn967&?;*OV*bt%-H^K;+< zhajmNPZjA3Qi$>lPMO3zPx+=K@g#BA`l1L1tD?lQ4RzH#!-c~7$$(i)z7NHTsyobF zb0I)JH6VD@Fyo#UuJhrqLd?Zq=WXY1K&stVL8r61B7;?z?QSM#;_?*u^!zoic{?YA zwfOHxY8jcGL&ttvnJ`KUQthK}|z+l}I)t0sy{?PQe)UfB%e{sP{v_$H; zI+tcVPm5o4mA^lcacGJwR9f1iaZzAd8sVGXjm2bVe0DZ1dy(Hm0-sDq0-pZC{OHwxOlREt^UI$>)uzC&?$WIo21Bhes#JoRKq(_Hk30 zsbExdwQJ;BQR+SXE5syq;qT-sSH!T zbgh?1q7^TTT*~0s_OhuQ$RZ67{ukeeapZXW)SQWWS?(_1H4Rp_I|d&Y%v(}p3w}=C zLLklGDc>;Hj`MqC^iUeyi^SoKaQ#cG`s$LLRi`yihVYKDak$^+wZbX zikOsxGxy|||8#-d2#V^l9}{I`@_d5zeoCosL#~BpP0ed5|8Re`dOPm#e#wb7X>fl? zu{?;771+y!>AFDGxH2Chj=^d)gFtj0?=9VJ&pC7u=bJyQ{FjJJXH0yc?3@N?CBFun zRF6k+OMHdV$+C0uzz!U`%Loa#IBEA5U$W1FEH3p-XuJu&4X0f6gJIeX=-i=5LC!&WIXJ=~oKEk8{d8utrb-pl_b7~M*P;4( zY>m(WU*Gw(C+RDFGkt8b+oI3-CWps#ChfZ$zbC`deMo(aBva4j)`yr=@(e zl{FXED=Ds!PdSNQq@#d*s(Vu*DUGj<{UMH(8(Iy>k+>`7`(N%Y9=<+7QF4dNa=Pr5 zaKpMY9_;pqRc1*1V#NB71W;r zaA(Ogbe2glG|xnjW*psiD)(?s#aH1!c|OA1lvX|_=4F=Nce^rA8Kk5hw4FEWdaIzb zKyfhQ^3B3uoDhM9yNk2D=nBEhoG}T5-HZVzr+>U29sFIxrEUNIuTj!L=+ggl}{& zY9~m^u?s}D_nMec8< zmAETQLw@zg^zqRTVYy46yD|%)t#-?FRJqK2BuZA3OZVyS6Rb<9=X@)7 zeMcan5+*6BPRV+u_AVtmF+JT8_3Ik<>F?L%eap(p2~0`~U~kAL zJVeHRSet^LwiTiQh7J}+gnE#57yf;&mQpKfYW_oH4Yu@R?xO?0uENf7y2li%$1W?S z&={q3G&L6MZk?&dEUHaMGRSfM{h_}l3~bvgq-o>CC(FM~mu?ZR|52dxgo;|qi?W=I z&AKt7j99@cl@|`oNp*=7yXGbn#CzFaVf7=3DCfEEqfKPd)?MHStkBBL$pgUuV z-@+kKx4K+GYOyimv0m9YYqAm@^Dg>w_2~BEZu@wABZK)3m96#+l#Ts2himB8;bk_I z&1U~!TYAh>jdiu#HqC#In6wBRSVNP2XB_FhkyVsQX|U#-TWhpD6HDGY#ZT021$J-=WPkS&{1sMw*N%VR z^Guk?EC)S`Q$!i6eKtA0>UXiq1FT^^EJuj(_%#VTS$2-hZTT8b0j|5YqMNIy^Xn21 zAT~z-#Bb215S91LBBRS^{@#ZFvf?}w@`Z@SZ*Xk8z(nhlm{~A2hBgXzOk%~q(JWu5wc6Yg=4h2-#?Wy^l$4J>0YHbfJ2>HArxt+Axv<;UYsWlOS9l0+Zu zQ*M1mEwXz~ejsLiw;Jn+5Akquw=E~Ih~QZF8}+FmzeYC02U+k<^J7j8i^ua3dGfYtI| zGN|Po$XNL~ecvBz@R2r|G|F|?$DwNprW_YcYFXOw$kBAn1f>>zUVYl9yq+CO5vMzX zKjnDhbUyQuwj*`_CU)L~I!#nG8_AZEJ|_2RwefWEGT(=F`LY9(k6HZeoKv4){oOA@ zC|9F^oOygnMRRqK2Saf||`JYC?~ru3bRiiQpq71gpn7+{O;VWDcAna1z>>GWg= zaNJR{|c-wD51~tDF48if72=kkv5`$Nm*hPH2!6O`K8IOr_%Fm1Z`geN?4z zuGJ(~B-S7MR_lKB&bArv$N7r=Bz3UyOGk&W=Ck}JK2w#VL8KUMvixS3+cjA23wp;G z{#eta!!q(msTa*c^!s>UtBWb6H%wBHnAdgQ86J|qr>N7h{lo%zvpiiS?rh~a-R`3& z%kqas-9V@5e{3)J$A+7v!`=yi^B~={bBZSnE?UeYXQzIejJ(W;ugGLS)-(YL^Y$G;hWW;bi^rO0n?eej&6J`heC4OsF? zvi(xk9UiTvTf0)d6yCF1KlEyt0dJnOX4 zr&X0dWA_t(jSzg3wwnCwu{iV$N~)kcG?!VmZQtlU^mUZW1WU8xUY-#fDwPOx#k(|A zD!f}RT6eLQ56lKRQ8qXAPU9j!;<7l1dPhdzX!Drnz$S=*w|G}5;AqxeA9&b>42@Q< z;p~ABwWxW|=g%!GK{e*x=64Heh(5WOSF!!ZK(^%ka07~!o&OWni5+hQQb%Wv84-6e zyh>^82r{QhD4VXWl8xerE_nQscaZ&>Wlm!LCi!F+(x{C`JbsYig?->ORmq32R8+37 z_nZ41P*a7Wy>-Igk&Bm&gA)m!>>lLbCEsE3q-Lt|`Gy6-@W-|@#~=3iYB4jcer-$; zD2ZLt*4lgRU}Tgi9d1D2W-aB*}wH{rBfA;|5Phmw15FMEba5w z$hx5FHkQ5z^_>Or6kn91slk*~aK3U>4jLuqDF5UbC&EZG;9(aJV zA&#Ga)nekY=7F*~aF#e~=R?!YfO}dn>3_v@8Zr?Hf7@uLoU4zm}xAy`*qh5{kIX zHk3nP@G-03_~X;j`?^}rM3*FRMeg-_j8`u~uzP~(3~@fcVwHyrpN#O?o}QdJ&$}-L zx>@?4EC!&5;mm;z6^9>twft#BXME33F-#>QkxY%F;XMuEWp8+VuVW~w91EjK1zzrc z?n?wkxFdf_d0*P&In@>-|#0{qnQ_-B>5!b^-e z!o~5sZl8K|ayPfOz-?Fyisw2+?F`tkK*#+)+}$izJT%~FW42wF``H7^J3sIXse~kw z>1~p1LD1tc_Ol<;u_!_B8dlS_vBsXn80_CyS3$J1Iz5BYTmF8Sl;e;U>Qmd~<#Q*c z(Y3Q~so?Q*k*j?1W9q%N;}`F7Am^RJm*ubI4R%{Lk5I6hvCTz zlk>ZK@Y|tEVHSfJsf9)LIA_DIW@!bmUv0HjKGHPRcxTudJ8}Q_uIUqHNhRQ)2S5TJ|=artWs#{Z|_En$$PSg%gKpqtm_@W{@FLr);8Ie);Tz}lcJ z)7R>sS!AzH(j^M;@Jum-@tm2=pd3CZ{66ML>0X;OGLt za1tefl?jESOS*@oZlO7dw{Igyf=CecZ}+hC)f0M^bl-xY*aU`Yq14!mzN#3tgbD$p zXkV3oq&T?G?n-fef7by=g04lV)0k(I)JB!q!`+NH5C3@dJG|3fK+JZmKO+;~*6*>^ z@HekUDa*=+&CkEBqI}!*;~X#NTkBN+low-lCdq!{{0+T_^XNTnwnQac2cPKiaG+LQSg~!jPcknlv z?yuUX6A;S7im*dJ*nOQhRy$rO9@p7;eW<`;uquhv>dh+Bm7sL3N6A)~AwjE|E?j1tgS*w6xCkDW_OKn7neObz>_`%>VU%xU<4|`~gH6-^U~% zgV>I=#_C9xL34uZ2V~{XAup4(*x)MrMsMAf5e7}&f*E__uID{uNlF7Mssf)iSDgwo zSu^H#=zyflLVd0Xc@#^C;kQ`)9g2PhaH6wspJ?0<@)7|GR^@Xe`Cc!@rTU})S+)Np zgz`}QG7`ecTrm;{bFBOOA?dgv&sipFkVBjySTuNgw(`mpX;vdk67$p;=ZW2-a~MwF z=$l#tJPQc2uL!TV5=*f!mP?=VDRQo!Drh1N+ShyA)F*3Sm;1ha&{8vpR-c6Qb$G?P zaD=elg^^Ymzx%d$*dOwoXu7Kej{9;d%fyUj16RwYlR0`?&2^rfjO#m6r7=aE-x$+zn78unk?mtlj0a!=1#+|} z2@W&mkM)e(g59hiArVRN?40mu{L4G^UeMd!ktqQT8gXbZ)o|)!u%IEWGpw| z@o4o3*($ytSSRScT_C!NvJtLl&VaNO!;z-wb@PM z8DD_a?^SNLfHn&~1KBeSzoIhK663DHkdf|RI!Tnl%0`#O%wx$R{p%4`0?8a~|CTv; zyDS!TtBc%csTs{;f0m=0v-0!x%ECyO>-1B&VA!?nBjLGeS^FN6%N&4`dkheHNw%PbmJTDUP{>sL|mF*N#I3=Xtbv}G`j^p|le}!=|dig6?-s^EEJ2a2RG*GyW z$zK&69HK3!N7|+^wUlp3a_*HJe?{SRCzc;YC?Q8jo|oRLmvw+&$MKa>=h=f9u?r?) z>*A1_&2I^WUGx(q-E~_-XORq}vi^+|geJ5+INs>{#pY6l-M76c&9aF~&TO0}I}T^K zjY6B^_!vnFLZbHD-0&6V7?sr^tA>fyB>ZY!QszR z*Kbj(BZz?lQSHKy#nK3NlucW86V$psFHbx{*@(Ia`_rhg(EmdDFx(o_5vtPTIhQ(TLUQHJk zaT<%u!toIMQcJE0{; z*9nkRdzk)TPUtEwn0~f)x&UdTDpJ1bl*(8lrHylUYzjSsA|R*l`Rl%#WB=GUWVv)R z1RWic`$S?Hw3b@9`L)s~4U76Bh)0UkiQjzYeowW%6^GGuCmryW{mo796Ve%rW8BLV zUO=jN$V|3}J(nb-?`0u<(&+10{I1?PXN&DNDeyl2;MOIh5rmza9`1BtIKK;h6tZ{S zIj1V=$=G*n%5Hh!%bzwaCHp&4z_j=aDG(c6r9H~BF9O+aj>CcJ$6uYLf1(E;r6v?D ztgrmg!2mqY02LGgQ!AaP9Yl;6ky0+)WYg%)+eS&IT@%p}e1y>b+ zC23^UsPESq+}HC+c_BP#9}XOu94ER4NLjga31^bUGN~3)l`mYx6WV%y9@fAbRPxAA?C)6 z%(9N}6?|$7s)MMFmc0b?jqxUG8*jJs3Q+=+6{)$O`s5byhVq;ZRHHj7KBP6|9x`hz zi_tr-ve50smXszVCvW27Lj9|b4RuFJ*&8YdQz1y^a}I9P?i}rtRk`){E=X$yTr ziy|lIp8vpi7+D^DK|d`bpYX41F-Ili%9K;)B=KVL*rV~6yba+V&yF-cU?6##!`E8azg9{%XnuWs`F`&1m;` z)Lh165a7~vcP~d``(K=7_m1bi7X5Z?;%ycJa@|Xg@K2^UPWBJ$Nee3lZ({nHz7u@a zzm01w@f$(N9>^l{S^NHxhuT9g0nQV-Crc6TtOl}Uw98?ML$UCHQ2Q9op|7m>LfOSU zqcPHnQ?aDQujhO~MJCE-fG(+y$L!*-t`d4W38V{cxsW-K3-LH0 zk>%kh8)M;8u%N<9KVMYJxSSwWT8LmvUsID#qi(Pme=W9V%v-?kuKkqx=Jvl0jHc5h zP_M%#=e6*UmGSgG>T7C_pYNYTt<*1??4}8Hr1(?b4DPgZJOCHS(BTOgDl5-~viY2B z35Q1)ofn7w>~Az2Z$HxXq~v~TPFKO}x4(ccfAnpFASfO_pS}V94qX$8X0$Io&tG%F zigpHP)%&b5nC-8@n;aOw{V~A&JY#jB}=PA*yJH#3Khr_doDH#os`~38#1b z$9tk1=b-xYDP%Z*`WWuG`m^E*eIh(LArWp6mIfq(p>@H>o8cdGm_<%@l@x+)p)%|<|f z41c9vwF&+w?C}LsToIiRP%21;JSplEGT`m_$)%?eX;Rmz+lyG$24iKY{4rh?%KnxG zB*Ij!$elvfZf@+L$mMR!<0e?M=6d!Fri9NM@tWo%D)oB7vq zz5T+s=<>gVG$erZp$TD(%VH5{V?IS*op2}B`U~5Wz!BLOLGostZ#M**$k1U0ZpN7d zVSgF$1V}kLIr)?~H8)3qw8{NdvS_5b4ZMx!%S*ooh(IWZU`jURk{^A!Vg%s*$PLCG zu`=!y`IR>LWVIW2&ynm|cj1{kQ{s^ORFZX_}U{|uC@twx>~<5{9YrvaM%t#)8X2CjvxcEGQ9+{O;NyNxq@s5u=!UUpuO-m9fWLF z9aEFq0&@cKPfXHn#Af17CFZ#c&$19W`{nni23|#TBSD$~g2(-&&po zqMmSIyjhKueo1$@r_|= zm_sgDT*#heArtL?DdFP>Q++$Bojm!R_c1*@iXUvDV$OFb#2r&3Z;H4UKG%@p6^TltYd_HXTj!m+z zGJ!ofF8$Gj{P`A5k*pm+gK}zb6h>0V`dZVwac7(9`;!GS`?@&{%GEnMy!SG}Fjq#b2SOm$ z0kevwOFeP=^!vKwUGorIq!o#MTo!&;NNh2P)OOvsFYB!0;qkvJRXzI0F5f)LjYW!# zS06i2(8UR#Ele}6>{qb+{n?HXf9;kFCs%V!?UWp~f6IQ>rRnKuf`XyohW;G8(?kZi z?O0c)JBhM=QufI8V9s|-L~^?C#kIImdz7uWjyhcj=nHte-7fnI)Lfw}3u9}Ga>lJA z1=l}cJ{1EK)%S>{3O-tl0`con1f!j9lPk82>*eJ|E<8^eRrk5}O4 z$E)k_PVU9nOwQBoJT(E>7Pq{TU?&`P#Yw1#qkSaM!Ar4H zf8IE4*6o$$bfr7s4~v5j{;4f(fkdx=WzfBHX!BfE;3YV6ocH7Edvl&A$_Z2b6WpB# zui?Db6AohyV?`;cyG3?=S2{X7&B1|$$Ha{Bc6$DpXasVmGr%kuKIprq7_XGBd_ss4 zQUz%sxnbH*N_%}v{e)U6%J#~YE5HrUd_`ZMEBi#*jMt`@n z{eoX4bp8Ql$&k)CHDo{o^ZWZ(e${fGsN{X!74uE(2r-HJ@t+_Z!I4!BSEvc%4ih_j zbEOf%DHwx&Wsql|qlL!^41W;-$v!RE*xXn{>AtJmc|V~W!wPT&H!QQMAAy)AbsU_;cEJ% zG)3u2l#TBO#4?K&6w0O|Ixzj;2cM3N3C|A~yiy51=R;=*go1M~j1TL!hq%LB)gqGxA-C8kNw zp^}M>B4{A3U@9KSVP?=Ms@q>GGX*`@+$R{Bn96SPsb5zD>hE;zg=J7G86o|U?`0fJ z?0W^H0Q5JNqrw#=hfZ8%ghBEm(4lSf(yC3|Pn<)|XBBz?c;npk*<`-H+JB0Y%8IJV z0y@YpmO%GNAUOlyErp`GGGO#{^ZDV>_pLkW(q0cpx)ACu?hmyavnz;b0vQg!c_cY=LemK86nljS8zwqggaX@zL^!1nvnJF8I0RYf7S^Wie z{z?TYPy>h^Oi>YOgp7z8h+YgS{4X=ytqI=Cle!hiAuFrMp^=?F# z&_vHlU5|398%(3pUI3cuM)Md0=CZOfY%A$W;cuj(kAUB0)K?>eD)ew>4Hn9Q@`pz0 zN++tnWS0YBi16zD+n`mcq9pWPAYlqedNVqycl^1b>wYUAdgNG6@`;TiE`fd3VQAQS6wx0wg;Dj+U z(dze#vmiwIgva0gg$zM=%VQy}yvilr_NxasKt?TW(RpynVH0KBCc0+lHW!lIwxuPj zV`gS%b^e~Ku_7>FnZvOBlY;2m<(UdnY+lMm=PPSy7{;96-^gBAF6vZrvb4|AJ^AfM z>0Vn%=pQHXG*|`C0uf*+5LR1HJH{}vurvcXCCiD6&U1P!Z$rS(G_$71(*xmMR}PJW zaVzk<&>@0z{A;S0q}cW-YtC0y#K&;!XchjR`%8Y9BS&ZyZq)nrryckE3%pF z#tkwg6aNaP$bY`0nlr=UxjmQ^1~OX|ATJ;8pELX;5k=G8C72LUh(^kvxRA^=i!i@l z)`y2$-26;mWQJ@%9g~sc%^rW1eUh)Y2Ag%QRag`_UCd#?I?6zTK7TZbw=EQ*FrI&8 zaq1^Y&I$-)J+BHctW^{@%ydOpjiCK9GYWu7`xSN2KEQ=j)bdIeijl`_|Bb*0v=fPwQGF&7Dxqh^{?AD*F=<& zh=Ay0X9VeJI_UOvYJNH*v+>1`XfoMv37#_Ua2`-xCajG`4(E#` zh5dizkYxEU(b!3nCF!LHNEe_Ax1u?OH;CU=0B+287_B-z`bVI)S+|*ZhGB4 z4rw3gUP=%=gt#NE?s{Z4Hz!BI(09cg$rSp%W-FiEw5TY7da)7QsDVySL2UdOp zw&=Hk%9j~IECU~%+C|1@24D6MF2KP4$Jy2mHo{BhueFP;!lpi!D60>(!|u(tDGWao z%dMf|-w%}dgK4Nei2f5IAOs!c&5y5&Q)kxT`|0uRwFPQ0`sNs}9$GBhENI8U^KW0J zk-31!x8wk`mPhBX3)CR0C=4kP)ck4T~^3Q{7wcba3 z?Nhl%*AIz}klHjCk=DFIt&0QP>>L3`&`oS1@})_ou#}Hu;~m19@heT*{)+4%=Eb!S z4G;4;dXY8^e^p4GgXC0kZT$ZL6QBgnLB%XLguePx$RzT5tK`9P!J%Kz3%?o>Yoc+s z-A7|*+zJd#r-60CNnjRG5g-oP`tGc;qDR1@@BRJF%otE2X2YJQI3|u=LP+!o(vJ11 z?`cPL#MJoVnt>>`JW%uatf~sEWe?o~=dAHD9d*p2EuOWc-%-BUv7I8f23x%`?SSMU z%277e8pi$~j3C9$)z`@|O;1hLU|$x#XJOp>Hd&ni)>Yu9Vg#z_@Zn*Tc5ZgR>;*-F zckT{s;$g(v_v_M*YNw3O`E4!xiQ=iU^~#&;BJ`Pj0p5tDcMFYL@m0v4BVQ6@-+f5% zS<*p5cRMGQddg<*d7G{V%S7V&D;SA^xQjqeJug3Nvh4I@_PJ5D@34AUx5oJ>ekp=a zsZXD(v*xtSCsz81%;O==t^E=vbgz&Y5o0u2y|a4M?L3tOuZCgrgm%H>4Es& zAEF$`yMOwUlx2okBhUAAWJmD)1a4-x-8z`#0dfd9_G~YGkg6)M?cq#3K*hHA0kNm5 z9$+%&V2+u3jV+4c8k#761_6PR3GV)f8fjP{hy0kXPlcd4Gc7{8IzmM#ThL}wMWlO` zjrJcp85yB;v2l8&uv3Hk>R($~IOBh6 z_6s60fXL>mj+J$%p{_#iHd@#`SpJjbzFMCTgrN&a8LDiQH3U~M>H%jtSWb)!A{f8c zkJ%~6ZI{NC2_y_08<~80*;e=n)iBkQ)=Hm596z``doWpWtn0;$*mm66poRgDSE_&S z`niSLG<<#B&fdECYa~x&mJ6E4mNqh||8;n@#?UHjWY?m}va+0RCS!WEoSaQ8W7z~V zi;#YG^QUU2#vd2@SY?M-|GLH4@53lR93ajhg*B1+M9OP=e zx42&MFnzh~j+;S3{X=ly-wUH#{>LK|fML)yYu44JKkjab&HR4!sNe`R&6<4|sv6XH z$THndt{)wF`|_T|>|VC0+{*+t>Yt>LY^**cmtz&!UsE9+jcR|tmn!f(z^3KRAg{(G zCRY8y_XlGKhJT`N9Z0fQgT$%uiS<==4KVRF8yA+jMf|>h(XJ z0yKg!zN`xT*7mut!_+u!oT%NaSjLc6ht9m8!RkXe(g23JPW0`Q#FJ$_4Pk@;x2l9^MEw;CA-zy3@{wVsN)uzn5E1%}#7MD!)X z8pozx_w7ht4GmS2BY5Fe+NG+snTW;+mbFN&v%P>Z2xTk2=lP*+YXBu`I`x6`zU%I8 zFHX*iUiO&*Q#=!^c`jNdUSx}C zg+gppZRQ!BK8By<2uCO=^RCfKnM+)W4O@HxFn<3Di7y7y=8tqL+;0?{L>Wju_8N#= zU7iEOcpME_7mftyFDYl9bFc2mH_wYOz+ur%^JCQ=#w6yadEh1DxjpSKssc3K4T43( z*Ls;x3f|Fvw2z{7>QD}k*R>c){8|K|%N?5lM77FCBvC*EhLf|P>j$R_bRLHGIymtWY*g3sEs z4-biL%7F|&>qyzD{S?}rAUom#!ODA;u$T_^z$NFned#60zA9A?9d~?*Mw$VhHY{?5 znC0p$1OxmE)rmA(v0-%k)^4xACJ64hJMYG-ZJf?R65nL$l@QUZmF#h;oksjk+iw$r z)Ob;EES8_09a(k|l7Dx4gNv28=jozo31QE&f&QH!X%A zq?khiIr`~((nK}`!|$~;6^6*70<)dCu%lHgAUvnyV%du)nO^dC<>+3zi+%gl`fq3) z+8rM(A23EpRr&O3lw4-&L1I-hX$EBkV*jrN=dAvR{mDT83c z4J5}`E=x}W!92%rZ%?;(+Elj-j?n^@r+G0?B@03h2gIt@nzF7Ns%{s9H$;@=6!vp>7FHkX;C8fPEq>;6y9{dHuNaPpLLIPerdI(oX0~ku}%19|CD4liP ze#0g^g?h76HotH*rU`RR@oZcu+}P+7ks&FZ;03#4{PF%>XCNW&8-wl7vW|3Q@xMKxB7k*>YTn!1lUfskMSlR|&lM1U%MR|m&%*Z21ks5B@wlcL!1gTR)$ZXLzm&M@8k+Z2pafU|+E>*E z&@UhZGNC+)8z9o-{P4A9K;lhEJTvUhu?5z7d5y+eA_(3hXCAyCMM6yv5OQ`w%R&;Q zL&zI%yV~-sWulKJqGx1dK5=h#`8r^wYmr{WU1jfpa1^oh#JVO%cOcFXfWs%{Ako}^ zNem<$zuQmv4gl^IE8_KHRFs`qyfQ)e+>upWCa_~JObtr2>aMbjkB;A9K;hH+8jemQ zB`SC3t{tBvikf&CH(H_1*m;sGw1AA_yxxky2hl4*jK`qXyZP?P&UpFXA|bTCsN+M2 zR&>3^Xp`*p6-Cf9+wDs@IV_Zu7NUd@M}c#{yy4H5fU;HZj=Fgh)!5K5CrA!57<7k( z=lqq+*fK!3-L5zP67XWr78dyLE} z=Le*Mj-B@0dQmYM0KbQzT^OV~2R=P$+UE=a|IgOZ&RjhKodUCa$}cM_gfjsbRAy#? z`t7D|g@DFZuj#|6Tl)`r&N_-|UE=gx`#9*ml<8+WF^F9rh1vtEQ%6upDc@VFPS*~c z#N(g3HuTNWHlY7B$f1Z0R-l~7Ei+7da!{oQl%)l1xw z`^)vx0WF{D#>=rHWp7>fT5_Mw#7#tzWuY^+^N0eqJ}!7*9Dl8?t2;s3@e{g6vZvKv zU4TNhpdS>?-ZzOT!|gyM)ZmR{K|OQH3qe{-9E@1GxSnYaRQY(VELU&kQZJ^kN%7{7 zf)sGVkSHV-sr&yJu0;)_;wg?1i*C@U>^9AmfzSndy z^0v}ynz^9d=jFi4$~xaFFxX(7{&=*q`EjnS`L+3ha<^GdNMhzVUBym8u^9y1$(D&t z_K5hhTT;lf5*0dy>dXk(@O_p>$8*#ACi|}V_x;5$5FU8m>`+aELi1!p<<^riOMgH9 zWLSTyXP-5=TRWW`QPtBBvjMIEmjk9);$3>i%Ry>gSuo`s)vr@b^^&;@nGPvyt<$3!75l({)XRa@`fG=|> zZEDIc(I*RSpcNUrT9R^}s)*OL?tpbq-s3fo_gfkKS8P+eTfBH_v{UL9;B}%2#9F66 z-C0{X;nx3IAVab6Qs5mpM&iOa-h|yvM%O$=mm0lJ^zg;Ph}mS7s$gVtX40eC=$OVP zW%;kwMp2FMEN_50m%J!(d^^KwAES z%R2M(=;zJj*M8Qh7v(}F|H6P~A1-A63)UM_PHLsjb(z5Nn@3wSQ`7x;2X(K{gNbt(eE0=@E%Ud?) z770*`WVFx$zWu%>h+^V7cn|fVMkpL|`pm;8CrRF4C^|oq+Fv0Mr6_GK^nE~G4Bk{I zsH~n8XV#EJoizj9G3Zs;Ki*$fXi*bjvj#a(VD%K&fKRqR!+VD$MRU4UP%uJiM4&PJ zctUeob3ohLBVyzrAEj#E7B6U6%$_ij`=EL#30jXDVU6E96N%fd;PGv~K%xroTvv{c znr?~xS+=#1Zdb_PKma&bNJZMVy4>~uG4|C_QE1)UR|F{uMMOXlrKCg}qy~{Lr5hxN z?#=;4Q5pehB&EAsy1P^9mTvgYpkBTA@~+?ahpurg8BXl8^V!e-Ttn{`iI(^n{u9#uTKc|Svo zR@fx|dOK^aUjm@wn7KCJroT;H^_KGavH6)VrZw$elNY$s++0bYOR%eu8nHM(8o7gy zOB`8d45HhkIO8(A7=luhk@RA`kM}5y%qwLsVk!vgtD`G&WLJM>;ADqy172g(EkN*m zyp!Vb5?iM1JUFKK(J^x5>eIdcl8v0Hx(;;IvCn}n@hlh4Rxcuo96L5_P^F+y!B~>7; z`+NWB`y)h6ES;pT%u`6-!4IM;Tt0C98Z!A@&b*_p_)eQDPF8h~}e%X;%AOT3gBYuhnVZG2ztlO2x&%3J6^JE2g+rmzr?kbm4U2tBYyddev z`uvR{NAO0P&uz1cO)q9>H$*{JceDhII7J^IcQQ2TZg#Z4d{cR}np#8NZ1ULB9H};1jg)&ysS2(QZ+c&MX5B7l$S?fGW2%!_! zO@|xE&sP0E{2rG1u2_0dfitbi((8($gU8swAMGdu5SkZP*@4eGu>i7^u^Al1nNLH$ z3PpEO4-4qtWXvlxo0=rLW78`_iJ!WjB_k_KhC?a&0oc}y+P|PpGJ*#W7^&LfijIah z+b<&(fJ0Q-I$^{4g=OpQrVJZSTCa;lB2Id+@z# zmc4V;PaQt;Kb=&;i>BH`Q9sZJs&(KFT#eZ*F|3xNsZ+Okqdl{NueHw^^Z-4OcX*Ok z+@CJgFMH&8!CX`_WR+xLHDi`$xLXXmAiefmf^E*f@(a=3YlY_`0fo0ul`en3nG!yyj_c%m-4&HoS}H(qA4JUU2rYAXG7L~qPU^r<#=%|0 zUIv6&ymq|Q&s*}>#!F>n4?U33xdg7b6&ntSf}AO3hohldZ*T82UHKQhlM89B$^~Ge zh20=Au3|!Qs^-0r9tzb+w06h+2|Jr|F%c09eMIS%l=)Of3Ih{RX9)(mP;p}W=_@Z* za8~6L1TpqGEPDj-T7dUUv0S1Yi6$(AZz}t}6Kt$7O_pXGPca|b^I&PR(y6daF7^W1 z1W;G9bZO2fV8rD6R#okW+dvlH<#zw#;kk&=5pO@X>%|h& zIhlrIp+gBgbuK!;u-{&RMG=T>)x5e}`h9tM!(s*F6dt{(g%JhiNv|pEoe3K43mas> zW0w`0=7Y-~C^eF-==UGE!7Qn}62|bpQszX+?TQ!1@puszNJD$X1NTZ-If# z3qDcm?*d3@rvM(c9!tb&`xXrittpwYHOgjCDIS4SHm(t5`~-CQbG2l)0YHcPYCAZz zxfMc(T6j=>e#~n}A_e@1)v4;K z%Jt3RZKup7|8VkC?;LoEz zqGqiwFL5D`wyw?BbCK7Jq8e&Wl@^%r&H2jB`Y6slhT(Zc$-PkCWsNCMoCf_BD; zTZ7a+^Hrxl5`Qi_J9}+*yRH8Ip|o_4H&!J_zbmu3h{6Ewbgap>u zl+;|JRN5OaCmNSlc8mq!f(fTvbG+v}r>vwCUaJ=YlsWqME4Y-Pxt;`@_)1pFSBpfv zKa!FU$gx|E4z48R&m~_8_wqWJ&wstus{Pt)SsL}?=3w?WOSJ7nPu3=B`DG$N!*Rt9 zl&`St(}{1^;1#KFk^szDq9RRkLFWEz<3E@AT#kf^M#M|JGthJ>QGpKgC^tcMb}ko* zaiJkTZmbtB55m@0c;ZBNnA{IRt8xiqNsO0Rkn11Gyth7(ob0cJY*L{kG)5wZ%G2Vj zV!RInUlcD0=smc5G2-Q~D}-o15ur4ACoJFfYe4GQZZN{6nv+`p#_H5!s~6W>6>x^% zYz@Ni{5SFJ4v~WqZnOgWt9&wYmhZ?xa$^p>>a5kzVoEqQ(6-Z4(D$>N;9aVJ!AOBb z+SGdpfxWrogJb+>+dO0z$-@PM_uJgv(#269_p7I%UVUWE{qXROee4sG+qf57`X*13 zA{f-Js4fN)RG92d}oYoZZfcNfuM3+XbII&GcX>$_#Fsn->=9)9#F%dsTVj;0pQlW>#y7RZm2e;W!JW0IbGeaJ%2A>f9HsgM^D6OASB zT1D7C1wD-!A*6>Vx7$P+vHp;wA3q9GJ^X-|g`(}_kYy4ewcy`9m22f){m_Iw-^Pm< za*+P?g1n&S9H`58GVpeA6#u`5`o6RGqW`hVz?)!|C!RP~v#l|({DF#n(LgTV3KD6V zY4#tYHLO0p-jp|Y#L0Bk&+2Sd3!k^-fsw>xw}h*<;;&2KL~M^j14S-N;_OA>r-2zQg&()pMp7$5u&Am8!D0nd;Md)zGC`b;1s+1>g0?!}I>%o0| zM8H!lA9OO)G#V5bp2#`Pe@xUn)9z_`;J(sf!20u8%+dQlN0XVk$%q*a_DCJetImE% zA0rN^@RVdYVk7uge*>)3VlV>q0sp$>-z&C9Rh=Z|zvkZ+x^w*$i>5N-kn42*y)?d+ ze$3s`t~cR4?6=_m`4MSRC!e=Yb0NHe84%K6XTQ! z0qh)TivDOnj*%>)#->=mmD?ZrOy!9K6b1?|H)2)DMp3mis}Kk8K;kc}2trQK3XEf^ zwe@F3Jt>Z+G;aw{|K`mi{!D!g6e;W#&SOU$kuSB6UxKqB5eDyt&*KHrg+jUb3-%EG z4tOtfGZDSX+G*=hcm!&*h9zv^ZOUT%<2(Wa5Dbh=Ecf@Fx7)4R=~@oyz5#@j z&H2yVdJzW~k8>^octS|7AQ}!z1ig^4N}6#nNY+d5eZ#vAfzi6A{33z)CQ-8}LAJ?i zHV@~#d8OjMVo)Nm^e1k}2()2&@h*SVad49`5kU)3bO9X*;b%IZ3a=*H{kUB%#kh?+ zrQYK++6jF2=m$elmXP&wC!Z-tz~Hf8?oYHy1Ih^}S#+Qk`1iJdeL{Ik!XYs0_j1H? zdm@~#pf~I2Z0CW)%V)3;A%+_%@Jy^QGiY@SB#S`ZhGSiy0^>sPj=<#aM+REYVnBc1 zcZG?F`}_V~Jw!T6sWPVQYjL1u^^=N!^w0avgEQ4_t-BeD7)H1jEWbkDp7X&GJV<(w z(?~C&x&h=bD=ZAO-2PYo5NW#S-dQ{RDEqqAu{^K-UG{bE#&3Ri3e3ql=nsD2?S`ZW zXYu=pH|=OR89@AdjapK1>pd-&Ef`CAS^#A_CQB@X^LUHktcA@gX}e*mZ2QPiB$dm0 z`{l%wAC?NpabU`1+WqK9qJ2qo((#f^_`Ido=C9JcDJ+r)RC%D{zi4|I_}yLp_ia}E5M`!0CanQZgF zI5WTr?BNJoHAK;lNGk*d3$SL<1>>TN>K=Z%Ia1Jh#>XnCUe|S=RMej~6A{(9*B|Gs zbfA|jiSe_hmXT0_l^Khda>i~)L|2*Ya)Nzc1Tw725te3LRC19{4 zdK#NnbW-%WQ-${ka=N@=uh_*GhdkE8!~oxg4_J5ITM>m{TL*Lvh4Qg3Alh5n*J zSVIGWiDVOoTWe7~@KUxOIf4gF31Q;d&B%PMez00#AxmNeC! zwri(H@L;&Q={_KVT<+A{J`GEfmN)zyP96e|e}j!#%n_rrmwPY1_&sR6+p<~7`Gqp@ zL*Y76^#huIMi|zZz8@mH{nZ~`Y z;A~$1Zz-k8dXS4Mm;IH>NMVl+-`f}BqKx1?ot^X)|L?DZRG^$B*?Dn&7nkhrYvEk{ zK#v#JyoE%*wT7pAqw8VTe#~3PpH7YPDWO{|kuu4)Ivtwh`h~>-()a=?Yb}gwpC>Sr z^HhycDs(qiBTK2tZzDe`B}EM0B?#b45!%V!6(Ay*$5{GB|MKTOknkb)G6l_^>F3Sm zMegt}Ua$XZPM!f+$w6T#^?6h$q;Ld&-1SxPx@s;jryg8c4fEId-8&fL_j>W$V%B>? z-dIV`jbIr@M2G^$s;Z+5S@{wV<0@roY9xojYL4_D+qtkg31?v(7)ut4Rkps7zi6s_ zP@^X3Bw}34y-er$ISE^ru^gd;xqZjRfEvLjUA{Nj#%Ls0`wgvHk+@a+tq44loW_d# zzZh7-qJA%h>|@P9v2JrsQyw`TT}yxa02?_ED~ZMymeTo^tW?+q8|P!HI6EBgmMnt{ zp26?DS2$g!yW)R;2MM+*EWuAC)a^u((|95@lznbYm%2Gw_H52EcCVYqXfk2IN$Odp zmz%yEoxw1(fSo#b7sta$H>#n`I?12n&iQy<_?#Pi+%{v)s7ZES#WBi1;Lbfk2?YE{^16z~ozRpyDy)6!a; zerTPH&iXL(a&%`B=SB8cUR4FS#dq^ROp`~}Igk17OC>Io0ICd+A3o35lPI0`KqsT5 z6oS|Az-)Mi;UGhxB-7lF#?sCjmrashk8BOBoU)`p+je2ibSLN{LCx3{R@{!PAuv*1 z!u@4{;U3e^t&&{%-5#65ER#=1ZQhErKih_PFZ3tTpSv0ofMevYe8h)y$pbik&q)pM zV8$K#zwaDkj3$0skQ_CBf1tOPQ_b6G5Rg!|;Q{GW<>fqkjMp81A$#Xb^G|}pGw;z_ zTjZa{Px9*lnvh`}Xm6soGaS)TVxhf19i8=F93-rDKq)hq4PVd)avk+^b>^~J#-zM@ zD20Y(wMxDy^Q3+s`sdB-K{W*auUM)IQSZfJprfS1joy1Wd|}6z^#idQv4>&ZPk$BZyGtkV{+@xnY5p(vy0%fH&riv zfoZWp9yLBAKVUQ6y|}QjwG5h;BUGcr6^7&bmyfC_i9MBdxNcm>NC1_~pW6g)4H)pn0S zxV_oC{dN}lY%f&P`u8i{r0zB{58WY*z%5)dnS8Du-ZCF{&j)E_v63=gy)HPH!mzCc zcH`~a8USd&z;$wfG2ex=0Fliz2Yhb;64JV_E%EpY3o-8hxnc-xMkNJKf}UiteM=^P zs&e9f-SKQo+4+a?KiC@op+mrLs6c@;0^xIW58duNw0fVw*sKSfU{|JAL;zqkS2IbK zk>b_ukjunuKI2Zz$Zhz-gwlpYzzii>Zrprc493B?!c%Sy4Go`cZw%U!3i*BLNf1(4 z0l3fT`1uy#01W;uTFM{kG%6=G^52DMXyS-MeDwnm2kpr+4ka{wS+aJ1KjYt?Vn7@` z@2xZ2R%&Tm%q)WdD#+nG&tbIob;S41K1N*ky-XhAw-|hpR&B>E6yLjfHV=2y8ot~d zl1lyTGdm|&MNjoyvx76;P^2#TNTa`hJIXWf5KkN5@(VAg<1>;x1nOxW&>NkMshq9O zJyLF$oyzlNK+#thWUArqkR|1`py^({(y;}A+w_;QL7Pi3Kz)@TKcu4z0R^{VSvO`u zl1apf=noI_tNYzLo?DkBJ8#SLcBHD@P}By*?M%Y|=VfZb63GI8X0U!xvga#OVE%)) z?QiAsx0-ot0`qAnQ>rNSBU_=g_g*H$TC-~odoMP3K2nbL7gg)F|4bK4Rxclf{RzT5 zEmCR*Lj(e`{$VFX+**%2zPUF91RCl+8r7elKSOG`*^lB~DQK+tmPDWg=SF~QR)%t3lKAu?)6OAdc+tt>}-8SFwGrWc38V$&5354Puh*1Zb z{b`*3+p`BW4n*)?D7nlAJ$9xRPFumwdxG#MRnJ&6cI)#9i!S{EaG=VCHTki2K{2mI zqB1O&LPHd#%UnNZ92&b(jr9)fzO$1@UOStsb>`T4wR$bP6mQ(cCYdI?U{~2$WG_q%x)*=nnlDG+r&eY<}0v zB)L3THm~=y`;sZn2s3w))<(=*=w|;`C4YPxMyN#AY3`7^-CXk(pTXOBVm8nKM|5s` zzl75d`4ZbR-JW)PLjmH7RPp)orU}%9P3@m0 z|37r{g*_E^g)s;7Ee$fMp&{!FSKps(s?t-hRu(Iah{r9o>`Rp9SV=VS^;n6UsFO6* zSKv0YCg1)NF;{3gxM=c8{woWjw4l4Dgnd{L_)9Wlz!pi*ZMf$I^Ttu~8?h;_r>wO1 zh;LCvXi8XJGmH|vnPEW|u@I;!v0aj<@XMC}{oLT|AwY?;7_v)VAKg zUBOb_TE+j;Ar)7PPW=*Un2Rk1DUf87NZ78&nj-5lGt02EPY@%Hxk0@O+Wgj-`a`)^ z4$l>+_9f|p-&u+!OT|t?WvshRV`2DPJ55A{YC;-0?M*dJm{Si_*ft%^g&(Smqr&FV z1{1^UC-0qoM+PIt*N;v1RzY8STWEkOsC9;@*-Z>ocLtG*&HA!Ue&@C8iUNTD_%$=b z2sS_$4T?Jwne%R^c-0325W=0;0NL6Miq8hwGBPrxa42>5J>z*$d1K}kJHWr$?xmYb z*_~<>ak4$u8P7NIypPhVQS7j&lTX2$OfmQ^#J5k_gT?RJHrLGz17d}}%XGUtaeM;PG+$k=sI&{9)Q8Hd$-eIwq^lk0!A4ZkWVs5eCp(!$iC3H52(&&4g#f%g+kZSN8 zrwDd2MQKVrxXL2Qk2=VHvtwI0C)q)DgywG-?@#0Gi)PK{CR}A94_hrV(@R)+wf%Gn zQ_QsL^Rr2}%yq27uf|PJ{?G}3IQ8xjE+k9Kz7t%1G>KjOOi165Y+TPWlhRs5iLNsj zVeix9qYc6V%avK_k-Q$9ZVz)07N!{LfSxyn=)+lO!Tx75bP6$531?a{qyd%)9k>}U zKFdgQ2+X&K<7nE}-w3+DMW|FJG&1e0QdFuZ*o z-d*FG4O-}Wp11oE!D|C?InHc~Ks0W#~>b~{gTm*_Q=CmR~NAES} z?xcl4st>_Qn4lDoVvZL$IaQNoaKa|bmR5O}iH7$r_N@Zr(p58u-bb7}$Q2TW20bbR zmNWG?N2-!Gd83#MvDE*==Kj;ou-xujeaG~gg1xT`QNIEg+J5pV`A8h+s@z!6zWe4JDdYu zO}8=1*@Le^!9<2xt`HuVqh_F<5<#=UnQqfvE1wE5T>ESxuw6WcO9>!@iO(qluNj>X zmg&Jk0&pT$&F&*Yu^4(?gv*ht>J zq@NdV0D=^1Qh8=DJ9mhp?q9X*2#{3MK8|8^=z79K*LS6~i%0Q3mK1&Pa$5KCbxOqq zC;RC_%)GHG7%tWFhC^EyF^9$MAcen@8)pn@cLd@xvJpJw1T(kIhf{I@;mhH2diK*S zH_%`EE-P$aEZ-n0j6u7x8Nfhw&GrGdz4?U@(cDxMXiK1mD`{STYcEZSM6C>eh&6)J z+Ov6=5s@c$=%-HYK~hGu9;8KLG8;XJhVkW?sa3eO5wg`^qV8Ryd?4@90kV!_h*y>5 zm^cboMunP&w)9j=H_zNuSN!-TJnQohBlzQ=&{KrNHMrJcW`}E>+EO zkFwV2`o0Z1^cQPn1&z_uhpefHw?sTnG52IaBI=uMFnc0mE2-SfZ8r5Su+KGD!qyn0 z8solQ^LrGsa7erd3m}Bp0uAiV!1$aZ0Q5{?9VVwZ=yKAc-?rzn?B+vmLB8iatw9-q z@4?dZITr&V5I)$3qKkIgJXO%)`&+W(GW=iLEpy6kP14;>KL&Svbgq$rA&v=Y~ zhCoJi8Umt`^lq!A`tRNR{v<+W{=H{ycG+o*Jey?a-it`XlcD#9vt?GII(?2(GU;1S zE|DH!#K=k^u5Xx^^ubXmJ2V1)5u#tQjUS%t68dpAWiq~lhQ9C_O+&?z^{m{NI*h?Z zRCNpes=F@ow!sTWDDTSxsmt1%kl&BxuV^EPHao`Bu&T>+3CmMSpFxoFM2M z1YXH=Mka|T49(UnnZ>OvL#jBlAm!b+=jA_0q!@gk%4iTxN^yYyL!8hs!e&ineud z?C+mu`sY6b{(`mB%D5!^)39rMFkkg@h-I_E+e2igH^6+^I4Y)$koQcCCo^yfOgGK zt@_L_tNP3_oYh46v;j`KF#NrW%6i{Q#MT) z9&zSdgFnZx|Kk8QZvdL)4iyV<%}1D`#p&JG@5bEc+;4+gYC@fryPxby%WH}BY$;PI zf6^ePV)Zv_-yVxGHA4`VAbYOGE`X7JGNm@RRlhc88$dp)Ch!EhPmeX<_KA{Nt#Cd? z%io9BKJvr*V^mTKL}_7?o?3!T`Fz6xYARaV>(B3UI~F*DW~D1_@h(quD3m#h_~Q(& zWX|s&j1eX2zwE2VIaxRqEj0)#R`y-z=-r2=upk=W^)5ODewT^5UFW5S02Og3>%G2Y zOQ2PDr_q+=YYCS9sV)PDZN}7$Y5zTZVryckXQ^$u)| z!N(3rhDNkX)q^|9?wt5>P~K|I^o;ArP}Db-sf**IF}3xK_YjlzdU;a zEw($iE;p3WlkYp7=?F{H8GRL`hpicgQV<1+_hczw&3msFO~J;-Hl3*75kY=|mdk_2 zVrO{E`>kO^l{H5bkhUVVBdhp6O}=`bK2So_EpSAvR?R|pBL`4p`c@q7jqOH$*}jF- zJ%!+Tel1FivUTZFp~m*Dshan%AL5OoC*ovtX-ay2tdW~2m>i?_fH#X_w=?`Q6$&zZ zdN52i@!fDfo7(Uy&q`b<8nU!YqpwQYglz1lTvX4rc#kMX-$x-CSaMNgrC#4Qh=hZ2 zI@=5!8&HN69~VpOsmoC)Q&AGjFnik4SKOD9tbANyb=)*DxAlEz%bq#Jg(Tn>g7@`7 zK)lj?yirXL{=BfYVrlEo`+Yy7U6wa;L?=pGXPu?}%$_TenDQ&MxSIsy$<>pLg&HYWR`=_p? zqw7vhPvv1^=Z~89!AV@=u91yJrC;doO$i8?F~Sx|@3@t{b4@>r#P`v5KdT$g9yhz# zdejilBjlr#O2g8_Z_*At_{BhpjYpN)17AQuN$EZ)h99K1mDIJmd()v zS)~sEOAUgKP?yf6q@?&Z(A+M9546S9O8}9#95qNej1^)Eeyb^=t{ww@{1z2fL=yKY zLd>)iePy5VlyGs5axFk=%D_Iq7CMy>$!OXMKbYhlnHd`omQ)KO4)jZ0AQ&R*T|3Dl zRW9zXlO9T+>I^SvA2NEH&XGWpbXl~u1PaBa$pGQ|S1KJOvRx-znIz2x>zGg9L@YC{ zX&+b6z5bXuDjTb$v6@TMS>nl*UX>XVWI}iBptT>}H+M+S*-)Rku)jz*$GA}SPOtp% zIW2fCB|K7+G$?u-%uQxmwa_WDgV*JSTZicL34D{>16EFm=b&aqx-J zc=$2sWX{#mADS3n1@vhbRIb&giA)_gGT=>haNOWo@@h5crQB?~cO1(EkDjA=Srj^> zf(ZAPxUI}ybD8rib?<6B_+ysUIig3BYVzkK6I;IHAy*8J#|!Pd>`6g+U=xD6trGcY zi7H*grXh!QY09O0t2Yl_4G>JpN1X4j{z)D2_hG~Sf^|-a+v~k$gUn1(>+IYj4fM*`6Vp`g8egt|uXh{Wq0su$WahL#O-`&~>5ZkE3*)_}>L7IRD zq+eKI&0caGCo~M65SrWF)7!Xq^B{1ZdbFCaxTou@YF=-fYA`$YAas8*hw!DmkA4mC zijD?N{{k#4mFdvV^ufB}&IsB&doOvADT^ z#$O!PCB#L!o#Fi<9-jRItYgXxgRN@eWUHO#~tJztB{Ogj`2fJ?r7SH{6l zQ-WGUt@BsK{13|mA-RvBEd`}?tD@1cwA3aP`F?mjz_?a%bEM3hw}fK$iv{-Is^a%M zxuOE$9qL_XTAvoLzK`GQ_PKP$Royt&A?c=tToT|IY9zIV3VJfpRBTVVsnF<>n=CL@ zZYs>S9`G)B*%%qF*A~$cJDg$OKr893%)O`_TuQ@nX5KrI1AC!I8#)_%c62eV8CpL7Dgv@lx`rk9@QU9!4ko zHa9v*eRz#+<Ws&=!VtKx+yVW}r@=4yP zXy_XURKYC6dad&C#v7xZ*#hOR6H1!7SSi`oG? zy%PSY$*(O`8+>Qy!~^vH#ZqWtQ6xQe$dCpKy$C_q{-Po+De5qAw*|^}jm2`3cU5VW zFH3L-%p$;J{4!*8o%38JhQflf)}U~Oke0T5m3jY829}shtCz~M5SsR#!DS{2c3|RW zF#3iE^tCcd#^Wh(FL)}*D{jpgYMARKWgoR~DFbVn`5`PQ2DO1(XaBmxYKNb1*4Bgq zi{(tBG!h6EoioC3zZROIEr8ZuUnA z7I+UIK7{w$;8Ybn;}--@leA17M*la=4$PSc0j7COr?xEtfyg?oi*=(dRml3Hdh$9U zBT-(98{%#ZY}c=+Nc-kXR7@pAp9&t|k%U{Xg0f5_PGG%O9D9^6lP5B~ZcaD9bE~W< z7l*7xXWBlR^Uoj3vuHz>zngx))%I!lGVzVWMO|EwoNx^P?vs7wBOj9sqO8_{nAd?* z1{Ju`j`b1~6}1X3daoUr`LI$DI{b~eWMjP*`^sTn#kaH8$EUZYFy3)lnZeVMs)lI^ z;|@`*Mt*$db$hKJs(EBcqRSf3xRb924mm5(jAF56><)*R6qyty>O_(!anhzf+;)`< zccNeN{n#&4$5BX;E^E}d?9`snq&?y?jJf!c_M^N^e7tnj6YO%h;~ex1;OriV;h8qeerXOEl=bh2 zPlAiMh1RR1pUDG?EzW!dm2LL6lE$%|Ngn=In7DJvM?R0FI-i770mRFXIU)RK_y|ovAV?0kRrfwU zR!Btb*d-=1;3QDtRfG$XwsLAAD47_lNp)VkL@SYaBRXO=2SlD{L#|;m8HC(P&Wz+@ zG$BJ;uu2o3lMxK zm7-c`;zHP2Gxz0VsnkD(=r4OPue>XHAs&C+61_dz2A;sk8<&{|>e88a(&eL~@nb#1 zn-NysrpX*@s6(?Ysd#hDpGW%?ofI#iSMCsMl=_4xYF1T3O?|^eIZDN*(eOBYbDaBF z^yw8377_aw&_6Nszw$GXWfW-YE{*v>lRbl8C->qb@lVwV5@kej24SE+BqYllo0r}N zwbv`X1~p6?eg&1MXByBK*Cj}v#Xgwv;o?}GH4b->OQm%#qUIo&GZc7mZOt%eak+Xy zY+oI5T6L%W0&SW2xu)?Rx8-(2?i9-78yh{F6^H~mpy8?G~&x^L65Lqf)N3V#{+Y zz5fU*cyM2Ex|f-hb(6alERxN0*o6Cr5Dm&U+NYg_UZi)OoXDs(;A3<`-36;%se#$o%R3AiBjmU(yVGI%oy_NSVd1g1H!CbUGW;^AvA7AH8eK~3SELIfi# zgXGmW`pur`oWhc(6Zc$-O*WfFNQ*6yyYHBc{F)#BdymozadFxaJNN|)cPIZ;Tzr1^I; z0HSh3nC)Kp&f@|7f>9qfc5UjOj}9)AnUtgp(XMfxkKEK1z$G>-xFipQ5cvG+fc{-d zVjP-oX;0fiGtNMX)NPB7aQ&&aYV~Mln;?$(c zgq32?1(bd~5=9w}S3gJt|GggOe26?}AXV{f8-u=n6Chj~@3-1(w+z=^zm;_L&V%sY zc1lmC7(;sGyAin7`4~prmdl?rrEy$LDHmOpE;%N$NQmok!L?d^vyY9ku`ODf6;_oy zg7ik!*|t)eh`~`yL4wW4*ng*K6+VBS$od?w2#wQG4ILp~N=Wf7m zV+$wql}DGSw7F{M>G+>A>ehc2FJBIkuh;sqxws_69XlQjQMYXoU*}y5U*{9SLgUGR zk5jurOWb8iCmg1hXxJGdohwh%f4_#`pGM!-bO(kro_ZrJy}V{y&zMP*7Gl)(2p;6C z1*xU?LklC4*MmOW-94?NFZP~HdiSH>>>s8Cih-a^{zb)vg8wLdTKp>sP8`Gih%bCg zLEvuA$!X~eLEUqG+6ObMzsoZ%{UjZP@aee1^WeS`k|wYA>Mpo0^|~xrFXhR=`6wtr zup`FzhPkB!ucbvS->kX+kLo9vHT&0ict3tf$qwWUUE(fAWk&puqXTL1Txg)c#b zG$7`_cM8O$ ze)xDK97y*5lJJ-H3}vtz{r98#!b{1c{%g`}VJm9=_*_A8rBd9Q2K`8|A-h6}T(}Xo=xc8=W76 zNEg(iDVLToG^A#O?9@|(s(t81X76*{{*MHar9x7&3~V(UQ9Ey8vI0lVJ=xAJt*eB7 z#4pnZxZvzFhz72Tax{hG)%6k$Tp+U3>^2=28TlCS@xMG2lefa8VOgZuSn zTX=ifvq5=A+nxVdEt&TPN%?9Z{$|nU==4Ae%^bjcZH^Kh|EE*|Bg0-CS4;1(2ibF) z?$z-w*;s>8CucI4xF$}K$>sqK!2Jk%G7Hdf#SiFnjlUtoey@*02K&p?HhB6$H{y>y zdZ2tKCPI8IAaWl#MO2Tj`u;mUy2y^i8T?riiBvDeAMEDLi7D%19VzMjko{jM8%&-w zE|zMCSn~@Lzc^9^-;y-@u!?u`dG~b?c7T(+znkxWPr=B&kuajCiKVS_Kwq@zg-fHw zw;QlQ67Vzz%|oE1aM6IMz@G-4`tG1bC-4HAY~n*MJ-Y)WKTb*&3aPH(_KbQg=kR05 z>v21^@M^mD-}3+S6J!g;dhP2)ya#YTy-E7_K{8#zV1>e8%>)P?J6}X0DB{f6Y7xT* zY2j;e-i2~rtc4o=J8^WYLa|LOVQs{q%PExmKhg_UOo%&dBAYzUoDM156_@%9aY!Yn zTq~3-GW+@{6ZQ3i=D*i}fC#{BItyn6aSU=GHtW#baIRKkBxB>vzS|vo~rZ5w!sXQfY+~S8VtiD2ImPwptN)5X z5)&bk>hOr+5kbVJeB7p7EW;H77vC0|=Stvi!Fg3^Og{Dn!7a_#ZPX)>%Vxd>^aMXn z=np9fxDHGiWu06cMlH}2h%zsKH+21W;sK^u{3pud+ZUF7(A&06oCVbtW&U@|EUX?K zY7=f+Spf^L;&=9^5SC$oyUetk-8hdytOQbrw>W{~64s8%rrCNc;F`>X*9AKJUV%g6 zpZ@+cDyDk~R0R4rtHl7IPoHjme{hLt{e{p%-#s+mu=mx?E}+7rexk*;PT4=|iD7!b zEM+wo-M>{G$qj_k!{noOh=O_JEB&Kz5?}d*mKKTe>Jc1^tlYc&G}C7#qciDTGZ>w> z!bv(JHVl(0KJ19o78wH;K^tKDGxIeuFMLUu&P||J!?UiLSfFEPSQtIN#Jm8}r@`rd z+`&&F+t>BV=qC4sqeyDSp15v2R@>$uHuvK0p$tHw=F6CwDJExM)4w*n&e`F|wxs?fl>a$F)n3tAotE zZwATo`^G3s-z5Kr{07h*8P($iIk=OPiJ}7i!ZhIo zG-N4>BfoF#&|z8^bO0YGs;8ByfyPMp6bn=dqwJsk1)IGIq});sOBvpk4O(Jt)a5n{%h9q3&>G3g_uIrQ(1)KdgZ z-IqW^cBJWKhev=EYI&nzWj%ECyK=D>9!v!B3>rpN+rqj?7eVa}NSqCD9g1yKDU~l; zPP_LI?fp%ihAIl97=RkJOoIM{lICxH%>#>h4g7OLqD1Y5*%GJqq^6C4uBr6-qrd;h z&y{s+Avn%>69c%WnmNTp7FR-7`JS+!8*lL)zm*zd|K`SfE8q!cKHhGtyb^(7)bU;% z{2=5V+@BG6M3!0DU7v&uuR0N zEVe?8E-bcy)L@jK|6ivHPiZ6oFu+6pBg`!H3tt9$EgZm?mKgQ z>t9Xe%tqBNZp))L3d&Mr{#UIdZWk4f+elVUzos{i3q6WhP_vB(_E?}0WShftuQE|E z%VgBzYXs=cJW1-gX_UmTV}dn!zSNKq-au9Q$Lve`O1Yjl_HUse*z0P_(CV7F{~_L*!* zu&D<#es3uu&;{r-4Chhm)kRs~KuTvOH@*Ah1m~xa1J-;1ynIE|;P^u-$^3yHm@U0+ zl1mPZ-Z#00sDHn3xE@pvfh?>qZ7l*Jcgmh6Hs4v639$r7{>;|U#(!<3UZ^IEC!rR9 zTaJC0FskRf_{No`pzuUC@3&pyLPcRgCLrZkO7$A3DFyr0CKkOjVd)hv3nr=Xx> zxy&=BGxKCUF>(j*{k4BC@CAxagj>Y=IQ?VxKD)Q6f=py;Pi!UEBl(_Ll)W$mF6bcc z5E9U#PQWFl5YBhFdamb35Q+g#1%?9d?wNZ-+Ru~o1}8^WifvMW4^D3J^+Lg=C-BK=Vm5Z3=lT78HHFXc#vm5-s4f-w4kAS=y$11VY~i zdcH_guu4{!Lk@@k1PfqCgCucwh{Od($=And>YR03&9?{K!mf*S30DnS zlBYQ&5PJVFt#JZ}H9G<|aVl<}+>Hpw3h|gtd4Ko0DyO2|Que@~9&W8O7;vG3poTNX zx^1S>f9! zF%BJ0-gmz)BIc1Rm2XNDMrlfKR%E5$^sm$Wif+B0JfOGi0Z%0?*s*?!(5ZOIf1rPR zilx|$;Zu0X<#m>g@G(Sqi(!p zOf#@xAQ%Kd+wzExZf*%(LY$JGoDRv#KAg!>lSppM-Wa%d$hl8(H}>kEvIvR11@Z=t z`AFry=Gc!P{; zu)USvCHYTaKE5FCbk^7H@5vYS#QA!eS}R#e{c;f3>;6?}ijzRKUXOWn8a3TMT}C32 z{S<_=oF0?kYl)&PsJk=N)MyG>eyO;BddAQGXXXN`jlhlGxAu;;PP|+1BkCwX`A{jZ zQN;9l6%upU^vkEF`YouBzWVv0VjK#r^PBpgBc*! zc2!-wkqH89{ddmWoJG=ng)AB>qdy8fzug!}JY0JyN6q}pBmeP>0(1}z=4HNo;lpP% zra$e?kx0Hi!p)y&rA3%y(>5!u^f-mFrL)K(GFb2N{+Jmrd=?O`Qr z3t;=g6_6off|yibZb#vvU5b3H!P(OUZ{DvD{Yz|uDM{F8FnaB0n^+3JrTSW?82>xi z0h=rV__$IEhw;A*lVj$X|*FRS8wv-3JYb7D|9uIsQ~hh5&F0i$27_sePU# zzWAJj3EUP$1&@8JnN$}5C8VDRm_6)GZ2W-0wcFqK{|I~Yc&OXL^SYhcB#MJz0 z$2dVb`_FMPyk1lK;>7rORgoMw8}|RWrotE%YDcc}uSRD7zKtGQoGngE)Rf7~Mo8F8 zO)4#aE`Q+ruo-aJ{0Nr%mtAv&9J~=97nteaV~Vqck>r{WxLxCqg9r&^=~FM?oW|bc)?A`VRi_=A7-0okg=Zm zH@0cjktcWIJaLsEKB;<(X#K*xIE_fgd5FZM%bG2&Y1Fc`Tb`$84 z3HNPnhy0`YQZLJJ*kKa;0pobLa8zxJTlO^ZKOWY*O$JO$J2i0qKkk7)E6yRq>n!R9 z*x?j9>d%_@8B( zd*9a4qj|Nbh`z^!GwNV7f16ZE>N@a>?kX;87FkI3jDjEaEpKb+ z_r7W;Hl59R2qSl1>HLYandd$eg%b&;l+eg+9^0Q^UV8wGSr#PrOuGF8SHPVfEHOnr zKM_U*LB2%A(U`pDF`#D@{MG+}1ZaYn?b7}7W)~LjfdtiC6R04qvX8 zo?Hja$I+1Nkf>VH>d5ZEk08gS3{HM|@B~*KS$^{FM8o%T_@)lmm3p377(ng;R_Zv1 zu}RVX=WJXVfJL3rCJ%>~oV7GPuDsbFCW1Z2r!dSmV$bmw2r@cA=m|bw9z=xYf=EQ# zg8v%i_kaVCw|TU2=cmXMh@9!N95C&V)(Au^{Dj+K`w<9hlfyf8(WgzsUPVdgacPEQ z5UgZ4W90Ln;jy6Rdw!2iQ-wG42CP(^!@8pj(6YV$PVuSAYfb?m#SOM;=VFtkN3Anc zeN-qewiP_rtg@brMe&zN=8V`jS_;Y8%u|xiYN0H^EUxHkwyY!{HhFIuJ+aPysQ^6!CMmfk0pCL$uTaw3+wx-E)NlwsVU`a2uYfzIp54gF{d z={ZYBt-e?jk`&ZYqCLC*E%^bZzrSa)&XZdFprTEu1+3Q&oU8>ZjM@1VSCXMTATVQR z8JTRPJk1}+^c;#UA6rruD%&IX1nS!P8Ce|%#_s(%&-y_Lv@`o&e161=Igsx6LkfP$ zoRczj-4s?XB&*uP)_XcRT*~KpTPdKttHh?|w4P6Vl$kyGUcg`^9K0|91q2(Q#z%_# z{_cg50j+3t55Ct}@Xr_M|M}zH`~3N8C19Pjm zURuUsB#e>M%Qi2Ew-0j#&JmJ9WUoRb((BAUptxW}mu%##QtyIlzhG$rytA4poAJP0 zd^h2ub)M^Vb7k8BSSm3Mn5rvn_N&p(F}eVkU<+$pZ$7E!zSJM>G$X4XghptJdeh$Zg4jj-M6iwS1d^we!v-Y4p6P)4}{9zz54qUPfa zi{#7th2P*F=WK_+RCrBY$_C;^iY2)2!g9XR-tX$8OUYoQ$~gxCs(YYzdc1K2;NBTp zTS?F^SP+MOV+%KHpOewOEp7(l{+G$)&j)kj{&o737H5r@9p%8<=zngszx>T4?YUk> z8#h;hFc@A(%+(=gI+?-WAgmE9_4v{)jAMh2VTsvACT6zZOyJQ3czi#HmN^&0U>@Jk z*G_w~o?xk|$}Tsc`fgD`6DS97CBU|lt%kBf`9x+HNOD4_JkqJ(?O0jZ)=+y*yiS=!MKBw@LT*4o2w%(Xw=5 zY>J3w?fchx(h6ORFx;+tp?c#i-v=YWIsePXL-w0TlqTpC-?-*m@-psVUVh&H|Yx8ogn zkR=wM1(53q3?}rZRKF|8123UX%7H_eIdWs~2Fp-kg1D&&@b7eOI9n=(ebM;s+ilyo z+kJfe(cr-ydzXFQ9JBK=1O@H>Nzr{w&wYYA+0emwI+;Aw-9C8ygiAwD#ux=;CC`0k zI)2P}?0WGZ_Hik?l&B4vz7;><=;Z;l^32NWo?=R%I?VxJi*jGI|CZxKd(f4VB0XJ; za}G;WFFJEHqT{1g$lsg7;mzgc{iTm`+7uje(;4NDwp9k-#U8es{}`+N9>j8C2=p&R ziSLJn(@*r~ApvlH`BEmqfiaQUhw0|?xHeupYm{>i@p5lJ#jenx)DQGIOsA`lU>Wlm zJu-NCsh{Kfn&gXi5S=hgC)!PU5@)N2bl6L7V$S40I|w6h6C|d~$WzVgs->pFhUR{` zK;o@f`jH_&w}~n)KER1h6JGCSKu}2oj#9mb>qiKl=DmM2)to&cu#aGw{HscW^cRQP ze^2I&hP>dps?m(&ZIH4u2h`+VVsD*E@6_1VLm^kB2DMoFSW-4?Kwg?~=BZodTgwtd zC%(DDDW(CRo7Vzn+7ObiQ;p)qNtu9*215O7*p2{h6TvBNRLWcOLDtbxjIG1Mun8Q^)j$ZJz4q;av&p@ zEalvv`GVx{-&2k5%}`bS3;(W<+%>=Zk@ z>h}KC&4u4TLj_y})S`!SG>$V=uXL^mPKkJsBhuz^h(gg*vv$lKsi;1s>)=or#LH^! z@ZE8DW9}MX2tw^B=wQ1TCOUM@tYB0>L7$q$x%6?G6LRU8jC?zIr}~}@WZ$Ogv&sGV zBkAhnm&arXk3;SY5I|}O2y?Rlc}*pY1Sa@ym*pN_U2zCx`2?uy<(XMeQ378aCYJck zXx(@TJt$;k6Pz5yPwisDA`RR+$|KLp=Run;tBRJ`4!vOMzjTqZkf``5 zXPU)i>7FpvqTem-jSeFhQ66*+x0&8RMlm9`j3TA_E@wK!L`!2Dc$eaB;jYURDmZbY ziv$QneSqM;;M)Oa@KJRBD2wYaRYs#;4Kgz{x5xR8yu8PSRl-1({DvHp#-3j{;xqU7Gxt;2icfI_CNJal%d8u_(QMNbq+7e)I| zgZ*C|#{k;y;lXx#E^Uv3J<2garNb=K%JuxA9+>N7f)W<1#m=p_aFYUYPd%H&06qPz0dHJ0rHPNy39`1pKnzjk9^*RgIC!^_7qBB=d0VY3sbPC%8*ZN)1g0GKi z)~OX{KT>`FPH9Vhe!72A02B|@fi?HT+8VmyL5)&JImN3t13F&qUZGGGt?m)nai20X zGh5uNwHSsnu15*Gu#`#dta-x{lR3xOcFA*7zKrz|=k&23(*yv{37Au6dC7ad2QU?lx4kh(Ry&oGbLG$@;&qX%IrbO zk<|U;ndjIVUN_s4@K}i--g>xpGPnh)l!C&-Pxo_^pL?Ho&S!=-h7xJM7LhFwXCmlE z7hH3Chl40P+T9jLD9sY%mPeCei%N{?9#=)B*DD{)7@EOiFyk#{Zo$oRZyHuVrT9J% z#vLA3yxuyKA|mg@)jp=77d_6u8qxc9^dfBcAU8ypP49<%4=0T$g^OcY1cFEH=~8hS zE1BT|bjTZ`Hhcod%Azm!;Ok#J zBkkk6!h2Pw|JZDVZ~1&>mpJkG6R)VbATK($L9=?~ao}#c4Hv_|=CrWi9J(!KEFI~6aN1Dt@UB%~+FUQJzS)Iv1-pQ?2yl)_OEBm+ zY49mYm|Qa25`P}xE)B5M@=uRvm|?BV(+P*!9gRAb9d>SooNN)=Uf~aO$#ZVon16#1d}0p3nk{QOeGd@a z8AEnJ9DD;R4`w<~3-IQnwm{dJWR6KguT8Jh0oaDLq%Iro!+sz8RM?){SpD$`2GBU< zGkmIP3i(Y?KmT;^m0BlQnWe3XdBB69yh2z9K9KouJCFZ+(BG5xiQj*3kyxPeVAgE0 z@4vMwi%iaS#}}`6)psanx`HDSMX_^EN=gETcLpI6e6=RBen|TeC}>%oa4y{szG|{N z4eY~enVa&tnS)P(Es9KC4*(_&P;Xt=lI+qeCiO+V%1IzW(-}amrBiZuqjMJ~A2pm> z|Ff+6FZ`@vAvk_}_p>#0g2}rEzPJY<9}9dbO9($ri{e z6L9?W{OrDUw^l#v{QAJ}F!+W!U70j0_!E1(ZM}nh<+wp`eGvHb#Ie|G=fdn0poZUK3)}{6{F(X+V4S! z^a>yA#h%kp=43rk%l4S`vtrXOky&C=MLB>}-FmUNvv)UCZ_5E>haI<1Q8Ctg^u%H3 z2N?4zq-(P+(ICUV1pIid@~?b(hH63c4b2o=^SNjp45qPWQcBxSc`9+c$%=nJ2R_<=62tmh27#ZTGzxwOJdGp%mGCgYI!21 z>;CrJ{CGaS38e6m2-2=P-e;2KEB2!ftE#{TF#!#CVL!d99H&xMuP`AaJCCzdn<}egw~z)8MR>Mf;hj% zg*AZ|`&F=qIfwdl^E6&;!>^`q(BCpSEl!omH23G+wQu@WljbkBh3X2R`5V%h*yJ(? zJ}uz}o7%iBGJ-c8a_}%yPBFae;U~Q97Wfiz z53x6juOHCveeP~}v}XkbKD%z0h@02fBD?h^1>4&ZJe;UtL&J);fIWLr%wmn0xVX=j zU^Mp=blVXQtBp5@_xD*Qysnp7{<%J^?>^ubWzb>ol(LVB*@%OKV;^v5I`PXUT6tc9 zvx`4b4g%ypEljNWU+!q_ev89n>!<>ce5#`DD{vxH`W|Lpn zjII`}Ere|&16kRA`^L*J{7OYvnH6KIzwW;B>;|q7W71V?lgSs2YRTr!7qT4 zsKutTV}%Des#juA^c2m|)YJz2jzp22FCpR+)nlf&%cgqGWcV9?McFupx|@l@+#bMf z<;rA9Mx4lX7hrWh&zvQoXpf&pwU0YBN_)+$=(Ps=98{ny#8Xvf8`qS`A<*V7p1a?Y zf$`riX$>crXN4f_Xsbr#f)ndPF1S$vR-T_rGmSKKw}~3XLgs#Raq-QT4XC3~IF`5y z8f79$#~f(~Rz)~qG>XsWAtG&P@0?fV6^5240ih+Ul%;IlkLjPr&qb!o7?#@1%RV<+ zX+L6!d4!?=I-arhEEHkF9&JPt%xgiK4g z!tc*aJUADCI_xXfIEAd3n49p|4hx62j3a$Je02&rkcEm>Zbi-qh=)HRgY_XObN~(D z;%~dsc5%-A4RqL#Ze@LaL(_2`9R8w*#l-C1efJFXP@4(+=>ZX$aiNl_jivky1&Oh& zWVhyw^YR(b^pOKMD81L+oXgWExb0F0J`z=F>&MM;s>&dP^Bk&BV7`AJQ7f&C?F{zw zyWpk1@ju-@5JRr1u#X{YYJ8xx=}Fm6rOQG1kJdCdlWGgcbM{Fs;A>~1j@BUzzIo`3 z2e`ZH9u08yMQI*GtNEO_U5YM4k z-Zt_OXVVBwj1vq52e;=2DkMQ9Xjbfpu8#KE(;fiAI|5t zHXTSr@uSnoR$bPY*;m&1I8ct zyG6kh`+26`I9mBTu&6@~;Q5e!ud2Eamk&cf+i0c8h^@6B&KKLl4v6SO&W<{Xs6H|< zFkyJ{Tw#rqJ9mw$LfNr#ecnw=ze)$8x(_EOEL4r82)he83U5f@TGK!-E21Sl$6*bnP5Km|T__}&Sh!C^+^9_&7p|R3CB)-*pNT*1# zEEfQ~%fF51PFIm>Tx$siM~>Lx%zegkzx5Ut!iFYWAeISLiWc79h#C+GtnM6>mga08 zv^By&RS2eSHNH|5kX>uc7~*oK&<1XliD{Z`iBZLu(j&PeOEh8z-3Si;q`oM-Ctml} z*D2_?5wNy@91<>-)m>waz&TnDL0_4|gIFu-@P=+OkEFIcn78fmn8if4tr zgcci=c=$N0w(%pcnKZY3RWzE}arm(eR?y{4DcUo*1ywjL@LpL(Rd9Jb!#7XTh={50 z#S97fR@*A+Tbav=^^tK&V;Fu40OW8$3*P7HrEe<`}p(Z_e}ZU)~u$ffy_It9v#6H)UciM)nT{~_V>9%m1YaKc3A8%7>tP)Yapg&aE>F+cDwl;!d5z$t?2jy zL>1g&-V;f6R!jr{JHQ+iQ#%4qZ~wl#@ZG!J7sI+$pnrB5wGNP@;wC9O0=bcfp!oIw|floNi>*43^uS8<@QH=fVLzJRq`r-^&RB@wVOD+U$#noBcYearV z5v-Q3{%IkB*#*hREWG(`hIcO+WnRVD+^%eT!!_*<|EZYjT(Q#P$4uL&ksEiV z#b?^1x7RRt^%Cu(l}SeTu^6tmDYIbT5x!8rTDoorg6oY2Mw*h=Z^_hci_h zXbXyA2z7Y6j2Jjlq)(fHDgHW%tl)8?4Vi%*?<(XL95|gfg?etOn*W{(AiS35^1c(V zYDDbxO+!-XBQ5p7krkZ zH;9F>9QSdxj*E{sp{zBO)qv}4G+JSLG=W)drGsDBam+W`mteXetev{Z_j`%=8>-Zm ztEftPHmB;XCymT?1^j5DWd~O505?o49X({x)YTZ^|MN8`1cxb{{fQ(z+I1t1jOH-I zmai)58Y10!ALd&3H2IXb4Me(rgYX?H$vO&Xo8KnoJ;h3@A3dzhS$keu#~9=MaXbyB zTM3L^9ZLGp&->$W=z)rSK9^PvrmEM@H!l?~+2`q9z zOnLx9!o0EyZjxV_rrQ<e{ye8G&NH}oc%S^88Wq*$8#-Q=y?=`?sG zbdF-IBZ#@R%h_o(gmSeMM*W`5z8#@FSYAA|WGIUHeh<ucsCiu~0J$JTb#>#n}ddPbf_hH7vakqY)pT4;zuIe(&p)&}mVk5Z5Vfft6X< zFmM0C>MH%5x&IHybtd~iSTpzi&j&vOviAus2T1A$%3q>CZ#QfCU!VP7A7ox&EvOKh z>~@d{@4^|eJHtWbd%$K|yo;N6$}Ml~&r%s<~eb1<90-Z_=zCu!-sGCJV$ z=5dj{O`5pxG) zwC$F#=ib^D*wqPC&t<$hPM51dMi|YsWh7Jx4IViO+w;B;e&u$x?@q!d_iWRlA`vbd z25Mpa10+vB7fHNlnU3PBwCe=M8Q@pHSa~p}?6112(COZ4yWe931&@f4T+mb>3h&~) zBQBL+Ih7WdzA=Oai8A}739=W&bC;1;5g9R#a8AKkx9~|zl^eKVd zH!IWA{o*8Wq3+HaDDyp#dTrn~DY-Q_V#vax=CS%pa5E)F24sR00BdPNW`7tY<2~8z zVSRGpu(Z_uV<{kGJW~4Cxc9<$vAW@P8|3BbK5NH4x6qAg)3#)9JSOh$J>4{88$_J8 zrYZzi_#i0i6Gs!qXKS}AG!<0bGPN92v(tP%3Cmdvg-NYRclW}eg$;Mxk{_}4i4GXe zY>UWSYq?qK_;JJL`*h+y^qv;7MyQIkpYN>g$Aa&7%OZGp?t5}k>t%7MwN@78M$lYC zdJE6g|2`f6dj6k-OZN%ct7c>>(@v$VXSx5+@%h&m{Oe%75C~^>`U+_f?w{r=Fx~7_ zw$}Pcbr0aGP+wpStRs)V|BSv%-|z3G;vHB&fI&R#@-YM3 zS$ad{eGBeLFT>o{AOK(-n{PByg)KdDgDLwLe{5pd)v$xm&Nq1nLU#lFMw8VGV2b zqAMu%ob}_1S7BEM7NKB4%{oYpRo5;stMf1_t-iL~1}PjW!-y7F*ali54;QV26=l4q zfF|B%lB%7i;0Nd>+B^--ZmSf|pQ12L1w689V>#9%@Yh>mWQ?S~XHjo=+sFkB8V=W4 zkSy(UcYs{8UmCnvF_Mp(wWzC_R%lD!pqlNL!J86fR$ogN)-FnFep`paBPoVh%{m!j^(NlvbV%{wHrx+Hf-XcVdDvqB8Huk#w^+m zv+yqxoN<*S8jFxPLw{~NOmC{EMFIhG!1Y5x?W>L39wLAlEQpM=0Y63J7Raqyn9S%m5+>|OO* zdr`&~ZOPx;24tt6305F#>l|_QHO_*u&PQDLLuc;aV66gqyC zXTLu79wISDhbP&P)l^4i_ah3pp&ROd6l>btnm?t1AWs&9jep@PaH3S}PAq-2ydumo zVXxhVHec&Wl4?(pbI(T1X3a#N8B1t`;C{maLDmoOGT&_jQjJFN9yU2WNFq+cU&6m+ zJ~D8jpm78CHTe=fFumqInF}$Sy@jTcVFw?(fhF56ECOGxc#p^NxgXe%HvuXv=SMMf zSV^JKS?Q;pANn8V*q|4)BL?|7Mxty6OU)HwXNL2yH|&5$Yb@Zh4Pt7&aWE2^oPP^s zywPsiAU`mrf7S- zLWl@2nkm;`>(^gT7KbJihvU_s30Ywu{BHl_vAWKrs>FH=0d+~SuG2uibz;BrszO~> z(-jBV({~+{E1Zu9FYBA>*HQe+3QoGdwr$RnkpX8EycXYy2pl8zu!nE=?2-4WhkC-`zB zxa+8BSVfyU^6d$+zA&gl89=E}d7+DYunW@7S#qXKzKZ2JGy{m0y>(IVm#0&< z84wig*g9p+cMkw+eaooi+R2lMCpkfSHoeOu#W-g|0($SM!S2UvmllR~&E~_PHf@n_ z4Q9+ed!X{$=L%hSKf-2Td-lq=>-h-4_bO0;eweB168A2_qY(cIGP_YYF{dy1HrZ)& zmkZdMT}OouU{faLou}{VXjA?BG&~m2cFMvf*lU$hZdl6 zSr#)YzwVzJY##waCoB525D;kRWL`5IU-k5Op%-~`$pXZk4lOr;ZBT1ljRaZ#ngSef z#twDCh9#R8;NpiOR+B2!S$KHC8p6V4VjKfjU5nGK8$rJb$167ggx#cl`&W#}$Gvne z*cTR&MU5;$%%Yrk@MhTAiZbah10Y5uS+Dxr;!YjyC)JnVvp4l0?yR}YePe7z zawQf|{?qvb7ug4MCKg_|=eX+p2GV3((@m=WrrG?($o=fqmWON*pD1846go5bLZ0bm z@*8P|H;P`dPv`RnJ_a*5hNX!h7Nc2tq4KWxTJh#NwKoTB){Pg{$IU1nKyUKV{TZMR zv3CW_)9zUs?eoB0O1`HUt+a8ch&8E9k_T38zH5Am2k+_N3-61S#OypvE%jVQsSp5< z;t0G~mA=A1y;~*Q~u(cB8Oxp1M8loAzk| z#B5wGo`#s8t#AH%JLIi;qi)*5`1H-&$irB5#qeLqFvU7j{)64&3z>Q6P%o5@)V<3) z2vt|vp7gx&kqxU^k&my1w7qZ3;i2deqC76*b;bJ-rSc>#s8I-s#RkFSz07;1+v7;- zL)2tk5IPb~nWDKM2V7WGUqdl+a_QTE<#5qa_^w`VF6fhch87JlUT0e2fU-oA(kjg` zHw#EG_c88#B&e1s@0o`!f82_s6+3kEf!)Rhd@!g2IA_<0#Kam}tBN zZ434kg(e7hAEM%8Rr2g$v~q+|j`!`1$eY|S=_8Y2Ck6LP+q&uCA5%iOJsLEsGbGW) zU-GT|P22qEwet?eydnNM!E_^6D4dU}_1IO(sNA(V-mKPWnIAcr>8CQ71N!!-V}g1bPppQvC0~bwl4fHu zGq@1c9<`c9U!4uTfRZsq?^C4*Uo}oU4x?%5u+nj!oxvxF+RC&+F3+!7*B^po20JVXR?Z`CP z5W4L_sOl4apflBk*XKPYQSDSI#-pDszH-C7#QESoIqEsx{=Y21sHg9dKaQ<*hk2Qe zbyxR)D2+SNo(_Q}Lt*o*5a~;>Rky9agiA)REqtZgzu~C_^iU%E{DHr}9CrBapWh|( z-+!oWnJvjy9r<^o*q`U+w;J|3dHy=Q*xC;Q`w|BAS+J@wEC_=_zdPs!AE*6ngLB`SM#)W;xEofKi|bxB;yhpp4CrxMX=3rF5G#63-#Z}X=M!xzM;pn@#lhYWjqiFtB^k?RY3#<0 z7YXK zILR-&OkY)%JP`fGXB|Un83T?PNBwTB1~{C+T97&fJjd(^JZ%yo$Che5z+}#mTh& zb?PZ7tRpX`@1Zz+e)r{3@e^uuY{I^->0Hv9{_`XDcsBC}DZC<3>Ppax?!^JAIugz?7*FOo`}U z=IL$8U<^4(5u}npS=M!du%7oXIGk5|XJXw~Ognz@(C$XfNwt?+(f)&4OO7&^O47ml zonjtybDRcZ74;pH2A3yeDfJxz+iSSNe565* zz3)IiV*EO&OVt{&JWj{&6=J+S*VC^~2y~i&9`LEZNJPavnDBLOoNNOEQ^ zI_8J^RBE<24NKdUN?O5Dy?Fx%m$3N?fo2%lyv1-lGDtSQB^#`hq0$rYwmJ=1f5tWu zQThnkff*noyK)U3uisplGa3L+;k_&Dxb89|OsV;dewjtnS4jxRdGDR8_e^5FQdNXi z3AGg$HS`sMR-We3W=F((8E($x1_&&BHJVTHlNF%r4n-O8JAYm^{!pc^@!eOc{+vF2BVaR8$}TD& z-lAM8K1W$lrOPMdTpV42^4E!0t3WbHPJSY}zGzugrkkT~FzsbS1-hf5wk!$FiFfc3 zeZ!~gbO3zYK=XK}LfQC4YRK%ia2CF9S!;x33KSM^8E2X1WMTePka<-seNMLw>T}!n zXB&@ecXII{IZHP=wc`9|yqIP4WW(<-N7?a%(4PQP4Xa+UWGpW3U&*0epCe9bWX#)0=;<6f5e+I&1gpInTe26EOgh-80($^?CvWS1n`n;!mj6tZ!V9BR@?`qCS*sK#4H_9 zOHK?%fETXvQLi?q~iN87Jwk2bov05SM@w@~ARD_Z$eWbze_ zNUoE;@Y7e@lD`Dnx)UFckAWLyKV1dPFHtp*Ti;9psln;epSte0$++Rs{Ju0rpr2ov z%Wef^j}dJ7Z&NT*VC-Jn-%0^W*9p6y01>Y4k(<5S2ElSFCp(qXJJcQt}K$1En1r=7AEclvG@0^zw^ zD*F44>_2rtmCy&5pPv_IJ9Pbz{U@IPap3G9`~IK5PP^{6-n)9L?gHsN2z zzO7y+x+I&e4)2I=l!;RcIN~y@m~7MX^5A^+koHg)QcZ>}IYPYtlBhXe707S9y|Lz; zQ>L|UStkXK=kA_YqtQ_v1wLBb}6FfoQcUrUz4)oJ-AWeFNDQ-6*UM^17HZ zh`1GZwQ@{p<%J|x{u$Ulg7GfU=Bt&J^z>^^l8jigEQ(lW@*onRveFs?-XF%wAFCOu z5VK8c9BqLVIKHNd^S7nM(tq-z_*gtq z`{XcE6qlBw5>yJ+zdc0W(^#Ot(oQ>-aqgNf*R?4wbDJ+};c&{TWR>me_~`oWjNQc= zuCPchk1viS(rd1l-NZh+W&iz)b-^v0`0eRWeYrJaJY=mh3(h;AH0J>jBGnYIEn|JZ z0`^6e$?}?^*||w3gzwVexBH1#&mkXXFug@uS!%SG9Zpm5k;GCrP3kr>(3fL{dEQDs zCEC))Yu$7FcIOhLVq3BGLfXmFmxEkpOH0j*k_tBh7thV#0&^~Q)NVLjJQ4oZ>=mJ-?o;y%SO&j4PiM7K-B^J)#52kxUtyl)SiW3c^He8m2@=%_&>T>I;|s!;%J@ zb<~Gyr=<3uy7*1nzW;3TsUROoRnbMIzEpXsZl0j#ul*^t&0%#nFp~<8hx)>;KTE4k`FAawwbQ}1Fxuy)zEKQouensb?{0tJ!5|8$CL=_WAZkgC%nF6kKTQNX zFHH5IO}nI{D+l^8Ng52C%=<>y+kM|B!J1P2el^MSnQbsIEBf2(!wP;Ob2?_7iRm9v zX-3P`ybS?DVM&{&M=0CoVT+Lb!ydCGVvM*QP_pKEs`?hPwQ4NP@4<2`n*7tb9-eoyu7?rGtZ&eB)@_kX=}rg4JtuOv#HJ}=8cjlZF7$3z z+#;vfpL`*F7W(V%q-9Dp%ra8%A>u={!A}wGL^?xKI9I*^E(<|d+ZxA_4Um3%Qrgs? zVtwm-1EO|)?QXLA(T$vrCtt#wqbyhwt>1t3ijm_-aM?gpKdS~*X0x6SsB9TmoQae= zg*Rj-08@?CRLh6K8pUo^DK?ZjY61oNFkJCNj?+7FcjSOPXNb{*VF9<8NcV|PB~xvz zJmzsECCA|cqyp4B0sepgmv%c&PcsADfXea~gBX_-n^^A@m$X!fJ$j~l`)k2NN9uSR z(7GoPiJXxac>7spC*SGuK;-SVibj^c3EKP)5J&5&9U=yc;cK}ln$8PAU3sMItHB4| zZL&AM>9U?s{#G`iHRXPamDgz0rlCe{qU433!rXgQo?z=8MRA=>co6!ob;(KN!3Cwf z?8FOVf_e2{{bR?wgv|wE4#Sf9bo;N6ru90i)$k zsvzP%M~Ns!VczE*7!Ii_OCMvcCmaCj=z()Ze$4Y_Y?(lcgn;=wSwGx!R;Pag0m==f z%MC^5A|z!V|7ETA@7e!f3%3Vr5Vtl+!*2id3oe(V!x8rH(LYs3nG)l>h!@D$t*0+a z-ZfdXPg_$jU0tB$`o;=rDZPFFBe}xPxfnF8Z>c@G2mtd1Fr>dGO>4I?J1<|Afp|=` z_yWBc^-A~myTTy zcR6t*y!nIub&E-L*xTS35n;oD>?pKtSYAHIp|v?{Syie5$uh>>=CvZ7io*#L3%3H8Z<^nlUSXac!+jz_FLT$pStWIE1WURefz?@C6 zDP_ab7mc&s{Z6g7>Je?L)wp0sD6Yk)aF@fC8+(&eB40%&d@@^VgZRzwXOB7)R@~}+ z*5B2Y2R3Q)2sB1I=Qp37f?gf2ax{qM=rVi;6s$*w%##Lt0UM*#oac-Cw@5m`M-Jl| z>m-_-O%DjDO>GnJO%*)}GmDjReP5wYDa%k}*s#oFk79!pxh~v!bs2Vu7m%8NiZ#6} zkon0anKTJ-j>l7#-Dol1Y5~*~EC9R{TboT}aP+iSG;Gn&%tvbur2qb>HvKa{%qm*+ zN7uF8$`j|l{O9rd_i}e7fK|>$%S$o)tKeZ-b}|o>ltun@+~l`(mxtQPI&d`)b-uM+ zMUCn+fYfeGVm7QynU~Es-T>%Ttut;wJHBpJRaXOiEdbOlUxSYb`;hv)OE$P489JxW zJDUC@u;a=6NW&IqXizU!pWgUM@gaWt=yLc<1llG6w7Nuq*q2g8QtzAwt z@9&APyRz)fL_#5jBL25}ZYFIl!Kf?Q%-=z}lt#os>^G9KC9C9`XM{@5nwYv4_F@u# ztsXDlf&Y3+ujxXZG`;j3H83m2;TKuQ#LTdqlInuB%cnK$&j*od^mA#Xg>!6%}abL7d3Ia-8R z#S}q2R!R}&DkaLcd zZOR%Ix6(Gp)C|G2%xVHNna{WL@%*0iywCfd|NCtJ_ngR{w(f9kTLS$6DEFbhdtYWr=5XzWfD9*vguldN+(x)kw7YSrgGEfP1`)BDm$b zJIdj7d5QD<0fJ+HH27J?6$H={2SPA}Cp+)y`f@7EoVltmSVzFYD4Ltiix*iS`fL9x zCr(~Z+lc*2Zt2!!t|=va-A%ZiE+GY3077?#quq0_+`(KP9~<$$ZzFNK1<`)$jOd4d=RJ(u3FjkqKqTohDp zm(Rk-S6ok~-AQEkmZO_Zf!HF1hvZce8{sj5k?1qL0zE>6!7K#7^4va+>=91fz~wyD zht}{}iTU)Ze7NkGO#WSOg{177v>ujFhfpzMQ?s!y!sRqrLCBVSxw?-WABlouMFV$< zr*7cQym9Q7XlHw}?=vUf%9_3==4j(T{c87kif%F5pfhKV@RG+LMxTySH!`+7!S~Fm z&R+2lNJ7o7pjTt0nrG56{S?G_O;3&v(dK_9otm2}zJ8f*Z;B zleJGl@!u?(7%y42G3&rP3_Ho%uIal!m)w6Y#P3?J*jfL^!qqc(3EIu-K>N>)YQJ)? zcVaUlD{&!lJ!LgM9H`99HQy@WogEMgj=E!ovS)^*??jzFoR80)k4UZQ8`WZuO{|G2*| zV+ATvGjdG^bdb=#w~=|*r5s0^Odk;O90^#y!)086lpTbWoz%|quwJE)hpI{L=wNAi zkrn2R)_TLN%rjAaq2eAR0*-I1FXZ_cLJXCcXE|i{0~%U7VQM2;YaC^1?LJsVa?XCKvqQ}I9EZFdWoiLy^L%@IYOmR{kfAW+^9EhhJg$l$kgUa0t~#m6zxe;)caKP zeRheoVYLI;i^s0}wFhP$7z$IJ$-?!of6 zs~T7DtwwU5>L7u!9VDBlH>-xb4(CTbQyr(bj@$iur+Q~P0E#N;0^#KGKbGyP&mUuI zr0K={HXob}>66}0NmB&nI`=z2E?u5uG#EBzT-8w(=zB%-mPBh~HRSJ6{36Z}rQQmm z0CC=Nm#;{WRJsN_Q+9afO=K(c?QqQzZfvJUcST2Q^y!kJlJp4ppwCgRt!BV#8}y78 zL6rFLjQrq&V?KW=P(x5b%8&)v+m=LTwt0jc%k-{C2sQKy0xow)w$YK;H;4TMxZ z=~`E*Z00J$Aq8}s&lQ?Rx7|n5=RLE_X%rLcRq~5ULhEhy1~|*ag4dn*CazIrlDJA0 zhDkv}fxIwWosTu`X&=8Fo)JP{XLxQ~Phn`ByMfIsDHq%G*x@9VD7;p|?|m(?EQ-96 zIt^%i48Sxz_(3mJR%CA!z%2-)5?L47Oy28F90`i>3p4qR01EN|Al#bfq#Bx+Rt~gC|m!7TSQYD1ils!Bc0g{xutr;Z! zZs(Q=!05f-)C8cM$|K>FZ_T##sKLDYUMa2J3v+dLFuZauYE_|XH8Hdy6U?#u6GI+1 zX&}bn&_7W0U}4h?rgx7{{q)4l)OA#_ADyxlE1`sT2#u3H$U;?We!8x_31KE5WY%g< zd2pipv@vqYBO6kO862euMElW)yLmn)*}sk!OxuPIX{-xK)tuVGwIRW{-s!t}mky5Z zjukB=;p$NODMx`kyRLeR0Is9M5jTKsQr43Q<>;y6lHgR&4U`;&3J0#X@ z0{A~#x~P9W=DcF43tNI08jtMI(paSN`H>fX;A?nyNFG9)K8N<3%F$$_^J-M*p5$Hz z?Q$9pc>jcOftm?wFfYc4cS_QAJ*-tbjK+r zTkko)PO}CcC_L`dRalOw3KzOn;SpR2Z6#I*~PV`R&Ip}*mCO$vWW)X3U z*{vgli_@_cw$%r9W2)1~Ce7B5+5?U5G*4BnG1t%KIeQ(EIQ9?^3sew&FtFbLons<; zgHyVVWC49oiyfNBz@8tXI#$JR?JZE^!C0_Od@=C2B|gZ)I;s7)&H~6qX;_thxhO|( zd-DFZ72zYq*qS&Ns3WK`)*B37XvESII)wxMx5;L_kjh|S!yXq`70IKNZc4j0W84I- znu|02zA7dy#0VsfeLicZKqk$j7gT?NFpxi2I}Ui+oQh}`*z;D}BB7^%yB)yZE?4b(K^h2b%Ima zf-5i=lK-qf%G1pBisX>@OV5|HIf|H+*j`@)9&yGH#2Z@uWb?SvxzM}BJmJ#`#aX3| zr@gLj|M|uG_#eUfivkChElmNf@cZTB7bU+WP~83PE}q-i{Hd_NXTf56SEy8NIlEcw z6M^Kf4{!si{s8V;K6w4v7emfxYo~wFC0l-Y0MA%*@#LR)lfQ1vzr)+PB+9*ccP1rTZlxx!4=~$i%Op`e->mw_aaC z^;fsRS5W4FRO=NgUI62yBmIl?15)J?HBfcGRl zuM-D!StZyaErQrEL4a6GHid3(Hy)`flyBl^V*)o5`x4m-gNQ)37 zr43tvUncfpnAH0kN$^d^*YNXcX040gaVL*48b6M7gQzGci&zx2Af`K}8*9T?hcH;< z$WOqx;oD(r?I9AJPiU>t9K51?fzpN_--4((J7IRHUHa$Kngl9(jjqIJyPwpt^U1^L zSKE_UMSjx@*TA?TfX~DL+MU}f^3crA%>xuk;bE!d6zU+eH)A~+mD4^W>OG17Hc3t$jA*Dfn=>=(Yj=_EFb9=Z-Th^)^Z1;?~$LCDx zf??=mHR2&6N1K=PMq97n(R$01ox8JZs;gv!XOFeNOCk$%j3Pe`@#%mVqOb?Q3nN<; zsUf1oEcPrBSa~&TWKFrShboUs;V0BjHGBKg&+ui;5M|FR3xE% zts}phZ}w9wTqwmnhxR(Cxs{%&?@fwwp>pI1(M!E1{V%%|7?aVRBahm```sTr^u$3# z{}8;v=exAKx(n~UdzJ3&(HIiz#fv>xbufD^3ON)JVPmsC7bJ2e_x9MgzT)-RFpobR z`3m1s`#42KDQ(euDgd&8yKSAlgwoz7Q2$HV1$RVb?IJUq4Pi%qo z$at#QVBzI(HXJA&HmZc-$2W8Y-(h0G_z5BX61^X7-%ym1KdpKlhk6QPjP~7S3$)?nA8dr)vF}<`K z;uaM)oql|~mUv>aunwgX`&Yg{x};0d3P|(Yzbx4`g*q5EPD&&NkJvoehp1blP(~gf zGM<~evo~Qb_)M%6o~vF{&j)$Y{zM5xbn~V6c_B&j20IH^8il~$!vBT;h&8JN&OA8zCKLS%aBV?K_5a*X;AUG%X| z658|R4PF^1e{j-s!l>N>xf<7~>dpJ`bwM z=5dcDl1ltYAIK>BI<6?Me4x0Hlamvl>zpH&kD|JsSD-kRZ!5ROE<`D9bYuTl_j(@mX; zt8arpu|@~S^@g~Wr!RU&J)(zaV{8LV?0oHuiJi1#&CCl}9czjgL}j_Q+0 zp}6?*eT=dDeg4Rt;_Hm(5(E*Zlqb_u0|^`2TkaNI7WO|k`7_8Qnr%y+aB9r0YuBWm zD0b>vDmzc|6YCQ@3I__i=h}qF8hdXZD<_h4YWE9mJUcu*i(j$nSjosvG-=xK9BghN zZzyYYbajXs|GRe3-wYA4#Xz|(BPtffY1 zMzoXJ9NpY;_wmlHir$UzN(@4XO|C%tlQM^Z7+S+}`0S&mg1CZ(f?kQ)VfZ2*wg1PG zk89Mt{Nm)4*?}WO+mr%K72L15nR(20CNr$-t)-lgHSEndCkc!WUTTO3(~#0UqocQd zxq8E}lf$SOlo2wdI21D^ZzSH?AI?uE6Pb)(&v~ko*Y z#dS7x5_wXb?0nHfj{U~^UT?d~zMW&4W2lU*&m-=DVS<^J*{i{DH}og z_tDlPg+E#ock&DKn5wX=@y%W8xD9ru7UG-7%sD63s`hpqhfW75*acsk&6=4ylJ0B2 z4jY#?b90PXaBy*I+3ykvs{7$)fA)C~$t}|@^+0CM$;fN+HWr~D!2$UxmKsGm^hu$_ zcJ{;>_ZuF2p2xh7Tmd|lTyES@fn8_kE1VJ97zu|DEW+Z#YVPKX&PzwPc*}T=^qg`c zmI!X_EQ!5({gB1J+E=^nT$IsheR)?Kf6j=m$I^EnT z)N8rjJUWw!h!bYvbqe3&bL>3p{hkk}KB&E-UGFTs?Ajf1PF8LCp?S(B%q#!OabQo~ z32ooKN$`wvNq5U5;)(zZ9jbC?aMhh6S3Qt{g+N&)9O_|z#(r=VM(-luWKSTPDO~9M z_E$mHOzoAVyu#qx#!8A)BX;xotk$pW^;A_>3th_VzJubbrf*F}>YvmRiiw(syvlD1 z`(|Qqb8e9jY!^H{^)8>?wSS20k2Dc|oR|pNokNS% zQ_%Aef+%u9mW3b!uD=y1gz~=+#*{tx-|&_l(i^cIX=!E*<=nusxtoPg$a{ERdqcEN z;_mRYqDC7O6rsi%Qg3BtAy2?-6bK?5DFg|;f&&i`II_RL7KdYiApG$;JOmQ-9)kGi zHge$k{_i7r-0$|1|OhWOKRFdAcT+ZA8=Aibcf*hlkZhD>@{Rx2^d*fuo%3tGBjp!wy?fG z4n)XV0KBv?wl|=1wlKG}6L1!$`C|(K@cRB^RvM~5HnBGorqPg9pn73tYfQz%!p6cz zBZ5XnMI~hW=Be*0yZ+Nx|LjzX;W*Zxmq@wb8g z<5MuwB4|Raf1foGG=E%;`v4+;FD9=7oy%#w9N@E~arW;f;Bn4dG;u)9Ic1Q26*7^mv+o}1OT^B+Wh{JB+nSq5SQS-jra85Eu@%LZzu{<%pbMCSSvhWqqz{zFH=qkWm*px6N_~O&(+Z z^Z#p>n+5Bz1%o$>=3gW-ICzWc3dKm_(|FV2Z&Ksh>jTO8mnS>flrF0{mF81r1vbtf zQLufksY_ZPkmc+Y)ytjiPARJv>k6B-9yDDQ)t!uMjcpEPl&5SwqfvN=I3RqcJyva{ zr&?_}SD>08tj(f*7mwN*^bq+ zEDi0G6r+NoaG8!uVi2>zC~SME)jEZ*cFVVS%Lmn%)Qc)Y2POZn>n$z*KE=hm`Z-Yl zV{BoBh^C`CUwP)8ja19u%2v9bm{uBgqE)(I{2E=*0}THW5*E(=WrY&KIU{aPSDF=| z-Cix+se$lOl8I#wiTMx(F5x5X&$MR<+z#6+s?DA^8VRj4uv8Hb!%TxWG#?S+cZ!>v zNJTx}w*_$N@8Wb_rIMYOLu@{=vHV|C83P(X4~9@nhE(a%JXM)Wi<$A-)&;M-#xESk zp?0p1>HfSRg#wh(LM`>Z>IKidmtlmt&2x@3vKCDj>x>4F@GoUZg_W0sUbh*Zms{DR z3w^B31u5V}%oSb2?}1nWABEgyHEKJ8ciuYh;d=G)fZ!nGQ#^3>iyvCdiW_5pE#vSa z2a{@5TNXZk6_3r!xT0>02u36hx2cW`kLfa!n4LyV$+^7dblS`)6P2bttVLN~nBaOf z_Wz3WpAq5lQ9g_Ds-{TaF5KOuei8Agv-3NoCeA0cT~jbYNdV#f$7G=Rn2zP;wquEE zC%ddCY;R^ns*#zO_~bYairzJB&(@YRU_E|(KPYqou$U*RqgbNXX;ssvOxZNI*T?de zKX_(xYV9@zGEHc})GpIn&)Re|qG0PFsOvkuEV9k^Q;(-`njNZ*(inrzmZ1vnmiT?) zHj902)p%l_UW~T^CR9!K3zs7HItR9o5)7idK_z50U6GroUaY$<{A51U5Sni9oOX3{ zwlJ3dGE8X(q>ZdD6v8(bzxr62eh5xr@XjjS$9kSYd!X5E)vRsbsEGghVQ-LIZ>rZV ze`Tl0?RtMg2AH`-rA^a(0mIvAlT?pULM`)BOeoLvJK9S7tzm9$2)#FQjkldzBhi0+b}1E)vtj#a1=g^I)bE zNXgypReq^a_v@H$kRcXOT6*eb6M4*TPbZDA2-baA@+{dN1lb5R*rP*5v?EBlr41-q zV<3txI1=Pv1st|N|8hr=uVOKnu6Vy4K%^^qBSlze!>IM;!NL4e=31H`rnC)w8)O1P z{k;(Dr1-POAs8O}A9*>$2JYk_4~2}O#^0RIScR+&hJyq^_2&xwS2@!Ly9HNc z!0Vvl_``+cB0cen_J(UsmBH!ml;q>?DRj|e`RY4*o)<3@W4wPy z%ZudxkifGD->2Q#54CX>IF5R*bfPj1E?_mYXzOIX>55$O$z;MffK7JS`{!?T*;S-gk3SR5QmUIhf zadW4~jl*85tydtF^KH2E?0)0fJb85kkLsc~4oa}|Sf)%I+Qk~_0+z^mS`IUv$ldjE zVPBsrQA&Q&M9A}#d`)lh1)FXP*W2q0!w*5m-VG5sI*FY=p^oUpSgLhK-5)M%H&RBr zR?Ib&lOoAVy_=4@$Q)L>BEks$@>KJ)*v`QMPMRT!!9HN^ii8%|JMQHj$z>=soGI=* zOz04eX%AgA-|SgEiipGtPe3kqT7`hC_=xbYpI}4QFtsSJ>lJ7^QPx&Sl)6ZW!EAUo z5$iOR*D^_U?r!1k$}8RWlQjAeMC5t}>B4cw!eopvt|=V`yTDxX%c0*SwCd&u*^{=uZo1ETALm1MEus zgNJ>wPw^sW@Z^P}R$}3O(8znTVJ!vMtn1bQ5}u5v9($}M9mr(rMeu6h^m7hw0=n^{ z-(m(`pZs=MhIQ*X^L})`9+fs5rH4f#b!gDe68D65#*gjemz>bi0!`(!&7l`puOZ(F z)1aQ`&-CnvUe<|6kiPVL$&&Id)eIydo|IUN#BKaYcsO0!Vg7E9Uq0ki$UT6I|Es68 z7V?h{-tx3pQM3~4Cz-Z@2_)(MdMjhU7Nh=ptWhK4;qZ*V>L@Y>>9<5~v$tbee27{1 z!?djbqvoh23r0n$yGnFKgFMRzSxKiuK!Uftc`ky-YfB|cen^e&3=&79XhzB1@yK0f zs9mjS`xW*dAVXe_kD{^&%SASl5+~CFPtRb{u|>RppCJ zJytbKftO&Z4dzSIw7lCM&As$Sz+^a2`dR0&)9?@h9^LmI@bYE8%V0OihLdtX$?-JQ zLPL~xD_X1kbR+R^0|mmb@STt9;3vS0*}jLW1@pc{*B9{4=Z8zW+YztK)#q4|R(v6! zMenYaML}Yz1DSIE(jOk~!ntqaoT1tl@N?e2h+}iBTmFSI1Z4Ig*AwB9>3 zF0wQ0y~>Fv$A;6weiff3$Zh;xulA}(KG2nG6~5*+7WthIKtJqZJlFeA(?*fP1;3sp zoNSMkhiWlL^_#-BK}@S;NJJ8K=Yrj!@HPO&V*5QqzhD?6)ggG34_GM6P~Lr-$+O!S2#Ia&2Pu}}DWb0P5>mhw zd7M7;yHNsl?XO)QD0V)%CvyQt7zqg0wLtd@Ip2D`(I}uRg!HH@xNtc4z+%<#Fpov2 zj?d_PB~nyi@Yz5BhrtjnI1STo3Mc!b4HA>2uMe;&&0}r>BrCribI7kTh}xbgF1|fZ zz4K3Ax1ssS08gZ2AH|^?|M`gO<2!yEPQ4O+pEiyD4G)rDGB$nhJWx%{Za>CdVE*!L zy4tGP`=to{{?-p)3DZI0vwjJi(%u%%ZvKs=3;?j?Ogc?8R#j7PO##N|0cspVa*)V&H^&&H5L!f*mdCe5|Y$1S@!9 z*WV?UCK}MoMQLg^6EridNP1DV;{bMH6qS^wej*bMOn$r|1W?yZXc)6?!LZ<0jmdR6 zEL{#?)=AreJk>D>+0strvG{VV@=mO6I=HZLoW9X=mNk+cr#iLohNKC=?SK&>D%9h* z;)f}rhLzC1o#)+gx{2ZMI=`rQF{s=fbwdY)Zdaq_3;LdL6)`ve(&-N8Ye}fTkPJ4N z1>BOA)o8V1L~g`cRL9(4xg*5oh^_?CogK~cw**?pOryxUEbgu}r~KI@ikbm+k1zZv z5uYq*??#99hh6{seCAEw!-;$iVPXF*=|wH*uszz~u2KWgW+aSYkN5p>N8LcCsWvub zwBE^Tr|K;&2NJwzmllt?%d5brNbnrjJ)+AJn5*k8s_Hrf+R}J)N>m@~p*_mW${)x- zk{VnRqU_cmG`UWd8Ozxjko*0#-8HM?Pv9?_OKDBXb#)I6)+NeEqy4RKc=`d<+~ef^DyRkxu_!xtXTMK9{0 zqom9RX6nDCMFnw>1b8;d)Y5eQt8ZYCDyC3=D&=}W8LUFAro!rZ*GrJR`WrApu019V zf^24o-C$~%lEtz%NbrkC$xibm->3Rfgxya2UwaL-UnB?h;T(VzqgMR7@=5fkmse!I zYz5Y-VtNkyvo1f5Er;OspYV8IJ2!rRoao%GpAo?`Y}6IbxSmz4TzyXf=54Ik)Ie@J zQP=aRl%t3ig84v-af;lH1#E-<6&n5tkyK!u;2f&w9FI?RPr^9|B!55RP@6ld-2Mr8 zJ9d6iOlu8fKO<7)a#LduGZ=7$)FZ;h?}eg5VBCTpxkxd8_X#D>d0m;OTVwq-?&=#V z-s4S>q_@_8B<_GbQCLgZZe0wN2G{z%DlNP48--G6F!B+DI;LahKKE#3&OR^r8~5<46IrRKF*tt`HGFUM&@f43q-H$esELc#g;bp-?C z*A5_OY*yYZ-T>mKCDv%JPT=m;ns?L5W@%No^|)TzE&L@IIik)Mk8vL%y1xjqb13pP z9Q92LQA3c&dV&eAhfg>GlSe>JQ5Tb+4O~g0s8>@o4h<6gZ5J86O|ym))gqDnuW08_ z2xk1=G5DEq56ZHW9Z4fTzk3(ADa_HmH*KSpQ1VeEJ3*C;i7 zX<9itUZ@p)mUM;I>jPj_J{61FRp?|?`J_Ozylj5DABZ-hzkj|6DM(Aw#oCX%J&|^` zu*E?^Z15Q}oiv@rKEVXVfmQhr9;9R^-#S~ZOKqpE_Uu$ofgN%!G~{}xgMEwL#V^O- z=~F*HFJ~GZa!^b**KTctWUfllPy_=(g=Ni$L970kLxEKEW70wV3rtYFZp

    XwuL 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

    -Y^uS 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\*lwV%$=WUv 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%0DBchXkDC)yRbfCt^lcRrvkorxUU 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 F{}+=J91;Kk literal 0 HcmV?d00001 From 7ce8d2e5fb9cc5f6f9de214584170a8cf01b98de Mon Sep 17 00:00:00 2001 From: David Truby Date: Thu, 16 May 2024 13:47:48 +0100 Subject: [PATCH 029/576] [clang][flang][windows] Prefer user-provided library paths (-L) (#90758) Currently the paths to compiler-rt and the Flang runtimes from the LLVM build/install directory are preferred over any user-provided library paths. This means a user can't override compiler-rt or the Flang runtimes with custom versions. This patch changes the link order to prefer library paths specified with -L over the LLVM paths. This matches the behaviour of clang and flang on Linux. --- clang/lib/Driver/ToolChains/MSVC.cpp | 8 ++++---- clang/test/Driver/flang/msvc-link.f90 | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 clang/test/Driver/flang/msvc-link.f90 diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index fbf2f45b543844..b7021d4b996ddd 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -134,6 +134,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } + if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) + for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) + CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); + if (C.getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(TC, Args, CmdArgs); addFortranRuntimeLibs(TC, Args, CmdArgs); @@ -154,10 +158,6 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (TC.getVFS().exists(CRTPath)) CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); - if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) - for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) - CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); - CmdArgs.push_back("-nologo"); if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) diff --git a/clang/test/Driver/flang/msvc-link.f90 b/clang/test/Driver/flang/msvc-link.f90 new file mode 100644 index 00000000000000..536da2599431f4 --- /dev/null +++ b/clang/test/Driver/flang/msvc-link.f90 @@ -0,0 +1,5 @@ +! RUN: %clang --driver-mode=flang -target x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s +! +! Test that user provided paths come before the Flang runtimes +! CHECK: "-libpath:test" +! CHECK: "-libpath:{{.*(\\|/)}}lib" From 7a66e4209b0b4cc0dc871a54c4f07a4b0054b5f7 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 16 May 2024 07:49:01 -0500 Subject: [PATCH 030/576] [flang][OpenMP] Remove unnecessary `Fortran::` qualification, NFC (#92298) The `Fortran::` namespace is redundant for all parts of the code in this PR, except for names of functions in their definitions. --- flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 201 ++-- flang/lib/Lower/OpenMP/ClauseProcessor.h | 113 +- flang/lib/Lower/OpenMP/Clauses.cpp | 7 +- flang/lib/Lower/OpenMP/Clauses.h | 7 +- .../lib/Lower/OpenMP/DataSharingProcessor.cpp | 148 ++- flang/lib/Lower/OpenMP/DataSharingProcessor.h | 66 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 1057 ++++++++--------- flang/lib/Lower/OpenMP/ReductionProcessor.cpp | 23 +- flang/lib/Lower/OpenMP/ReductionProcessor.h | 13 +- flang/lib/Lower/OpenMP/Utils.cpp | 100 +- flang/lib/Lower/OpenMP/Utils.h | 24 +- 11 files changed, 790 insertions(+), 969 deletions(-) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 0ea87314d571f9..40d66460a69848 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -62,13 +62,13 @@ getSimdModifier(const omp::clause::Schedule &clause) { } static void -genAllocateClause(Fortran::lower::AbstractConverter &converter, +genAllocateClause(lower::AbstractConverter &converter, const omp::clause::Allocate &clause, llvm::SmallVectorImpl &allocatorOperands, llvm::SmallVectorImpl &allocateOperands) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; auto &objects = std::get(clause.t); @@ -144,7 +144,7 @@ genDependKindAttr(fir::FirOpBuilder &firOpBuilder, } static mlir::Value -getIfClauseOperand(Fortran::lower::AbstractConverter &converter, +getIfClauseOperand(lower::AbstractConverter &converter, const omp::clause::If &clause, omp::clause::If::DirectiveNameModifier directiveName, mlir::Location clauseLocation) { @@ -154,7 +154,7 @@ getIfClauseOperand(Fortran::lower::AbstractConverter &converter, if (directive && directive.value() != directiveName) return nullptr; - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Value ifVal = fir::getBase( converter.genExprValue(std::get(clause.t), stmtCtx)); @@ -163,12 +163,11 @@ getIfClauseOperand(Fortran::lower::AbstractConverter &converter, } static void addUseDeviceClause( - Fortran::lower::AbstractConverter &converter, - const omp::ObjectList &objects, + lower::AbstractConverter &converter, const omp::ObjectList &objects, llvm::SmallVectorImpl &operands, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSyms) { + llvm::SmallVectorImpl &useDeviceSyms) { genObjectList(objects, converter, operands); for (mlir::Value &operand : operands) { checkMapType(operand.getLoc(), operand.getType()); @@ -179,7 +178,7 @@ static void addUseDeviceClause( useDeviceSyms.push_back(object.id()); } -static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, +static void convertLoopBounds(lower::AbstractConverter &converter, mlir::Location loc, mlir::omp::CollapseClauseOps &result, std::size_t loopVarTypeSize) { @@ -202,45 +201,43 @@ static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, //===----------------------------------------------------------------------===// bool ClauseProcessor::processCollapse( - mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, + mlir::Location currentLocation, lower::pft::Evaluation &eval, mlir::omp::CollapseClauseOps &result, - llvm::SmallVectorImpl &iv) const { + llvm::SmallVectorImpl &iv) const { bool found = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // Collect the loops to collapse. - Fortran::lower::pft::Evaluation *doConstructEval = - &eval.getFirstNestedEvaluation(); - if (doConstructEval->getIf() - ->IsDoConcurrent()) { + lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation(); + if (doConstructEval->getIf()->IsDoConcurrent()) { TODO(currentLocation, "Do Concurrent in Worksharing loop construct"); } std::int64_t collapseValue = 1l; if (auto *clause = findUniqueClause()) { - collapseValue = Fortran::evaluate::ToInt64(clause->v).value(); + collapseValue = evaluate::ToInt64(clause->v).value(); found = true; } std::size_t loopVarTypeSize = 0; do { - Fortran::lower::pft::Evaluation *doLoop = + lower::pft::Evaluation *doLoop = &doConstructEval->getFirstNestedEvaluation(); - auto *doStmt = doLoop->getIf(); + auto *doStmt = doLoop->getIf(); assert(doStmt && "Expected do loop to be in the nested evaluation"); const auto &loopControl = - std::get>(doStmt->t); - const Fortran::parser::LoopControl::Bounds *bounds = - std::get_if(&loopControl->u); + std::get>(doStmt->t); + const parser::LoopControl::Bounds *bounds = + std::get_if(&loopControl->u); assert(bounds && "Expected bounds for worksharing do loop"); - Fortran::lower::StatementContext stmtCtx; - result.loopLBVar.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->lower), stmtCtx))); - result.loopUBVar.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->upper), stmtCtx))); + lower::StatementContext stmtCtx; + result.loopLBVar.push_back(fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->lower), stmtCtx))); + result.loopUBVar.push_back(fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->upper), stmtCtx))); if (bounds->step) { - result.loopStepVar.push_back(fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(bounds->step), stmtCtx))); + result.loopStepVar.push_back(fir::getBase( + converter.genExprValue(*semantics::GetExpr(bounds->step), stmtCtx))); } else { // If `step` is not present, assume it as `1`. result.loopStepVar.push_back(firOpBuilder.createIntegerConstant( currentLocation, firOpBuilder.getIntegerType(32), 1)); @@ -280,9 +277,9 @@ bool ClauseProcessor::processDefault() const { return false; } -bool ClauseProcessor::processDevice(Fortran::lower::StatementContext &stmtCtx, +bool ClauseProcessor::processDevice(lower::StatementContext &stmtCtx, mlir::omp::DeviceClauseOps &result) const { - const Fortran::parser::CharBlock *source = nullptr; + const parser::CharBlock *source = nullptr; if (auto *clause = findUniqueClause(&source)) { mlir::Location clauseLocation = converter.genLocation(*source); if (auto deviceModifier = @@ -320,9 +317,9 @@ bool ClauseProcessor::processDeviceType( return false; } -bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, +bool ClauseProcessor::processFinal(lower::StatementContext &stmtCtx, mlir::omp::FinalClauseOps &result) const { - const Fortran::parser::CharBlock *source = nullptr; + const parser::CharBlock *source = nullptr; if (auto *clause = findUniqueClause(&source)) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location clauseLocation = converter.genLocation(*source); @@ -339,7 +336,7 @@ bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, bool ClauseProcessor::processHint(mlir::omp::HintClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - int64_t hintValue = *Fortran::evaluate::ToInt64(clause->v); + int64_t hintValue = *evaluate::ToInt64(clause->v); result.hintAttr = firOpBuilder.getI64IntegerAttr(hintValue); return true; } @@ -356,7 +353,7 @@ bool ClauseProcessor::processNowait(mlir::omp::NowaitClauseOps &result) const { } bool ClauseProcessor::processNumTeams( - Fortran::lower::StatementContext &stmtCtx, + lower::StatementContext &stmtCtx, mlir::omp::NumTeamsClauseOps &result) const { // TODO Get lower and upper bounds for num_teams when parser is updated to // accept both. @@ -371,7 +368,7 @@ bool ClauseProcessor::processNumTeams( } bool ClauseProcessor::processNumThreads( - Fortran::lower::StatementContext &stmtCtx, + lower::StatementContext &stmtCtx, mlir::omp::NumThreadsClauseOps &result) const { if (auto *clause = findUniqueClause()) { // OMPIRBuilder expects `NUM_THREADS` clause as a `Value`. @@ -388,7 +385,7 @@ bool ClauseProcessor::processOrdered( fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); int64_t orderedClauseValue = 0l; if (clause->v.has_value()) - orderedClauseValue = *Fortran::evaluate::ToInt64(*clause->v); + orderedClauseValue = *evaluate::ToInt64(*clause->v); result.orderedAttr = firOpBuilder.getI64IntegerAttr(orderedClauseValue); return true; } @@ -396,7 +393,7 @@ bool ClauseProcessor::processOrdered( } bool ClauseProcessor::processPriority( - Fortran::lower::StatementContext &stmtCtx, + lower::StatementContext &stmtCtx, mlir::omp::PriorityClauseOps &result) const { if (auto *clause = findUniqueClause()) { result.priorityVar = @@ -420,8 +417,7 @@ bool ClauseProcessor::processSafelen( mlir::omp::SafelenClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - const std::optional safelenVal = - Fortran::evaluate::ToInt64(clause->v); + const std::optional safelenVal = evaluate::ToInt64(clause->v); result.safelenAttr = firOpBuilder.getI64IntegerAttr(*safelenVal); return true; } @@ -429,7 +425,7 @@ bool ClauseProcessor::processSafelen( } bool ClauseProcessor::processSchedule( - Fortran::lower::StatementContext &stmtCtx, + lower::StatementContext &stmtCtx, mlir::omp::ScheduleClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -479,8 +475,7 @@ bool ClauseProcessor::processSimdlen( mlir::omp::SimdlenClauseOps &result) const { if (auto *clause = findUniqueClause()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - const std::optional simdlenVal = - Fortran::evaluate::ToInt64(clause->v); + const std::optional simdlenVal = evaluate::ToInt64(clause->v); result.simdlenAttr = firOpBuilder.getI64IntegerAttr(*simdlenVal); return true; } @@ -488,7 +483,7 @@ bool ClauseProcessor::processSimdlen( } bool ClauseProcessor::processThreadLimit( - Fortran::lower::StatementContext &stmtCtx, + lower::StatementContext &stmtCtx, mlir::omp::ThreadLimitClauseOps &result) const { if (auto *clause = findUniqueClause()) { result.threadLimitVar = @@ -509,8 +504,7 @@ bool ClauseProcessor::processUntied(mlir::omp::UntiedClauseOps &result) const { bool ClauseProcessor::processAllocate( mlir::omp::AllocateClauseOps &result) const { return findRepeatableClause( - [&](const omp::clause::Allocate &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::Allocate &clause, const parser::CharBlock &) { genAllocateClause(converter, clause, result.allocatorVars, result.allocateVars); }); @@ -521,30 +515,28 @@ bool ClauseProcessor::processCopyin() const { mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint(); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); auto checkAndCopyHostAssociateVar = - [&](Fortran::semantics::Symbol *sym, + [&](semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr) { - assert(sym->has() && + assert(sym->has() && "No host-association found"); if (converter.isPresentShallowLookup(*sym)) converter.copyHostAssociateVar(*sym, copyAssignIP); }; bool hasCopyin = findRepeatableClause( - [&](const omp::clause::Copyin &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::Copyin &clause, const parser::CharBlock &) { for (const omp::Object &object : clause.v) { - Fortran::semantics::Symbol *sym = object.id(); + semantics::Symbol *sym = object.id(); assert(sym && "Expecting symbol"); if (const auto *commonDetails = - sym->detailsIf()) { + sym->detailsIf()) { for (const auto &mem : commonDetails->objects()) checkAndCopyHostAssociateVar(&*mem, &insPt); break; } - if (Fortran::semantics::IsAllocatableOrObjectPointer( - &sym->GetUltimate())) + if (semantics::IsAllocatableOrObjectPointer(&sym->GetUltimate())) TODO(converter.getCurrentLocation(), "pointer or allocatable variables in Copyin clause"); - assert(sym->has() && + assert(sym->has() && "No host-association found"); checkAndCopyHostAssociateVar(sym); } @@ -616,7 +608,7 @@ void TypeInfo::typeScan(mlir::Type ty) { // Create a function that performs a copy between two variables, compatible // with their types and attributes. static mlir::func::FuncOp -createCopyFunc(mlir::Location loc, Fortran::lower::AbstractConverter &converter, +createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter, mlir::Type varType, fir::FortranVariableFlagsEnum varAttrs) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::ModuleOp module = builder.getModule(); @@ -671,7 +663,7 @@ createCopyFunc(mlir::Location loc, Fortran::lower::AbstractConverter &converter, bool ClauseProcessor::processCopyprivate( mlir::Location currentLocation, mlir::omp::CopyprivateClauseOps &result) const { - auto addCopyPrivateVar = [&](Fortran::semantics::Symbol *sym) { + auto addCopyPrivateVar = [&](semantics::Symbol *sym) { mlir::Value symVal = converter.getSymbolAddress(*sym); auto declOp = symVal.getDefiningOp(); if (!declOp) @@ -704,12 +696,11 @@ bool ClauseProcessor::processCopyprivate( }; bool hasCopyPrivate = findRepeatableClause( - [&](const clause::Copyprivate &clause, - const Fortran::parser::CharBlock &) { + [&](const clause::Copyprivate &clause, const parser::CharBlock &) { for (const Object &object : clause.v) { - Fortran::semantics::Symbol *sym = object.id(); + semantics::Symbol *sym = object.id(); if (const auto *commonDetails = - sym->detailsIf()) { + sym->detailsIf()) { for (const auto &mem : commonDetails->objects()) addCopyPrivateVar(&*mem); break; @@ -725,8 +716,7 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); return findRepeatableClause( - [&](const omp::clause::Depend &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::Depend &clause, const parser::CharBlock &) { using Depend = omp::clause::Depend; assert(std::holds_alternative(clause.u) && "Only the modern form is handled at the moment"); @@ -741,15 +731,15 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const { for (const omp::Object &object : objects) { assert(object.ref() && "Expecting designator"); - if (Fortran::evaluate::ExtractSubstring(*object.ref())) { + if (evaluate::ExtractSubstring(*object.ref())) { TODO(converter.getCurrentLocation(), "substring not supported for task depend"); - } else if (Fortran::evaluate::IsArrayElement(*object.ref())) { + } else if (evaluate::IsArrayElement(*object.ref())) { TODO(converter.getCurrentLocation(), "array sections not supported for task depend"); } - Fortran::semantics::Symbol *sym = object.id(); + semantics::Symbol *sym = object.id(); const mlir::Value variable = converter.getSymbolAddress(*sym); result.dependVars.push_back(variable); } @@ -760,11 +750,10 @@ bool ClauseProcessor::processHasDeviceAddr( mlir::omp::HasDeviceAddrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, - llvm::SmallVectorImpl &isDeviceSymbols) - const { + llvm::SmallVectorImpl &isDeviceSymbols) const { return findRepeatableClause( [&](const omp::clause::HasDeviceAddr &devAddrClause, - const Fortran::parser::CharBlock &) { + const parser::CharBlock &) { addUseDeviceClause(converter, devAddrClause.v, result.hasDeviceAddrVars, isDeviceTypes, isDeviceLocs, isDeviceSymbols); }); @@ -774,19 +763,18 @@ bool ClauseProcessor::processIf( omp::clause::If::DirectiveNameModifier directiveName, mlir::omp::IfClauseOps &result) const { bool found = false; - findRepeatableClause( - [&](const omp::clause::If &clause, - const Fortran::parser::CharBlock &source) { - mlir::Location clauseLocation = converter.genLocation(source); - mlir::Value operand = getIfClauseOperand(converter, clause, - directiveName, clauseLocation); - // Assume that, at most, a single 'if' clause will be applicable to the - // given directive. - if (operand) { - result.ifVar = operand; - found = true; - } - }); + findRepeatableClause([&](const omp::clause::If &clause, + const parser::CharBlock &source) { + mlir::Location clauseLocation = converter.genLocation(source); + mlir::Value operand = + getIfClauseOperand(converter, clause, directiveName, clauseLocation); + // Assume that, at most, a single 'if' clause will be applicable to the + // given directive. + if (operand) { + result.ifVar = operand; + found = true; + } + }); return found; } @@ -794,11 +782,10 @@ bool ClauseProcessor::processIsDevicePtr( mlir::omp::IsDevicePtrClauseOps &result, llvm::SmallVectorImpl &isDeviceTypes, llvm::SmallVectorImpl &isDeviceLocs, - llvm::SmallVectorImpl &isDeviceSymbols) - const { + llvm::SmallVectorImpl &isDeviceSymbols) const { return findRepeatableClause( [&](const omp::clause::IsDevicePtr &devPtrClause, - const Fortran::parser::CharBlock &) { + const parser::CharBlock &) { addUseDeviceClause(converter, devPtrClause.v, result.isDevicePtrVars, isDeviceTypes, isDeviceLocs, isDeviceSymbols); }); @@ -807,7 +794,7 @@ bool ClauseProcessor::processIsDevicePtr( bool ClauseProcessor::processLink( llvm::SmallVectorImpl &result) const { return findRepeatableClause( - [&](const omp::clause::Link &clause, const Fortran::parser::CharBlock &) { + [&](const omp::clause::Link &clause, const parser::CharBlock &) { // Case: declare target link(var1, var2)... gatherFuncAndVarSyms( clause.v, mlir::omp::DeclareTargetCaptureClause::link, result); @@ -815,25 +802,24 @@ bool ClauseProcessor::processLink( } bool ClauseProcessor::processMap( - mlir::Location currentLocation, Fortran::lower::StatementContext &stmtCtx, + mlir::Location currentLocation, lower::StatementContext &stmtCtx, mlir::omp::MapClauseOps &result, - llvm::SmallVectorImpl *mapSyms, + llvm::SmallVectorImpl *mapSyms, llvm::SmallVectorImpl *mapSymLocs, llvm::SmallVectorImpl *mapSymTypes) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); // We always require tracking of symbols, even if the caller does not, // so we create an optionally used local set of symbols when the mapSyms // argument is not present. - llvm::SmallVector localMapSyms; - llvm::SmallVectorImpl *ptrMapSyms = + llvm::SmallVector localMapSyms; + llvm::SmallVectorImpl *ptrMapSyms = mapSyms ? mapSyms : &localMapSyms; - std::map> parentMemberIndices; bool clauseFound = findRepeatableClause( - [&](const omp::clause::Map &clause, - const Fortran::parser::CharBlock &source) { + [&](const omp::clause::Map &clause, const parser::CharBlock &source) { using Map = omp::clause::Map; mlir::Location clauseLocation = converter.genLocation(source); const auto &mapType = std::get>(clause.t); @@ -881,9 +867,9 @@ bool ClauseProcessor::processMap( llvm::SmallVector bounds; std::stringstream asFortran; - Fortran::lower::AddrAndBoundsInfo info = - Fortran::lower::gatherDataOperandAddrAndBounds< - mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>( + lower::AddrAndBoundsInfo info = + lower::gatherDataOperandAddrAndBounds( converter, firOpBuilder, semaCtx, stmtCtx, *object.id(), object.ref(), clauseLocation, asFortran, bounds, treatIndexAsSection); @@ -928,18 +914,16 @@ bool ClauseProcessor::processMap( bool ClauseProcessor::processReduction( mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result, llvm::SmallVectorImpl *outReductionTypes, - llvm::SmallVectorImpl *outReductionSyms) - const { + llvm::SmallVectorImpl *outReductionSyms) const { return findRepeatableClause( - [&](const omp::clause::Reduction &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::Reduction &clause, const parser::CharBlock &) { // Use local lists of reductions to prevent variables from other // already-processed reduction clauses from impacting this reduction. // For example, the whole `reductionVars` array is queried to decide // whether to do the reduction byref. llvm::SmallVector reductionVars; llvm::SmallVector reductionDeclSymbols; - llvm::SmallVector reductionSyms; + llvm::SmallVector reductionSyms; ReductionProcessor rp; rp.addDeclareReduction(currentLocation, converter, clause, reductionVars, reductionDeclSymbols, @@ -965,7 +949,7 @@ bool ClauseProcessor::processReduction( bool ClauseProcessor::processSectionsReduction( mlir::Location currentLocation, mlir::omp::ReductionClauseOps &) const { return findRepeatableClause( - [&](const omp::clause::Reduction &, const Fortran::parser::CharBlock &) { + [&](const omp::clause::Reduction &, const parser::CharBlock &) { TODO(currentLocation, "OMPC_Reduction"); }); } @@ -973,7 +957,7 @@ bool ClauseProcessor::processSectionsReduction( bool ClauseProcessor::processTo( llvm::SmallVectorImpl &result) const { return findRepeatableClause( - [&](const omp::clause::To &clause, const Fortran::parser::CharBlock &) { + [&](const omp::clause::To &clause, const parser::CharBlock &) { // Case: declare target to(func, var1, var2)... gatherFuncAndVarSyms(std::get(clause.t), mlir::omp::DeclareTargetCaptureClause::to, result); @@ -983,8 +967,7 @@ bool ClauseProcessor::processTo( bool ClauseProcessor::processEnter( llvm::SmallVectorImpl &result) const { return findRepeatableClause( - [&](const omp::clause::Enter &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::Enter &clause, const parser::CharBlock &) { // Case: declare target enter(func, var1, var2)... gatherFuncAndVarSyms( clause.v, mlir::omp::DeclareTargetCaptureClause::enter, result); @@ -995,11 +978,9 @@ bool ClauseProcessor::processUseDeviceAddr( mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSyms) - const { + llvm::SmallVectorImpl &useDeviceSyms) const { return findRepeatableClause( - [&](const omp::clause::UseDeviceAddr &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::UseDeviceAddr &clause, const parser::CharBlock &) { addUseDeviceClause(converter, clause.v, result.useDeviceAddrVars, useDeviceTypes, useDeviceLocs, useDeviceSyms); }); @@ -1009,11 +990,9 @@ bool ClauseProcessor::processUseDevicePtr( mlir::omp::UseDeviceClauseOps &result, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSyms) - const { + llvm::SmallVectorImpl &useDeviceSyms) const { return findRepeatableClause( - [&](const omp::clause::UseDevicePtr &clause, - const Fortran::parser::CharBlock &) { + [&](const omp::clause::UseDevicePtr &clause, const parser::CharBlock &) { addUseDeviceClause(converter, clause.v, result.useDevicePtrVars, useDeviceTypes, useDeviceLocs, useDeviceSyms); }); diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 54ffcd0c964bfb..7e7a291b94aeee 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -47,44 +47,43 @@ namespace omp { /// construct. class ClauseProcessor { public: - ClauseProcessor(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, + ClauseProcessor(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses) : converter(converter), semaCtx(semaCtx), clauses(clauses) {} // 'Unique' clauses: They can appear at most once in the clause list. - bool processCollapse( - mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, - mlir::omp::CollapseClauseOps &result, - llvm::SmallVectorImpl &iv) const; + bool + processCollapse(mlir::Location currentLocation, lower::pft::Evaluation &eval, + mlir::omp::CollapseClauseOps &result, + llvm::SmallVectorImpl &iv) const; bool processDefault() const; - bool processDevice(Fortran::lower::StatementContext &stmtCtx, + bool processDevice(lower::StatementContext &stmtCtx, mlir::omp::DeviceClauseOps &result) const; bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const; - bool processFinal(Fortran::lower::StatementContext &stmtCtx, + bool processFinal(lower::StatementContext &stmtCtx, mlir::omp::FinalClauseOps &result) const; - bool - processHasDeviceAddr(mlir::omp::HasDeviceAddrClauseOps &result, - llvm::SmallVectorImpl &isDeviceTypes, - llvm::SmallVectorImpl &isDeviceLocs, - llvm::SmallVectorImpl - &isDeviceSymbols) const; + bool processHasDeviceAddr( + mlir::omp::HasDeviceAddrClauseOps &result, + llvm::SmallVectorImpl &isDeviceTypes, + llvm::SmallVectorImpl &isDeviceLocs, + llvm::SmallVectorImpl &isDeviceSymbols) const; bool processHint(mlir::omp::HintClauseOps &result) const; bool processMergeable(mlir::omp::MergeableClauseOps &result) const; bool processNowait(mlir::omp::NowaitClauseOps &result) const; - bool processNumTeams(Fortran::lower::StatementContext &stmtCtx, + bool processNumTeams(lower::StatementContext &stmtCtx, mlir::omp::NumTeamsClauseOps &result) const; - bool processNumThreads(Fortran::lower::StatementContext &stmtCtx, + bool processNumThreads(lower::StatementContext &stmtCtx, mlir::omp::NumThreadsClauseOps &result) const; bool processOrdered(mlir::omp::OrderedClauseOps &result) const; - bool processPriority(Fortran::lower::StatementContext &stmtCtx, + bool processPriority(lower::StatementContext &stmtCtx, mlir::omp::PriorityClauseOps &result) const; bool processProcBind(mlir::omp::ProcBindClauseOps &result) const; bool processSafelen(mlir::omp::SafelenClauseOps &result) const; - bool processSchedule(Fortran::lower::StatementContext &stmtCtx, + bool processSchedule(lower::StatementContext &stmtCtx, mlir::omp::ScheduleClauseOps &result) const; bool processSimdlen(mlir::omp::SimdlenClauseOps &result) const; - bool processThreadLimit(Fortran::lower::StatementContext &stmtCtx, + bool processThreadLimit(lower::StatementContext &stmtCtx, mlir::omp::ThreadLimitClauseOps &result) const; bool processUntied(mlir::omp::UntiedClauseOps &result) const; @@ -98,12 +97,11 @@ class ClauseProcessor { processEnter(llvm::SmallVectorImpl &result) const; bool processIf(omp::clause::If::DirectiveNameModifier directiveName, mlir::omp::IfClauseOps &result) const; - bool - processIsDevicePtr(mlir::omp::IsDevicePtrClauseOps &result, - llvm::SmallVectorImpl &isDeviceTypes, - llvm::SmallVectorImpl &isDeviceLocs, - llvm::SmallVectorImpl - &isDeviceSymbols) const; + bool processIsDevicePtr( + mlir::omp::IsDevicePtrClauseOps &result, + llvm::SmallVectorImpl &isDeviceTypes, + llvm::SmallVectorImpl &isDeviceLocs, + llvm::SmallVectorImpl &isDeviceSymbols) const; bool processLink(llvm::SmallVectorImpl &result) const; @@ -113,35 +111,32 @@ class ClauseProcessor { // They may be used later on to create the block_arguments for some of the // target directives that require it. bool processMap( - mlir::Location currentLocation, Fortran::lower::StatementContext &stmtCtx, + mlir::Location currentLocation, lower::StatementContext &stmtCtx, mlir::omp::MapClauseOps &result, - llvm::SmallVectorImpl *mapSyms = - nullptr, + llvm::SmallVectorImpl *mapSyms = nullptr, llvm::SmallVectorImpl *mapSymLocs = nullptr, llvm::SmallVectorImpl *mapSymTypes = nullptr) const; bool processReduction( mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result, llvm::SmallVectorImpl *reductionTypes = nullptr, - llvm::SmallVectorImpl *reductionSyms = + llvm::SmallVectorImpl *reductionSyms = nullptr) const; bool processSectionsReduction(mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result) const; bool processTo(llvm::SmallVectorImpl &result) const; - bool - processUseDeviceAddr(mlir::omp::UseDeviceClauseOps &result, - llvm::SmallVectorImpl &useDeviceTypes, - llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl - &useDeviceSyms) const; - bool - processUseDevicePtr(mlir::omp::UseDeviceClauseOps &result, - llvm::SmallVectorImpl &useDeviceTypes, - llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl - &useDeviceSyms) const; + bool processUseDeviceAddr( + mlir::omp::UseDeviceClauseOps &result, + llvm::SmallVectorImpl &useDeviceTypes, + llvm::SmallVectorImpl &useDeviceLocs, + llvm::SmallVectorImpl &useDeviceSyms) const; + bool processUseDevicePtr( + mlir::omp::UseDeviceClauseOps &result, + llvm::SmallVectorImpl &useDeviceTypes, + llvm::SmallVectorImpl &useDeviceLocs, + llvm::SmallVectorImpl &useDeviceSyms) const; template - bool processMotionClauses(Fortran::lower::StatementContext &stmtCtx, + bool processMotionClauses(lower::StatementContext &stmtCtx, mlir::omp::MapClauseOps &result); // Call this method for these clauses that should be supported but are not @@ -162,36 +157,34 @@ class ClauseProcessor { /// `nullptr` if not present. If more than one instance is expected, use /// `findRepeatableClause` instead. template - const T * - findUniqueClause(const Fortran::parser::CharBlock **source = nullptr) const; + const T *findUniqueClause(const parser::CharBlock **source = nullptr) const; /// Call `callbackFn` for each occurrence of the given clause. Return `true` /// if at least one instance was found. template bool findRepeatableClause( - std::function + std::function callbackFn) const; /// Set the `result` to a new `mlir::UnitAttr` if the clause is present. template bool markClauseOccurrence(mlir::UnitAttr &result) const; - Fortran::lower::AbstractConverter &converter; - Fortran::semantics::SemanticsContext &semaCtx; + lower::AbstractConverter &converter; + semantics::SemanticsContext &semaCtx; List clauses; }; template -bool ClauseProcessor::processMotionClauses( - Fortran::lower::StatementContext &stmtCtx, - mlir::omp::MapClauseOps &result) { - std::map> parentMemberIndices; - llvm::SmallVector mapSymbols; + llvm::SmallVector mapSymbols; bool clauseFound = findRepeatableClause( - [&](const T &clause, const Fortran::parser::CharBlock &source) { + [&](const T &clause, const parser::CharBlock &source) { mlir::Location clauseLocation = converter.genLocation(source); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -209,9 +202,9 @@ bool ClauseProcessor::processMotionClauses( llvm::SmallVector bounds; std::stringstream asFortran; - Fortran::lower::AddrAndBoundsInfo info = - Fortran::lower::gatherDataOperandAddrAndBounds< - mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>( + lower::AddrAndBoundsInfo info = + lower::gatherDataOperandAddrAndBounds( converter, firOpBuilder, semaCtx, stmtCtx, *object.id(), object.ref(), clauseLocation, asFortran, bounds, treatIndexAsSection); @@ -277,8 +270,8 @@ ClauseProcessor::findClause(ClauseIterator begin, ClauseIterator end) { } template -const T *ClauseProcessor::findUniqueClause( - const Fortran::parser::CharBlock **source) const { +const T * +ClauseProcessor::findUniqueClause(const parser::CharBlock **source) const { ClauseIterator it = findClause(clauses.begin(), clauses.end()); if (it != clauses.end()) { if (source) @@ -290,8 +283,8 @@ const T *ClauseProcessor::findUniqueClause( template bool ClauseProcessor::findRepeatableClause( - std::function - callbackFn) const { + std::function callbackFn) + const { bool found = false; ClauseIterator nextIt, endIt = clauses.end(); for (ClauseIterator it = clauses.begin(); it != endIt; it = nextIt) { diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 87370c92964a5c..1e3fea7c4cdc75 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -150,9 +150,8 @@ Object makeObject(const parser::OmpObject &object, return makeObject(std::get(object.u), semaCtx); } -std::optional -getBaseObject(const Object &object, - Fortran::semantics::SemanticsContext &semaCtx) { +std::optional getBaseObject(const Object &object, + semantics::SemanticsContext &semaCtx) { // If it's just the symbol, then there is no base. if (!object.id()) return std::nullopt; @@ -1211,7 +1210,7 @@ UsesAllocators make(const parser::OmpClause::UsesAllocators &inp, // Write: empty } // namespace clause -Clause makeClause(const Fortran::parser::OmpClause &cls, +Clause makeClause(const parser::OmpClause &cls, semantics::SemanticsContext &semaCtx) { return std::visit( [&](auto &&s) { diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index ca610c6528962f..5391b134e979dc 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -107,9 +107,8 @@ std::optional maybeApply(FuncTy &&func, return std::move(func(*arg)); } -std::optional -getBaseObject(const Object &object, - Fortran::semantics::SemanticsContext &semaCtx); +std::optional getBaseObject(const Object &object, + semantics::SemanticsContext &semaCtx); namespace clause { using DefinedOperator = tomp::type::DefinedOperatorT; @@ -262,7 +261,7 @@ Clause makeClause(llvm::omp::Clause id, Specific &&specific, return Clause(typename Clause::BaseT{id, specific}, source); } -Clause makeClause(const Fortran::parser::OmpClause &cls, +Clause makeClause(const parser::OmpClause &cls, semantics::SemanticsContext &semaCtx); List makeClauses(const parser::OmpClauseList &clauses, diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 82d8d8dd98ea29..84e745f28f9742 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -25,7 +25,7 @@ namespace omp { void DataSharingProcessor::processStep1( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms) { + llvm::SmallVectorImpl *privateSyms) { collectSymbolsForPrivatization(); collectDefaultSymbols(); collectImplicitSymbols(); @@ -57,14 +57,14 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) { } void DataSharingProcessor::insertDeallocs() { - for (const Fortran::semantics::Symbol *sym : privatizedSymbols) - if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) { + for (const semantics::Symbol *sym : privatizedSymbols) + if (semantics::IsAllocatable(sym->GetUltimate())) { if (!useDelayedPrivatization) { converter.createHostAssociateVarCloneDealloc(*sym); return; } - Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym); + lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym); assert(hsb && "Host symbol box not found"); mlir::Type symType = hsb.getAddr().getType(); mlir::Location symLoc = hsb.getAddr().getLoc(); @@ -91,10 +91,10 @@ void DataSharingProcessor::insertDeallocs() { } } -void DataSharingProcessor::cloneSymbol(const Fortran::semantics::Symbol *sym) { +void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) { // Privatization for symbols which are pre-determined (like loop index // variables) happen separately, for everything else privatize here. - if (sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) + if (sym->test(semantics::Symbol::Flag::OmpPreDetermined)) return; bool success = converter.createHostAssociateVarClone(*sym); (void)success; @@ -102,22 +102,21 @@ void DataSharingProcessor::cloneSymbol(const Fortran::semantics::Symbol *sym) { } void DataSharingProcessor::copyFirstPrivateSymbol( - const Fortran::semantics::Symbol *sym, - mlir::OpBuilder::InsertPoint *copyAssignIP) { - if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate)) + const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP) { + if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate)) converter.copyHostAssociateVar(*sym, copyAssignIP); } void DataSharingProcessor::copyLastPrivateSymbol( - const Fortran::semantics::Symbol *sym, + const semantics::Symbol *sym, [[maybe_unused]] mlir::OpBuilder::InsertPoint *lastPrivIP) { - if (sym->test(Fortran::semantics::Symbol::Flag::OmpLastPrivate)) + if (sym->test(semantics::Symbol::Flag::OmpLastPrivate)) converter.copyHostAssociateVar(*sym, lastPrivIP); } void DataSharingProcessor::collectOmpObjectListSymbol( const omp::ObjectList &objects, - llvm::SetVector &symbolSet) { + llvm::SetVector &symbolSet) { for (const omp::Object &object : objects) symbolSet.insert(object.id()); } @@ -150,9 +149,9 @@ bool DataSharingProcessor::needBarrier() { // initialization of firstprivate variables and post-update of lastprivate // variables. // Emit implicit barrier for linear clause. Maybe on somewhere else. - for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { - if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) && - sym->test(Fortran::semantics::Symbol::Flag::OmpLastPrivate)) + for (const semantics::Symbol *sym : privatizedSymbols) { + if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) && + sym->test(semantics::Symbol::Flag::OmpLastPrivate)) return true; } return false; @@ -238,26 +237,26 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { } } -static const Fortran::parser::CharBlock * -getSource(const Fortran::semantics::SemanticsContext &semaCtx, - const Fortran::lower::pft::Evaluation &eval) { - const Fortran::parser::CharBlock *source = nullptr; +static const parser::CharBlock * +getSource(const semantics::SemanticsContext &semaCtx, + const lower::pft::Evaluation &eval) { + const parser::CharBlock *source = nullptr; - auto ompConsVisit = [&](const Fortran::parser::OpenMPConstruct &x) { - std::visit(Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPSectionsConstruct &x) { + auto ompConsVisit = [&](const parser::OpenMPConstruct &x) { + std::visit(common::visitors{ + [&](const parser::OpenMPSectionsConstruct &x) { source = &std::get<0>(x.t).source; }, - [&](const Fortran::parser::OpenMPLoopConstruct &x) { + [&](const parser::OpenMPLoopConstruct &x) { source = &std::get<0>(x.t).source; }, - [&](const Fortran::parser::OpenMPBlockConstruct &x) { + [&](const parser::OpenMPBlockConstruct &x) { source = &std::get<0>(x.t).source; }, - [&](const Fortran::parser::OpenMPCriticalConstruct &x) { + [&](const parser::OpenMPCriticalConstruct &x) { source = &std::get<0>(x.t).source; }, - [&](const Fortran::parser::OpenMPAtomicConstruct &x) { + [&](const parser::OpenMPAtomicConstruct &x) { std::visit([&](const auto &x) { source = &x.source; }, x.u); }, @@ -266,14 +265,10 @@ getSource(const Fortran::semantics::SemanticsContext &semaCtx, x.u); }; - eval.visit(Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPConstruct &x) { ompConsVisit(x); }, - [&](const Fortran::parser::OpenMPDeclarativeConstruct &x) { - source = &x.source; - }, - [&](const Fortran::parser::OmpEndLoopDirective &x) { - source = &x.source; - }, + eval.visit(common::visitors{ + [&](const parser::OpenMPConstruct &x) { ompConsVisit(x); }, + [&](const parser::OpenMPDeclarativeConstruct &x) { source = &x.source; }, + [&](const parser::OmpEndLoopDirective &x) { source = &x.source; }, [&](const auto &x) {}, }); @@ -281,12 +276,9 @@ getSource(const Fortran::semantics::SemanticsContext &semaCtx, } void DataSharingProcessor::collectSymbolsInNestedRegions( - Fortran::lower::pft::Evaluation &eval, - Fortran::semantics::Symbol::Flag flag, - llvm::SetVector - &symbolsInNestedRegions) { - for (Fortran::lower::pft::Evaluation &nestedEval : - eval.getNestedEvaluations()) { + lower::pft::Evaluation &eval, semantics::Symbol::Flag flag, + llvm::SetVector &symbolsInNestedRegions) { + for (lower::pft::Evaluation &nestedEval : eval.getNestedEvaluations()) { if (nestedEval.hasNestedEvaluations()) { if (nestedEval.isConstruct()) // Recursively look for OpenMP constructs within `nestedEval`'s region @@ -307,46 +299,45 @@ void DataSharingProcessor::collectSymbolsInNestedRegions( // Later, in current context, all symbols in the set // `defaultSymbols` - `symbolsInNestedRegions` will be privatized. void DataSharingProcessor::collectSymbols( - Fortran::semantics::Symbol::Flag flag, - llvm::SetVector &symbols) { + semantics::Symbol::Flag flag, + llvm::SetVector &symbols) { // Collect all scopes associated with 'eval'. - llvm::SetVector clauseScopes; - std::function collectScopes = - [&](const Fortran::semantics::Scope *scope) { + llvm::SetVector clauseScopes; + std::function collectScopes = + [&](const semantics::Scope *scope) { clauseScopes.insert(scope); - for (const Fortran::semantics::Scope &child : scope->children()) + for (const semantics::Scope &child : scope->children()) collectScopes(&child); }; - const Fortran::parser::CharBlock *source = + const parser::CharBlock *source = clauses.empty() ? getSource(semaCtx, eval) : &clauses.front().source; - const Fortran::semantics::Scope *curScope = nullptr; + const semantics::Scope *curScope = nullptr; if (source && !source->empty()) { curScope = &semaCtx.FindScope(*source); collectScopes(curScope); } // Collect all symbols referenced in the evaluation being processed, // that matches 'flag'. - llvm::SetVector allSymbols; + llvm::SetVector allSymbols; converter.collectSymbolSet(eval, allSymbols, flag, /*collectSymbols=*/true, /*collectHostAssociatedSymbols=*/true); - llvm::SetVector symbolsInNestedRegions; + llvm::SetVector symbolsInNestedRegions; collectSymbolsInNestedRegions(eval, flag, symbolsInNestedRegions); // Filter-out symbols that must not be privatized. - bool collectImplicit = flag == Fortran::semantics::Symbol::Flag::OmpImplicit; - auto isPrivatizable = [](const Fortran::semantics::Symbol &sym) -> bool { - return !Fortran::semantics::IsProcedure(sym) && - !sym.GetUltimate().has() && - !sym.GetUltimate().has() && - !Fortran::semantics::IsImpliedDoIndex(sym.GetUltimate()); + bool collectImplicit = flag == semantics::Symbol::Flag::OmpImplicit; + auto isPrivatizable = [](const semantics::Symbol &sym) -> bool { + return !semantics::IsProcedure(sym) && + !sym.GetUltimate().has() && + !sym.GetUltimate().has() && + !semantics::IsImpliedDoIndex(sym.GetUltimate()); }; for (const auto *sym : allSymbols) { assert(curScope && "couldn't find current scope"); if (isPrivatizable(*sym) && !symbolsInNestedRegions.contains(sym) && !privatizedSymbols.contains(sym) && - !sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined) && - (collectImplicit || - !sym->test(Fortran::semantics::Symbol::Flag::OmpImplicit)) && + !sym->test(semantics::Symbol::Flag::OmpPreDetermined) && + (collectImplicit || !sym->test(semantics::Symbol::Flag::OmpImplicit)) && clauseScopes.contains(&sym->owner())) symbols.insert(sym); } @@ -358,10 +349,9 @@ void DataSharingProcessor::collectDefaultSymbols() { if (const auto *defaultClause = std::get_if(&clause.u)) { if (defaultClause->v == DataSharingAttribute::Private) - collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate, - defaultSymbols); + collectSymbols(semantics::Symbol::Flag::OmpPrivate, defaultSymbols); else if (defaultClause->v == DataSharingAttribute::Firstprivate) - collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate, + collectSymbols(semantics::Symbol::Flag::OmpFirstPrivate, defaultSymbols); } } @@ -370,16 +360,15 @@ void DataSharingProcessor::collectDefaultSymbols() { void DataSharingProcessor::collectImplicitSymbols() { // There will be no implicit symbols when a default clause is present. if (defaultSymbols.empty()) - collectSymbols(Fortran::semantics::Symbol::Flag::OmpImplicit, - implicitSymbols); + collectSymbols(semantics::Symbol::Flag::OmpImplicit, implicitSymbols); } void DataSharingProcessor::privatize( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms) { - for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { + llvm::SmallVectorImpl *privateSyms) { + for (const semantics::Symbol *sym : privatizedSymbols) { if (const auto *commonDet = - sym->detailsIf()) { + sym->detailsIf()) { for (const auto &mem : commonDet->objects()) doPrivatize(&*mem, clauseOps, privateSyms); } else @@ -389,9 +378,9 @@ void DataSharingProcessor::privatize( void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { insertLastPrivateCompare(op); - for (const Fortran::semantics::Symbol *sym : privatizedSymbols) + for (const semantics::Symbol *sym : privatizedSymbols) if (const auto *commonDet = - sym->detailsIf()) { + sym->detailsIf()) { for (const auto &mem : commonDet->objects()) { copyLastPrivateSymbol(&*mem, &lastPrivIP); } @@ -402,36 +391,34 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { void DataSharingProcessor::defaultPrivatize( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms) { - for (const Fortran::semantics::Symbol *sym : defaultSymbols) + llvm::SmallVectorImpl *privateSyms) { + for (const semantics::Symbol *sym : defaultSymbols) doPrivatize(sym, clauseOps, privateSyms); } void DataSharingProcessor::implicitPrivatize( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms) { - for (const Fortran::semantics::Symbol *sym : implicitSymbols) + llvm::SmallVectorImpl *privateSyms) { + for (const semantics::Symbol *sym : implicitSymbols) doPrivatize(sym, clauseOps, privateSyms); } void DataSharingProcessor::doPrivatize( - const Fortran::semantics::Symbol *sym, - mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms) { + const semantics::Symbol *sym, mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms) { if (!useDelayedPrivatization) { cloneSymbol(sym); copyFirstPrivateSymbol(sym); return; } - Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym); + lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym); assert(hsb && "Host symbol box not found"); mlir::Type symType = hsb.getAddr().getType(); mlir::Location symLoc = hsb.getAddr().getLoc(); std::string privatizerName = sym->name().ToString() + ".privatizer"; - bool isFirstPrivate = - sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate); + bool isFirstPrivate = sym->test(semantics::Symbol::Flag::OmpFirstPrivate); mlir::omp::PrivateClauseOp privatizerOp = [&]() { auto moduleOp = firOpBuilder.getModule(); @@ -468,8 +455,7 @@ void DataSharingProcessor::doPrivatize( hlfir::translateToExtendedValue( symLoc, firOpBuilder, hlfir::Entity{allocRegion.getArgument(0)}, /*contiguousHint=*/ - Fortran::evaluate::IsSimplyContiguous( - *sym, converter.getFoldingContext())) + evaluate::IsSimplyContiguous(*sym, converter.getFoldingContext())) .first; symTable->addSymbol(*sym, localExV); diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index ec6848f7bba365..111266eeb7848a 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -37,65 +37,61 @@ class DataSharingProcessor { mlir::OpBuilder::InsertPoint insPt; mlir::Value loopIV; // Symbols in private, firstprivate, and/or lastprivate clauses. - llvm::SetVector privatizedSymbols; - llvm::SetVector defaultSymbols; - llvm::SetVector implicitSymbols; - llvm::DenseMap + llvm::SetVector privatizedSymbols; + llvm::SetVector defaultSymbols; + llvm::SetVector implicitSymbols; + llvm::DenseMap symToPrivatizer; - Fortran::lower::AbstractConverter &converter; - Fortran::semantics::SemanticsContext &semaCtx; + lower::AbstractConverter &converter; + semantics::SemanticsContext &semaCtx; fir::FirOpBuilder &firOpBuilder; omp::List clauses; - Fortran::lower::pft::Evaluation &eval; + lower::pft::Evaluation &eval; bool useDelayedPrivatization; - Fortran::lower::SymMap *symTable; + lower::SymMap *symTable; bool needBarrier(); - void - collectSymbols(Fortran::semantics::Symbol::Flag flag, - llvm::SetVector &symbols); + void collectSymbols(semantics::Symbol::Flag flag, + llvm::SetVector &symbols); void collectSymbolsInNestedRegions( - Fortran::lower::pft::Evaluation &eval, - Fortran::semantics::Symbol::Flag flag, - llvm::SetVector - &symbolsInNestedRegions); + lower::pft::Evaluation &eval, semantics::Symbol::Flag flag, + llvm::SetVector &symbolsInNestedRegions); void collectOmpObjectListSymbol( const omp::ObjectList &objects, - llvm::SetVector &symbolSet); + llvm::SetVector &symbolSet); void collectSymbolsForPrivatization(); void insertBarrier(); void collectDefaultSymbols(); void collectImplicitSymbols(); - void privatize( - mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms); + void privatize(mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms); void defaultPrivatize( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms); + llvm::SmallVectorImpl *privateSyms); void implicitPrivatize( mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms); - void doPrivatize( - const Fortran::semantics::Symbol *sym, - mlir::omp::PrivateClauseOps *clauseOps, - llvm::SmallVectorImpl *privateSyms); + llvm::SmallVectorImpl *privateSyms); + void + doPrivatize(const semantics::Symbol *sym, + mlir::omp::PrivateClauseOps *clauseOps, + llvm::SmallVectorImpl *privateSyms); void copyLastPrivatize(mlir::Operation *op); void insertLastPrivateCompare(mlir::Operation *op); - void cloneSymbol(const Fortran::semantics::Symbol *sym); + void cloneSymbol(const semantics::Symbol *sym); void - copyFirstPrivateSymbol(const Fortran::semantics::Symbol *sym, + copyFirstPrivateSymbol(const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr); - void copyLastPrivateSymbol(const Fortran::semantics::Symbol *sym, + void copyLastPrivateSymbol(const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *lastPrivIP); void insertDeallocs(); public: - DataSharingProcessor(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, + DataSharingProcessor(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, - Fortran::lower::pft::Evaluation &eval, + lower::pft::Evaluation &eval, bool useDelayedPrivatization = false, - Fortran::lower::SymMap *symTable = nullptr) + lower::SymMap *symTable = nullptr) : hasLastPrivateOp(false), converter(converter), semaCtx(semaCtx), firOpBuilder(converter.getFirOpBuilder()), clauses(clauses), eval(eval), useDelayedPrivatization(useDelayedPrivatization), symTable(symTable) {} @@ -111,9 +107,9 @@ class DataSharingProcessor { // Step2 performs the copying for lastprivates and requires knowledge of the // MLIR operation to insert the last private update. Step2 adds // dealocation code as well. - void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr, - llvm::SmallVectorImpl - *privateSyms = nullptr); + void processStep1( + mlir::omp::PrivateClauseOps *clauseOps = nullptr, + llvm::SmallVectorImpl *privateSyms = nullptr); void processStep2(mlir::Operation *op, bool isLoop); void setLoopIV(mlir::Value iv) { diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index f05cf1f5120f8d..af27c59eb9937c 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -45,45 +45,45 @@ using namespace Fortran::lower::omp; // Code generation helper functions //===----------------------------------------------------------------------===// -static void genOMPDispatch(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const ConstructQueue &queue, +static void genOMPDispatch(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item); -static Fortran::lower::pft::Evaluation * -getCollapsedLoopEval(Fortran::lower::pft::Evaluation &eval, int collapseValue) { +static lower::pft::Evaluation * +getCollapsedLoopEval(lower::pft::Evaluation &eval, int collapseValue) { // Return the Evaluation of the innermost collapsed loop, or the current one // if there was no COLLAPSE. if (collapseValue == 0) return &eval; - Fortran::lower::pft::Evaluation *curEval = &eval.getFirstNestedEvaluation(); + lower::pft::Evaluation *curEval = &eval.getFirstNestedEvaluation(); for (int i = 1; i < collapseValue; i++) { // The nested evaluations should be DoConstructs (i.e. they should form // a loop nest). Each DoConstruct is a tuple . - assert(curEval->isA()); + assert(curEval->isA()); curEval = &*std::next(curEval->getNestedEvaluations().begin()); } return curEval; } -static void genNestedEvaluations(Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &eval, +static void genNestedEvaluations(lower::AbstractConverter &converter, + lower::pft::Evaluation &eval, int collapseValue = 0) { - Fortran::lower::pft::Evaluation *curEval = - getCollapsedLoopEval(eval, collapseValue); + lower::pft::Evaluation *curEval = getCollapsedLoopEval(eval, collapseValue); - for (Fortran::lower::pft::Evaluation &e : curEval->getNestedEvaluations()) + for (lower::pft::Evaluation &e : curEval->getNestedEvaluations()) converter.genEval(e); } -static fir::GlobalOp globalInitialization( - Fortran::lower::AbstractConverter &converter, - fir::FirOpBuilder &firOpBuilder, const Fortran::semantics::Symbol &sym, - const Fortran::lower::pft::Variable &var, mlir::Location currentLocation) { +static fir::GlobalOp globalInitialization(lower::AbstractConverter &converter, + fir::FirOpBuilder &firOpBuilder, + const semantics::Symbol &sym, + const lower::pft::Variable &var, + mlir::Location currentLocation) { mlir::Type ty = converter.genType(sym); std::string globalName = converter.mangleName(sym); mlir::StringAttr linkage = firOpBuilder.createInternalLinkage(); @@ -91,9 +91,9 @@ static fir::GlobalOp globalInitialization( firOpBuilder.createGlobal(currentLocation, ty, globalName, linkage); // Create default initialization for non-character scalar. - if (Fortran::semantics::IsAllocatableOrObjectPointer(&sym)) { + if (semantics::IsAllocatableOrObjectPointer(&sym)) { mlir::Type baseAddrType = mlir::dyn_cast(ty).getEleTy(); - Fortran::lower::createGlobalInitialization( + lower::createGlobalInitialization( firOpBuilder, global, [&](fir::FirOpBuilder &b) { mlir::Value nullAddr = b.createNullConstant(currentLocation, baseAddrType); @@ -102,7 +102,7 @@ static fir::GlobalOp globalInitialization( b.create(currentLocation, box); }); } else { - Fortran::lower::createGlobalInitialization( + lower::createGlobalInitialization( firOpBuilder, global, [&](fir::FirOpBuilder &b) { mlir::Value undef = b.create(currentLocation, ty); b.create(currentLocation, undef); @@ -126,20 +126,19 @@ static fir::ExtendedValue getExtendedValue(fir::ExtendedValue base, } #ifndef NDEBUG -static bool isThreadPrivate(Fortran::lower::SymbolRef sym) { - if (const auto *details = - sym->detailsIf()) { +static bool isThreadPrivate(lower::SymbolRef sym) { + if (const auto *details = sym->detailsIf()) { for (const auto &obj : details->objects()) - if (!obj->test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) + if (!obj->test(semantics::Symbol::Flag::OmpThreadprivate)) return false; return true; } - return sym->test(Fortran::semantics::Symbol::Flag::OmpThreadprivate); + return sym->test(semantics::Symbol::Flag::OmpThreadprivate); } #endif -static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, - Fortran::lower::pft::Evaluation &eval) { +static void threadPrivatizeVars(lower::AbstractConverter &converter, + lower::pft::Evaluation &eval) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); mlir::OpBuilder::InsertionGuard guard(firOpBuilder); @@ -152,7 +151,7 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, // non-threadprivate variable. This can happen, for instance, with a common // block, declared in a separate module, used by a parent procedure and // privatized in its child procedure. - auto genThreadprivateOp = [&](Fortran::lower::SymbolRef sym) -> mlir::Value { + auto genThreadprivateOp = [&](lower::SymbolRef sym) -> mlir::Value { assert(isThreadPrivate(sym)); mlir::Value symValue = converter.getSymbolAddress(sym); mlir::Operation *op = symValue.getDefiningOp(); @@ -164,28 +163,28 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, currentLocation, symValue.getType(), symValue); }; - llvm::SetVector threadprivateSyms; + llvm::SetVector threadprivateSyms; converter.collectSymbolSet(eval, threadprivateSyms, - Fortran::semantics::Symbol::Flag::OmpThreadprivate, + semantics::Symbol::Flag::OmpThreadprivate, /*collectSymbols=*/true, /*collectHostAssociatedSymbols=*/true); - std::set threadprivateSymNames; + std::set threadprivateSymNames; // For a COMMON block, the ThreadprivateOp is generated for itself instead of // its members, so only bind the value of the new copied ThreadprivateOp // inside the parallel region to the common block symbol only once for // multiple members in one COMMON block. - llvm::SetVector commonSyms; + llvm::SetVector commonSyms; for (std::size_t i = 0; i < threadprivateSyms.size(); i++) { - const Fortran::semantics::Symbol *sym = threadprivateSyms[i]; + const semantics::Symbol *sym = threadprivateSyms[i]; mlir::Value symThreadprivateValue; // The variable may be used more than once, and each reference has one // symbol with the same name. Only do once for references of one variable. if (threadprivateSymNames.find(sym->name()) != threadprivateSymNames.end()) continue; threadprivateSymNames.insert(sym->name()); - if (const Fortran::semantics::Symbol *common = - Fortran::semantics::FindCommonBlockContaining(sym->GetUltimate())) { + if (const semantics::Symbol *common = + semantics::FindCommonBlockContaining(sym->GetUltimate())) { mlir::Value commonThreadprivateValue; if (commonSyms.contains(common)) { commonThreadprivateValue = converter.getSymbolAddress(*common); @@ -194,7 +193,7 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, converter.bindSymbol(*common, commonThreadprivateValue); commonSyms.insert(common); } - symThreadprivateValue = Fortran::lower::genCommonBlockMember( + symThreadprivateValue = lower::genCommonBlockMember( converter, currentLocation, *sym, commonThreadprivateValue); } else { symThreadprivateValue = genThreadprivateOp(*sym); @@ -208,9 +207,9 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, } static mlir::Operation * -createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter, +createAndSetPrivatizedLoopVar(lower::AbstractConverter &converter, mlir::Location loc, mlir::Value indexVal, - const Fortran::semantics::Symbol *sym) { + const semantics::Symbol *sym) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint(); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); @@ -250,8 +249,7 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( mlir::omp::UseDeviceClauseOps &clauseOps, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl - &useDeviceSymbols) { + llvm::SmallVectorImpl &useDeviceSymbols) { auto moveElementToBack = [](size_t idx, auto &vector) { auto *iter = std::next(vector.begin(), idx); vector.push_back(*iter); @@ -285,23 +283,20 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( /// Extract the list of function and variable symbols affected by the given /// 'declare target' directive and return the intended device type for them. static void getDeclareTargetInfo( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, mlir::omp::DeclareTargetClauseOps &clauseOps, llvm::SmallVectorImpl &symbolAndClause) { - const auto &spec = std::get( - declareTargetConstruct.t); - if (const auto *objectList{ - Fortran::parser::Unwrap(spec.u)}) { + const auto &spec = + std::get(declareTargetConstruct.t); + if (const auto *objectList{parser::Unwrap(spec.u)}) { ObjectList objects{makeObjects(*objectList, semaCtx)}; // Case: declare target(func, var1, var2) gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to, symbolAndClause); } else if (const auto *clauseList{ - Fortran::parser::Unwrap( - spec.u)}) { + parser::Unwrap(spec.u)}) { List clauses = makeClauses(*clauseList, semaCtx); if (clauses.empty()) { // Case: declare target, implicit capture of function @@ -322,11 +317,10 @@ static void getDeclareTargetInfo( } static void collectDeferredDeclareTargets( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, - llvm::SmallVectorImpl + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, + llvm::SmallVectorImpl &deferredDeclareTarget) { mlir::omp::DeclareTargetClauseOps clauseOps; llvm::SmallVector symbolAndClause; @@ -337,8 +331,8 @@ static void collectDeferredDeclareTargets( mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol(converter.mangleName( - std::get(symClause))); + mlir::Operation *op = mod.lookupSymbol( + converter.mangleName(std::get(symClause))); if (!op) { deferredDeclareTarget.push_back({std::get<0>(symClause), @@ -350,11 +344,9 @@ static void collectDeferredDeclareTargets( static std::optional getDeclareTargetFunctionDevice( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclareTargetConstruct - &declareTargetConstruct) { + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct) { mlir::omp::DeclareTargetClauseOps clauseOps; llvm::SmallVector symbolAndClause; getDeclareTargetInfo(converter, semaCtx, eval, declareTargetConstruct, @@ -364,8 +356,8 @@ getDeclareTargetFunctionDevice( // directive is a function or subroutine mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol(converter.mangleName( - std::get(symClause))); + mlir::Operation *op = mod.lookupSymbol( + converter.mangleName(std::get(symClause))); if (mlir::isa_and_nonnull(op)) return clauseOps.deviceType; @@ -392,16 +384,15 @@ getDeclareTargetFunctionDevice( /// entry block arguments. /// \param [in] wrapperArgs - entry block arguments of parent loop wrappers. static void -genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter, - mlir::Location &loc, - llvm::ArrayRef args, - llvm::ArrayRef wrapperSyms = {}, +genLoopVars(mlir::Operation *op, lower::AbstractConverter &converter, + mlir::Location &loc, llvm::ArrayRef args, + llvm::ArrayRef wrapperSyms = {}, llvm::ArrayRef wrapperArgs = {}) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto ®ion = op->getRegion(0); std::size_t loopVarTypeSize = 0; - for (const Fortran::semantics::Symbol *arg : args) + for (const semantics::Symbol *arg : args) loopVarTypeSize = std::max(loopVarTypeSize, arg->GetUltimate().size()); mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize); llvm::SmallVector tiv(args.size(), loopVarType); @@ -424,11 +415,11 @@ genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter, firOpBuilder.setInsertionPointAfter(storeOp); } -static void genReductionVars( - mlir::Operation *op, Fortran::lower::AbstractConverter &converter, - mlir::Location &loc, - llvm::ArrayRef reductionArgs, - llvm::ArrayRef reductionTypes) { +static void +genReductionVars(mlir::Operation *op, lower::AbstractConverter &converter, + mlir::Location &loc, + llvm::ArrayRef reductionArgs, + llvm::ArrayRef reductionTypes) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); llvm::SmallVector blockArgLocs(reductionArgs.size(), loc); @@ -443,8 +434,7 @@ static void genReductionVars( } static void -markDeclareTarget(mlir::Operation *op, - Fortran::lower::AbstractConverter &converter, +markDeclareTarget(mlir::Operation *op, lower::AbstractConverter &converter, mlir::omp::DeclareTargetCaptureClause captureClause, mlir::omp::DeclareTargetDeviceType deviceType) { // TODO: Add support for program local variables with declare target applied @@ -477,14 +467,13 @@ struct OpWithBodyGenInfo { /// which the code is being generated and returns the arguments of the op's /// region. using GenOMPRegionEntryCBFn = - std::function( + std::function( mlir::Operation *)>; - OpWithBodyGenInfo(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, Fortran::lower::pft::Evaluation &eval, - llvm::omp::Directive dir) + OpWithBodyGenInfo(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, mlir::Location loc, + lower::pft::Evaluation &eval, llvm::omp::Directive dir) : converter(converter), symTable(symTable), semaCtx(semaCtx), loc(loc), eval(eval), dir(dir) {} @@ -503,9 +492,9 @@ struct OpWithBodyGenInfo { return *this; } - OpWithBodyGenInfo &setReductions( - llvm::SmallVectorImpl *value1, - llvm::SmallVectorImpl *value2) { + OpWithBodyGenInfo & + setReductions(llvm::SmallVectorImpl *value1, + llvm::SmallVectorImpl *value2) { reductionSymbols = value1; reductionTypes = value2; return *this; @@ -517,15 +506,15 @@ struct OpWithBodyGenInfo { } /// [inout] converter to use for the clauses. - Fortran::lower::AbstractConverter &converter; + lower::AbstractConverter &converter; /// [in] Symbol table - Fortran::lower::SymMap &symTable; + lower::SymMap &symTable; /// [in] Semantics context - Fortran::semantics::SemanticsContext &semaCtx; + semantics::SemanticsContext &semaCtx; /// [in] location in source code. mlir::Location loc; /// [in] current PFT node/evaluation. - Fortran::lower::pft::Evaluation &eval; + lower::pft::Evaluation &eval; /// [in] leaf directive for which to generate the op body. llvm::omp::Directive dir; /// [in] is this an outer operation - prevents privatization. @@ -535,8 +524,7 @@ struct OpWithBodyGenInfo { /// [in] if provided, processes the construct's data-sharing attributes. DataSharingProcessor *dsp = nullptr; /// [in] if provided, list of reduction symbols - llvm::SmallVectorImpl *reductionSymbols = - nullptr; + llvm::SmallVectorImpl *reductionSymbols = nullptr; /// [in] if provided, list of reduction types llvm::SmallVectorImpl *reductionTypes = nullptr; /// [in] if provided, emits the op's region entry. Otherwise, an emtpy block @@ -565,8 +553,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, // argument. Also update the symbol's address with the mlir argument value. // e.g. For loops the argument is the induction variable. And all further // uses of the induction variable should use this mlir value. - auto regionArgs = - [&]() -> llvm::SmallVector { + auto regionArgs = [&]() -> llvm::SmallVector { if (info.genRegionEntryCB != nullptr) { return info.genRegionEntryCB(&op); } @@ -580,8 +567,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, // If it is an unstructured region and is not the outer region of a combined // construct, create empty blocks for all evaluations. if (info.eval.lowerAsUnstructured() && !info.outerCombined) - Fortran::lower::createEmptyRegionBlocks( + lower::createEmptyRegionBlocks( firOpBuilder, info.eval.getNestedEvaluations()); // Start with privatization, so that the lowering of the nested @@ -617,8 +603,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, // is delayed past this point. Insert a temporary terminator here, then // delete it. firOpBuilder.setInsertionPointToEnd(&op.getRegion(0).back()); - auto *temp = - Fortran::lower::genOpenMPTerminator(firOpBuilder, &op, info.loc); + auto *temp = lower::genOpenMPTerminator(firOpBuilder, &op, info.loc); firOpBuilder.setInsertionPointAfter(marker); genNestedEvaluations(info.converter, info.eval); temp->erase(); @@ -662,8 +647,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, if (auto *exitBlock = getUniqueExit(op.getRegion(0))) { firOpBuilder.setInsertionPointToEnd(exitBlock); - auto *term = - Fortran::lower::genOpenMPTerminator(firOpBuilder, &op, info.loc); + auto *term = lower::genOpenMPTerminator(firOpBuilder, &op, info.loc); // Only insert lastprivate code when there actually is an exit block. // Such a block may not exist if the nested code produced an infinite // loop (this may not make sense in production code, but a user could @@ -699,13 +683,11 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info, } static void genBodyOfTargetDataOp( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::omp::TargetDataOp &dataOp, - llvm::ArrayRef useDeviceTypes, + lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::omp::TargetDataOp &dataOp, llvm::ArrayRef useDeviceTypes, llvm::ArrayRef useDeviceLocs, - llvm::ArrayRef useDeviceSymbols, + llvm::ArrayRef useDeviceSymbols, const mlir::Location ¤tLocation, const ConstructQueue &queue, ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -721,7 +703,7 @@ static void genBodyOfTargetDataOp( converter.bindSymbol(*argSymbol, arg); } else { // Avoid capture of a reference to a structured binding. - const Fortran::semantics::Symbol *sym = argSymbol; + const semantics::Symbol *sym = argSymbol; extVal.match( [&](const fir::MutableBoxValue &mbv) { converter.bindSymbol( @@ -751,8 +733,7 @@ static void genBodyOfTargetDataOp( // Create blocks for unstructured regions. This has to be done since // blocks are initially allocated with the function as the parent region. if (eval.lowerAsUnstructured()) { - Fortran::lower::createEmptyRegionBlocks( + lower::createEmptyRegionBlocks( firOpBuilder, eval.getNestedEvaluations()); } @@ -772,12 +753,10 @@ static void genBodyOfTargetDataOp( // This functions creates a block for the body of the targetOp's region. It adds // all the symbols present in mapSymbols as block arguments to this block. static void -genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::omp::TargetOp &targetOp, - llvm::ArrayRef mapSyms, +genBodyOfTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::omp::TargetOp &targetOp, + llvm::ArrayRef mapSyms, llvm::ArrayRef mapSymLocs, llvm::ArrayRef mapSymTypes, const mlir::Location ¤tLocation, @@ -812,7 +791,7 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, for (auto [argIndex, argSymbol] : llvm::enumerate(mapSyms)) { const mlir::BlockArgument &arg = region.getArgument(argIndex); // Avoid capture of a reference to a structured binding. - const Fortran::semantics::Symbol *sym = argSymbol; + const semantics::Symbol *sym = argSymbol; // Structure component symbols don't have bindings. if (sym->owner().IsDerivedType()) continue; @@ -914,8 +893,7 @@ genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, // Create blocks for unstructured regions. This has to be done since // blocks are initially allocated with the function as the parent region. if (eval.lowerAsUnstructured()) { - Fortran::lower::createEmptyRegionBlocks( + lower::createEmptyRegionBlocks( firOpBuilder, eval.getNestedEvaluations()); } @@ -946,20 +924,20 @@ static OpTy genOpWithBody(const OpWithBodyGenInfo &info, // Code generation functions for clauses //===----------------------------------------------------------------------===// -static void -genCriticalDeclareClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - const List &clauses, mlir::Location loc, - mlir::omp::CriticalClauseOps &clauseOps, - llvm::StringRef name) { +static void genCriticalDeclareClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, + const List &clauses, + mlir::Location loc, + mlir::omp::CriticalClauseOps &clauseOps, + llvm::StringRef name) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processHint(clauseOps); clauseOps.nameAttr = mlir::StringAttr::get(converter.getFirOpBuilder().getContext(), name); } -static void genFlushClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genFlushClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const ObjectList &objects, const List &clauses, mlir::Location loc, llvm::SmallVectorImpl &operandRange) { @@ -970,20 +948,20 @@ static void genFlushClauses(Fortran::lower::AbstractConverter &converter, TODO(converter.getCurrentLocation(), "Handle OmpMemoryOrderClause"); } -static void genLoopNestClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, const List &clauses, - mlir::Location loc, mlir::omp::LoopNestClauseOps &clauseOps, - llvm::SmallVectorImpl &iv) { +static void +genLoopNestClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, const List &clauses, + mlir::Location loc, mlir::omp::LoopNestClauseOps &clauseOps, + llvm::SmallVectorImpl &iv) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processCollapse(loc, eval, clauseOps, iv); clauseOps.loopInclusiveAttr = converter.getFirOpBuilder().getUnitAttr(); } static void -genOrderedRegionClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +genOrderedRegionClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::OrderedRegionClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -991,13 +969,12 @@ genOrderedRegionClauses(Fortran::lower::AbstractConverter &converter, } static void genParallelClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, const List &clauses, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, bool processReduction, mlir::omp::ParallelClauseOps &clauseOps, llvm::SmallVectorImpl &reductionTypes, - llvm::SmallVectorImpl &reductionSyms) { + llvm::SmallVectorImpl &reductionSyms) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processAllocate(clauseOps); cp.processDefault(); @@ -1012,8 +989,8 @@ static void genParallelClauses( } } -static void genSectionsClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genSectionsClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::SectionsClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1023,8 +1000,8 @@ static void genSectionsClauses(Fortran::lower::AbstractConverter &converter, // TODO Support delayed privatization. } -static void genSimdClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genSimdClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::SimdClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1039,8 +1016,8 @@ static void genSimdClauses(Fortran::lower::AbstractConverter &converter, loc, llvm::omp::Directive::OMPD_simd); } -static void genSingleClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genSingleClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::SingleClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1051,18 +1028,17 @@ static void genSingleClauses(Fortran::lower::AbstractConverter &converter, } static void genTargetClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, const List &clauses, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, bool processHostOnlyClauses, bool processReduction, mlir::omp::TargetClauseOps &clauseOps, - llvm::SmallVectorImpl &mapSyms, + llvm::SmallVectorImpl &mapSyms, llvm::SmallVectorImpl &mapLocs, llvm::SmallVectorImpl &mapTypes, - llvm::SmallVectorImpl &deviceAddrSyms, + llvm::SmallVectorImpl &deviceAddrSyms, llvm::SmallVectorImpl &deviceAddrLocs, llvm::SmallVectorImpl &deviceAddrTypes, - llvm::SmallVectorImpl &devicePtrSyms, + llvm::SmallVectorImpl &devicePtrSyms, llvm::SmallVectorImpl &devicePtrLocs, llvm::SmallVectorImpl &devicePtrTypes) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1087,13 +1063,12 @@ static void genTargetClauses( } static void genTargetDataClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, const List &clauses, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, mlir::omp::TargetDataClauseOps &clauseOps, llvm::SmallVectorImpl &useDeviceTypes, llvm::SmallVectorImpl &useDeviceLocs, - llvm::SmallVectorImpl &useDeviceSyms) { + llvm::SmallVectorImpl &useDeviceSyms) { ClauseProcessor cp(converter, semaCtx, clauses); cp.processDevice(stmtCtx, clauseOps); cp.processIf(llvm::omp::Directive::OMPD_target_data, clauseOps); @@ -1119,9 +1094,8 @@ static void genTargetDataClauses( } static void genTargetEnterExitUpdateDataClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, const List &clauses, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, llvm::omp::Directive directive, mlir::omp::TargetEnterExitUpdateDataClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1138,9 +1112,9 @@ static void genTargetEnterExitUpdateDataClauses( } } -static void genTaskClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, +static void genTaskClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, mlir::omp::TaskClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1158,8 +1132,8 @@ static void genTaskClauses(Fortran::lower::AbstractConverter &converter, loc, llvm::omp::Directive::OMPD_task); } -static void genTaskgroupClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genTaskgroupClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::TaskgroupClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1168,8 +1142,8 @@ static void genTaskgroupClauses(Fortran::lower::AbstractConverter &converter, llvm::omp::Directive::OMPD_taskgroup); } -static void genTaskwaitClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, +static void genTaskwaitClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, const List &clauses, mlir::Location loc, mlir::omp::TaskwaitClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1177,9 +1151,9 @@ static void genTaskwaitClauses(Fortran::lower::AbstractConverter &converter, loc, llvm::omp::Directive::OMPD_taskwait); } -static void genTeamsClauses(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, +static void genTeamsClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, mlir::omp::TeamsClauseOps &clauseOps) { ClauseProcessor cp(converter, semaCtx, clauses); @@ -1194,12 +1168,11 @@ static void genTeamsClauses(Fortran::lower::AbstractConverter &converter, } static void genWsloopClauses( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::StatementContext &stmtCtx, const List &clauses, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, const List &clauses, mlir::Location loc, mlir::omp::WsloopClauseOps &clauseOps, llvm::SmallVectorImpl &reductionTypes, - llvm::SmallVectorImpl &reductionSyms) { + llvm::SmallVectorImpl &reductionSyms) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); ClauseProcessor cp(converter, semaCtx, clauses); cp.processNowait(clauseOps); @@ -1220,21 +1193,19 @@ static void genWsloopClauses( //===----------------------------------------------------------------------===// static mlir::omp::BarrierOp -genBarrierOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genBarrierOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } static mlir::omp::CriticalOp -genCriticalOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genCriticalOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item, - const std::optional &name) { + const std::optional &name) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::FlatSymbolRefAttr nameAttr; @@ -1261,22 +1232,19 @@ genCriticalOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::DistributeOp -genDistributeOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genDistributeOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Distribute construct"); return nullptr; } static mlir::omp::FlushOp -genFlushOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ObjectList &objects, const ConstructQueue &queue, - ConstructQueue::iterator item) { +genFlushOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ObjectList &objects, + const ConstructQueue &queue, ConstructQueue::iterator item) { llvm::SmallVector operandRange; genFlushClauses(converter, semaCtx, objects, item->clauses, loc, operandRange); @@ -1286,11 +1254,10 @@ genFlushOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::MasterOp -genMasterOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genMasterOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { return genOpWithBody( OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, llvm::omp::Directive::OMPD_master), @@ -1298,20 +1265,18 @@ genMasterOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::OrderedOp -genOrderedOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genOrderedOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "OMPD_ordered"); return nullptr; } static mlir::omp::OrderedRegionOp -genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genOrderedRegionOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::OrderedRegionClauseOps clauseOps; genOrderedRegionClauses(converter, semaCtx, item->clauses, loc, clauseOps); @@ -1323,18 +1288,17 @@ genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::ParallelOp -genParallelOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genParallelOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; mlir::omp::ParallelClauseOps clauseOps; - llvm::SmallVector privateSyms; + llvm::SmallVector privateSyms; llvm::SmallVector reductionTypes; - llvm::SmallVector reductionSyms; + llvm::SmallVector reductionSyms; genParallelClauses(converter, semaCtx, stmtCtx, item->clauses, loc, /*processReduction=*/!outerCombined, clauseOps, reductionTypes, reductionSyms); @@ -1385,15 +1349,14 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, firOpBuilder.createBlock(®ion, /*insertPt=*/{}, privateVarTypes, privateVarLocs); - llvm::SmallVector allSymbols = - reductionSyms; + llvm::SmallVector allSymbols = reductionSyms; allSymbols.append(privateSyms); for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments())) { fir::ExtendedValue hostExV = converter.getSymbolExtendedValue(*arg); converter.bindSymbol(*arg, hlfir::translateToExtendedValue( loc, firOpBuilder, hlfir::Entity{prv}, /*contiguousHint=*/ - Fortran::evaluate::IsSimplyContiguous( + evaluate::IsSimplyContiguous( *arg, converter.getFoldingContext())) .first); } @@ -1406,11 +1369,10 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::SectionOp -genSectionOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genSectionOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { // Currently only private/firstprivate clause is handled, and // all privatization is done within `omp.section` operations. return genOpWithBody( @@ -1421,10 +1383,9 @@ genSectionOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::SectionsOp -genSectionsOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::SectionsClauseOps clauseOps; genSectionsClauses(converter, semaCtx, item->clauses, loc, clauseOps); @@ -1478,7 +1439,7 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, mlir::OpBuilder::InsertPoint insp = builder.saveInsertionPoint(); const auto &objList = std::get(lastp->t); for (const Object &object : objList) { - Fortran::semantics::Symbol *sym = object.id(); + semantics::Symbol *sym = object.id(); converter.copyHostAssociateVar(*sym, &insp); } } @@ -1498,19 +1459,18 @@ genSectionsOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::SimdOp -genSimdOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genSimdOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval); dsp.processStep1(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; mlir::omp::LoopNestClauseOps loopClauseOps; mlir::omp::SimdClauseOps simdClauseOps; - llvm::SmallVector iv; + llvm::SmallVector iv; genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc, loopClauseOps, iv); genSimdClauses(converter, semaCtx, item->clauses, loc, simdClauseOps); @@ -1521,7 +1481,7 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, // TODO: Add reduction-related arguments to the wrapper's entry block. firOpBuilder.createBlock(&simdOp.getRegion()); firOpBuilder.setInsertionPoint( - Fortran::lower::genOpenMPTerminator(firOpBuilder, simdOp, loc)); + lower::genOpenMPTerminator(firOpBuilder, simdOp, loc)); // Create nested omp.loop_nest and fill body with loop contents. auto loopOp = firOpBuilder.create(loc, loopClauseOps); @@ -1546,11 +1506,10 @@ genSimdOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::SingleOp -genSingleOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { mlir::omp::SingleClauseOps clauseOps; genSingleClauses(converter, semaCtx, item->clauses, loc, clauseOps); @@ -1562,21 +1521,19 @@ genSingleOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TargetOp -genTargetOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item, - bool outerCombined = false) { +genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; bool processHostOnlyClauses = !llvm::cast(*converter.getModuleOp()) .getIsTargetDevice(); mlir::omp::TargetClauseOps clauseOps; - llvm::SmallVector mapSyms, devicePtrSyms, + llvm::SmallVector mapSyms, devicePtrSyms, deviceAddrSyms; llvm::SmallVector mapLocs, devicePtrLocs, deviceAddrLocs; llvm::SmallVector mapTypes, devicePtrTypes, deviceAddrTypes; @@ -1590,12 +1547,12 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, // The following code follows the implicit data-mapping rules to map all the // symbols used inside the region that have not been explicitly mapped using // the map clause. - auto captureImplicitMap = [&](const Fortran::semantics::Symbol &sym) { + auto captureImplicitMap = [&](const semantics::Symbol &sym) { if (llvm::find(mapSyms, &sym) == mapSyms.end()) { mlir::Value baseOp = converter.getSymbolAddress(sym); if (!baseOp) - if (const auto *details = sym.template detailsIf< - Fortran::semantics::HostAssocDetails>()) { + if (const auto *details = + sym.template detailsIf()) { baseOp = converter.getSymbolAddress(details->symbol()); converter.copySymbolBinding(details->symbol(), sym); } @@ -1606,21 +1563,20 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym); name << sym.name().ToString(); - Fortran::lower::AddrAndBoundsInfo info = getDataOperandBaseAddr( + lower::AddrAndBoundsInfo info = getDataOperandBaseAddr( converter, firOpBuilder, sym, converter.getCurrentLocation()); if (mlir::isa( fir::unwrapRefType(info.addr.getType()))) - bounds = - Fortran::lower::genBoundsOpsFromBox( - firOpBuilder, converter.getCurrentLocation(), converter, - dataExv, info); + bounds = lower::genBoundsOpsFromBox( + firOpBuilder, converter.getCurrentLocation(), converter, dataExv, + info); if (mlir::isa( fir::unwrapRefType(info.addr.getType()))) { bool dataExvIsAssumedSize = - Fortran::semantics::IsAssumedSizeArray(sym.GetUltimate()); - bounds = Fortran::lower::genBaseBoundsOps( + semantics::IsAssumedSizeArray(sym.GetUltimate()); + bounds = lower::genBaseBoundsOps( firOpBuilder, converter.getCurrentLocation(), converter, dataExv, dataExvIsAssumedSize); } @@ -1671,7 +1627,7 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, } } }; - Fortran::lower::pft::visitAllSymbols(eval, captureImplicitMap); + lower::pft::visitAllSymbols(eval, captureImplicitMap); auto targetOp = firOpBuilder.create(loc, clauseOps); genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms, @@ -1680,16 +1636,15 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TargetDataOp -genTargetDataOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genTargetDataOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; mlir::omp::TargetDataClauseOps clauseOps; llvm::SmallVector useDeviceTypes; llvm::SmallVector useDeviceLocs; - llvm::SmallVector useDeviceSyms; + llvm::SmallVector useDeviceSyms; genTargetDataClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps, useDeviceTypes, useDeviceLocs, useDeviceSyms); @@ -1703,14 +1658,14 @@ genTargetDataOp(Fortran::lower::AbstractConverter &converter, } template -static OpTy -genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location loc, const ConstructQueue &queue, - ConstructQueue::iterator item) { +static OpTy genTargetEnterExitUpdateDataOp(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; // GCC 9.3.0 emits a (probably) bogus warning about an unused variable. [[maybe_unused]] llvm::omp::Directive directive; @@ -1732,12 +1687,11 @@ genTargetEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TaskOp -genTaskOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { - Fortran::lower::StatementContext stmtCtx; +genTaskOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { + lower::StatementContext stmtCtx; mlir::omp::TaskClauseOps clauseOps; genTaskClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps); @@ -1749,10 +1703,9 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TaskgroupOp -genTaskgroupOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genTaskgroupOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::TaskgroupClauseOps clauseOps; genTaskgroupClauses(converter, semaCtx, item->clauses, loc, clauseOps); @@ -1765,19 +1718,17 @@ genTaskgroupOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TaskloopOp -genTaskloopOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genTaskloopOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { TODO(loc, "Taskloop construct"); } static mlir::omp::TaskwaitOp -genTaskwaitOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genTaskwaitOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { mlir::omp::TaskwaitClauseOps clauseOps; genTaskwaitClauses(converter, semaCtx, item->clauses, loc, clauseOps); @@ -1786,22 +1737,19 @@ genTaskwaitOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::TaskyieldOp -genTaskyieldOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, +genTaskyieldOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::iterator item) { return converter.getFirOpBuilder().create(loc); } static mlir::omp::TeamsOp -genTeamsOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item, - bool outerCombined = false) { - Fortran::lower::StatementContext stmtCtx; +genTeamsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item, bool outerCombined = false) { + lower::StatementContext stmtCtx; mlir::omp::TeamsClauseOps clauseOps; genTeamsClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps); @@ -1814,21 +1762,20 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, } static mlir::omp::WsloopOp -genWsloopOp(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { +genWsloopOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval); dsp.processStep1(); - Fortran::lower::StatementContext stmtCtx; + lower::StatementContext stmtCtx; mlir::omp::LoopNestClauseOps loopClauseOps; mlir::omp::WsloopClauseOps wsClauseOps; - llvm::SmallVector iv; + llvm::SmallVector iv; llvm::SmallVector reductionTypes; - llvm::SmallVector reductionSyms; + llvm::SmallVector reductionSyms; genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc, loopClauseOps, iv); genWsloopClauses(converter, semaCtx, stmtCtx, item->clauses, loc, wsClauseOps, @@ -1841,7 +1788,7 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, mlir::Block *wsloopEntryBlock = firOpBuilder.createBlock( &wsloopOp.getRegion(), {}, reductionTypes, reductionLocs); firOpBuilder.setInsertionPoint( - Fortran::lower::genOpenMPTerminator(firOpBuilder, wsloopOp, loc)); + lower::genOpenMPTerminator(firOpBuilder, wsloopOp, loc)); // Create nested omp.loop_nest and fill body with loop contents. auto loopOp = firOpBuilder.create(loc, loopClauseOps); @@ -1871,38 +1818,36 @@ genWsloopOp(Fortran::lower::AbstractConverter &converter, //===----------------------------------------------------------------------===// static void genCompositeDistributeParallelDo( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { + lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO"); } static void genCompositeDistributeParallelDoSimd( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, mlir::Location loc, - const ConstructQueue &queue, ConstructQueue::iterator item) { + lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + mlir::Location loc, const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE PARALLEL DO SIMD"); } -static void -genCompositeDistributeSimd(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const ConstructQueue &queue, - ConstructQueue::iterator item) { +static void genCompositeDistributeSimd(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::iterator item) { TODO(loc, "Composite DISTRIBUTE SIMD"); } -static void genCompositeDoSimd(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - mlir::Location loc, const ConstructQueue &queue, +static void genCompositeDoSimd(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, ConstructQueue::iterator item) { ClauseProcessor cp(converter, semaCtx, item->clauses); cp.processTODO symbolAndClause; mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); @@ -2097,8 +2034,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, clauseOps, symbolAndClause); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol(converter.mangleName( - std::get(symClause))); + mlir::Operation *op = mod.lookupSymbol( + converter.mangleName(std::get(symClause))); // Some symbols are deferred until later in the module, these are handled // upon finalization of the module for OpenMP inside of Bridge, so we simply @@ -2113,33 +2050,28 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, } } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPRequiresConstruct &requiresConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPRequiresConstruct &requiresConstruct) { // Requires directives are gathered and processed in semantics and // then combined in the lowering bridge before triggering codegen // just once. Hence, there is no need to lower each individual // occurrence here. } -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPThreadprivate &threadprivate) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPThreadprivate &threadprivate) { // The directive is lowered when instantiating the variable to // support the case of threadprivate variable declared in module. } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclarativeConstruct &ompDeclConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclarativeConstruct &ompDeclConstruct) { std::visit( [&](auto &&s) { return genOMP(converter, symTable, semaCtx, eval, s); }, ompDeclConstruct.u); @@ -2149,18 +2081,14 @@ genOMP(Fortran::lower::AbstractConverter &converter, // OpenMPStandaloneConstruct visitors //===----------------------------------------------------------------------===// -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPSimpleStandaloneConstruct - &simpleStandaloneConstruct) { - const auto &directive = - std::get( - simpleStandaloneConstruct.t); +static void genOMP( + lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + const parser::OpenMPSimpleStandaloneConstruct &simpleStandaloneConstruct) { + const auto &directive = std::get( + simpleStandaloneConstruct.t); List clauses = makeClauses( - std::get(simpleStandaloneConstruct.t), - semaCtx); + std::get(simpleStandaloneConstruct.t), semaCtx); mlir::Location currentLocation = converter.genLocation(directive.source); ConstructQueue queue{ @@ -2177,17 +2105,15 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, } } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { - const auto &verbatim = std::get(flushConstruct.t); +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPFlushConstruct &flushConstruct) { + const auto &verbatim = std::get(flushConstruct.t); const auto &objectList = - std::get>(flushConstruct.t); + std::get>(flushConstruct.t); const auto &clauseList = - std::get>>( + std::get>>( flushConstruct.t); ObjectList objects = objectList ? makeObjects(*objectList, semaCtx) : ObjectList{}; @@ -2204,30 +2130,25 @@ genOMP(Fortran::lower::AbstractConverter &converter, queue, queue.begin()); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPCancelConstruct &cancelConstruct) { TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); } -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPCancellationPointConstruct +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPCancellationPointConstruct &cancellationPointConstruct) { TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); } static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) { +genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + const parser::OpenMPStandaloneConstruct &standaloneConstruct) { std::visit( [&](auto &&s) { return genOMP(converter, symTable, semaCtx, eval, s); }, standaloneConstruct.u); @@ -2237,79 +2158,68 @@ genOMP(Fortran::lower::AbstractConverter &converter, // OpenMPConstruct visitors //===----------------------------------------------------------------------===// -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPAllocatorsConstruct &allocsConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPAllocatorsConstruct &allocsConstruct) { TODO(converter.getCurrentLocation(), "OpenMPAllocatorsConstruct"); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPAtomicConstruct &atomicConstruct) { std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OmpAtomicRead &atomicRead) { + common::visitors{ + [&](const parser::OmpAtomicRead &atomicRead) { mlir::Location loc = converter.genLocation(atomicRead.source); - Fortran::lower::genOmpAccAtomicRead< - Fortran::parser::OmpAtomicRead, - Fortran::parser::OmpAtomicClauseList>(converter, atomicRead, - loc); + lower::genOmpAccAtomicRead( + converter, atomicRead, loc); }, - [&](const Fortran::parser::OmpAtomicWrite &atomicWrite) { + [&](const parser::OmpAtomicWrite &atomicWrite) { mlir::Location loc = converter.genLocation(atomicWrite.source); - Fortran::lower::genOmpAccAtomicWrite< - Fortran::parser::OmpAtomicWrite, - Fortran::parser::OmpAtomicClauseList>(converter, atomicWrite, - loc); + lower::genOmpAccAtomicWrite( + converter, atomicWrite, loc); }, - [&](const Fortran::parser::OmpAtomic &atomicConstruct) { + [&](const parser::OmpAtomic &atomicConstruct) { mlir::Location loc = converter.genLocation(atomicConstruct.source); - Fortran::lower::genOmpAtomic( + lower::genOmpAtomic( converter, atomicConstruct, loc); }, - [&](const Fortran::parser::OmpAtomicUpdate &atomicUpdate) { + [&](const parser::OmpAtomicUpdate &atomicUpdate) { mlir::Location loc = converter.genLocation(atomicUpdate.source); - Fortran::lower::genOmpAccAtomicUpdate< - Fortran::parser::OmpAtomicUpdate, - Fortran::parser::OmpAtomicClauseList>(converter, atomicUpdate, - loc); + lower::genOmpAccAtomicUpdate( + converter, atomicUpdate, loc); }, - [&](const Fortran::parser::OmpAtomicCapture &atomicCapture) { + [&](const parser::OmpAtomicCapture &atomicCapture) { mlir::Location loc = converter.genLocation(atomicCapture.source); - Fortran::lower::genOmpAccAtomicCapture< - Fortran::parser::OmpAtomicCapture, - Fortran::parser::OmpAtomicClauseList>(converter, atomicCapture, - loc); + lower::genOmpAccAtomicCapture( + converter, atomicCapture, loc); }, }, atomicConstruct.u); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPBlockConstruct &blockConstruct) { const auto &beginBlockDirective = - std::get(blockConstruct.t); + std::get(blockConstruct.t); const auto &endBlockDirective = - std::get(blockConstruct.t); + std::get(blockConstruct.t); mlir::Location currentLocation = converter.genLocation(beginBlockDirective.source); const auto origDirective = - std::get(beginBlockDirective.t).v; + std::get(beginBlockDirective.t).v; List clauses = makeClauses( - std::get(beginBlockDirective.t), semaCtx); + std::get(beginBlockDirective.t), semaCtx); clauses.append(makeClauses( - std::get(endBlockDirective.t), semaCtx)); + std::get(endBlockDirective.t), semaCtx)); assert(llvm::omp::blockConstructSet.test(origDirective) && "Expected block construct"); @@ -2356,51 +2266,44 @@ genOMP(Fortran::lower::AbstractConverter &converter, queue.begin()); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPCriticalConstruct &criticalConstruct) { - const auto &cd = - std::get(criticalConstruct.t); +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPCriticalConstruct &criticalConstruct) { + const auto &cd = std::get(criticalConstruct.t); List clauses = - makeClauses(std::get(cd.t), semaCtx); + makeClauses(std::get(cd.t), semaCtx); ConstructQueue queue{buildConstructQueue( converter.getFirOpBuilder().getModule(), semaCtx, eval, cd.source, llvm::omp::Directive::OMPD_critical, clauses)}; - const auto &name = std::get>(cd.t); + const auto &name = std::get>(cd.t); mlir::Location currentLocation = converter.getCurrentLocation(); genCriticalOp(converter, symTable, semaCtx, eval, currentLocation, queue, queue.begin(), name); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPExecutableAllocate &execAllocConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPExecutableAllocate &execAllocConstruct) { TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate"); } -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPLoopConstruct &loopConstruct) { const auto &beginLoopDirective = - std::get(loopConstruct.t); + std::get(loopConstruct.t); List clauses = makeClauses( - std::get(beginLoopDirective.t), semaCtx); + std::get(beginLoopDirective.t), semaCtx); if (auto &endLoopDirective = - std::get>( + std::get>( loopConstruct.t)) { clauses.append(makeClauses( - std::get(endLoopDirective->t), - semaCtx)); + std::get(endLoopDirective->t), semaCtx)); } mlir::Location currentLocation = @@ -2417,12 +2320,10 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, queue.begin()); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPSectionConstruct §ionConstruct) { mlir::Location loc = converter.getCurrentLocation(); ConstructQueue queue{buildConstructQueue( converter.getFirOpBuilder().getModule(), semaCtx, eval, @@ -2430,22 +2331,18 @@ genOMP(Fortran::lower::AbstractConverter &converter, genOMPDispatch(converter, symTable, semaCtx, eval, loc, queue, queue.begin()); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPSectionsConstruct §ionsConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPSectionsConstruct §ionsConstruct) { const auto &beginSectionsDirective = - std::get(sectionsConstruct.t); + std::get(sectionsConstruct.t); List clauses = makeClauses( - std::get(beginSectionsDirective.t), - semaCtx); + std::get(beginSectionsDirective.t), semaCtx); const auto &endSectionsDirective = - std::get(sectionsConstruct.t); + std::get(sectionsConstruct.t); clauses.append(makeClauses( - std::get(endSectionsDirective.t), - semaCtx)); + std::get(endSectionsDirective.t), semaCtx)); mlir::Location currentLocation = converter.getCurrentLocation(); llvm::omp::Directive directive = @@ -2459,11 +2356,10 @@ genOMP(Fortran::lower::AbstractConverter &converter, queue.begin()); } -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPConstruct &ompConstruct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPConstruct &ompConstruct) { std::visit( [&](auto &&s) { return genOMP(converter, symTable, semaCtx, eval, s); }, ompConstruct.u); @@ -2482,62 +2378,57 @@ mlir::Operation *Fortran::lower::genOpenMPTerminator(fir::FirOpBuilder &builder, return builder.create(loc); } -void Fortran::lower::genOpenMPConstruct( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPConstruct &omp) { +void Fortran::lower::genOpenMPConstruct(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPConstruct &omp) { symTable.pushScope(); genOMP(converter, symTable, semaCtx, eval, omp); symTable.popScope(); } void Fortran::lower::genOpenMPDeclarativeConstruct( - Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclarativeConstruct &omp) { + lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + const parser::OpenMPDeclarativeConstruct &omp) { genOMP(converter, symTable, semaCtx, eval, omp); genNestedEvaluations(converter, eval); } void Fortran::lower::genOpenMPSymbolProperties( - Fortran::lower::AbstractConverter &converter, - const Fortran::lower::pft::Variable &var) { + lower::AbstractConverter &converter, const lower::pft::Variable &var) { assert(var.hasSymbol() && "Expecting Symbol"); - const Fortran::semantics::Symbol &sym = var.getSymbol(); + const semantics::Symbol &sym = var.getSymbol(); - if (sym.test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) - Fortran::lower::genThreadprivateOp(converter, var); + if (sym.test(semantics::Symbol::Flag::OmpThreadprivate)) + lower::genThreadprivateOp(converter, var); - if (sym.test(Fortran::semantics::Symbol::Flag::OmpDeclareTarget)) - Fortran::lower::genDeclareTargetIntGlobal(converter, var); + if (sym.test(semantics::Symbol::Flag::OmpDeclareTarget)) + lower::genDeclareTargetIntGlobal(converter, var); } -int64_t Fortran::lower::getCollapseValue( - const Fortran::parser::OmpClauseList &clauseList) { - for (const Fortran::parser::OmpClause &clause : clauseList.v) { +int64_t +Fortran::lower::getCollapseValue(const parser::OmpClauseList &clauseList) { + for (const parser::OmpClause &clause : clauseList.v) { if (const auto &collapseClause = - std::get_if(&clause.u)) { - const auto *expr = Fortran::semantics::GetExpr(collapseClause->v); - return Fortran::evaluate::ToInt64(*expr).value(); + std::get_if(&clause.u)) { + const auto *expr = semantics::GetExpr(collapseClause->v); + return evaluate::ToInt64(*expr).value(); } } return 1; } -void Fortran::lower::genThreadprivateOp( - Fortran::lower::AbstractConverter &converter, - const Fortran::lower::pft::Variable &var) { +void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter, + const lower::pft::Variable &var) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); - const Fortran::semantics::Symbol &sym = var.getSymbol(); + const semantics::Symbol &sym = var.getSymbol(); mlir::Value symThreadprivateValue; - if (const Fortran::semantics::Symbol *common = - Fortran::semantics::FindCommonBlockContaining(sym.GetUltimate())) { + if (const semantics::Symbol *common = + semantics::FindCommonBlockContaining(sym.GetUltimate())) { mlir::Value commonValue = converter.getSymbolAddress(*common); if (mlir::isa(commonValue.getDefiningOp())) { // Generate ThreadprivateOp for a common block instead of its members and @@ -2600,8 +2491,7 @@ void Fortran::lower::genThreadprivateOp( // that have the implicit SAVE attribute, to simplifiy LLVM-IR and MLIR // generation. void Fortran::lower::genDeclareTargetIntGlobal( - Fortran::lower::AbstractConverter &converter, - const Fortran::lower::pft::Variable &var) { + lower::AbstractConverter &converter, const lower::pft::Variable &var) { if (!var.isGlobal()) { // A non-global variable which can be in a declare target directive must // be a variable in the main program, and it has the implicit SAVE @@ -2613,48 +2503,42 @@ void Fortran::lower::genDeclareTargetIntGlobal( } bool Fortran::lower::isOpenMPTargetConstruct( - const Fortran::parser::OpenMPConstruct &omp) { + const parser::OpenMPConstruct &omp) { llvm::omp::Directive dir = llvm::omp::Directive::OMPD_unknown; - if (const auto *block = - std::get_if(&omp.u)) { - const auto &begin = - std::get(block->t); - dir = std::get(begin.t).v; + if (const auto *block = std::get_if(&omp.u)) { + const auto &begin = std::get(block->t); + dir = std::get(begin.t).v; } else if (const auto *loop = - std::get_if(&omp.u)) { - const auto &begin = - std::get(loop->t); - dir = std::get(begin.t).v; + std::get_if(&omp.u)) { + const auto &begin = std::get(loop->t); + dir = std::get(begin.t).v; } return llvm::omp::allTargetSet.test(dir); } void Fortran::lower::gatherOpenMPDeferredDeclareTargets( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclarativeConstruct &ompDecl, llvm::SmallVectorImpl &deferredDeclareTarget) { - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPDeclareTargetConstruct &ompReq) { - collectDeferredDeclareTargets(converter, semaCtx, eval, ompReq, - deferredDeclareTarget); - }, - [&](const auto &) {}, - }, - ompDecl.u); + std::visit(common::visitors{ + [&](const parser::OpenMPDeclareTargetConstruct &ompReq) { + collectDeferredDeclareTargets(converter, semaCtx, eval, + ompReq, deferredDeclareTarget); + }, + [&](const auto &) {}, + }, + ompDecl.u); } bool Fortran::lower::isOpenMPDeviceDeclareTarget( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl) { + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclarativeConstruct &ompDecl) { return std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPDeclareTargetConstruct &ompReq) { + common::visitors{ + [&](const parser::OpenMPDeclareTargetConstruct &ompReq) { mlir::omp::DeclareTargetDeviceType targetType = getDeclareTargetFunctionDevice(converter, semaCtx, eval, ompReq) .value_or(mlir::omp::DeclareTargetDeviceType::host); @@ -2701,20 +2585,19 @@ bool Fortran::lower::markOpenMPDeferredDeclareTargetFunctions( return deviceCodeFound; } -void Fortran::lower::genOpenMPRequires( - mlir::Operation *mod, const Fortran::semantics::Symbol *symbol) { +void Fortran::lower::genOpenMPRequires(mlir::Operation *mod, + const semantics::Symbol *symbol) { using MlirRequires = mlir::omp::ClauseRequires; - using SemaRequires = Fortran::semantics::WithOmpDeclarative::RequiresFlag; + using SemaRequires = semantics::WithOmpDeclarative::RequiresFlag; if (auto offloadMod = llvm::dyn_cast(mod)) { - Fortran::semantics::WithOmpDeclarative::RequiresFlags semaFlags; + semantics::WithOmpDeclarative::RequiresFlags semaFlags; if (symbol) { - Fortran::common::visit( + common::visit( [&](const auto &details) { - if constexpr (std::is_base_of_v< - Fortran::semantics::WithOmpDeclarative, - std::decay_t>) { + if constexpr (std::is_base_of_v>) { if (details.has_ompRequires()) semaFlags = *details.ompRequires(); } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index b3f08eb81c799a..be6dcd6f5569a1 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -72,8 +72,8 @@ ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( bool ReductionProcessor::supportedIntrinsicProcReduction( const omp::clause::ProcedureDesignator &pd) { - Fortran::semantics::Symbol *sym = pd.v.id(); - if (!sym->GetUltimate().attrs().test(Fortran::semantics::Attr::INTRINSIC)) + semantics::Symbol *sym = pd.v.id(); + if (!sym->GetUltimate().attrs().test(semantics::Attr::INTRINSIC)) return false; auto redType = llvm::StringSwitch(getRealName(sym).ToString()) .Case("max", true) @@ -180,7 +180,7 @@ ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type, case ReductionIdentifier::NEQV: if (auto cplxTy = mlir::dyn_cast(type)) { mlir::Type realTy = - Fortran::lower::convertReal(builder.getContext(), cplxTy.getFKind()); + lower::convertReal(builder.getContext(), cplxTy.getFKind()); mlir::Value initRe = builder.createRealConstant( loc, realTy, getOperationIdentity(redId, loc)); mlir::Value initIm = builder.createRealConstant(loc, realTy, 0); @@ -680,13 +680,11 @@ bool ReductionProcessor::doReductionByRef( } void ReductionProcessor::addDeclareReduction( - mlir::Location currentLocation, - Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, lower::AbstractConverter &converter, const omp::clause::Reduction &reduction, llvm::SmallVectorImpl &reductionVars, llvm::SmallVectorImpl &reductionDeclSymbols, - llvm::SmallVectorImpl - *reductionSymbols) { + llvm::SmallVectorImpl *reductionSymbols) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); if (std::get>( @@ -716,7 +714,7 @@ void ReductionProcessor::addDeclareReduction( // should happen byref fir::FirOpBuilder &builder = converter.getFirOpBuilder(); for (const Object &object : objectList) { - const Fortran::semantics::Symbol *symbol = object.id(); + const semantics::Symbol *symbol = object.id(); if (reductionSymbols) reductionSymbols->push_back(symbol); mlir::Value symVal = converter.getSymbolAddress(*symbol); @@ -731,8 +729,7 @@ void ReductionProcessor::addDeclareReduction( // information needed to iterate over the array if (mlir::isa(eleType)) { // For Host associated symbols, use `SymbolBox` instead - Fortran::lower::SymbolBox symBox = - converter.lookupOneLevelUpSymbol(*symbol); + lower::SymbolBox symBox = converter.lookupOneLevelUpSymbol(*symbol); hlfir::Entity entity{symBox.getAddr()}; entity = genVariableBox(currentLocation, builder, entity); mlir::Value box = entity.getBase(); @@ -828,12 +825,12 @@ void ReductionProcessor::addDeclareReduction( } } -const Fortran::semantics::SourceName -ReductionProcessor::getRealName(const Fortran::semantics::Symbol *symbol) { +const semantics::SourceName +ReductionProcessor::getRealName(const semantics::Symbol *symbol) { return symbol->GetUltimate().name(); } -const Fortran::semantics::SourceName +const semantics::SourceName ReductionProcessor::getRealName(const omp::clause::ProcedureDesignator &pd) { return getRealName(pd.v.id()); } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.h b/flang/lib/Lower/OpenMP/ReductionProcessor.h index 8b116a4c520411..2852abad003690 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.h +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.h @@ -67,10 +67,10 @@ class ReductionProcessor { static bool supportedIntrinsicProcReduction(const omp::clause::ProcedureDesignator &pd); - static const Fortran::semantics::SourceName - getRealName(const Fortran::semantics::Symbol *symbol); + static const semantics::SourceName + getRealName(const semantics::Symbol *symbol); - static const Fortran::semantics::SourceName + static const semantics::SourceName getRealName(const omp::clause::ProcedureDesignator &pd); static bool @@ -124,13 +124,12 @@ class ReductionProcessor { /// Creates a reduction declaration and associates it with an OpenMP block /// directive. static void addDeclareReduction( - mlir::Location currentLocation, - Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, lower::AbstractConverter &converter, const omp::clause::Reduction &reduction, llvm::SmallVectorImpl &reductionVars, llvm::SmallVectorImpl &reductionDeclSymbols, - llvm::SmallVectorImpl - *reductionSymbols = nullptr); + llvm::SmallVectorImpl *reductionSymbols = + nullptr); }; template diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index cb1d1a5a7f3dda..4d665e6dd34c50 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -52,22 +52,22 @@ int64_t getCollapseValue(const List &clauses) { } void genObjectList(const ObjectList &objects, - Fortran::lower::AbstractConverter &converter, + lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands) { for (const Object &object : objects) { - const Fortran::semantics::Symbol *sym = object.id(); + const semantics::Symbol *sym = object.id(); assert(sym && "Expected Symbol"); if (mlir::Value variable = converter.getSymbolAddress(*sym)) { operands.push_back(variable); } else if (const auto *details = - sym->detailsIf()) { + sym->detailsIf()) { operands.push_back(converter.getSymbolAddress(details->symbol())); converter.copySymbolBinding(details->symbol(), *sym); } } } -mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, +mlir::Type getLoopVarType(lower::AbstractConverter &converter, std::size_t loopVarTypeSize) { // OpenMP runtime requires 32-bit or 64-bit loop variables. loopVarTypeSize = loopVarTypeSize * 8; @@ -85,24 +85,21 @@ mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize); } -Fortran::semantics::Symbol * -getIterationVariableSymbol(const Fortran::lower::pft::Evaluation &eval) { - return eval.visit(Fortran::common::visitors{ - [&](const Fortran::parser::DoConstruct &doLoop) { +semantics::Symbol * +getIterationVariableSymbol(const lower::pft::Evaluation &eval) { + return eval.visit(common::visitors{ + [&](const parser::DoConstruct &doLoop) { if (const auto &maybeCtrl = doLoop.GetLoopControl()) { - using LoopControl = Fortran::parser::LoopControl; + using LoopControl = parser::LoopControl; if (auto *bounds = std::get_if(&maybeCtrl->u)) { - static_assert( - std::is_same_vname), - Fortran::parser::Scalar>); + static_assert(std::is_same_vname), + parser::Scalar>); return bounds->name.thing.symbol; } } - return static_cast(nullptr); - }, - [](auto &&) { - return static_cast(nullptr); + return static_cast(nullptr); }, + [](auto &&) { return static_cast(nullptr); }, }); } @@ -139,12 +136,11 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, } static int -getComponentPlacementInParent(const Fortran::semantics::Symbol *componentSym) { - const auto *derived = - componentSym->owner() - .derivedTypeSpec() - ->typeSymbol() - .detailsIf(); +getComponentPlacementInParent(const semantics::Symbol *componentSym) { + const auto *derived = componentSym->owner() + .derivedTypeSpec() + ->typeSymbol() + .detailsIf(); assert(derived && "expected derived type details when processing component symbol"); for (auto [placement, name] : llvm::enumerate(derived->componentNames())) @@ -155,7 +151,7 @@ getComponentPlacementInParent(const Fortran::semantics::Symbol *componentSym) { static std::optional getComponentObject(std::optional object, - Fortran::semantics::SemanticsContext &semaCtx) { + semantics::SemanticsContext &semaCtx) { if (!object) return std::nullopt; @@ -176,7 +172,7 @@ getComponentObject(std::optional object, static void generateMemberPlacementIndices(const Object &object, llvm::SmallVectorImpl &indices, - Fortran::semantics::SemanticsContext &semaCtx) { + semantics::SemanticsContext &semaCtx) { auto compObj = getComponentObject(object, semaCtx); while (compObj) { indices.push_back(getComponentPlacementInParent(compObj->id())); @@ -189,16 +185,14 @@ generateMemberPlacementIndices(const Object &object, void addChildIndexAndMapToParent( const omp::Object &object, - std::map> &parentMemberIndices, - mlir::omp::MapInfoOp &mapOp, - Fortran::semantics::SemanticsContext &semaCtx) { - std::optional dataRef = - ExtractDataRef(object.designator); + mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) { + std::optional dataRef = ExtractDataRef(object.designator); assert(dataRef.has_value() && "DataRef could not be extracted during mapping of derived type " "cannot proceed"); - const Fortran::semantics::Symbol *parentSym = &dataRef->GetFirstSymbol(); + const semantics::Symbol *parentSym = &dataRef->GetFirstSymbol(); assert(parentSym && "Could not find parent symbol during lower of " "a component member in OpenMP map clause"); llvm::SmallVector indices; @@ -236,14 +230,14 @@ static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices( llvm::SmallVector shape; calculateShapeAndFillIndices(shape, memberPlacementData); - llvm::SmallVector indicesFlattened = std::accumulate( - memberPlacementData.begin(), memberPlacementData.end(), - llvm::SmallVector(), - [](llvm::SmallVector &x, OmpMapMemberIndicesData y) { - x.insert(x.end(), y.memberPlacementIndices.begin(), - y.memberPlacementIndices.end()); - return x; - }); + llvm::SmallVector indicesFlattened = + std::accumulate(memberPlacementData.begin(), memberPlacementData.end(), + llvm::SmallVector(), + [](llvm::SmallVector &x, OmpMapMemberIndicesData y) { + x.insert(x.end(), y.memberPlacementIndices.begin(), + y.memberPlacementIndices.end()); + return x; + }); return mlir::DenseIntElementsAttr::get( mlir::VectorType::get(shape, @@ -252,11 +246,11 @@ static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices( } void insertChildMapInfoIntoParent( - Fortran::lower::AbstractConverter &converter, - std::map> &parentMemberIndices, llvm::SmallVectorImpl &mapOperands, - llvm::SmallVectorImpl &mapSyms, + llvm::SmallVectorImpl &mapSyms, llvm::SmallVectorImpl *mapSymTypes, llvm::SmallVectorImpl *mapSymLocs) { for (auto indices : parentMemberIndices) { @@ -323,30 +317,28 @@ void insertChildMapInfoIntoParent( } } -Fortran::semantics::Symbol * -getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) { - Fortran::semantics::Symbol *sym = nullptr; +semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject) { + semantics::Symbol *sym = nullptr; std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { + common::visitors{ + [&](const parser::Designator &designator) { if (auto *arrayEle = - Fortran::parser::Unwrap( - designator)) { + parser::Unwrap(designator)) { // Use getLastName to retrieve the arrays symbol, this will // provide the farthest right symbol (the last) in a designator, // i.e. providing something like the following: // "dtype1%dtype2%array[2:10]", will result in "array" sym = GetLastName(arrayEle->base).symbol; - } else if (auto *structComp = Fortran::parser::Unwrap< - Fortran::parser::StructureComponent>(designator)) { - sym = structComp->component.symbol; - } else if (const Fortran::parser::Name *name = - Fortran::semantics::getDesignatorNameIfDataRef( + } else if (auto *structComp = + parser::Unwrap( designator)) { + sym = structComp->component.symbol; + } else if (const parser::Name *name = + semantics::getDesignatorNameIfDataRef(designator)) { sym = name->symbol; } }, - [&](const Fortran::parser::Name &name) { sym = name.symbol; }}, + [&](const parser::Name &name) { sym = name.symbol; }}, ompObject.u); return sym; } diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 345ce55620ee9e..d20f9187640f0c 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -42,8 +42,7 @@ class AbstractConverter; namespace omp { using DeclareTargetCapturePair = - std::pair; + std::pair; // A small helper structure for keeping track of a component members MapInfoOp // and index data when lowering OpenMP map clauses. Keeps track of the @@ -69,24 +68,24 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, void addChildIndexAndMapToParent( const omp::Object &object, - std::map> &parentMemberIndices, - mlir::omp::MapInfoOp &mapOp, Fortran::semantics::SemanticsContext &semaCtx); + mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx); void insertChildMapInfoIntoParent( - Fortran::lower::AbstractConverter &converter, - std::map> &parentMemberIndices, llvm::SmallVectorImpl &mapOperands, - llvm::SmallVectorImpl &mapSyms, + llvm::SmallVectorImpl &mapSyms, llvm::SmallVectorImpl *mapSymTypes, llvm::SmallVectorImpl *mapSymLocs); -mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, +mlir::Type getLoopVarType(lower::AbstractConverter &converter, std::size_t loopVarTypeSize); -Fortran::semantics::Symbol * -getIterationVariableSymbol(const Fortran::lower::pft::Evaluation &eval); +semantics::Symbol * +getIterationVariableSymbol(const lower::pft::Evaluation &eval); void gatherFuncAndVarSyms( const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause, @@ -94,11 +93,10 @@ void gatherFuncAndVarSyms( int64_t getCollapseValue(const List &clauses); -Fortran::semantics::Symbol * -getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject); +semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject); void genObjectList(const ObjectList &objects, - Fortran::lower::AbstractConverter &converter, + lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands); } // namespace omp From 2bc9af96567eeda1effdf0cb7662511d896fb386 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 16:49:56 +0400 Subject: [PATCH 031/576] [lldb][Windows] Disable the TestGdbRemoteLibrariesSvr4Support test for Windows host (#92341) Windows does not allow quotes in file names. So it is impossible to build `libsvr4lib_b".so` on Windows. --- .../libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/test/API/tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py b/lldb/test/API/tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py index 846adade344020..02c9d318525fb8 100644 --- a/lldb/test/API/tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py +++ b/lldb/test/API/tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py @@ -4,6 +4,8 @@ from lldbsuite.test.lldbtest import * +# Windows does not allow quotes in file names. +@skipIf(hostoslist=["windows"]) class TestGdbRemoteLibrariesSvr4Support(gdbremote_testcase.GdbRemoteTestCaseBase): FEATURE_NAME = "qXfer:libraries-svr4:read" From 588ce34ba626a369a416b883342af48c69e70925 Mon Sep 17 00:00:00 2001 From: zibi2 <62662650+zibi2@users.noreply.github.com> Date: Thu, 16 May 2024 08:51:56 -0400 Subject: [PATCH 032/576] [libc++][z/OS] Fixup two linear_congruential_engine tests (#92261) --- .../std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp | 3 +++ .../std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp index 73829071bd9580..63a1a8adf4e35d 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/assign.pass.cpp @@ -83,7 +83,10 @@ int main(int, char**) test(); test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 test_ext(); +#endif test(); // This isn't implemented on platforms without __int128 #ifndef _LIBCPP_HAS_NO_INT128 diff --git a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp index 8387a1763714f0..c45f45d0f20a32 100644 --- a/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.eng/rand.eng.lcong/copy.pass.cpp @@ -82,7 +82,10 @@ int main(int, char**) test(); test_ext(); test(); + // This isn't implemented on platforms without __int128 +#ifndef _LIBCPP_HAS_NO_INT128 test_ext(); +#endif test(); // This isn't implemented on platforms without __int128 #ifndef _LIBCPP_HAS_NO_INT128 From e948da1021b207dbcee9ed484ccb3409c2295561 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Thu, 16 May 2024 20:51:51 +0800 Subject: [PATCH 033/576] [Transforms] Fix -Wunused-variable in DemoteRegToStack.cpp (NFC) llvm-project/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:58:21: error: unused variable 'BB' [-Werror,-Wunused-variable] BasicBlock *BB = SplitCriticalEdge(II, i); ^ 1 error generated. --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp index 653ea8bbb72b97..7995b754080313 100644 --- a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +++ b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -55,7 +55,7 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads, auto *Succ = CBI->getSuccessor(i); if (!Succ->getSinglePredecessor()) { assert(isCriticalEdge(II, i) && "Expected a critical edge!"); - BasicBlock *BB = SplitCriticalEdge(II, i); + [[maybe_unused]] BasicBlock *BB = SplitCriticalEdge(II, i); assert(BB && "Unable to split critical edge."); } } From 80fac30a09ce0fbd2047cc210ec0a42cfa95b79d Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 16 May 2024 13:51:27 +0100 Subject: [PATCH 034/576] [X86] rot32.ll - remove old shld check prefixes This was missed in 8dbd745b09c9f65fefc2ffac14e8f7f288766861 --- llvm/test/CodeGen/X86/rot32.ll | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/test/CodeGen/X86/rot32.ll b/llvm/test/CodeGen/X86/rot32.ll index d8edd31c3c06a9..114d558954f4c9 100644 --- a/llvm/test/CodeGen/X86/rot32.ll +++ b/llvm/test/CodeGen/X86/rot32.ll @@ -285,8 +285,6 @@ define i32 @xunp(ptr %p) nounwind readnone { ; BMI264-NEXT: rorxl $7, (%rdi), %eax ; BMI264-NEXT: retq entry: -; shld-label: xunp: -; shld: shldl $25 %x = load i32, ptr %p %a = lshr i32 %x, 7 %b = shl i32 %x, 25 From 44eded31e0bd5739391298497affe3412e4091aa Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 16:55:06 +0400 Subject: [PATCH 035/576] [lldb] Move TestBase.runCmd() to the Base class (#92252) runCmd() is called from Base.getCPUInfo() but implemented only in TestBase(Base). Usually it works if TestBase is used. But call getCPUInfo() from a class based on Base will cause something like ``` File "E:\projects\llvm-nino\lldb\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 1256, in getCPUInfo self.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path) AttributeError: 'TestGdbRemoteExpeditedRegisters' object has no attribute 'runCmd' ``` BTW, TestBase.setUp() called runCmd() before applying LLDB_MAX_LAUNCH_COUNT and LLDB_TIME_WAIT_NEXT_LAUNCH. This patch fixes the test TestGdbRemoteExpeditedRegisters in case of Windows host and Linux target. --- .../Python/lldbsuite/test/lldbtest.py | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 5fd686c143e9f9..1ad8ab6e6e462d 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -531,6 +531,14 @@ class Base(unittest.TestCase): # Keep track of the old current working directory. oldcwd = None + # Maximum allowed attempts when launching the inferior process. + # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. + maxLaunchCount = 1 + + # Time to wait before the next launching attempt in second(s). + # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. + timeWaitNextLaunch = 1.0 + @staticmethod def compute_mydir(test_file): """Subclasses should call this function to correctly calculate the @@ -796,6 +804,12 @@ def setUp(self): # import traceback # traceback.print_stack() + if "LLDB_MAX_LAUNCH_COUNT" in os.environ: + self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) + + if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: + self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) + if "LIBCXX_PATH" in os.environ: self.libcxxPath = os.environ["LIBCXX_PATH"] else: @@ -937,6 +951,57 @@ def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=Tr self.subprocesses.append(proc) return proc + def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): + """ + Ask the command interpreter to handle the command and then check its + return status. + """ + # Fail fast if 'cmd' is not meaningful. + if cmd is None: + raise Exception("Bad 'cmd' parameter encountered") + + trace = True if traceAlways else trace + + if cmd.startswith("target create "): + cmd = cmd.replace("target create ", "file ") + + running = cmd.startswith("run") or cmd.startswith("process launch") + + for i in range(self.maxLaunchCount if running else 1): + with recording(self, trace) as sbuf: + print("runCmd:", cmd, file=sbuf) + if not check: + print("check of return status not required", file=sbuf) + + self.ci.HandleCommand(cmd, self.res, inHistory) + + with recording(self, trace) as sbuf: + if self.res.Succeeded(): + print("output:", self.res.GetOutput(), file=sbuf) + else: + print("runCmd failed!", file=sbuf) + print(self.res.GetError(), file=sbuf) + + if self.res.Succeeded(): + break + elif running: + # For process launch, wait some time before possible next try. + time.sleep(self.timeWaitNextLaunch) + with recording(self, trace) as sbuf: + print("Command '" + cmd + "' failed!", file=sbuf) + + if check: + output = "" + if self.res.GetOutput(): + output += "\nCommand output:\n" + self.res.GetOutput() + if self.res.GetError(): + output += "\nError output:\n" + self.res.GetError() + if msg: + msg += output + if cmd: + cmd += output + self.assertTrue(self.res.Succeeded(), msg if (msg) else CMD_MSG(cmd)) + def HideStdout(self): """Hide output to stdout from the user. @@ -1764,14 +1829,6 @@ class TestBase(Base, metaclass=LLDBTestCaseFactory): # test multiple times with various debug info types. NO_DEBUG_INFO_TESTCASE = False - # Maximum allowed attempts when launching the inferior process. - # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. - maxLaunchCount = 1 - - # Time to wait before the next launching attempt in second(s). - # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. - timeWaitNextLaunch = 1.0 - def generateSource(self, source): template = source + ".template" temp = os.path.join(self.getSourceDir(), template) @@ -1812,12 +1869,6 @@ def setUp(self): for s in self.setUpCommands(): self.runCmd(s) - if "LLDB_MAX_LAUNCH_COUNT" in os.environ: - self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) - - if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: - self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) - # We want our debugger to be synchronous. self.dbg.SetAsync(False) @@ -1983,57 +2034,6 @@ def switch_to_thread_with_stop_reason(self, stop_reason): if matched: self.runCmd("thread select %s" % matched.group(1)) - def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): - """ - Ask the command interpreter to handle the command and then check its - return status. - """ - # Fail fast if 'cmd' is not meaningful. - if cmd is None: - raise Exception("Bad 'cmd' parameter encountered") - - trace = True if traceAlways else trace - - if cmd.startswith("target create "): - cmd = cmd.replace("target create ", "file ") - - running = cmd.startswith("run") or cmd.startswith("process launch") - - for i in range(self.maxLaunchCount if running else 1): - with recording(self, trace) as sbuf: - print("runCmd:", cmd, file=sbuf) - if not check: - print("check of return status not required", file=sbuf) - - self.ci.HandleCommand(cmd, self.res, inHistory) - - with recording(self, trace) as sbuf: - if self.res.Succeeded(): - print("output:", self.res.GetOutput(), file=sbuf) - else: - print("runCmd failed!", file=sbuf) - print(self.res.GetError(), file=sbuf) - - if self.res.Succeeded(): - break - elif running: - # For process launch, wait some time before possible next try. - time.sleep(self.timeWaitNextLaunch) - with recording(self, trace) as sbuf: - print("Command '" + cmd + "' failed!", file=sbuf) - - if check: - output = "" - if self.res.GetOutput(): - output += "\nCommand output:\n" + self.res.GetOutput() - if self.res.GetError(): - output += "\nError output:\n" + self.res.GetError() - if msg: - msg += output - if cmd: - cmd += output - self.assertTrue(self.res.Succeeded(), msg if (msg) else CMD_MSG(cmd)) - def match( self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True ): From f7392f40f3f6d5d4fc4ec11a982cf5379ab3c5d1 Mon Sep 17 00:00:00 2001 From: Hassnaa Hamdi Date: Thu, 16 May 2024 13:56:02 +0100 Subject: [PATCH 036/576] [AArch64] Add intrinsics for bfloat16 min/max/minnm/maxnm (#90105) According to specifications in [ARM-software/acle/pull/309](https://github.com/ARM-software/acle/pull/309) Add following intrinsics: ``` // svmax single,multi svbfloat16x2_t svmax_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) svbfloat16x4_t svmax_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) svbfloat16x2_t svmax_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) svbfloat16x4_t svmax_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) ``` ``` // svmin single,multi svbfloat16x2_t svmin_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) svbfloat16x4_t svmin_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) svbfloat16x2_t svmin_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) svbfloat16x4_t svmin_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) ``` ``` // svmaxnm single,multi svbfloat16x2_t svmaxnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) svbfloat16x4_t svmaxnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) svbfloat16x2_t svmaxnm_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) svbfloat16x4_t svmaxnm_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) ``` ``` // svminnm single,multi svbfloat16x2_t svminnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) svbfloat16x4_t svminnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) svbfloat16x2_t svminnm_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) svbfloat16x4_t svminnm_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) ``` - Variations other than bfloat16 are already supported. --- clang/include/clang/Basic/arm_sve.td | 10 +- .../aarch64-sme2-intrinsics/acle_sme2_max.c | 150 +++++++++++++++++- .../aarch64-sme2-intrinsics/acle_sme2_maxnm.c | 150 +++++++++++++++++- .../aarch64-sme2-intrinsics/acle_sme2_min.c | 150 +++++++++++++++++- .../aarch64-sme2-intrinsics/acle_sme2_minnm.c | 150 +++++++++++++++++- .../Target/AArch64/AArch64ISelDAGToDAG.cpp | 74 +++++---- .../CodeGen/AArch64/sme2-intrinsics-max.ll | 126 ++++++++++++++- .../CodeGen/AArch64/sme2-intrinsics-min.ll | 127 ++++++++++++++- 8 files changed, 875 insertions(+), 62 deletions(-) diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 15340ebb62b365..a9ea71cd077740 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -2095,7 +2095,7 @@ def SVFCLAMP_BF : SInst<"svclamp[_{d}]", "dddd", "b", MergeNone, "aarch64_sve_ multiclass MinMaxIntr { def SVS # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "csil", MergeNone, "aarch64_sve_s" # i # zm # "_" # mul, [IsStreaming], []>; def SVU # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "UcUsUiUl", MergeNone, "aarch64_sve_u" # i # zm # "_" # mul, [IsStreaming], []>; - def SVF # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "hfd", MergeNone, "aarch64_sve_f" # i # zm # "_" # mul, [IsStreaming], []>; + def SVF # NAME : SInst<"sv" # i # "[" # zm # "_{d}_" # mul # "]", t, "bhfd", MergeNone, "aarch64_sve_f" # i # zm # "_" # mul, [IsStreaming], []>; } let TargetGuard = "sme2" in { @@ -2113,11 +2113,11 @@ let TargetGuard = "sme2" in { } multiclass SInstMinMaxByVector { - def NAME # _SINGLE_X2 : SInst<"sv" # name # "nm[_single_{d}_x2]", "22d", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x2", [IsStreaming], []>; - def NAME # _SINGLE_X4 : SInst<"sv" # name # "nm[_single_{d}_x4]", "44d", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x4", [IsStreaming], []>; + def NAME # _SINGLE_X2 : SInst<"sv" # name # "nm[_single_{d}_x2]", "22d", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x2", [IsStreaming], []>; + def NAME # _SINGLE_X4 : SInst<"sv" # name # "nm[_single_{d}_x4]", "44d", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_single_x4", [IsStreaming], []>; - def NAME # _X2 : SInst<"sv" # name # "nm[_{d}_x2]", "222", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_x2", [IsStreaming], []>; - def NAME # _X4 : SInst<"sv" # name # "nm[_{d}_x4]", "444", "hfd", MergeNone, "aarch64_sve_f" # name # "nm_x4", [IsStreaming], []>; + def NAME # _X2 : SInst<"sv" # name # "nm[_{d}_x2]", "222", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_x2", [IsStreaming], []>; + def NAME # _X4 : SInst<"sv" # name # "nm[_{d}_x4]", "444", "bhfd", MergeNone, "aarch64_sve_f" # name # "nm_x4", [IsStreaming], []>; } let TargetGuard = "sme2" in { diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c index 8e696f1d1fa4c4..2b9343a2c6b6cd 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c @@ -1,9 +1,9 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include @@ -224,6 +224,32 @@ svuint64x2_t test_svmax_single_u64_x2(svuint64x2_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmax,_single_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmax_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svmax_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmax_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -608,6 +634,44 @@ svuint64x4_t test_svmax_single_u64_x4(svuint64x4_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmax,_single_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmax_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z25test_svmax_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmax_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -964,6 +1028,36 @@ svuint64x2_t test_svmax_u64_x2(svuint64x2_t zdn, svuint64x2_t zm) __arm_streamin return SVE_ACLE_FUNC(svmax,_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmax_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z18test_svmax_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmax.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmax_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -1424,6 +1518,52 @@ svuint64x4_t test_svmax_u64_x4(svuint64x4_t zdn, svuint64x4_t zm) __arm_streamin return SVE_ACLE_FUNC(svmax,_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmax_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z18test_svmax_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmax.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmax_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmax,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmax_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c index a956235034e14f..ac2e20cf98b862 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c @@ -1,11 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include #ifdef SVE_OVERLOADED_FORMS @@ -17,6 +17,32 @@ // Single, x2 +// CHECK-LABEL: @test_svmaxnm_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z27test_svmaxnm_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmaxnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -97,6 +123,44 @@ svfloat64x2_t test_svmaxnm_single_f64_x2(svfloat64x2_t zdn, svfloat64_t zm) __ar // Single, x4 +// CHECK-LABEL: @test_svmaxnm_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z27test_svmaxnm_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmaxnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -213,6 +277,36 @@ svfloat64x4_t test_svmaxnm_single_f64_x4(svfloat64x4_t zdn, svfloat64_t zm) __ar // Multi, x2 +// CHECK-LABEL: @test_svmaxnm_multi_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z26test_svmaxnm_multi_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmaxnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmaxnm_multi_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_multi_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -305,6 +399,52 @@ svfloat64x2_t test_svmaxnm_multi_f64_x2(svfloat64x2_t zdn, svfloat64x2_t zm) __a // Multi, x4 +// CHECK-LABEL: @test_svmaxnm_multi_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z26test_svmaxnm_multi_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmaxnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmaxnm_multi_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmaxnm,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmaxnm_multi_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c index 860e6237bb9c81..dda0837cf1f3cb 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c @@ -1,9 +1,9 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // REQUIRES: aarch64-registered-target #include @@ -224,6 +224,32 @@ svuint64x2_t test_svmin_single_u64_x2(svuint64x2_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmin,_single_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmin_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svmin_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svmin_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -608,6 +634,44 @@ svuint64x4_t test_svmin_single_u64_x4(svuint64x4_t zdn, svuint64_t zm) __arm_str return SVE_ACLE_FUNC(svmin,_single_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmin_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z25test_svmin_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svmin_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -964,6 +1028,36 @@ svuint64x2_t test_svmin_u64_x2(svuint64x2_t zdn, svuint64x2_t zm) __arm_streamin return SVE_ACLE_FUNC(svmin,_u64_x2)(zdn, zm); } +// CHECK-LABEL: @test_svmin_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z18test_svmin_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fmin.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svmin_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -1424,6 +1518,52 @@ svuint64x4_t test_svmin_u64_x4(svuint64x4_t zdn, svuint64x4_t zm) __arm_streamin return SVE_ACLE_FUNC(svmin,_u64_x4)(zdn, zm); } +// CHECK-LABEL: @test_svmin_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z18test_svmin_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fmin.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svmin_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svmin,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svmin_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c index e34b9d98eff33d..23378ffdf85d4e 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c @@ -1,11 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sme2 -target-feature +b16b16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include #ifdef SVE_OVERLOADED_FORMS @@ -17,6 +17,32 @@ // Single, x2 +// CHECK-LABEL: @test_svminnm_single_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z27test_svminnm_single_bf16_x214svbfloat16x2_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.single.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svbfloat16x2_t test_svminnm_single_bf16_x2(svbfloat16x2_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_single_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_single_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -97,6 +123,44 @@ svfloat64x2_t test_svminnm_single_f64_x2(svfloat64x2_t zdn, svfloat64_t zm) __ar // Single, x4 +// CHECK-LABEL: @test_svminnm_single_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z27test_svminnm_single_bf16_x414svbfloat16x4_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.single.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[ZM:%.*]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP8]], [[TMP9]], i64 16) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svbfloat16x4_t test_svminnm_single_bf16_x4(svbfloat16x4_t zdn, svbfloat16_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_single_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_single_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) @@ -213,6 +277,36 @@ svfloat64x4_t test_svminnm_single_f64_x4(svfloat64x4_t zdn, svfloat64_t zm) __ar // Multi, x2 +// CHECK-LABEL: @test_svminnm_multi_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z26test_svminnm_multi_bf16_x214svbfloat16x2_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv16bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , } @llvm.aarch64.sve.fminnm.x2.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x2_t test_svminnm_multi_bf16_x2(svbfloat16x2_t zdn, svbfloat16x2_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_bf16_x2)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_multi_f16_x2( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv16f16( [[ZDN:%.*]], i64 0) @@ -305,6 +399,52 @@ svfloat64x2_t test_svminnm_multi_f64_x2(svfloat64x2_t zdn, svfloat64x2_t zm) __a // Multi, x4 +// CHECK-LABEL: @test_svminnm_multi_bf16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CHECK-NEXT: ret [[TMP16]] +// +// CPP-CHECK-LABEL: @_Z26test_svminnm_multi_bf16_x414svbfloat16x4_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 16) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZDN]], i64 24) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 8) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = tail call @llvm.vector.extract.nxv8bf16.nxv32bf16( [[ZM]], i64 24) +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call { , , , } @llvm.aarch64.sve.fminnm.x4.nxv8bf16( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]], [[TMP5]], [[TMP6]], [[TMP7]]) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP8]], 0 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP9]], i64 0) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP8]], 1 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP10]], [[TMP11]], i64 8) +// CPP-CHECK-NEXT: [[TMP13:%.*]] = extractvalue { , , , } [[TMP8]], 2 +// CPP-CHECK-NEXT: [[TMP14:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP12]], [[TMP13]], i64 16) +// CPP-CHECK-NEXT: [[TMP15:%.*]] = extractvalue { , , , } [[TMP8]], 3 +// CPP-CHECK-NEXT: [[TMP16:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP14]], [[TMP15]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP16]] +// +svbfloat16x4_t test_svminnm_multi_bf16_x4(svbfloat16x4_t zdn, svbfloat16x4_t zm) __arm_streaming { + return SVE_ACLE_FUNC(svminnm,_bf16_x4)(zdn, zm); +} + // CHECK-LABEL: @test_svminnm_multi_f16_x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8f16.nxv32f16( [[ZDN:%.*]], i64 0) diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index 80272213dd3897..25f2e4d7c4de63 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -1675,6 +1675,7 @@ static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef Opcodes) { return 0; EVT EltVT = VT.getVectorElementType(); + unsigned Key = VT.getVectorMinNumElements(); switch (Kind) { case SelectTypeKind::AnyType: break; @@ -1688,14 +1689,17 @@ static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef Opcodes) { return 0; break; case SelectTypeKind::FP: - if (EltVT != MVT::f16 && EltVT != MVT::f32 && EltVT != MVT::f64) + if (EltVT == MVT::bf16) + Key = 16; + else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 && + EltVT != MVT::f64) return 0; break; } unsigned Offset; - switch (VT.getVectorMinNumElements()) { - case 16: // 8-bit + switch (Key) { + case 16: // 8-bit or bf16 Offset = 0; break; case 8: // 16-bit @@ -5482,8 +5486,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmax_single_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_S, - AArch64::FMAX_VG2_2ZZ_D})) + {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H, + AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 2, false, Op); return; case Intrinsic::aarch64_sve_smax_single_x4: @@ -5503,8 +5507,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmax_single_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_S, - AArch64::FMAX_VG4_4ZZ_D})) + {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H, + AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 4, false, Op); return; case Intrinsic::aarch64_sve_smin_single_x2: @@ -5524,8 +5528,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmin_single_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_S, - AArch64::FMIN_VG2_2ZZ_D})) + {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H, + AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 2, false, Op); return; case Intrinsic::aarch64_sve_smin_single_x4: @@ -5545,8 +5549,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmin_single_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_S, - AArch64::FMIN_VG4_4ZZ_D})) + {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H, + AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 4, false, Op); return; case Intrinsic::aarch64_sve_smax_x2: @@ -5566,8 +5570,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmax_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_S, - AArch64::FMAX_VG2_2Z2Z_D})) + {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H, + AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D})) SelectDestructiveMultiIntrinsic(Node, 2, true, Op); return; case Intrinsic::aarch64_sve_smax_x4: @@ -5587,8 +5591,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmax_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAX_VG4_4Z4Z_H, AArch64::FMAX_VG4_4Z4Z_S, - AArch64::FMAX_VG4_4Z4Z_D})) + {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H, + AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D})) SelectDestructiveMultiIntrinsic(Node, 4, true, Op); return; case Intrinsic::aarch64_sve_smin_x2: @@ -5608,8 +5612,8 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmin_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_S, - AArch64::FMIN_VG2_2Z2Z_D})) + {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H, + AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D})) SelectDestructiveMultiIntrinsic(Node, 2, true, Op); return; case Intrinsic::aarch64_sve_smin_x4: @@ -5629,64 +5633,64 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { case Intrinsic::aarch64_sve_fmin_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMIN_VG4_4Z4Z_H, AArch64::FMIN_VG4_4Z4Z_S, - AArch64::FMIN_VG4_4Z4Z_D})) + {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H, + AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D})) SelectDestructiveMultiIntrinsic(Node, 4, true, Op); return; case Intrinsic::aarch64_sve_fmaxnm_single_x2 : if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_S, - AArch64::FMAXNM_VG2_2ZZ_D})) + {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H, + AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 2, false, Op); return; case Intrinsic::aarch64_sve_fmaxnm_single_x4 : if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_S, - AArch64::FMAXNM_VG4_4ZZ_D})) + {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H, + AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 4, false, Op); return; case Intrinsic::aarch64_sve_fminnm_single_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_S, - AArch64::FMINNM_VG2_2ZZ_D})) + {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H, + AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 2, false, Op); return; case Intrinsic::aarch64_sve_fminnm_single_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_S, - AArch64::FMINNM_VG4_4ZZ_D})) + {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H, + AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D})) SelectDestructiveMultiIntrinsic(Node, 4, false, Op); return; case Intrinsic::aarch64_sve_fmaxnm_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_S, - AArch64::FMAXNM_VG2_2Z2Z_D})) + {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H, + AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D})) SelectDestructiveMultiIntrinsic(Node, 2, true, Op); return; case Intrinsic::aarch64_sve_fmaxnm_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMAXNM_VG4_4Z4Z_H, AArch64::FMAXNM_VG4_4Z4Z_S, - AArch64::FMAXNM_VG4_4Z4Z_D})) + {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H, + AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D})) SelectDestructiveMultiIntrinsic(Node, 4, true, Op); return; case Intrinsic::aarch64_sve_fminnm_x2: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_S, - AArch64::FMINNM_VG2_2Z2Z_D})) + {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H, + AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D})) SelectDestructiveMultiIntrinsic(Node, 2, true, Op); return; case Intrinsic::aarch64_sve_fminnm_x4: if (auto Op = SelectOpcodeFromVT( Node->getValueType(0), - {0, AArch64::FMINNM_VG4_4Z4Z_H, AArch64::FMINNM_VG4_4Z4Z_S, - AArch64::FMINNM_VG4_4Z4Z_D})) + {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H, + AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D})) SelectDestructiveMultiIntrinsic(Node, 4, true, Op); return; case Intrinsic::aarch64_sve_fcvtzs_x2: diff --git a/llvm/test/CodeGen/AArch64/sme2-intrinsics-max.ll b/llvm/test/CodeGen/AArch64/sme2-intrinsics-max.ll index 92e8877927ea57..79db677853cb58 100644 --- a/llvm/test/CodeGen/AArch64/sme2-intrinsics-max.ll +++ b/llvm/test/CodeGen/AArch64/sme2-intrinsics-max.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -mattr=+b16b16 -verify-machineinstrs < %s | FileCheck %s ; SMAX (Single, x2) @@ -109,6 +109,19 @@ define { , } @multi_vec_max_single_x2_u64(< ret { , } %res } +; BFMAX (Single, x2) + +define { , } @multi_vec_max_single_x2_bf16( %zdn1, %zdn2, %zm) { +; CHECK-LABEL: multi_vec_max_single_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: bfmax { z0.h, z1.h }, { z0.h, z1.h }, z2.h +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmax.single.x2.nxv8bf16( %zdn1, %zdn2, %zm) + ret { , } %res +} + ; FMAX (Single, x2) define { , } @multi_vec_max_single_x2_f16( %unused, %zdn1, %zdn2, %zm) { @@ -298,6 +311,21 @@ define { , , , , , , } %res } +; BFMAX (Single, x4) + +define { , , , } @multi_vec_max_single_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) { +; CHECK-LABEL: multi_vec_max_single_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: bfmax { z0.h - z3.h }, { z0.h - z3.h }, z4.h +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmax.single.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) + ret { , , , } %res +} + ; FMAX (SINGLE, x4) define { , , , } @multi_vec_max_single_x4_f16( %unused, %zdn1, %zdn2, %zdn3, %zdn4, %zm) { @@ -478,6 +506,21 @@ define { , } @multi_vec_max_multi_x2_u64(, } %res } +; BFMAX (Multi, x2) + +define { , } @multi_vec_max_x2_bf16( %zdn1, %zdn2, %zm1, %zm2) { +; CHECK-LABEL: multi_vec_max_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: bfmax { z0.h, z1.h }, { z0.h, z1.h }, { z2.h, z3.h } +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmax.x2.nxv8bf16( %zdn1, %zdn2, %zm1, %zm2) + ret { , } %res +} + ; FMAX (Multi, x2) define { , } @multi_vec_max_multi_x2_f16( %unused, %zdn1, %zdn2, %zm1, %zm2) { @@ -729,6 +772,25 @@ define { , , , , , , } %res } +; BFMAX (Multi, x4) + +define { , , , } @multi_vec_max_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { +; CHECK-LABEL: multi_vec_max_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: bfmax { z0.h - z3.h }, { z0.h - z3.h }, { z4.h - z7.h } +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmax.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) + ret { , , , } %res +} + ; FMAX (Multi, x4) define { , , , } @multi_vec_max_multi_x4_f16( %unused, %zdn1, %zdn2, %zdn3, %zdn4, @@ -806,6 +868,19 @@ define { , , , , , , } %res } +; BFMAXNM (Single, x2) + +define { , } @multi_vec_maxnm_single_x2_bf16( %zdn1, %zdn2, %zm) { +; CHECK-LABEL: multi_vec_maxnm_single_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: bfmaxnm { z0.h, z1.h }, { z0.h, z1.h }, z2.h +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmaxnm.single.x2.nxv8bf16( %zdn1, %zdn2, %zm) + ret { , } %res +} + ; FMAXNM (Single, x2) define { , } @multi_vec_maxnm_single_x2_f16( %dummy, %zdn1, %zdn2, %zm) { @@ -847,6 +922,21 @@ define { , } @multi_vec_maxnm_single ret { , } %res } +; BFMAXNM (Single, x4) + +define { , , , } @multi_vec_maxnm_single_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) { +; CHECK-LABEL: multi_vec_maxnm_single_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: bfmaxnm { z0.h - z3.h }, { z0.h - z3.h }, z4.h +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmaxnm.single.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) + ret { , , , } %res +} + ; FMAXNM (Single, x4) define { , , , } @multi_vec_maxnm_single_x4_f16( %dummy, %zdn1, %zdn2, %zdn3, %zdn4, %zm) { @@ -903,6 +993,21 @@ define { , , , , , , } %res } +; BFMAXNM (Multi, x2) + +define { , } @multi_vec_maxnm_x2_bf16( %zdn1, %zdn2, %zm1, %zm2) { +; CHECK-LABEL: multi_vec_maxnm_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: bfmaxnm { z0.h, z1.h }, { z0.h, z1.h }, { z2.h, z3.h } +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmaxnm.x2.nxv8bf16( %zdn1, %zdn2, %zm1, %zm2) + ret { , } %res +} + ; FMAXNM (Multi, x2) define { , } @multi_vec_maxnm_x2_f16( %dummy, %zdn1, %zdn2, %zm1, %zm2) { @@ -950,6 +1055,25 @@ define { , } @multi_vec_maxnm_x2_f64( ret { , } %res } +; BFMAXNM (Multi, x4) + +define { , , , } @multi_vec_maxnm_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { +; CHECK-LABEL: multi_vec_maxnm_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: bfmaxnm { z0.h - z3.h }, { z0.h - z3.h }, { z4.h - z7.h } +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmaxnm.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) + ret { , , , } %res +} + ; FMAXNM (Multi, x4) define { , , , } @multi_vec_maxnm_x4_f16( %dummy, %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { diff --git a/llvm/test/CodeGen/AArch64/sme2-intrinsics-min.ll b/llvm/test/CodeGen/AArch64/sme2-intrinsics-min.ll index 363f9ba5d3530e..e5c36d42fb1351 100644 --- a/llvm/test/CodeGen/AArch64/sme2-intrinsics-min.ll +++ b/llvm/test/CodeGen/AArch64/sme2-intrinsics-min.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -mattr=+b16b16 -verify-machineinstrs < %s | FileCheck %s ; SMIN (Single, x2) @@ -109,6 +109,19 @@ define { , } @multi_vec_min_single_x2_u64(< ret { , } %res } +; BFMIN (Single, x2) + +define { , } @multi_vec_min_single_x2_bf16( %zdn1, %zdn2, %zm) { +; CHECK-LABEL: multi_vec_min_single_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: bfmin { z0.h, z1.h }, { z0.h, z1.h }, z2.h +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmin.single.x2.nxv8bf16( %zdn1, %zdn2, %zm) + ret { , } %res +} + ; FMIN (Single, x2) define { , } @multi_vec_min_single_x2_f16( %unused, %zdn1, %zdn2, %zm) { @@ -298,6 +311,21 @@ define { , , , , , , } %res } +; BFMIN (Single, x4) + +define { , , , } @multi_vec_min_single_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) { +; CHECK-LABEL: multi_vec_min_single_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: bfmin { z0.h - z3.h }, { z0.h - z3.h }, z4.h +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmin.single.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) + ret { , , , } %res +} + ; FMIN (SINGLE, x4) define { , , , } @multi_vec_min_single_x4_f16( %unused, %zdn1, %zdn2, %zdn3, %zdn4, %zm) { @@ -478,6 +506,21 @@ define { , } @multi_vec_min_multi_x2_u64(, } %res } +; BFMIN (Multi, x2) + +define { , } @multi_vec_min_x2_bf16( %zdn1, %zdn2, %zm1, %zm2) { +; CHECK-LABEL: multi_vec_min_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: bfmin { z0.h, z1.h }, { z0.h, z1.h }, { z2.h, z3.h } +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fmin.x2.nxv8bf16( %zdn1, %zdn2, %zm1, %zm2) + ret { , } %res +} + ; FMIN (Multi, x2) define { , } @multi_vec_min_multi_x2_f16( %unused, %zdn1, %zdn2, %zm1, %zm2) { @@ -729,6 +772,26 @@ define { , , , , , , } %res } + +; BFMIN (Multi, x4) + +define { , , , } @multi_vec_min_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { +; CHECK-LABEL: multi_vec_min_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: bfmin { z0.h - z3.h }, { z0.h - z3.h }, { z4.h - z7.h } +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fmin.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) + ret { , , , } %res +} + ; FMIN (Multi, x4) define { , , , } @multi_vec_min_multi_x4_f16( %unused, %zdn1, %zdn2, %zdn3, %zdn4, @@ -806,6 +869,19 @@ define { , , , , , , } %res } +; BFMINNM (Single, x2) + +define { , } @multi_vec_minnm_single_x2_bf16( %zdn1, %zdn2, %zm) { +; CHECK-LABEL: multi_vec_minnm_single_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: bfminnm { z0.h, z1.h }, { z0.h, z1.h }, z2.h +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fminnm.single.x2.nxv8bf16( %zdn1, %zdn2, %zm) + ret { , } %res +} + ; FMINNM (Single, x2) define { , } @multi_vec_minnm_single_x2_f16( %dummy, %zdn1, %zdn2, %zm) { @@ -847,6 +923,21 @@ define { , } @multi_vec_minnm_single ret { , } %res } +; BFMINNM (Single, x4) + +define { , , , } @multi_vec_minnm_single_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) { +; CHECK-LABEL: multi_vec_minnm_single_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: bfminnm { z0.h - z3.h }, { z0.h - z3.h }, z4.h +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fminnm.single.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm) + ret { , , , } %res +} + ; FMINNM (Single, x4) define { , , , } @multi_vec_minnm_single_x4_f16( %dummy, %zdn1, %zdn2, %zdn3, %zdn4, %zm) { @@ -903,6 +994,21 @@ define { , , , , , , } %res } +; BFMINNM (Multi, x2) + +define { , } @multi_vec_minnm_x2_bf16( %zdn1, %zdn2, %zm1, %zm2) { +; CHECK-LABEL: multi_vec_minnm_x2_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z2_z3 def $z2_z3 +; CHECK-NEXT: bfminnm { z0.h, z1.h }, { z0.h, z1.h }, { z2.h, z3.h } +; CHECK-NEXT: ret + %res = call { , } @llvm.aarch64.sve.fminnm.x2.nxv8bf16( %zdn1, %zdn2, %zm1, %zm2) + ret { , } %res +} + ; FMINNM (Multi, x2) define { , } @multi_vec_minnm_x2_f16( %dummy, %zdn1, %zdn2, %zm1, %zm2) { @@ -950,6 +1056,25 @@ define { , } @multi_vec_minnm_x2_f64( ret { , } %res } +; BFMINNM (Multi, x4) + +define { , , , } @multi_vec_minnm_x4_bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { +; CHECK-LABEL: multi_vec_minnm_x4_bf16: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $z3 killed $z3 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z7 killed $z7 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z2 killed $z2 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z6 killed $z6 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z1 killed $z1 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z5 killed $z5 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: // kill: def $z0 killed $z0 killed $z0_z1_z2_z3 def $z0_z1_z2_z3 +; CHECK-NEXT: // kill: def $z4 killed $z4 killed $z4_z5_z6_z7 def $z4_z5_z6_z7 +; CHECK-NEXT: bfminnm { z0.h - z3.h }, { z0.h - z3.h }, { z4.h - z7.h } +; CHECK-NEXT: ret + %res = call { , , , } @llvm.aarch64.sve.fminnm.x4.nxv8bf16( %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) + ret { , , , } %res +} + ; FMINNM (Multi, x4) define { , , , } @multi_vec_minnm_x4_f16( %dummy, %zdn1, %zdn2, %zdn3, %zdn4, %zm1, %zm2, %zm3, %zm4) { From af57ad6536c7df19e6df7217d9d976067fdaf882 Mon Sep 17 00:00:00 2001 From: zibi2 <62662650+zibi2@users.noreply.github.com> Date: Thu, 16 May 2024 08:58:44 -0400 Subject: [PATCH 037/576] [libc++][z/OS] Correct a definition of __native_vector_size (#91995) Fix `std/ranges/range.adaptors/range.lazy.split/general.pass.cpp` which started failing on z/OS after this [commit](https://github.com/llvm/llvm-project/commit/985c1a44f8d49e0af). This test case is passing on other platforms such as AIX. This is because the `__ALTIVEC__` macro is defined and `__mismatch` under `_LIBCPP_VECTORIZE_ALGORITHMS` guard is compiled out. However, on z/OS `_LIBCPP_VECTORIZE_ALGORITHMS` is defined. Analyzing the algorithm of `__mismatch` shows that the culprit is the definition of `__native_vector_size` which was defined wrongly as 1. This PR corrects the definition of `__native_vector_size` and fixes the affected test. --- libcxx/include/__algorithm/simd_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h index 71d65e8f4afb5d..aa4336a2214c87 100644 --- a/libcxx/include/__algorithm/simd_utils.h +++ b/libcxx/include/__algorithm/simd_utils.h @@ -74,7 +74,7 @@ using __get_as_integer_type_t = typename __get_as_integer_type_impl // This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance // in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms // as far as benchmarks are concerned. -# if defined(__AVX__) +# if defined(__AVX__) || defined(__MVS__) template inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp); # elif defined(__SSE__) || defined(__ARM_NEON__) From 4a5dffc67499640c71357d8f3f49edc97af5482f Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 15 May 2024 11:57:05 +0200 Subject: [PATCH 038/576] [CodeGen][ARM64EC][NFC] Add ARM64EC alias symbols test. (#92100) --- llvm/test/CodeGen/AArch64/arm64ec-symbols.ll | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/arm64ec-symbols.ll diff --git a/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll b/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll new file mode 100644 index 00000000000000..389c36974beda2 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll @@ -0,0 +1,27 @@ +; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s +; RUN: llc -mtriple=arm64ec-pc-windows-msvc -filetype=obj -o %t.o < %s +; RUN: llvm-objdump -t %t.o | FileCheck --check-prefix=SYM %s + +declare void @func() nounwind; + +define void @caller() nounwind { + call void @func() + ret void +} + +; CHECK: .weak_anti_dep caller +; CHECK-NEXT: .set caller, "#caller"@WEAKREF + +; CHECK: .weak_anti_dep func +; CHECK-NEXT: .set func, "#func"@WEAKREF +; CHECK-NEXT: .weak_anti_dep "#func" +; CHECK-NEXT: .set "#func", "#func$exit_thunk"@WEAKREF + +; SYM: [ 8](sec 4)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #caller +; SYM: [21](sec 7)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #func$exit_thunk +; SYM: [33](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 caller +; SYM-NEXT: AUX indx 8 srch 4 +; SYM-NEXT: [35](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 #func +; SYM-NEXT: AUX indx 21 srch 4 +; SYM: [39](sec 0)(fl 0x00)(ty 0)(scl 69) (nx 1) 0x00000000 func +; SYM-NEXT: AUX indx 35 srch 4 From 54e52aa5ebe68de122a3fe6064e0abef97f6b8e0 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 16 May 2024 14:44:00 +0100 Subject: [PATCH 039/576] [X86] Reduce znver3/4 LoopMicroOpBufferSize to practical loop unrolling values (#91340) The znver3/4 scheduler models have previously associated the LoopMicroOpBufferSize with the maximum size of their op caches, and when this led to quadratic complexity issues this were reduced to a value of 512 uops, based mainly on compilation time and not its effectiveness on runtime performance. From a runtime performance POV, a large LoopMicroOpBufferSize leads to a higher number of loop unrolls, meaning the cpu has to rely on the frontend decode rate (4 ins/cy max) for much longer to fill the op cache before looping begins and we make use of the faster op cache rate (8/9 ops/cy). This patch proposes we instead cap the size of the LoopMicroOpBufferSize based off the maximum rate from the op cache (znver3 = 8op/cy, znver4 = 9op/cy) and the branch misprediction penalty from the opcache (~12cy) as a estimate of the useful number of ops we can unroll a loop by before mispredictions are likely to cause stalls. This isn't a perfect metric, but does try to be closer to the spirit of how we use LoopMicroOpBufferSize in the compiler vs the size of a similar naming buffer in the cpu. --- llvm/lib/Target/X86/X86ScheduleZnver3.td | 11 +- llvm/lib/Target/X86/X86ScheduleZnver4.td | 16 +- llvm/test/Transforms/LoopUnroll/X86/znver3.ll | 982 +----------------- 3 files changed, 44 insertions(+), 965 deletions(-) diff --git a/llvm/lib/Target/X86/X86ScheduleZnver3.td b/llvm/lib/Target/X86/X86ScheduleZnver3.td index 2e87d5262818c9..cbf1de8408798f 100644 --- a/llvm/lib/Target/X86/X86ScheduleZnver3.td +++ b/llvm/lib/Target/X86/X86ScheduleZnver3.td @@ -33,13 +33,10 @@ def Znver3Model : SchedMachineModel { // The op cache is organized as an associative cache with 64 sets and 8 ways. // At each set-way intersection is an entry containing up to 8 macro ops. // The maximum capacity of the op cache is 4K ops. - // Agner, 22.5 µop cache - // The size of the µop cache is big enough for holding most critical loops. - // FIXME: PR50584: MachineScheduler/PostRAScheduler have quadradic complexity, - // with large values here the compilation of certain loops - // ends up taking way too long. - // let LoopMicroOpBufferSize = 4096; - let LoopMicroOpBufferSize = 512; + // Assuming a maximum dispatch of 8 ops/cy and a mispredict cost of 12cy from + // the op-cache, we limit the loop buffer to 8*12 = 96 to avoid loop unrolling + // leading to excessive filling of the op-cache from frontend. + let LoopMicroOpBufferSize = 96; // AMD SOG 19h, 2.6.2 L1 Data Cache // The L1 data cache has a 4- or 5- cycle integer load-to-use latency. // AMD SOG 19h, 2.12 L1 Data Cache diff --git a/llvm/lib/Target/X86/X86ScheduleZnver4.td b/llvm/lib/Target/X86/X86ScheduleZnver4.td index dac4d8422582a4..7107dbc63e2799 100644 --- a/llvm/lib/Target/X86/X86ScheduleZnver4.td +++ b/llvm/lib/Target/X86/X86ScheduleZnver4.td @@ -28,17 +28,11 @@ def Znver4Model : SchedMachineModel { // AMD SOG 19h, 2.9.1 Op Cache // The op cache is organized as an associative cache with 64 sets and 8 ways. // At each set-way intersection is an entry containing up to 8 macro ops. - // The maximum capacity of the op cache is 4K ops. - // Agner, 22.5 µop cache - // The size of the µop cache is big enough for holding most critical loops. - // FIXME: PR50584: MachineScheduler/PostRAScheduler have quadradic complexity, - // with large values here the compilation of certain loops - // ends up taking way too long. - // Ideally for znver4, we should have 6.75K. However we don't add that - // considerting the impact compile time and prefer using default values - // instead. - // Retaining minimal value to influence unrolling as we did for znver3. - let LoopMicroOpBufferSize = 512; + // The maximum capacity of the op cache is 6.75K ops. + // Assuming a maximum dispatch of 9 ops/cy and a mispredict cost of 12cy from + // the op-cache, we limit the loop buffer to 9*12 = 108 to avoid loop + // unrolling leading to excessive filling of the op-cache from frontend. + let LoopMicroOpBufferSize = 108; // AMD SOG 19h, 2.6.2 L1 Data Cache // The L1 data cache has a 4- or 5- cycle integer load-to-use latency. // AMD SOG 19h, 2.12 L1 Data Cache diff --git a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll index 30389062a09678..b1f1d7d814e6c3 100644 --- a/llvm/test/Transforms/LoopUnroll/X86/znver3.ll +++ b/llvm/test/Transforms/LoopUnroll/X86/znver3.ll @@ -73,456 +73,8 @@ define i32 @test(ptr %ary) "target-cpu"="znver3" { ; CHECK-NEXT: [[INDVARS_IV_NEXT_14:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 15 ; CHECK-NEXT: [[ARRAYIDX_15:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_14]] ; CHECK-NEXT: [[VAL_15:%.*]] = load i32, ptr [[ARRAYIDX_15]], align 4 -; CHECK-NEXT: [[SUM_NEXT_15:%.*]] = add nsw i32 [[VAL_15]], [[SUM_NEXT_14]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_15:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 16 -; CHECK-NEXT: [[ARRAYIDX_16:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_15]] -; CHECK-NEXT: [[VAL_16:%.*]] = load i32, ptr [[ARRAYIDX_16]], align 4 -; CHECK-NEXT: [[SUM_NEXT_16:%.*]] = add nsw i32 [[VAL_16]], [[SUM_NEXT_15]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_16:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 17 -; CHECK-NEXT: [[ARRAYIDX_17:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_16]] -; CHECK-NEXT: [[VAL_17:%.*]] = load i32, ptr [[ARRAYIDX_17]], align 4 -; CHECK-NEXT: [[SUM_NEXT_17:%.*]] = add nsw i32 [[VAL_17]], [[SUM_NEXT_16]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_17:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 18 -; CHECK-NEXT: [[ARRAYIDX_18:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_17]] -; CHECK-NEXT: [[VAL_18:%.*]] = load i32, ptr [[ARRAYIDX_18]], align 4 -; CHECK-NEXT: [[SUM_NEXT_18:%.*]] = add nsw i32 [[VAL_18]], [[SUM_NEXT_17]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_18:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 19 -; CHECK-NEXT: [[ARRAYIDX_19:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_18]] -; CHECK-NEXT: [[VAL_19:%.*]] = load i32, ptr [[ARRAYIDX_19]], align 4 -; CHECK-NEXT: [[SUM_NEXT_19:%.*]] = add nsw i32 [[VAL_19]], [[SUM_NEXT_18]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_19:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 20 -; CHECK-NEXT: [[ARRAYIDX_20:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_19]] -; CHECK-NEXT: [[VAL_20:%.*]] = load i32, ptr [[ARRAYIDX_20]], align 4 -; CHECK-NEXT: [[SUM_NEXT_20:%.*]] = add nsw i32 [[VAL_20]], [[SUM_NEXT_19]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_20:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 21 -; CHECK-NEXT: [[ARRAYIDX_21:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_20]] -; CHECK-NEXT: [[VAL_21:%.*]] = load i32, ptr [[ARRAYIDX_21]], align 4 -; CHECK-NEXT: [[SUM_NEXT_21:%.*]] = add nsw i32 [[VAL_21]], [[SUM_NEXT_20]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_21:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 22 -; CHECK-NEXT: [[ARRAYIDX_22:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_21]] -; CHECK-NEXT: [[VAL_22:%.*]] = load i32, ptr [[ARRAYIDX_22]], align 4 -; CHECK-NEXT: [[SUM_NEXT_22:%.*]] = add nsw i32 [[VAL_22]], [[SUM_NEXT_21]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_22:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 23 -; CHECK-NEXT: [[ARRAYIDX_23:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_22]] -; CHECK-NEXT: [[VAL_23:%.*]] = load i32, ptr [[ARRAYIDX_23]], align 4 -; CHECK-NEXT: [[SUM_NEXT_23:%.*]] = add nsw i32 [[VAL_23]], [[SUM_NEXT_22]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_23:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 24 -; CHECK-NEXT: [[ARRAYIDX_24:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_23]] -; CHECK-NEXT: [[VAL_24:%.*]] = load i32, ptr [[ARRAYIDX_24]], align 4 -; CHECK-NEXT: [[SUM_NEXT_24:%.*]] = add nsw i32 [[VAL_24]], [[SUM_NEXT_23]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_24:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 25 -; CHECK-NEXT: [[ARRAYIDX_25:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_24]] -; CHECK-NEXT: [[VAL_25:%.*]] = load i32, ptr [[ARRAYIDX_25]], align 4 -; CHECK-NEXT: [[SUM_NEXT_25:%.*]] = add nsw i32 [[VAL_25]], [[SUM_NEXT_24]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_25:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 26 -; CHECK-NEXT: [[ARRAYIDX_26:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_25]] -; CHECK-NEXT: [[VAL_26:%.*]] = load i32, ptr [[ARRAYIDX_26]], align 4 -; CHECK-NEXT: [[SUM_NEXT_26:%.*]] = add nsw i32 [[VAL_26]], [[SUM_NEXT_25]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_26:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 27 -; CHECK-NEXT: [[ARRAYIDX_27:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_26]] -; CHECK-NEXT: [[VAL_27:%.*]] = load i32, ptr [[ARRAYIDX_27]], align 4 -; CHECK-NEXT: [[SUM_NEXT_27:%.*]] = add nsw i32 [[VAL_27]], [[SUM_NEXT_26]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_27:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 28 -; CHECK-NEXT: [[ARRAYIDX_28:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_27]] -; CHECK-NEXT: [[VAL_28:%.*]] = load i32, ptr [[ARRAYIDX_28]], align 4 -; CHECK-NEXT: [[SUM_NEXT_28:%.*]] = add nsw i32 [[VAL_28]], [[SUM_NEXT_27]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_28:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 29 -; CHECK-NEXT: [[ARRAYIDX_29:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_28]] -; CHECK-NEXT: [[VAL_29:%.*]] = load i32, ptr [[ARRAYIDX_29]], align 4 -; CHECK-NEXT: [[SUM_NEXT_29:%.*]] = add nsw i32 [[VAL_29]], [[SUM_NEXT_28]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_29:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 30 -; CHECK-NEXT: [[ARRAYIDX_30:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_29]] -; CHECK-NEXT: [[VAL_30:%.*]] = load i32, ptr [[ARRAYIDX_30]], align 4 -; CHECK-NEXT: [[SUM_NEXT_30:%.*]] = add nsw i32 [[VAL_30]], [[SUM_NEXT_29]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_30:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 31 -; CHECK-NEXT: [[ARRAYIDX_31:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_30]] -; CHECK-NEXT: [[VAL_31:%.*]] = load i32, ptr [[ARRAYIDX_31]], align 4 -; CHECK-NEXT: [[SUM_NEXT_31:%.*]] = add nsw i32 [[VAL_31]], [[SUM_NEXT_30]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_31:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 32 -; CHECK-NEXT: [[ARRAYIDX_32:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_31]] -; CHECK-NEXT: [[VAL_32:%.*]] = load i32, ptr [[ARRAYIDX_32]], align 4 -; CHECK-NEXT: [[SUM_NEXT_32:%.*]] = add nsw i32 [[VAL_32]], [[SUM_NEXT_31]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_32:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 33 -; CHECK-NEXT: [[ARRAYIDX_33:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_32]] -; CHECK-NEXT: [[VAL_33:%.*]] = load i32, ptr [[ARRAYIDX_33]], align 4 -; CHECK-NEXT: [[SUM_NEXT_33:%.*]] = add nsw i32 [[VAL_33]], [[SUM_NEXT_32]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_33:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 34 -; CHECK-NEXT: [[ARRAYIDX_34:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_33]] -; CHECK-NEXT: [[VAL_34:%.*]] = load i32, ptr [[ARRAYIDX_34]], align 4 -; CHECK-NEXT: [[SUM_NEXT_34:%.*]] = add nsw i32 [[VAL_34]], [[SUM_NEXT_33]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_34:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 35 -; CHECK-NEXT: [[ARRAYIDX_35:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_34]] -; CHECK-NEXT: [[VAL_35:%.*]] = load i32, ptr [[ARRAYIDX_35]], align 4 -; CHECK-NEXT: [[SUM_NEXT_35:%.*]] = add nsw i32 [[VAL_35]], [[SUM_NEXT_34]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_35:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 36 -; CHECK-NEXT: [[ARRAYIDX_36:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_35]] -; CHECK-NEXT: [[VAL_36:%.*]] = load i32, ptr [[ARRAYIDX_36]], align 4 -; CHECK-NEXT: [[SUM_NEXT_36:%.*]] = add nsw i32 [[VAL_36]], [[SUM_NEXT_35]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_36:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 37 -; CHECK-NEXT: [[ARRAYIDX_37:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_36]] -; CHECK-NEXT: [[VAL_37:%.*]] = load i32, ptr [[ARRAYIDX_37]], align 4 -; CHECK-NEXT: [[SUM_NEXT_37:%.*]] = add nsw i32 [[VAL_37]], [[SUM_NEXT_36]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_37:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 38 -; CHECK-NEXT: [[ARRAYIDX_38:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_37]] -; CHECK-NEXT: [[VAL_38:%.*]] = load i32, ptr [[ARRAYIDX_38]], align 4 -; CHECK-NEXT: [[SUM_NEXT_38:%.*]] = add nsw i32 [[VAL_38]], [[SUM_NEXT_37]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_38:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 39 -; CHECK-NEXT: [[ARRAYIDX_39:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_38]] -; CHECK-NEXT: [[VAL_39:%.*]] = load i32, ptr [[ARRAYIDX_39]], align 4 -; CHECK-NEXT: [[SUM_NEXT_39:%.*]] = add nsw i32 [[VAL_39]], [[SUM_NEXT_38]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_39:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 40 -; CHECK-NEXT: [[ARRAYIDX_40:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_39]] -; CHECK-NEXT: [[VAL_40:%.*]] = load i32, ptr [[ARRAYIDX_40]], align 4 -; CHECK-NEXT: [[SUM_NEXT_40:%.*]] = add nsw i32 [[VAL_40]], [[SUM_NEXT_39]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_40:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 41 -; CHECK-NEXT: [[ARRAYIDX_41:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_40]] -; CHECK-NEXT: [[VAL_41:%.*]] = load i32, ptr [[ARRAYIDX_41]], align 4 -; CHECK-NEXT: [[SUM_NEXT_41:%.*]] = add nsw i32 [[VAL_41]], [[SUM_NEXT_40]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_41:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 42 -; CHECK-NEXT: [[ARRAYIDX_42:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_41]] -; CHECK-NEXT: [[VAL_42:%.*]] = load i32, ptr [[ARRAYIDX_42]], align 4 -; CHECK-NEXT: [[SUM_NEXT_42:%.*]] = add nsw i32 [[VAL_42]], [[SUM_NEXT_41]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_42:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 43 -; CHECK-NEXT: [[ARRAYIDX_43:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_42]] -; CHECK-NEXT: [[VAL_43:%.*]] = load i32, ptr [[ARRAYIDX_43]], align 4 -; CHECK-NEXT: [[SUM_NEXT_43:%.*]] = add nsw i32 [[VAL_43]], [[SUM_NEXT_42]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_43:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 44 -; CHECK-NEXT: [[ARRAYIDX_44:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_43]] -; CHECK-NEXT: [[VAL_44:%.*]] = load i32, ptr [[ARRAYIDX_44]], align 4 -; CHECK-NEXT: [[SUM_NEXT_44:%.*]] = add nsw i32 [[VAL_44]], [[SUM_NEXT_43]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_44:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 45 -; CHECK-NEXT: [[ARRAYIDX_45:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_44]] -; CHECK-NEXT: [[VAL_45:%.*]] = load i32, ptr [[ARRAYIDX_45]], align 4 -; CHECK-NEXT: [[SUM_NEXT_45:%.*]] = add nsw i32 [[VAL_45]], [[SUM_NEXT_44]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_45:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 46 -; CHECK-NEXT: [[ARRAYIDX_46:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_45]] -; CHECK-NEXT: [[VAL_46:%.*]] = load i32, ptr [[ARRAYIDX_46]], align 4 -; CHECK-NEXT: [[SUM_NEXT_46:%.*]] = add nsw i32 [[VAL_46]], [[SUM_NEXT_45]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_46:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 47 -; CHECK-NEXT: [[ARRAYIDX_47:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_46]] -; CHECK-NEXT: [[VAL_47:%.*]] = load i32, ptr [[ARRAYIDX_47]], align 4 -; CHECK-NEXT: [[SUM_NEXT_47:%.*]] = add nsw i32 [[VAL_47]], [[SUM_NEXT_46]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_47:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 48 -; CHECK-NEXT: [[ARRAYIDX_48:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_47]] -; CHECK-NEXT: [[VAL_48:%.*]] = load i32, ptr [[ARRAYIDX_48]], align 4 -; CHECK-NEXT: [[SUM_NEXT_48:%.*]] = add nsw i32 [[VAL_48]], [[SUM_NEXT_47]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_48:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 49 -; CHECK-NEXT: [[ARRAYIDX_49:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_48]] -; CHECK-NEXT: [[VAL_49:%.*]] = load i32, ptr [[ARRAYIDX_49]], align 4 -; CHECK-NEXT: [[SUM_NEXT_49:%.*]] = add nsw i32 [[VAL_49]], [[SUM_NEXT_48]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_49:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 50 -; CHECK-NEXT: [[ARRAYIDX_50:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_49]] -; CHECK-NEXT: [[VAL_50:%.*]] = load i32, ptr [[ARRAYIDX_50]], align 4 -; CHECK-NEXT: [[SUM_NEXT_50:%.*]] = add nsw i32 [[VAL_50]], [[SUM_NEXT_49]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_50:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 51 -; CHECK-NEXT: [[ARRAYIDX_51:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_50]] -; CHECK-NEXT: [[VAL_51:%.*]] = load i32, ptr [[ARRAYIDX_51]], align 4 -; CHECK-NEXT: [[SUM_NEXT_51:%.*]] = add nsw i32 [[VAL_51]], [[SUM_NEXT_50]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_51:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 52 -; CHECK-NEXT: [[ARRAYIDX_52:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_51]] -; CHECK-NEXT: [[VAL_52:%.*]] = load i32, ptr [[ARRAYIDX_52]], align 4 -; CHECK-NEXT: [[SUM_NEXT_52:%.*]] = add nsw i32 [[VAL_52]], [[SUM_NEXT_51]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_52:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 53 -; CHECK-NEXT: [[ARRAYIDX_53:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_52]] -; CHECK-NEXT: [[VAL_53:%.*]] = load i32, ptr [[ARRAYIDX_53]], align 4 -; CHECK-NEXT: [[SUM_NEXT_53:%.*]] = add nsw i32 [[VAL_53]], [[SUM_NEXT_52]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_53:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 54 -; CHECK-NEXT: [[ARRAYIDX_54:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_53]] -; CHECK-NEXT: [[VAL_54:%.*]] = load i32, ptr [[ARRAYIDX_54]], align 4 -; CHECK-NEXT: [[SUM_NEXT_54:%.*]] = add nsw i32 [[VAL_54]], [[SUM_NEXT_53]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_54:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 55 -; CHECK-NEXT: [[ARRAYIDX_55:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_54]] -; CHECK-NEXT: [[VAL_55:%.*]] = load i32, ptr [[ARRAYIDX_55]], align 4 -; CHECK-NEXT: [[SUM_NEXT_55:%.*]] = add nsw i32 [[VAL_55]], [[SUM_NEXT_54]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_55:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 56 -; CHECK-NEXT: [[ARRAYIDX_56:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_55]] -; CHECK-NEXT: [[VAL_56:%.*]] = load i32, ptr [[ARRAYIDX_56]], align 4 -; CHECK-NEXT: [[SUM_NEXT_56:%.*]] = add nsw i32 [[VAL_56]], [[SUM_NEXT_55]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_56:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 57 -; CHECK-NEXT: [[ARRAYIDX_57:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_56]] -; CHECK-NEXT: [[VAL_57:%.*]] = load i32, ptr [[ARRAYIDX_57]], align 4 -; CHECK-NEXT: [[SUM_NEXT_57:%.*]] = add nsw i32 [[VAL_57]], [[SUM_NEXT_56]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_57:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 58 -; CHECK-NEXT: [[ARRAYIDX_58:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_57]] -; CHECK-NEXT: [[VAL_58:%.*]] = load i32, ptr [[ARRAYIDX_58]], align 4 -; CHECK-NEXT: [[SUM_NEXT_58:%.*]] = add nsw i32 [[VAL_58]], [[SUM_NEXT_57]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_58:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 59 -; CHECK-NEXT: [[ARRAYIDX_59:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_58]] -; CHECK-NEXT: [[VAL_59:%.*]] = load i32, ptr [[ARRAYIDX_59]], align 4 -; CHECK-NEXT: [[SUM_NEXT_59:%.*]] = add nsw i32 [[VAL_59]], [[SUM_NEXT_58]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_59:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 60 -; CHECK-NEXT: [[ARRAYIDX_60:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_59]] -; CHECK-NEXT: [[VAL_60:%.*]] = load i32, ptr [[ARRAYIDX_60]], align 4 -; CHECK-NEXT: [[SUM_NEXT_60:%.*]] = add nsw i32 [[VAL_60]], [[SUM_NEXT_59]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_60:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 61 -; CHECK-NEXT: [[ARRAYIDX_61:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_60]] -; CHECK-NEXT: [[VAL_61:%.*]] = load i32, ptr [[ARRAYIDX_61]], align 4 -; CHECK-NEXT: [[SUM_NEXT_61:%.*]] = add nsw i32 [[VAL_61]], [[SUM_NEXT_60]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_61:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 62 -; CHECK-NEXT: [[ARRAYIDX_62:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_61]] -; CHECK-NEXT: [[VAL_62:%.*]] = load i32, ptr [[ARRAYIDX_62]], align 4 -; CHECK-NEXT: [[SUM_NEXT_62:%.*]] = add nsw i32 [[VAL_62]], [[SUM_NEXT_61]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_62:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 63 -; CHECK-NEXT: [[ARRAYIDX_63:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_62]] -; CHECK-NEXT: [[VAL_63:%.*]] = load i32, ptr [[ARRAYIDX_63]], align 4 -; CHECK-NEXT: [[SUM_NEXT_63:%.*]] = add nsw i32 [[VAL_63]], [[SUM_NEXT_62]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_63:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 64 -; CHECK-NEXT: [[ARRAYIDX_64:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_63]] -; CHECK-NEXT: [[VAL_64:%.*]] = load i32, ptr [[ARRAYIDX_64]], align 4 -; CHECK-NEXT: [[SUM_NEXT_64:%.*]] = add nsw i32 [[VAL_64]], [[SUM_NEXT_63]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_64:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 65 -; CHECK-NEXT: [[ARRAYIDX_65:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_64]] -; CHECK-NEXT: [[VAL_65:%.*]] = load i32, ptr [[ARRAYIDX_65]], align 4 -; CHECK-NEXT: [[SUM_NEXT_65:%.*]] = add nsw i32 [[VAL_65]], [[SUM_NEXT_64]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_65:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 66 -; CHECK-NEXT: [[ARRAYIDX_66:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_65]] -; CHECK-NEXT: [[VAL_66:%.*]] = load i32, ptr [[ARRAYIDX_66]], align 4 -; CHECK-NEXT: [[SUM_NEXT_66:%.*]] = add nsw i32 [[VAL_66]], [[SUM_NEXT_65]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_66:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 67 -; CHECK-NEXT: [[ARRAYIDX_67:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_66]] -; CHECK-NEXT: [[VAL_67:%.*]] = load i32, ptr [[ARRAYIDX_67]], align 4 -; CHECK-NEXT: [[SUM_NEXT_67:%.*]] = add nsw i32 [[VAL_67]], [[SUM_NEXT_66]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_67:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 68 -; CHECK-NEXT: [[ARRAYIDX_68:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_67]] -; CHECK-NEXT: [[VAL_68:%.*]] = load i32, ptr [[ARRAYIDX_68]], align 4 -; CHECK-NEXT: [[SUM_NEXT_68:%.*]] = add nsw i32 [[VAL_68]], [[SUM_NEXT_67]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_68:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 69 -; CHECK-NEXT: [[ARRAYIDX_69:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_68]] -; CHECK-NEXT: [[VAL_69:%.*]] = load i32, ptr [[ARRAYIDX_69]], align 4 -; CHECK-NEXT: [[SUM_NEXT_69:%.*]] = add nsw i32 [[VAL_69]], [[SUM_NEXT_68]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_69:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 70 -; CHECK-NEXT: [[ARRAYIDX_70:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_69]] -; CHECK-NEXT: [[VAL_70:%.*]] = load i32, ptr [[ARRAYIDX_70]], align 4 -; CHECK-NEXT: [[SUM_NEXT_70:%.*]] = add nsw i32 [[VAL_70]], [[SUM_NEXT_69]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_70:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 71 -; CHECK-NEXT: [[ARRAYIDX_71:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_70]] -; CHECK-NEXT: [[VAL_71:%.*]] = load i32, ptr [[ARRAYIDX_71]], align 4 -; CHECK-NEXT: [[SUM_NEXT_71:%.*]] = add nsw i32 [[VAL_71]], [[SUM_NEXT_70]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_71:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 72 -; CHECK-NEXT: [[ARRAYIDX_72:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_71]] -; CHECK-NEXT: [[VAL_72:%.*]] = load i32, ptr [[ARRAYIDX_72]], align 4 -; CHECK-NEXT: [[SUM_NEXT_72:%.*]] = add nsw i32 [[VAL_72]], [[SUM_NEXT_71]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_72:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 73 -; CHECK-NEXT: [[ARRAYIDX_73:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_72]] -; CHECK-NEXT: [[VAL_73:%.*]] = load i32, ptr [[ARRAYIDX_73]], align 4 -; CHECK-NEXT: [[SUM_NEXT_73:%.*]] = add nsw i32 [[VAL_73]], [[SUM_NEXT_72]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_73:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 74 -; CHECK-NEXT: [[ARRAYIDX_74:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_73]] -; CHECK-NEXT: [[VAL_74:%.*]] = load i32, ptr [[ARRAYIDX_74]], align 4 -; CHECK-NEXT: [[SUM_NEXT_74:%.*]] = add nsw i32 [[VAL_74]], [[SUM_NEXT_73]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_74:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 75 -; CHECK-NEXT: [[ARRAYIDX_75:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_74]] -; CHECK-NEXT: [[VAL_75:%.*]] = load i32, ptr [[ARRAYIDX_75]], align 4 -; CHECK-NEXT: [[SUM_NEXT_75:%.*]] = add nsw i32 [[VAL_75]], [[SUM_NEXT_74]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_75:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 76 -; CHECK-NEXT: [[ARRAYIDX_76:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_75]] -; CHECK-NEXT: [[VAL_76:%.*]] = load i32, ptr [[ARRAYIDX_76]], align 4 -; CHECK-NEXT: [[SUM_NEXT_76:%.*]] = add nsw i32 [[VAL_76]], [[SUM_NEXT_75]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_76:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 77 -; CHECK-NEXT: [[ARRAYIDX_77:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_76]] -; CHECK-NEXT: [[VAL_77:%.*]] = load i32, ptr [[ARRAYIDX_77]], align 4 -; CHECK-NEXT: [[SUM_NEXT_77:%.*]] = add nsw i32 [[VAL_77]], [[SUM_NEXT_76]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_77:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 78 -; CHECK-NEXT: [[ARRAYIDX_78:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_77]] -; CHECK-NEXT: [[VAL_78:%.*]] = load i32, ptr [[ARRAYIDX_78]], align 4 -; CHECK-NEXT: [[SUM_NEXT_78:%.*]] = add nsw i32 [[VAL_78]], [[SUM_NEXT_77]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_78:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 79 -; CHECK-NEXT: [[ARRAYIDX_79:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_78]] -; CHECK-NEXT: [[VAL_79:%.*]] = load i32, ptr [[ARRAYIDX_79]], align 4 -; CHECK-NEXT: [[SUM_NEXT_79:%.*]] = add nsw i32 [[VAL_79]], [[SUM_NEXT_78]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_79:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 80 -; CHECK-NEXT: [[ARRAYIDX_80:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_79]] -; CHECK-NEXT: [[VAL_80:%.*]] = load i32, ptr [[ARRAYIDX_80]], align 4 -; CHECK-NEXT: [[SUM_NEXT_80:%.*]] = add nsw i32 [[VAL_80]], [[SUM_NEXT_79]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_80:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 81 -; CHECK-NEXT: [[ARRAYIDX_81:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_80]] -; CHECK-NEXT: [[VAL_81:%.*]] = load i32, ptr [[ARRAYIDX_81]], align 4 -; CHECK-NEXT: [[SUM_NEXT_81:%.*]] = add nsw i32 [[VAL_81]], [[SUM_NEXT_80]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_81:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 82 -; CHECK-NEXT: [[ARRAYIDX_82:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_81]] -; CHECK-NEXT: [[VAL_82:%.*]] = load i32, ptr [[ARRAYIDX_82]], align 4 -; CHECK-NEXT: [[SUM_NEXT_82:%.*]] = add nsw i32 [[VAL_82]], [[SUM_NEXT_81]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_82:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 83 -; CHECK-NEXT: [[ARRAYIDX_83:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_82]] -; CHECK-NEXT: [[VAL_83:%.*]] = load i32, ptr [[ARRAYIDX_83]], align 4 -; CHECK-NEXT: [[SUM_NEXT_83:%.*]] = add nsw i32 [[VAL_83]], [[SUM_NEXT_82]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_83:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 84 -; CHECK-NEXT: [[ARRAYIDX_84:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_83]] -; CHECK-NEXT: [[VAL_84:%.*]] = load i32, ptr [[ARRAYIDX_84]], align 4 -; CHECK-NEXT: [[SUM_NEXT_84:%.*]] = add nsw i32 [[VAL_84]], [[SUM_NEXT_83]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_84:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 85 -; CHECK-NEXT: [[ARRAYIDX_85:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_84]] -; CHECK-NEXT: [[VAL_85:%.*]] = load i32, ptr [[ARRAYIDX_85]], align 4 -; CHECK-NEXT: [[SUM_NEXT_85:%.*]] = add nsw i32 [[VAL_85]], [[SUM_NEXT_84]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_85:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 86 -; CHECK-NEXT: [[ARRAYIDX_86:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_85]] -; CHECK-NEXT: [[VAL_86:%.*]] = load i32, ptr [[ARRAYIDX_86]], align 4 -; CHECK-NEXT: [[SUM_NEXT_86:%.*]] = add nsw i32 [[VAL_86]], [[SUM_NEXT_85]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_86:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 87 -; CHECK-NEXT: [[ARRAYIDX_87:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_86]] -; CHECK-NEXT: [[VAL_87:%.*]] = load i32, ptr [[ARRAYIDX_87]], align 4 -; CHECK-NEXT: [[SUM_NEXT_87:%.*]] = add nsw i32 [[VAL_87]], [[SUM_NEXT_86]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_87:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 88 -; CHECK-NEXT: [[ARRAYIDX_88:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_87]] -; CHECK-NEXT: [[VAL_88:%.*]] = load i32, ptr [[ARRAYIDX_88]], align 4 -; CHECK-NEXT: [[SUM_NEXT_88:%.*]] = add nsw i32 [[VAL_88]], [[SUM_NEXT_87]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_88:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 89 -; CHECK-NEXT: [[ARRAYIDX_89:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_88]] -; CHECK-NEXT: [[VAL_89:%.*]] = load i32, ptr [[ARRAYIDX_89]], align 4 -; CHECK-NEXT: [[SUM_NEXT_89:%.*]] = add nsw i32 [[VAL_89]], [[SUM_NEXT_88]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_89:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 90 -; CHECK-NEXT: [[ARRAYIDX_90:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_89]] -; CHECK-NEXT: [[VAL_90:%.*]] = load i32, ptr [[ARRAYIDX_90]], align 4 -; CHECK-NEXT: [[SUM_NEXT_90:%.*]] = add nsw i32 [[VAL_90]], [[SUM_NEXT_89]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_90:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 91 -; CHECK-NEXT: [[ARRAYIDX_91:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_90]] -; CHECK-NEXT: [[VAL_91:%.*]] = load i32, ptr [[ARRAYIDX_91]], align 4 -; CHECK-NEXT: [[SUM_NEXT_91:%.*]] = add nsw i32 [[VAL_91]], [[SUM_NEXT_90]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_91:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 92 -; CHECK-NEXT: [[ARRAYIDX_92:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_91]] -; CHECK-NEXT: [[VAL_92:%.*]] = load i32, ptr [[ARRAYIDX_92]], align 4 -; CHECK-NEXT: [[SUM_NEXT_92:%.*]] = add nsw i32 [[VAL_92]], [[SUM_NEXT_91]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_92:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 93 -; CHECK-NEXT: [[ARRAYIDX_93:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_92]] -; CHECK-NEXT: [[VAL_93:%.*]] = load i32, ptr [[ARRAYIDX_93]], align 4 -; CHECK-NEXT: [[SUM_NEXT_93:%.*]] = add nsw i32 [[VAL_93]], [[SUM_NEXT_92]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_93:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 94 -; CHECK-NEXT: [[ARRAYIDX_94:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_93]] -; CHECK-NEXT: [[VAL_94:%.*]] = load i32, ptr [[ARRAYIDX_94]], align 4 -; CHECK-NEXT: [[SUM_NEXT_94:%.*]] = add nsw i32 [[VAL_94]], [[SUM_NEXT_93]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_94:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 95 -; CHECK-NEXT: [[ARRAYIDX_95:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_94]] -; CHECK-NEXT: [[VAL_95:%.*]] = load i32, ptr [[ARRAYIDX_95]], align 4 -; CHECK-NEXT: [[SUM_NEXT_95:%.*]] = add nsw i32 [[VAL_95]], [[SUM_NEXT_94]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_95:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 96 -; CHECK-NEXT: [[ARRAYIDX_96:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_95]] -; CHECK-NEXT: [[VAL_96:%.*]] = load i32, ptr [[ARRAYIDX_96]], align 4 -; CHECK-NEXT: [[SUM_NEXT_96:%.*]] = add nsw i32 [[VAL_96]], [[SUM_NEXT_95]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_96:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 97 -; CHECK-NEXT: [[ARRAYIDX_97:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_96]] -; CHECK-NEXT: [[VAL_97:%.*]] = load i32, ptr [[ARRAYIDX_97]], align 4 -; CHECK-NEXT: [[SUM_NEXT_97:%.*]] = add nsw i32 [[VAL_97]], [[SUM_NEXT_96]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_97:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 98 -; CHECK-NEXT: [[ARRAYIDX_98:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_97]] -; CHECK-NEXT: [[VAL_98:%.*]] = load i32, ptr [[ARRAYIDX_98]], align 4 -; CHECK-NEXT: [[SUM_NEXT_98:%.*]] = add nsw i32 [[VAL_98]], [[SUM_NEXT_97]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_98:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 99 -; CHECK-NEXT: [[ARRAYIDX_99:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_98]] -; CHECK-NEXT: [[VAL_99:%.*]] = load i32, ptr [[ARRAYIDX_99]], align 4 -; CHECK-NEXT: [[SUM_NEXT_99:%.*]] = add nsw i32 [[VAL_99]], [[SUM_NEXT_98]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_99:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 100 -; CHECK-NEXT: [[ARRAYIDX_100:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_99]] -; CHECK-NEXT: [[VAL_100:%.*]] = load i32, ptr [[ARRAYIDX_100]], align 4 -; CHECK-NEXT: [[SUM_NEXT_100:%.*]] = add nsw i32 [[VAL_100]], [[SUM_NEXT_99]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_100:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 101 -; CHECK-NEXT: [[ARRAYIDX_101:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_100]] -; CHECK-NEXT: [[VAL_101:%.*]] = load i32, ptr [[ARRAYIDX_101]], align 4 -; CHECK-NEXT: [[SUM_NEXT_101:%.*]] = add nsw i32 [[VAL_101]], [[SUM_NEXT_100]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_101:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 102 -; CHECK-NEXT: [[ARRAYIDX_102:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_101]] -; CHECK-NEXT: [[VAL_102:%.*]] = load i32, ptr [[ARRAYIDX_102]], align 4 -; CHECK-NEXT: [[SUM_NEXT_102:%.*]] = add nsw i32 [[VAL_102]], [[SUM_NEXT_101]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_102:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 103 -; CHECK-NEXT: [[ARRAYIDX_103:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_102]] -; CHECK-NEXT: [[VAL_103:%.*]] = load i32, ptr [[ARRAYIDX_103]], align 4 -; CHECK-NEXT: [[SUM_NEXT_103:%.*]] = add nsw i32 [[VAL_103]], [[SUM_NEXT_102]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_103:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 104 -; CHECK-NEXT: [[ARRAYIDX_104:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_103]] -; CHECK-NEXT: [[VAL_104:%.*]] = load i32, ptr [[ARRAYIDX_104]], align 4 -; CHECK-NEXT: [[SUM_NEXT_104:%.*]] = add nsw i32 [[VAL_104]], [[SUM_NEXT_103]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_104:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 105 -; CHECK-NEXT: [[ARRAYIDX_105:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_104]] -; CHECK-NEXT: [[VAL_105:%.*]] = load i32, ptr [[ARRAYIDX_105]], align 4 -; CHECK-NEXT: [[SUM_NEXT_105:%.*]] = add nsw i32 [[VAL_105]], [[SUM_NEXT_104]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_105:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 106 -; CHECK-NEXT: [[ARRAYIDX_106:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_105]] -; CHECK-NEXT: [[VAL_106:%.*]] = load i32, ptr [[ARRAYIDX_106]], align 4 -; CHECK-NEXT: [[SUM_NEXT_106:%.*]] = add nsw i32 [[VAL_106]], [[SUM_NEXT_105]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_106:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 107 -; CHECK-NEXT: [[ARRAYIDX_107:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_106]] -; CHECK-NEXT: [[VAL_107:%.*]] = load i32, ptr [[ARRAYIDX_107]], align 4 -; CHECK-NEXT: [[SUM_NEXT_107:%.*]] = add nsw i32 [[VAL_107]], [[SUM_NEXT_106]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_107:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 108 -; CHECK-NEXT: [[ARRAYIDX_108:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_107]] -; CHECK-NEXT: [[VAL_108:%.*]] = load i32, ptr [[ARRAYIDX_108]], align 4 -; CHECK-NEXT: [[SUM_NEXT_108:%.*]] = add nsw i32 [[VAL_108]], [[SUM_NEXT_107]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_108:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 109 -; CHECK-NEXT: [[ARRAYIDX_109:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_108]] -; CHECK-NEXT: [[VAL_109:%.*]] = load i32, ptr [[ARRAYIDX_109]], align 4 -; CHECK-NEXT: [[SUM_NEXT_109:%.*]] = add nsw i32 [[VAL_109]], [[SUM_NEXT_108]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_109:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 110 -; CHECK-NEXT: [[ARRAYIDX_110:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_109]] -; CHECK-NEXT: [[VAL_110:%.*]] = load i32, ptr [[ARRAYIDX_110]], align 4 -; CHECK-NEXT: [[SUM_NEXT_110:%.*]] = add nsw i32 [[VAL_110]], [[SUM_NEXT_109]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_110:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 111 -; CHECK-NEXT: [[ARRAYIDX_111:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_110]] -; CHECK-NEXT: [[VAL_111:%.*]] = load i32, ptr [[ARRAYIDX_111]], align 4 -; CHECK-NEXT: [[SUM_NEXT_111:%.*]] = add nsw i32 [[VAL_111]], [[SUM_NEXT_110]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_111:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 112 -; CHECK-NEXT: [[ARRAYIDX_112:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_111]] -; CHECK-NEXT: [[VAL_112:%.*]] = load i32, ptr [[ARRAYIDX_112]], align 4 -; CHECK-NEXT: [[SUM_NEXT_112:%.*]] = add nsw i32 [[VAL_112]], [[SUM_NEXT_111]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_112:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 113 -; CHECK-NEXT: [[ARRAYIDX_113:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_112]] -; CHECK-NEXT: [[VAL_113:%.*]] = load i32, ptr [[ARRAYIDX_113]], align 4 -; CHECK-NEXT: [[SUM_NEXT_113:%.*]] = add nsw i32 [[VAL_113]], [[SUM_NEXT_112]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_113:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 114 -; CHECK-NEXT: [[ARRAYIDX_114:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_113]] -; CHECK-NEXT: [[VAL_114:%.*]] = load i32, ptr [[ARRAYIDX_114]], align 4 -; CHECK-NEXT: [[SUM_NEXT_114:%.*]] = add nsw i32 [[VAL_114]], [[SUM_NEXT_113]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_114:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 115 -; CHECK-NEXT: [[ARRAYIDX_115:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_114]] -; CHECK-NEXT: [[VAL_115:%.*]] = load i32, ptr [[ARRAYIDX_115]], align 4 -; CHECK-NEXT: [[SUM_NEXT_115:%.*]] = add nsw i32 [[VAL_115]], [[SUM_NEXT_114]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_115:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 116 -; CHECK-NEXT: [[ARRAYIDX_116:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_115]] -; CHECK-NEXT: [[VAL_116:%.*]] = load i32, ptr [[ARRAYIDX_116]], align 4 -; CHECK-NEXT: [[SUM_NEXT_116:%.*]] = add nsw i32 [[VAL_116]], [[SUM_NEXT_115]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_116:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 117 -; CHECK-NEXT: [[ARRAYIDX_117:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_116]] -; CHECK-NEXT: [[VAL_117:%.*]] = load i32, ptr [[ARRAYIDX_117]], align 4 -; CHECK-NEXT: [[SUM_NEXT_117:%.*]] = add nsw i32 [[VAL_117]], [[SUM_NEXT_116]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_117:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 118 -; CHECK-NEXT: [[ARRAYIDX_118:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_117]] -; CHECK-NEXT: [[VAL_118:%.*]] = load i32, ptr [[ARRAYIDX_118]], align 4 -; CHECK-NEXT: [[SUM_NEXT_118:%.*]] = add nsw i32 [[VAL_118]], [[SUM_NEXT_117]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_118:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 119 -; CHECK-NEXT: [[ARRAYIDX_119:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_118]] -; CHECK-NEXT: [[VAL_119:%.*]] = load i32, ptr [[ARRAYIDX_119]], align 4 -; CHECK-NEXT: [[SUM_NEXT_119:%.*]] = add nsw i32 [[VAL_119]], [[SUM_NEXT_118]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_119:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 120 -; CHECK-NEXT: [[ARRAYIDX_120:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_119]] -; CHECK-NEXT: [[VAL_120:%.*]] = load i32, ptr [[ARRAYIDX_120]], align 4 -; CHECK-NEXT: [[SUM_NEXT_120:%.*]] = add nsw i32 [[VAL_120]], [[SUM_NEXT_119]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_120:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 121 -; CHECK-NEXT: [[ARRAYIDX_121:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_120]] -; CHECK-NEXT: [[VAL_121:%.*]] = load i32, ptr [[ARRAYIDX_121]], align 4 -; CHECK-NEXT: [[SUM_NEXT_121:%.*]] = add nsw i32 [[VAL_121]], [[SUM_NEXT_120]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_121:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 122 -; CHECK-NEXT: [[ARRAYIDX_122:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_121]] -; CHECK-NEXT: [[VAL_122:%.*]] = load i32, ptr [[ARRAYIDX_122]], align 4 -; CHECK-NEXT: [[SUM_NEXT_122:%.*]] = add nsw i32 [[VAL_122]], [[SUM_NEXT_121]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_122:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 123 -; CHECK-NEXT: [[ARRAYIDX_123:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_122]] -; CHECK-NEXT: [[VAL_123:%.*]] = load i32, ptr [[ARRAYIDX_123]], align 4 -; CHECK-NEXT: [[SUM_NEXT_123:%.*]] = add nsw i32 [[VAL_123]], [[SUM_NEXT_122]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_123:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 124 -; CHECK-NEXT: [[ARRAYIDX_124:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_123]] -; CHECK-NEXT: [[VAL_124:%.*]] = load i32, ptr [[ARRAYIDX_124]], align 4 -; CHECK-NEXT: [[SUM_NEXT_124:%.*]] = add nsw i32 [[VAL_124]], [[SUM_NEXT_123]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_124:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 125 -; CHECK-NEXT: [[ARRAYIDX_125:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_124]] -; CHECK-NEXT: [[VAL_125:%.*]] = load i32, ptr [[ARRAYIDX_125]], align 4 -; CHECK-NEXT: [[SUM_NEXT_125:%.*]] = add nsw i32 [[VAL_125]], [[SUM_NEXT_124]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_125:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 126 -; CHECK-NEXT: [[ARRAYIDX_126:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_125]] -; CHECK-NEXT: [[VAL_126:%.*]] = load i32, ptr [[ARRAYIDX_126]], align 4 -; CHECK-NEXT: [[SUM_NEXT_126:%.*]] = add nsw i32 [[VAL_126]], [[SUM_NEXT_125]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_126:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 127 -; CHECK-NEXT: [[ARRAYIDX_127:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_126]] -; CHECK-NEXT: [[VAL_127:%.*]] = load i32, ptr [[ARRAYIDX_127]], align 4 -; CHECK-NEXT: [[SUM_NEXT_127]] = add nsw i32 [[VAL_127]], [[SUM_NEXT_126]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_127]] = add nuw nsw i64 [[INDVARS_IV]], 128 +; CHECK-NEXT: [[SUM_NEXT_127]] = add nsw i32 [[VAL_15]], [[SUM_NEXT_14]] +; CHECK-NEXT: [[INDVARS_IV_NEXT_127]] = add nuw nsw i64 [[INDVARS_IV]], 16 ; CHECK-NEXT: [[EXITCOND_NOT_127:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_127]], 8192 ; CHECK-NEXT: br i1 [[EXITCOND_NOT_127]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup: @@ -550,532 +102,68 @@ define i32 @test2(ptr %ary, i64 %n) "target-cpu"="znver3" { ; CHECK-LABEL: define i32 @test2( ; CHECK-SAME: ptr [[ARY:%.*]], i64 [[N:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 -; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[N]], 7 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7 -; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_COND_CLEANUP_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]] -; CHECK: entry.new: -; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[N]], [[XTRAITER]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_7:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[SUM_NEXT_7:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[NITER:%.*]] = phi i64 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_7:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[DUMMY1:%.*]] = mul i32 [[VAL]], [[VAL]] -; CHECK-NEXT: [[DUMMY2:%.*]] = mul i32 [[DUMMY1]], [[DUMMY1]] -; CHECK-NEXT: [[DUMMY3:%.*]] = mul i32 [[DUMMY2]], [[DUMMY2]] -; CHECK-NEXT: [[DUMMY4:%.*]] = mul i32 [[DUMMY3]], [[DUMMY3]] +; CHECK-NEXT: [[INDVARS_IV_EPIL:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_EPIL:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[SUM_EPIL:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT_EPIL:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_EPIL]] +; CHECK-NEXT: [[VAL_EPIL:%.*]] = load i32, ptr [[ARRAYIDX_EPIL]], align 4 +; CHECK-NEXT: [[DUMMY21:%.*]] = mul i32 [[VAL_EPIL]], [[VAL_EPIL]] +; CHECK-NEXT: [[DUMMY27:%.*]] = mul i32 [[DUMMY21]], [[DUMMY21]] +; CHECK-NEXT: [[DUMMY28:%.*]] = mul i32 [[DUMMY27]], [[DUMMY27]] +; CHECK-NEXT: [[DUMMY4:%.*]] = mul i32 [[DUMMY28]], [[DUMMY28]] ; CHECK-NEXT: [[DUMMY5:%.*]] = mul i32 [[DUMMY4]], [[DUMMY4]] ; CHECK-NEXT: [[DUMMY6:%.*]] = mul i32 [[DUMMY5]], [[DUMMY5]] ; CHECK-NEXT: [[DUMMY7:%.*]] = mul i32 [[DUMMY6]], [[DUMMY6]] ; CHECK-NEXT: [[DUMMY8:%.*]] = mul i32 [[DUMMY7]], [[DUMMY7]] ; CHECK-NEXT: [[DUMMY9:%.*]] = mul i32 [[DUMMY8]], [[DUMMY8]] ; CHECK-NEXT: [[DUMMY10:%.*]] = mul i32 [[DUMMY9]], [[DUMMY9]] -; CHECK-NEXT: [[DUMMY11:%.*]] = mul i32 [[DUMMY10]], [[DUMMY10]] -; CHECK-NEXT: [[DUMMY12:%.*]] = mul i32 [[DUMMY11]], [[DUMMY11]] -; CHECK-NEXT: [[DUMMY13:%.*]] = mul i32 [[DUMMY12]], [[DUMMY12]] -; CHECK-NEXT: [[DUMMY14:%.*]] = mul i32 [[DUMMY13]], [[DUMMY13]] -; CHECK-NEXT: [[DUMMY15:%.*]] = mul i32 [[DUMMY14]], [[DUMMY14]] +; CHECK-NEXT: [[DUMMY29:%.*]] = mul i32 [[DUMMY10]], [[DUMMY10]] +; CHECK-NEXT: [[DUMMY30:%.*]] = mul i32 [[DUMMY29]], [[DUMMY29]] +; CHECK-NEXT: [[DUMMY39:%.*]] = mul i32 [[DUMMY30]], [[DUMMY30]] +; CHECK-NEXT: [[DUMMY40:%.*]] = mul i32 [[DUMMY39]], [[DUMMY39]] +; CHECK-NEXT: [[DUMMY15:%.*]] = mul i32 [[DUMMY40]], [[DUMMY40]] ; CHECK-NEXT: [[DUMMY16:%.*]] = mul i32 [[DUMMY15]], [[DUMMY15]] ; CHECK-NEXT: [[DUMMY17:%.*]] = mul i32 [[DUMMY16]], [[DUMMY16]] ; CHECK-NEXT: [[DUMMY18:%.*]] = mul i32 [[DUMMY17]], [[DUMMY17]] ; CHECK-NEXT: [[DUMMY19:%.*]] = mul i32 [[DUMMY18]], [[DUMMY18]] ; CHECK-NEXT: [[DUMMY20:%.*]] = mul i32 [[DUMMY19]], [[DUMMY19]] -; CHECK-NEXT: [[DUMMY21:%.*]] = mul i32 [[DUMMY20]], [[DUMMY20]] -; CHECK-NEXT: [[DUMMY22:%.*]] = mul i32 [[DUMMY21]], [[DUMMY21]] +; CHECK-NEXT: [[VAL:%.*]] = mul i32 [[DUMMY20]], [[DUMMY20]] +; CHECK-NEXT: [[DUMMY1:%.*]] = mul i32 [[VAL]], [[VAL]] +; CHECK-NEXT: [[DUMMY2:%.*]] = mul i32 [[DUMMY1]], [[DUMMY1]] +; CHECK-NEXT: [[DUMMY3:%.*]] = mul i32 [[DUMMY2]], [[DUMMY2]] +; CHECK-NEXT: [[DUMMY41:%.*]] = mul i32 [[DUMMY3]], [[DUMMY3]] +; CHECK-NEXT: [[DUMMY26:%.*]] = mul i32 [[DUMMY41]], [[DUMMY41]] +; CHECK-NEXT: [[DUMMY11:%.*]] = mul i32 [[DUMMY26]], [[DUMMY26]] +; CHECK-NEXT: [[DUMMY12:%.*]] = mul i32 [[DUMMY11]], [[DUMMY11]] +; CHECK-NEXT: [[DUMMY13:%.*]] = mul i32 [[DUMMY12]], [[DUMMY12]] +; CHECK-NEXT: [[DUMMY14:%.*]] = mul i32 [[DUMMY13]], [[DUMMY13]] +; CHECK-NEXT: [[DUMMY31:%.*]] = mul i32 [[DUMMY14]], [[DUMMY14]] +; CHECK-NEXT: [[DUMMY32:%.*]] = mul i32 [[DUMMY31]], [[DUMMY31]] +; CHECK-NEXT: [[DUMMY22:%.*]] = mul i32 [[DUMMY32]], [[DUMMY32]] ; CHECK-NEXT: [[DUMMY23:%.*]] = mul i32 [[DUMMY22]], [[DUMMY22]] ; CHECK-NEXT: [[DUMMY24:%.*]] = mul i32 [[DUMMY23]], [[DUMMY23]] ; CHECK-NEXT: [[DUMMY25:%.*]] = mul i32 [[DUMMY24]], [[DUMMY24]] -; CHECK-NEXT: [[DUMMY26:%.*]] = mul i32 [[DUMMY25]], [[DUMMY25]] -; CHECK-NEXT: [[DUMMY27:%.*]] = mul i32 [[DUMMY26]], [[DUMMY26]] -; CHECK-NEXT: [[DUMMY28:%.*]] = mul i32 [[DUMMY27]], [[DUMMY27]] -; CHECK-NEXT: [[DUMMY29:%.*]] = mul i32 [[DUMMY28]], [[DUMMY28]] -; CHECK-NEXT: [[DUMMY30:%.*]] = mul i32 [[DUMMY29]], [[DUMMY29]] -; CHECK-NEXT: [[DUMMY31:%.*]] = mul i32 [[DUMMY30]], [[DUMMY30]] -; CHECK-NEXT: [[DUMMY32:%.*]] = mul i32 [[DUMMY31]], [[DUMMY31]] -; CHECK-NEXT: [[DUMMY33:%.*]] = mul i32 [[DUMMY32]], [[DUMMY32]] +; CHECK-NEXT: [[DUMMY37:%.*]] = mul i32 [[DUMMY25]], [[DUMMY25]] +; CHECK-NEXT: [[DUMMY38:%.*]] = mul i32 [[DUMMY37]], [[DUMMY37]] +; CHECK-NEXT: [[DUMMY33:%.*]] = mul i32 [[DUMMY38]], [[DUMMY38]] ; CHECK-NEXT: [[DUMMY34:%.*]] = mul i32 [[DUMMY33]], [[DUMMY33]] ; CHECK-NEXT: [[DUMMY35:%.*]] = mul i32 [[DUMMY34]], [[DUMMY34]] ; CHECK-NEXT: [[DUMMY36:%.*]] = mul i32 [[DUMMY35]], [[DUMMY35]] -; CHECK-NEXT: [[DUMMY37:%.*]] = mul i32 [[DUMMY36]], [[DUMMY36]] -; CHECK-NEXT: [[DUMMY38:%.*]] = mul i32 [[DUMMY37]], [[DUMMY37]] -; CHECK-NEXT: [[DUMMY39:%.*]] = mul i32 [[DUMMY38]], [[DUMMY38]] -; CHECK-NEXT: [[DUMMY40:%.*]] = mul i32 [[DUMMY39]], [[DUMMY39]] -; CHECK-NEXT: [[DUMMY41:%.*]] = mul i32 [[DUMMY40]], [[DUMMY40]] -; CHECK-NEXT: [[DUMMY42:%.*]] = mul i32 [[DUMMY41]], [[DUMMY41]] -; CHECK-NEXT: [[DUMMY43:%.*]] = mul i32 [[DUMMY42]], [[DUMMY42]] +; CHECK-NEXT: [[DUMMY43:%.*]] = mul i32 [[DUMMY36]], [[DUMMY36]] ; CHECK-NEXT: [[DUMMY44:%.*]] = mul i32 [[DUMMY43]], [[DUMMY43]] ; CHECK-NEXT: [[DUMMY45:%.*]] = mul i32 [[DUMMY44]], [[DUMMY44]] ; CHECK-NEXT: [[DUMMY46:%.*]] = mul i32 [[DUMMY45]], [[DUMMY45]] ; CHECK-NEXT: [[DUMMY47:%.*]] = mul i32 [[DUMMY46]], [[DUMMY46]] ; CHECK-NEXT: [[DUMMY48:%.*]] = mul i32 [[DUMMY47]], [[DUMMY47]] ; CHECK-NEXT: [[DUMMY49:%.*]] = mul i32 [[DUMMY48]], [[DUMMY48]] -; CHECK-NEXT: [[DUMMY50:%.*]] = mul i32 [[DUMMY49]], [[DUMMY49]] -; CHECK-NEXT: [[SUM_NEXT:%.*]] = add nsw i32 [[DUMMY50]], [[SUM]] -; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT]] -; CHECK-NEXT: [[VAL_1:%.*]] = load i32, ptr [[ARRAYIDX_1]], align 4 -; CHECK-NEXT: [[DUMMY1_1:%.*]] = mul i32 [[VAL_1]], [[VAL_1]] -; CHECK-NEXT: [[DUMMY2_1:%.*]] = mul i32 [[DUMMY1_1]], [[DUMMY1_1]] -; CHECK-NEXT: [[DUMMY3_1:%.*]] = mul i32 [[DUMMY2_1]], [[DUMMY2_1]] -; CHECK-NEXT: [[DUMMY4_1:%.*]] = mul i32 [[DUMMY3_1]], [[DUMMY3_1]] -; CHECK-NEXT: [[DUMMY5_1:%.*]] = mul i32 [[DUMMY4_1]], [[DUMMY4_1]] -; CHECK-NEXT: [[DUMMY6_1:%.*]] = mul i32 [[DUMMY5_1]], [[DUMMY5_1]] -; CHECK-NEXT: [[DUMMY7_1:%.*]] = mul i32 [[DUMMY6_1]], [[DUMMY6_1]] -; CHECK-NEXT: [[DUMMY8_1:%.*]] = mul i32 [[DUMMY7_1]], [[DUMMY7_1]] -; CHECK-NEXT: [[DUMMY9_1:%.*]] = mul i32 [[DUMMY8_1]], [[DUMMY8_1]] -; CHECK-NEXT: [[DUMMY10_1:%.*]] = mul i32 [[DUMMY9_1]], [[DUMMY9_1]] -; CHECK-NEXT: [[DUMMY11_1:%.*]] = mul i32 [[DUMMY10_1]], [[DUMMY10_1]] -; CHECK-NEXT: [[DUMMY12_1:%.*]] = mul i32 [[DUMMY11_1]], [[DUMMY11_1]] -; CHECK-NEXT: [[DUMMY13_1:%.*]] = mul i32 [[DUMMY12_1]], [[DUMMY12_1]] -; CHECK-NEXT: [[DUMMY14_1:%.*]] = mul i32 [[DUMMY13_1]], [[DUMMY13_1]] -; CHECK-NEXT: [[DUMMY15_1:%.*]] = mul i32 [[DUMMY14_1]], [[DUMMY14_1]] -; CHECK-NEXT: [[DUMMY16_1:%.*]] = mul i32 [[DUMMY15_1]], [[DUMMY15_1]] -; CHECK-NEXT: [[DUMMY17_1:%.*]] = mul i32 [[DUMMY16_1]], [[DUMMY16_1]] -; CHECK-NEXT: [[DUMMY18_1:%.*]] = mul i32 [[DUMMY17_1]], [[DUMMY17_1]] -; CHECK-NEXT: [[DUMMY19_1:%.*]] = mul i32 [[DUMMY18_1]], [[DUMMY18_1]] -; CHECK-NEXT: [[DUMMY20_1:%.*]] = mul i32 [[DUMMY19_1]], [[DUMMY19_1]] -; CHECK-NEXT: [[DUMMY21_1:%.*]] = mul i32 [[DUMMY20_1]], [[DUMMY20_1]] -; CHECK-NEXT: [[DUMMY22_1:%.*]] = mul i32 [[DUMMY21_1]], [[DUMMY21_1]] -; CHECK-NEXT: [[DUMMY23_1:%.*]] = mul i32 [[DUMMY22_1]], [[DUMMY22_1]] -; CHECK-NEXT: [[DUMMY24_1:%.*]] = mul i32 [[DUMMY23_1]], [[DUMMY23_1]] -; CHECK-NEXT: [[DUMMY25_1:%.*]] = mul i32 [[DUMMY24_1]], [[DUMMY24_1]] -; CHECK-NEXT: [[DUMMY26_1:%.*]] = mul i32 [[DUMMY25_1]], [[DUMMY25_1]] -; CHECK-NEXT: [[DUMMY27_1:%.*]] = mul i32 [[DUMMY26_1]], [[DUMMY26_1]] -; CHECK-NEXT: [[DUMMY28_1:%.*]] = mul i32 [[DUMMY27_1]], [[DUMMY27_1]] -; CHECK-NEXT: [[DUMMY29_1:%.*]] = mul i32 [[DUMMY28_1]], [[DUMMY28_1]] -; CHECK-NEXT: [[DUMMY30_1:%.*]] = mul i32 [[DUMMY29_1]], [[DUMMY29_1]] -; CHECK-NEXT: [[DUMMY31_1:%.*]] = mul i32 [[DUMMY30_1]], [[DUMMY30_1]] -; CHECK-NEXT: [[DUMMY32_1:%.*]] = mul i32 [[DUMMY31_1]], [[DUMMY31_1]] -; CHECK-NEXT: [[DUMMY33_1:%.*]] = mul i32 [[DUMMY32_1]], [[DUMMY32_1]] -; CHECK-NEXT: [[DUMMY34_1:%.*]] = mul i32 [[DUMMY33_1]], [[DUMMY33_1]] -; CHECK-NEXT: [[DUMMY35_1:%.*]] = mul i32 [[DUMMY34_1]], [[DUMMY34_1]] -; CHECK-NEXT: [[DUMMY36_1:%.*]] = mul i32 [[DUMMY35_1]], [[DUMMY35_1]] -; CHECK-NEXT: [[DUMMY37_1:%.*]] = mul i32 [[DUMMY36_1]], [[DUMMY36_1]] -; CHECK-NEXT: [[DUMMY38_1:%.*]] = mul i32 [[DUMMY37_1]], [[DUMMY37_1]] -; CHECK-NEXT: [[DUMMY39_1:%.*]] = mul i32 [[DUMMY38_1]], [[DUMMY38_1]] -; CHECK-NEXT: [[DUMMY40_1:%.*]] = mul i32 [[DUMMY39_1]], [[DUMMY39_1]] -; CHECK-NEXT: [[DUMMY41_1:%.*]] = mul i32 [[DUMMY40_1]], [[DUMMY40_1]] -; CHECK-NEXT: [[DUMMY42_1:%.*]] = mul i32 [[DUMMY41_1]], [[DUMMY41_1]] -; CHECK-NEXT: [[DUMMY43_1:%.*]] = mul i32 [[DUMMY42_1]], [[DUMMY42_1]] -; CHECK-NEXT: [[DUMMY44_1:%.*]] = mul i32 [[DUMMY43_1]], [[DUMMY43_1]] -; CHECK-NEXT: [[DUMMY45_1:%.*]] = mul i32 [[DUMMY44_1]], [[DUMMY44_1]] -; CHECK-NEXT: [[DUMMY46_1:%.*]] = mul i32 [[DUMMY45_1]], [[DUMMY45_1]] -; CHECK-NEXT: [[DUMMY47_1:%.*]] = mul i32 [[DUMMY46_1]], [[DUMMY46_1]] -; CHECK-NEXT: [[DUMMY48_1:%.*]] = mul i32 [[DUMMY47_1]], [[DUMMY47_1]] -; CHECK-NEXT: [[DUMMY49_1:%.*]] = mul i32 [[DUMMY48_1]], [[DUMMY48_1]] -; CHECK-NEXT: [[DUMMY50_1:%.*]] = mul i32 [[DUMMY49_1]], [[DUMMY49_1]] -; CHECK-NEXT: [[SUM_NEXT_1:%.*]] = add nsw i32 [[DUMMY50_1]], [[SUM_NEXT]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2 -; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_1]] -; CHECK-NEXT: [[VAL_2:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4 -; CHECK-NEXT: [[DUMMY1_2:%.*]] = mul i32 [[VAL_2]], [[VAL_2]] -; CHECK-NEXT: [[DUMMY2_2:%.*]] = mul i32 [[DUMMY1_2]], [[DUMMY1_2]] -; CHECK-NEXT: [[DUMMY3_2:%.*]] = mul i32 [[DUMMY2_2]], [[DUMMY2_2]] -; CHECK-NEXT: [[DUMMY4_2:%.*]] = mul i32 [[DUMMY3_2]], [[DUMMY3_2]] -; CHECK-NEXT: [[DUMMY5_2:%.*]] = mul i32 [[DUMMY4_2]], [[DUMMY4_2]] -; CHECK-NEXT: [[DUMMY6_2:%.*]] = mul i32 [[DUMMY5_2]], [[DUMMY5_2]] -; CHECK-NEXT: [[DUMMY7_2:%.*]] = mul i32 [[DUMMY6_2]], [[DUMMY6_2]] -; CHECK-NEXT: [[DUMMY8_2:%.*]] = mul i32 [[DUMMY7_2]], [[DUMMY7_2]] -; CHECK-NEXT: [[DUMMY9_2:%.*]] = mul i32 [[DUMMY8_2]], [[DUMMY8_2]] -; CHECK-NEXT: [[DUMMY10_2:%.*]] = mul i32 [[DUMMY9_2]], [[DUMMY9_2]] -; CHECK-NEXT: [[DUMMY11_2:%.*]] = mul i32 [[DUMMY10_2]], [[DUMMY10_2]] -; CHECK-NEXT: [[DUMMY12_2:%.*]] = mul i32 [[DUMMY11_2]], [[DUMMY11_2]] -; CHECK-NEXT: [[DUMMY13_2:%.*]] = mul i32 [[DUMMY12_2]], [[DUMMY12_2]] -; CHECK-NEXT: [[DUMMY14_2:%.*]] = mul i32 [[DUMMY13_2]], [[DUMMY13_2]] -; CHECK-NEXT: [[DUMMY15_2:%.*]] = mul i32 [[DUMMY14_2]], [[DUMMY14_2]] -; CHECK-NEXT: [[DUMMY16_2:%.*]] = mul i32 [[DUMMY15_2]], [[DUMMY15_2]] -; CHECK-NEXT: [[DUMMY17_2:%.*]] = mul i32 [[DUMMY16_2]], [[DUMMY16_2]] -; CHECK-NEXT: [[DUMMY18_2:%.*]] = mul i32 [[DUMMY17_2]], [[DUMMY17_2]] -; CHECK-NEXT: [[DUMMY19_2:%.*]] = mul i32 [[DUMMY18_2]], [[DUMMY18_2]] -; CHECK-NEXT: [[DUMMY20_2:%.*]] = mul i32 [[DUMMY19_2]], [[DUMMY19_2]] -; CHECK-NEXT: [[DUMMY21_2:%.*]] = mul i32 [[DUMMY20_2]], [[DUMMY20_2]] -; CHECK-NEXT: [[DUMMY22_2:%.*]] = mul i32 [[DUMMY21_2]], [[DUMMY21_2]] -; CHECK-NEXT: [[DUMMY23_2:%.*]] = mul i32 [[DUMMY22_2]], [[DUMMY22_2]] -; CHECK-NEXT: [[DUMMY24_2:%.*]] = mul i32 [[DUMMY23_2]], [[DUMMY23_2]] -; CHECK-NEXT: [[DUMMY25_2:%.*]] = mul i32 [[DUMMY24_2]], [[DUMMY24_2]] -; CHECK-NEXT: [[DUMMY26_2:%.*]] = mul i32 [[DUMMY25_2]], [[DUMMY25_2]] -; CHECK-NEXT: [[DUMMY27_2:%.*]] = mul i32 [[DUMMY26_2]], [[DUMMY26_2]] -; CHECK-NEXT: [[DUMMY28_2:%.*]] = mul i32 [[DUMMY27_2]], [[DUMMY27_2]] -; CHECK-NEXT: [[DUMMY29_2:%.*]] = mul i32 [[DUMMY28_2]], [[DUMMY28_2]] -; CHECK-NEXT: [[DUMMY30_2:%.*]] = mul i32 [[DUMMY29_2]], [[DUMMY29_2]] -; CHECK-NEXT: [[DUMMY31_2:%.*]] = mul i32 [[DUMMY30_2]], [[DUMMY30_2]] -; CHECK-NEXT: [[DUMMY32_2:%.*]] = mul i32 [[DUMMY31_2]], [[DUMMY31_2]] -; CHECK-NEXT: [[DUMMY33_2:%.*]] = mul i32 [[DUMMY32_2]], [[DUMMY32_2]] -; CHECK-NEXT: [[DUMMY34_2:%.*]] = mul i32 [[DUMMY33_2]], [[DUMMY33_2]] -; CHECK-NEXT: [[DUMMY35_2:%.*]] = mul i32 [[DUMMY34_2]], [[DUMMY34_2]] -; CHECK-NEXT: [[DUMMY36_2:%.*]] = mul i32 [[DUMMY35_2]], [[DUMMY35_2]] -; CHECK-NEXT: [[DUMMY37_2:%.*]] = mul i32 [[DUMMY36_2]], [[DUMMY36_2]] -; CHECK-NEXT: [[DUMMY38_2:%.*]] = mul i32 [[DUMMY37_2]], [[DUMMY37_2]] -; CHECK-NEXT: [[DUMMY39_2:%.*]] = mul i32 [[DUMMY38_2]], [[DUMMY38_2]] -; CHECK-NEXT: [[DUMMY40_2:%.*]] = mul i32 [[DUMMY39_2]], [[DUMMY39_2]] -; CHECK-NEXT: [[DUMMY41_2:%.*]] = mul i32 [[DUMMY40_2]], [[DUMMY40_2]] -; CHECK-NEXT: [[DUMMY42_2:%.*]] = mul i32 [[DUMMY41_2]], [[DUMMY41_2]] -; CHECK-NEXT: [[DUMMY43_2:%.*]] = mul i32 [[DUMMY42_2]], [[DUMMY42_2]] -; CHECK-NEXT: [[DUMMY44_2:%.*]] = mul i32 [[DUMMY43_2]], [[DUMMY43_2]] -; CHECK-NEXT: [[DUMMY45_2:%.*]] = mul i32 [[DUMMY44_2]], [[DUMMY44_2]] -; CHECK-NEXT: [[DUMMY46_2:%.*]] = mul i32 [[DUMMY45_2]], [[DUMMY45_2]] -; CHECK-NEXT: [[DUMMY47_2:%.*]] = mul i32 [[DUMMY46_2]], [[DUMMY46_2]] -; CHECK-NEXT: [[DUMMY48_2:%.*]] = mul i32 [[DUMMY47_2]], [[DUMMY47_2]] -; CHECK-NEXT: [[DUMMY49_2:%.*]] = mul i32 [[DUMMY48_2]], [[DUMMY48_2]] -; CHECK-NEXT: [[DUMMY50_2:%.*]] = mul i32 [[DUMMY49_2]], [[DUMMY49_2]] -; CHECK-NEXT: [[SUM_NEXT_2:%.*]] = add nsw i32 [[DUMMY50_2]], [[SUM_NEXT_1]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_2:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 3 -; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_2]] -; CHECK-NEXT: [[VAL_3:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4 -; CHECK-NEXT: [[DUMMY1_3:%.*]] = mul i32 [[VAL_3]], [[VAL_3]] -; CHECK-NEXT: [[DUMMY2_3:%.*]] = mul i32 [[DUMMY1_3]], [[DUMMY1_3]] -; CHECK-NEXT: [[DUMMY3_3:%.*]] = mul i32 [[DUMMY2_3]], [[DUMMY2_3]] -; CHECK-NEXT: [[DUMMY4_3:%.*]] = mul i32 [[DUMMY3_3]], [[DUMMY3_3]] -; CHECK-NEXT: [[DUMMY5_3:%.*]] = mul i32 [[DUMMY4_3]], [[DUMMY4_3]] -; CHECK-NEXT: [[DUMMY6_3:%.*]] = mul i32 [[DUMMY5_3]], [[DUMMY5_3]] -; CHECK-NEXT: [[DUMMY7_3:%.*]] = mul i32 [[DUMMY6_3]], [[DUMMY6_3]] -; CHECK-NEXT: [[DUMMY8_3:%.*]] = mul i32 [[DUMMY7_3]], [[DUMMY7_3]] -; CHECK-NEXT: [[DUMMY9_3:%.*]] = mul i32 [[DUMMY8_3]], [[DUMMY8_3]] -; CHECK-NEXT: [[DUMMY10_3:%.*]] = mul i32 [[DUMMY9_3]], [[DUMMY9_3]] -; CHECK-NEXT: [[DUMMY11_3:%.*]] = mul i32 [[DUMMY10_3]], [[DUMMY10_3]] -; CHECK-NEXT: [[DUMMY12_3:%.*]] = mul i32 [[DUMMY11_3]], [[DUMMY11_3]] -; CHECK-NEXT: [[DUMMY13_3:%.*]] = mul i32 [[DUMMY12_3]], [[DUMMY12_3]] -; CHECK-NEXT: [[DUMMY14_3:%.*]] = mul i32 [[DUMMY13_3]], [[DUMMY13_3]] -; CHECK-NEXT: [[DUMMY15_3:%.*]] = mul i32 [[DUMMY14_3]], [[DUMMY14_3]] -; CHECK-NEXT: [[DUMMY16_3:%.*]] = mul i32 [[DUMMY15_3]], [[DUMMY15_3]] -; CHECK-NEXT: [[DUMMY17_3:%.*]] = mul i32 [[DUMMY16_3]], [[DUMMY16_3]] -; CHECK-NEXT: [[DUMMY18_3:%.*]] = mul i32 [[DUMMY17_3]], [[DUMMY17_3]] -; CHECK-NEXT: [[DUMMY19_3:%.*]] = mul i32 [[DUMMY18_3]], [[DUMMY18_3]] -; CHECK-NEXT: [[DUMMY20_3:%.*]] = mul i32 [[DUMMY19_3]], [[DUMMY19_3]] -; CHECK-NEXT: [[DUMMY21_3:%.*]] = mul i32 [[DUMMY20_3]], [[DUMMY20_3]] -; CHECK-NEXT: [[DUMMY22_3:%.*]] = mul i32 [[DUMMY21_3]], [[DUMMY21_3]] -; CHECK-NEXT: [[DUMMY23_3:%.*]] = mul i32 [[DUMMY22_3]], [[DUMMY22_3]] -; CHECK-NEXT: [[DUMMY24_3:%.*]] = mul i32 [[DUMMY23_3]], [[DUMMY23_3]] -; CHECK-NEXT: [[DUMMY25_3:%.*]] = mul i32 [[DUMMY24_3]], [[DUMMY24_3]] -; CHECK-NEXT: [[DUMMY26_3:%.*]] = mul i32 [[DUMMY25_3]], [[DUMMY25_3]] -; CHECK-NEXT: [[DUMMY27_3:%.*]] = mul i32 [[DUMMY26_3]], [[DUMMY26_3]] -; CHECK-NEXT: [[DUMMY28_3:%.*]] = mul i32 [[DUMMY27_3]], [[DUMMY27_3]] -; CHECK-NEXT: [[DUMMY29_3:%.*]] = mul i32 [[DUMMY28_3]], [[DUMMY28_3]] -; CHECK-NEXT: [[DUMMY30_3:%.*]] = mul i32 [[DUMMY29_3]], [[DUMMY29_3]] -; CHECK-NEXT: [[DUMMY31_3:%.*]] = mul i32 [[DUMMY30_3]], [[DUMMY30_3]] -; CHECK-NEXT: [[DUMMY32_3:%.*]] = mul i32 [[DUMMY31_3]], [[DUMMY31_3]] -; CHECK-NEXT: [[DUMMY33_3:%.*]] = mul i32 [[DUMMY32_3]], [[DUMMY32_3]] -; CHECK-NEXT: [[DUMMY34_3:%.*]] = mul i32 [[DUMMY33_3]], [[DUMMY33_3]] -; CHECK-NEXT: [[DUMMY35_3:%.*]] = mul i32 [[DUMMY34_3]], [[DUMMY34_3]] -; CHECK-NEXT: [[DUMMY36_3:%.*]] = mul i32 [[DUMMY35_3]], [[DUMMY35_3]] -; CHECK-NEXT: [[DUMMY37_3:%.*]] = mul i32 [[DUMMY36_3]], [[DUMMY36_3]] -; CHECK-NEXT: [[DUMMY38_3:%.*]] = mul i32 [[DUMMY37_3]], [[DUMMY37_3]] -; CHECK-NEXT: [[DUMMY39_3:%.*]] = mul i32 [[DUMMY38_3]], [[DUMMY38_3]] -; CHECK-NEXT: [[DUMMY40_3:%.*]] = mul i32 [[DUMMY39_3]], [[DUMMY39_3]] -; CHECK-NEXT: [[DUMMY41_3:%.*]] = mul i32 [[DUMMY40_3]], [[DUMMY40_3]] -; CHECK-NEXT: [[DUMMY42_3:%.*]] = mul i32 [[DUMMY41_3]], [[DUMMY41_3]] -; CHECK-NEXT: [[DUMMY43_3:%.*]] = mul i32 [[DUMMY42_3]], [[DUMMY42_3]] -; CHECK-NEXT: [[DUMMY44_3:%.*]] = mul i32 [[DUMMY43_3]], [[DUMMY43_3]] -; CHECK-NEXT: [[DUMMY45_3:%.*]] = mul i32 [[DUMMY44_3]], [[DUMMY44_3]] -; CHECK-NEXT: [[DUMMY46_3:%.*]] = mul i32 [[DUMMY45_3]], [[DUMMY45_3]] -; CHECK-NEXT: [[DUMMY47_3:%.*]] = mul i32 [[DUMMY46_3]], [[DUMMY46_3]] -; CHECK-NEXT: [[DUMMY48_3:%.*]] = mul i32 [[DUMMY47_3]], [[DUMMY47_3]] -; CHECK-NEXT: [[DUMMY49_3:%.*]] = mul i32 [[DUMMY48_3]], [[DUMMY48_3]] -; CHECK-NEXT: [[DUMMY50_3:%.*]] = mul i32 [[DUMMY49_3]], [[DUMMY49_3]] -; CHECK-NEXT: [[SUM_NEXT_3:%.*]] = add nsw i32 [[DUMMY50_3]], [[SUM_NEXT_2]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_3:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 4 -; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_3]] -; CHECK-NEXT: [[VAL_4:%.*]] = load i32, ptr [[ARRAYIDX_4]], align 4 -; CHECK-NEXT: [[DUMMY1_4:%.*]] = mul i32 [[VAL_4]], [[VAL_4]] -; CHECK-NEXT: [[DUMMY2_4:%.*]] = mul i32 [[DUMMY1_4]], [[DUMMY1_4]] -; CHECK-NEXT: [[DUMMY3_4:%.*]] = mul i32 [[DUMMY2_4]], [[DUMMY2_4]] -; CHECK-NEXT: [[DUMMY4_4:%.*]] = mul i32 [[DUMMY3_4]], [[DUMMY3_4]] -; CHECK-NEXT: [[DUMMY5_4:%.*]] = mul i32 [[DUMMY4_4]], [[DUMMY4_4]] -; CHECK-NEXT: [[DUMMY6_4:%.*]] = mul i32 [[DUMMY5_4]], [[DUMMY5_4]] -; CHECK-NEXT: [[DUMMY7_4:%.*]] = mul i32 [[DUMMY6_4]], [[DUMMY6_4]] -; CHECK-NEXT: [[DUMMY8_4:%.*]] = mul i32 [[DUMMY7_4]], [[DUMMY7_4]] -; CHECK-NEXT: [[DUMMY9_4:%.*]] = mul i32 [[DUMMY8_4]], [[DUMMY8_4]] -; CHECK-NEXT: [[DUMMY10_4:%.*]] = mul i32 [[DUMMY9_4]], [[DUMMY9_4]] -; CHECK-NEXT: [[DUMMY11_4:%.*]] = mul i32 [[DUMMY10_4]], [[DUMMY10_4]] -; CHECK-NEXT: [[DUMMY12_4:%.*]] = mul i32 [[DUMMY11_4]], [[DUMMY11_4]] -; CHECK-NEXT: [[DUMMY13_4:%.*]] = mul i32 [[DUMMY12_4]], [[DUMMY12_4]] -; CHECK-NEXT: [[DUMMY14_4:%.*]] = mul i32 [[DUMMY13_4]], [[DUMMY13_4]] -; CHECK-NEXT: [[DUMMY15_4:%.*]] = mul i32 [[DUMMY14_4]], [[DUMMY14_4]] -; CHECK-NEXT: [[DUMMY16_4:%.*]] = mul i32 [[DUMMY15_4]], [[DUMMY15_4]] -; CHECK-NEXT: [[DUMMY17_4:%.*]] = mul i32 [[DUMMY16_4]], [[DUMMY16_4]] -; CHECK-NEXT: [[DUMMY18_4:%.*]] = mul i32 [[DUMMY17_4]], [[DUMMY17_4]] -; CHECK-NEXT: [[DUMMY19_4:%.*]] = mul i32 [[DUMMY18_4]], [[DUMMY18_4]] -; CHECK-NEXT: [[DUMMY20_4:%.*]] = mul i32 [[DUMMY19_4]], [[DUMMY19_4]] -; CHECK-NEXT: [[DUMMY21_4:%.*]] = mul i32 [[DUMMY20_4]], [[DUMMY20_4]] -; CHECK-NEXT: [[DUMMY22_4:%.*]] = mul i32 [[DUMMY21_4]], [[DUMMY21_4]] -; CHECK-NEXT: [[DUMMY23_4:%.*]] = mul i32 [[DUMMY22_4]], [[DUMMY22_4]] -; CHECK-NEXT: [[DUMMY24_4:%.*]] = mul i32 [[DUMMY23_4]], [[DUMMY23_4]] -; CHECK-NEXT: [[DUMMY25_4:%.*]] = mul i32 [[DUMMY24_4]], [[DUMMY24_4]] -; CHECK-NEXT: [[DUMMY26_4:%.*]] = mul i32 [[DUMMY25_4]], [[DUMMY25_4]] -; CHECK-NEXT: [[DUMMY27_4:%.*]] = mul i32 [[DUMMY26_4]], [[DUMMY26_4]] -; CHECK-NEXT: [[DUMMY28_4:%.*]] = mul i32 [[DUMMY27_4]], [[DUMMY27_4]] -; CHECK-NEXT: [[DUMMY29_4:%.*]] = mul i32 [[DUMMY28_4]], [[DUMMY28_4]] -; CHECK-NEXT: [[DUMMY30_4:%.*]] = mul i32 [[DUMMY29_4]], [[DUMMY29_4]] -; CHECK-NEXT: [[DUMMY31_4:%.*]] = mul i32 [[DUMMY30_4]], [[DUMMY30_4]] -; CHECK-NEXT: [[DUMMY32_4:%.*]] = mul i32 [[DUMMY31_4]], [[DUMMY31_4]] -; CHECK-NEXT: [[DUMMY33_4:%.*]] = mul i32 [[DUMMY32_4]], [[DUMMY32_4]] -; CHECK-NEXT: [[DUMMY34_4:%.*]] = mul i32 [[DUMMY33_4]], [[DUMMY33_4]] -; CHECK-NEXT: [[DUMMY35_4:%.*]] = mul i32 [[DUMMY34_4]], [[DUMMY34_4]] -; CHECK-NEXT: [[DUMMY36_4:%.*]] = mul i32 [[DUMMY35_4]], [[DUMMY35_4]] -; CHECK-NEXT: [[DUMMY37_4:%.*]] = mul i32 [[DUMMY36_4]], [[DUMMY36_4]] -; CHECK-NEXT: [[DUMMY38_4:%.*]] = mul i32 [[DUMMY37_4]], [[DUMMY37_4]] -; CHECK-NEXT: [[DUMMY39_4:%.*]] = mul i32 [[DUMMY38_4]], [[DUMMY38_4]] -; CHECK-NEXT: [[DUMMY40_4:%.*]] = mul i32 [[DUMMY39_4]], [[DUMMY39_4]] -; CHECK-NEXT: [[DUMMY41_4:%.*]] = mul i32 [[DUMMY40_4]], [[DUMMY40_4]] -; CHECK-NEXT: [[DUMMY42_4:%.*]] = mul i32 [[DUMMY41_4]], [[DUMMY41_4]] -; CHECK-NEXT: [[DUMMY43_4:%.*]] = mul i32 [[DUMMY42_4]], [[DUMMY42_4]] -; CHECK-NEXT: [[DUMMY44_4:%.*]] = mul i32 [[DUMMY43_4]], [[DUMMY43_4]] -; CHECK-NEXT: [[DUMMY45_4:%.*]] = mul i32 [[DUMMY44_4]], [[DUMMY44_4]] -; CHECK-NEXT: [[DUMMY46_4:%.*]] = mul i32 [[DUMMY45_4]], [[DUMMY45_4]] -; CHECK-NEXT: [[DUMMY47_4:%.*]] = mul i32 [[DUMMY46_4]], [[DUMMY46_4]] -; CHECK-NEXT: [[DUMMY48_4:%.*]] = mul i32 [[DUMMY47_4]], [[DUMMY47_4]] -; CHECK-NEXT: [[DUMMY49_4:%.*]] = mul i32 [[DUMMY48_4]], [[DUMMY48_4]] -; CHECK-NEXT: [[DUMMY50_4:%.*]] = mul i32 [[DUMMY49_4]], [[DUMMY49_4]] -; CHECK-NEXT: [[SUM_NEXT_4:%.*]] = add nsw i32 [[DUMMY50_4]], [[SUM_NEXT_3]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_4:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 5 -; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_4]] -; CHECK-NEXT: [[VAL_5:%.*]] = load i32, ptr [[ARRAYIDX_5]], align 4 -; CHECK-NEXT: [[DUMMY1_5:%.*]] = mul i32 [[VAL_5]], [[VAL_5]] -; CHECK-NEXT: [[DUMMY2_5:%.*]] = mul i32 [[DUMMY1_5]], [[DUMMY1_5]] -; CHECK-NEXT: [[DUMMY3_5:%.*]] = mul i32 [[DUMMY2_5]], [[DUMMY2_5]] -; CHECK-NEXT: [[DUMMY4_5:%.*]] = mul i32 [[DUMMY3_5]], [[DUMMY3_5]] -; CHECK-NEXT: [[DUMMY5_5:%.*]] = mul i32 [[DUMMY4_5]], [[DUMMY4_5]] -; CHECK-NEXT: [[DUMMY6_5:%.*]] = mul i32 [[DUMMY5_5]], [[DUMMY5_5]] -; CHECK-NEXT: [[DUMMY7_5:%.*]] = mul i32 [[DUMMY6_5]], [[DUMMY6_5]] -; CHECK-NEXT: [[DUMMY8_5:%.*]] = mul i32 [[DUMMY7_5]], [[DUMMY7_5]] -; CHECK-NEXT: [[DUMMY9_5:%.*]] = mul i32 [[DUMMY8_5]], [[DUMMY8_5]] -; CHECK-NEXT: [[DUMMY10_5:%.*]] = mul i32 [[DUMMY9_5]], [[DUMMY9_5]] -; CHECK-NEXT: [[DUMMY11_5:%.*]] = mul i32 [[DUMMY10_5]], [[DUMMY10_5]] -; CHECK-NEXT: [[DUMMY12_5:%.*]] = mul i32 [[DUMMY11_5]], [[DUMMY11_5]] -; CHECK-NEXT: [[DUMMY13_5:%.*]] = mul i32 [[DUMMY12_5]], [[DUMMY12_5]] -; CHECK-NEXT: [[DUMMY14_5:%.*]] = mul i32 [[DUMMY13_5]], [[DUMMY13_5]] -; CHECK-NEXT: [[DUMMY15_5:%.*]] = mul i32 [[DUMMY14_5]], [[DUMMY14_5]] -; CHECK-NEXT: [[DUMMY16_5:%.*]] = mul i32 [[DUMMY15_5]], [[DUMMY15_5]] -; CHECK-NEXT: [[DUMMY17_5:%.*]] = mul i32 [[DUMMY16_5]], [[DUMMY16_5]] -; CHECK-NEXT: [[DUMMY18_5:%.*]] = mul i32 [[DUMMY17_5]], [[DUMMY17_5]] -; CHECK-NEXT: [[DUMMY19_5:%.*]] = mul i32 [[DUMMY18_5]], [[DUMMY18_5]] -; CHECK-NEXT: [[DUMMY20_5:%.*]] = mul i32 [[DUMMY19_5]], [[DUMMY19_5]] -; CHECK-NEXT: [[DUMMY21_5:%.*]] = mul i32 [[DUMMY20_5]], [[DUMMY20_5]] -; CHECK-NEXT: [[DUMMY22_5:%.*]] = mul i32 [[DUMMY21_5]], [[DUMMY21_5]] -; CHECK-NEXT: [[DUMMY23_5:%.*]] = mul i32 [[DUMMY22_5]], [[DUMMY22_5]] -; CHECK-NEXT: [[DUMMY24_5:%.*]] = mul i32 [[DUMMY23_5]], [[DUMMY23_5]] -; CHECK-NEXT: [[DUMMY25_5:%.*]] = mul i32 [[DUMMY24_5]], [[DUMMY24_5]] -; CHECK-NEXT: [[DUMMY26_5:%.*]] = mul i32 [[DUMMY25_5]], [[DUMMY25_5]] -; CHECK-NEXT: [[DUMMY27_5:%.*]] = mul i32 [[DUMMY26_5]], [[DUMMY26_5]] -; CHECK-NEXT: [[DUMMY28_5:%.*]] = mul i32 [[DUMMY27_5]], [[DUMMY27_5]] -; CHECK-NEXT: [[DUMMY29_5:%.*]] = mul i32 [[DUMMY28_5]], [[DUMMY28_5]] -; CHECK-NEXT: [[DUMMY30_5:%.*]] = mul i32 [[DUMMY29_5]], [[DUMMY29_5]] -; CHECK-NEXT: [[DUMMY31_5:%.*]] = mul i32 [[DUMMY30_5]], [[DUMMY30_5]] -; CHECK-NEXT: [[DUMMY32_5:%.*]] = mul i32 [[DUMMY31_5]], [[DUMMY31_5]] -; CHECK-NEXT: [[DUMMY33_5:%.*]] = mul i32 [[DUMMY32_5]], [[DUMMY32_5]] -; CHECK-NEXT: [[DUMMY34_5:%.*]] = mul i32 [[DUMMY33_5]], [[DUMMY33_5]] -; CHECK-NEXT: [[DUMMY35_5:%.*]] = mul i32 [[DUMMY34_5]], [[DUMMY34_5]] -; CHECK-NEXT: [[DUMMY36_5:%.*]] = mul i32 [[DUMMY35_5]], [[DUMMY35_5]] -; CHECK-NEXT: [[DUMMY37_5:%.*]] = mul i32 [[DUMMY36_5]], [[DUMMY36_5]] -; CHECK-NEXT: [[DUMMY38_5:%.*]] = mul i32 [[DUMMY37_5]], [[DUMMY37_5]] -; CHECK-NEXT: [[DUMMY39_5:%.*]] = mul i32 [[DUMMY38_5]], [[DUMMY38_5]] -; CHECK-NEXT: [[DUMMY40_5:%.*]] = mul i32 [[DUMMY39_5]], [[DUMMY39_5]] -; CHECK-NEXT: [[DUMMY41_5:%.*]] = mul i32 [[DUMMY40_5]], [[DUMMY40_5]] -; CHECK-NEXT: [[DUMMY42_5:%.*]] = mul i32 [[DUMMY41_5]], [[DUMMY41_5]] -; CHECK-NEXT: [[DUMMY43_5:%.*]] = mul i32 [[DUMMY42_5]], [[DUMMY42_5]] -; CHECK-NEXT: [[DUMMY44_5:%.*]] = mul i32 [[DUMMY43_5]], [[DUMMY43_5]] -; CHECK-NEXT: [[DUMMY45_5:%.*]] = mul i32 [[DUMMY44_5]], [[DUMMY44_5]] -; CHECK-NEXT: [[DUMMY46_5:%.*]] = mul i32 [[DUMMY45_5]], [[DUMMY45_5]] -; CHECK-NEXT: [[DUMMY47_5:%.*]] = mul i32 [[DUMMY46_5]], [[DUMMY46_5]] -; CHECK-NEXT: [[DUMMY48_5:%.*]] = mul i32 [[DUMMY47_5]], [[DUMMY47_5]] -; CHECK-NEXT: [[DUMMY49_5:%.*]] = mul i32 [[DUMMY48_5]], [[DUMMY48_5]] -; CHECK-NEXT: [[DUMMY50_5:%.*]] = mul i32 [[DUMMY49_5]], [[DUMMY49_5]] -; CHECK-NEXT: [[SUM_NEXT_5:%.*]] = add nsw i32 [[DUMMY50_5]], [[SUM_NEXT_4]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_5:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 6 -; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_5]] -; CHECK-NEXT: [[VAL_6:%.*]] = load i32, ptr [[ARRAYIDX_6]], align 4 -; CHECK-NEXT: [[DUMMY1_6:%.*]] = mul i32 [[VAL_6]], [[VAL_6]] -; CHECK-NEXT: [[DUMMY2_6:%.*]] = mul i32 [[DUMMY1_6]], [[DUMMY1_6]] -; CHECK-NEXT: [[DUMMY3_6:%.*]] = mul i32 [[DUMMY2_6]], [[DUMMY2_6]] -; CHECK-NEXT: [[DUMMY4_6:%.*]] = mul i32 [[DUMMY3_6]], [[DUMMY3_6]] -; CHECK-NEXT: [[DUMMY5_6:%.*]] = mul i32 [[DUMMY4_6]], [[DUMMY4_6]] -; CHECK-NEXT: [[DUMMY6_6:%.*]] = mul i32 [[DUMMY5_6]], [[DUMMY5_6]] -; CHECK-NEXT: [[DUMMY7_6:%.*]] = mul i32 [[DUMMY6_6]], [[DUMMY6_6]] -; CHECK-NEXT: [[DUMMY8_6:%.*]] = mul i32 [[DUMMY7_6]], [[DUMMY7_6]] -; CHECK-NEXT: [[DUMMY9_6:%.*]] = mul i32 [[DUMMY8_6]], [[DUMMY8_6]] -; CHECK-NEXT: [[DUMMY10_6:%.*]] = mul i32 [[DUMMY9_6]], [[DUMMY9_6]] -; CHECK-NEXT: [[DUMMY11_6:%.*]] = mul i32 [[DUMMY10_6]], [[DUMMY10_6]] -; CHECK-NEXT: [[DUMMY12_6:%.*]] = mul i32 [[DUMMY11_6]], [[DUMMY11_6]] -; CHECK-NEXT: [[DUMMY13_6:%.*]] = mul i32 [[DUMMY12_6]], [[DUMMY12_6]] -; CHECK-NEXT: [[DUMMY14_6:%.*]] = mul i32 [[DUMMY13_6]], [[DUMMY13_6]] -; CHECK-NEXT: [[DUMMY15_6:%.*]] = mul i32 [[DUMMY14_6]], [[DUMMY14_6]] -; CHECK-NEXT: [[DUMMY16_6:%.*]] = mul i32 [[DUMMY15_6]], [[DUMMY15_6]] -; CHECK-NEXT: [[DUMMY17_6:%.*]] = mul i32 [[DUMMY16_6]], [[DUMMY16_6]] -; CHECK-NEXT: [[DUMMY18_6:%.*]] = mul i32 [[DUMMY17_6]], [[DUMMY17_6]] -; CHECK-NEXT: [[DUMMY19_6:%.*]] = mul i32 [[DUMMY18_6]], [[DUMMY18_6]] -; CHECK-NEXT: [[DUMMY20_6:%.*]] = mul i32 [[DUMMY19_6]], [[DUMMY19_6]] -; CHECK-NEXT: [[DUMMY21_6:%.*]] = mul i32 [[DUMMY20_6]], [[DUMMY20_6]] -; CHECK-NEXT: [[DUMMY22_6:%.*]] = mul i32 [[DUMMY21_6]], [[DUMMY21_6]] -; CHECK-NEXT: [[DUMMY23_6:%.*]] = mul i32 [[DUMMY22_6]], [[DUMMY22_6]] -; CHECK-NEXT: [[DUMMY24_6:%.*]] = mul i32 [[DUMMY23_6]], [[DUMMY23_6]] -; CHECK-NEXT: [[DUMMY25_6:%.*]] = mul i32 [[DUMMY24_6]], [[DUMMY24_6]] -; CHECK-NEXT: [[DUMMY26_6:%.*]] = mul i32 [[DUMMY25_6]], [[DUMMY25_6]] -; CHECK-NEXT: [[DUMMY27_6:%.*]] = mul i32 [[DUMMY26_6]], [[DUMMY26_6]] -; CHECK-NEXT: [[DUMMY28_6:%.*]] = mul i32 [[DUMMY27_6]], [[DUMMY27_6]] -; CHECK-NEXT: [[DUMMY29_6:%.*]] = mul i32 [[DUMMY28_6]], [[DUMMY28_6]] -; CHECK-NEXT: [[DUMMY30_6:%.*]] = mul i32 [[DUMMY29_6]], [[DUMMY29_6]] -; CHECK-NEXT: [[DUMMY31_6:%.*]] = mul i32 [[DUMMY30_6]], [[DUMMY30_6]] -; CHECK-NEXT: [[DUMMY32_6:%.*]] = mul i32 [[DUMMY31_6]], [[DUMMY31_6]] -; CHECK-NEXT: [[DUMMY33_6:%.*]] = mul i32 [[DUMMY32_6]], [[DUMMY32_6]] -; CHECK-NEXT: [[DUMMY34_6:%.*]] = mul i32 [[DUMMY33_6]], [[DUMMY33_6]] -; CHECK-NEXT: [[DUMMY35_6:%.*]] = mul i32 [[DUMMY34_6]], [[DUMMY34_6]] -; CHECK-NEXT: [[DUMMY36_6:%.*]] = mul i32 [[DUMMY35_6]], [[DUMMY35_6]] -; CHECK-NEXT: [[DUMMY37_6:%.*]] = mul i32 [[DUMMY36_6]], [[DUMMY36_6]] -; CHECK-NEXT: [[DUMMY38_6:%.*]] = mul i32 [[DUMMY37_6]], [[DUMMY37_6]] -; CHECK-NEXT: [[DUMMY39_6:%.*]] = mul i32 [[DUMMY38_6]], [[DUMMY38_6]] -; CHECK-NEXT: [[DUMMY40_6:%.*]] = mul i32 [[DUMMY39_6]], [[DUMMY39_6]] -; CHECK-NEXT: [[DUMMY41_6:%.*]] = mul i32 [[DUMMY40_6]], [[DUMMY40_6]] -; CHECK-NEXT: [[DUMMY42_6:%.*]] = mul i32 [[DUMMY41_6]], [[DUMMY41_6]] -; CHECK-NEXT: [[DUMMY43_6:%.*]] = mul i32 [[DUMMY42_6]], [[DUMMY42_6]] -; CHECK-NEXT: [[DUMMY44_6:%.*]] = mul i32 [[DUMMY43_6]], [[DUMMY43_6]] -; CHECK-NEXT: [[DUMMY45_6:%.*]] = mul i32 [[DUMMY44_6]], [[DUMMY44_6]] -; CHECK-NEXT: [[DUMMY46_6:%.*]] = mul i32 [[DUMMY45_6]], [[DUMMY45_6]] -; CHECK-NEXT: [[DUMMY47_6:%.*]] = mul i32 [[DUMMY46_6]], [[DUMMY46_6]] -; CHECK-NEXT: [[DUMMY48_6:%.*]] = mul i32 [[DUMMY47_6]], [[DUMMY47_6]] -; CHECK-NEXT: [[DUMMY49_6:%.*]] = mul i32 [[DUMMY48_6]], [[DUMMY48_6]] -; CHECK-NEXT: [[DUMMY50_6:%.*]] = mul i32 [[DUMMY49_6]], [[DUMMY49_6]] -; CHECK-NEXT: [[SUM_NEXT_6:%.*]] = add nsw i32 [[DUMMY50_6]], [[SUM_NEXT_5]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_6:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 7 -; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_NEXT_6]] -; CHECK-NEXT: [[VAL_7:%.*]] = load i32, ptr [[ARRAYIDX_7]], align 4 -; CHECK-NEXT: [[DUMMY1_7:%.*]] = mul i32 [[VAL_7]], [[VAL_7]] -; CHECK-NEXT: [[DUMMY2_7:%.*]] = mul i32 [[DUMMY1_7]], [[DUMMY1_7]] -; CHECK-NEXT: [[DUMMY3_7:%.*]] = mul i32 [[DUMMY2_7]], [[DUMMY2_7]] -; CHECK-NEXT: [[DUMMY4_7:%.*]] = mul i32 [[DUMMY3_7]], [[DUMMY3_7]] -; CHECK-NEXT: [[DUMMY5_7:%.*]] = mul i32 [[DUMMY4_7]], [[DUMMY4_7]] -; CHECK-NEXT: [[DUMMY6_7:%.*]] = mul i32 [[DUMMY5_7]], [[DUMMY5_7]] -; CHECK-NEXT: [[DUMMY7_7:%.*]] = mul i32 [[DUMMY6_7]], [[DUMMY6_7]] -; CHECK-NEXT: [[DUMMY8_7:%.*]] = mul i32 [[DUMMY7_7]], [[DUMMY7_7]] -; CHECK-NEXT: [[DUMMY9_7:%.*]] = mul i32 [[DUMMY8_7]], [[DUMMY8_7]] -; CHECK-NEXT: [[DUMMY10_7:%.*]] = mul i32 [[DUMMY9_7]], [[DUMMY9_7]] -; CHECK-NEXT: [[DUMMY11_7:%.*]] = mul i32 [[DUMMY10_7]], [[DUMMY10_7]] -; CHECK-NEXT: [[DUMMY12_7:%.*]] = mul i32 [[DUMMY11_7]], [[DUMMY11_7]] -; CHECK-NEXT: [[DUMMY13_7:%.*]] = mul i32 [[DUMMY12_7]], [[DUMMY12_7]] -; CHECK-NEXT: [[DUMMY14_7:%.*]] = mul i32 [[DUMMY13_7]], [[DUMMY13_7]] -; CHECK-NEXT: [[DUMMY15_7:%.*]] = mul i32 [[DUMMY14_7]], [[DUMMY14_7]] -; CHECK-NEXT: [[DUMMY16_7:%.*]] = mul i32 [[DUMMY15_7]], [[DUMMY15_7]] -; CHECK-NEXT: [[DUMMY17_7:%.*]] = mul i32 [[DUMMY16_7]], [[DUMMY16_7]] -; CHECK-NEXT: [[DUMMY18_7:%.*]] = mul i32 [[DUMMY17_7]], [[DUMMY17_7]] -; CHECK-NEXT: [[DUMMY19_7:%.*]] = mul i32 [[DUMMY18_7]], [[DUMMY18_7]] -; CHECK-NEXT: [[DUMMY20_7:%.*]] = mul i32 [[DUMMY19_7]], [[DUMMY19_7]] -; CHECK-NEXT: [[DUMMY21_7:%.*]] = mul i32 [[DUMMY20_7]], [[DUMMY20_7]] -; CHECK-NEXT: [[DUMMY22_7:%.*]] = mul i32 [[DUMMY21_7]], [[DUMMY21_7]] -; CHECK-NEXT: [[DUMMY23_7:%.*]] = mul i32 [[DUMMY22_7]], [[DUMMY22_7]] -; CHECK-NEXT: [[DUMMY24_7:%.*]] = mul i32 [[DUMMY23_7]], [[DUMMY23_7]] -; CHECK-NEXT: [[DUMMY25_7:%.*]] = mul i32 [[DUMMY24_7]], [[DUMMY24_7]] -; CHECK-NEXT: [[DUMMY26_7:%.*]] = mul i32 [[DUMMY25_7]], [[DUMMY25_7]] -; CHECK-NEXT: [[DUMMY27_7:%.*]] = mul i32 [[DUMMY26_7]], [[DUMMY26_7]] -; CHECK-NEXT: [[DUMMY28_7:%.*]] = mul i32 [[DUMMY27_7]], [[DUMMY27_7]] -; CHECK-NEXT: [[DUMMY29_7:%.*]] = mul i32 [[DUMMY28_7]], [[DUMMY28_7]] -; CHECK-NEXT: [[DUMMY30_7:%.*]] = mul i32 [[DUMMY29_7]], [[DUMMY29_7]] -; CHECK-NEXT: [[DUMMY31_7:%.*]] = mul i32 [[DUMMY30_7]], [[DUMMY30_7]] -; CHECK-NEXT: [[DUMMY32_7:%.*]] = mul i32 [[DUMMY31_7]], [[DUMMY31_7]] -; CHECK-NEXT: [[DUMMY33_7:%.*]] = mul i32 [[DUMMY32_7]], [[DUMMY32_7]] -; CHECK-NEXT: [[DUMMY34_7:%.*]] = mul i32 [[DUMMY33_7]], [[DUMMY33_7]] -; CHECK-NEXT: [[DUMMY35_7:%.*]] = mul i32 [[DUMMY34_7]], [[DUMMY34_7]] -; CHECK-NEXT: [[DUMMY36_7:%.*]] = mul i32 [[DUMMY35_7]], [[DUMMY35_7]] -; CHECK-NEXT: [[DUMMY37_7:%.*]] = mul i32 [[DUMMY36_7]], [[DUMMY36_7]] -; CHECK-NEXT: [[DUMMY38_7:%.*]] = mul i32 [[DUMMY37_7]], [[DUMMY37_7]] -; CHECK-NEXT: [[DUMMY39_7:%.*]] = mul i32 [[DUMMY38_7]], [[DUMMY38_7]] -; CHECK-NEXT: [[DUMMY40_7:%.*]] = mul i32 [[DUMMY39_7]], [[DUMMY39_7]] -; CHECK-NEXT: [[DUMMY41_7:%.*]] = mul i32 [[DUMMY40_7]], [[DUMMY40_7]] -; CHECK-NEXT: [[DUMMY42_7:%.*]] = mul i32 [[DUMMY41_7]], [[DUMMY41_7]] -; CHECK-NEXT: [[DUMMY43_7:%.*]] = mul i32 [[DUMMY42_7]], [[DUMMY42_7]] -; CHECK-NEXT: [[DUMMY44_7:%.*]] = mul i32 [[DUMMY43_7]], [[DUMMY43_7]] -; CHECK-NEXT: [[DUMMY45_7:%.*]] = mul i32 [[DUMMY44_7]], [[DUMMY44_7]] -; CHECK-NEXT: [[DUMMY46_7:%.*]] = mul i32 [[DUMMY45_7]], [[DUMMY45_7]] -; CHECK-NEXT: [[DUMMY47_7:%.*]] = mul i32 [[DUMMY46_7]], [[DUMMY46_7]] -; CHECK-NEXT: [[DUMMY48_7:%.*]] = mul i32 [[DUMMY47_7]], [[DUMMY47_7]] -; CHECK-NEXT: [[DUMMY49_7:%.*]] = mul i32 [[DUMMY48_7]], [[DUMMY48_7]] -; CHECK-NEXT: [[DUMMY50_7:%.*]] = mul i32 [[DUMMY49_7]], [[DUMMY49_7]] -; CHECK-NEXT: [[SUM_NEXT_7]] = add nsw i32 [[DUMMY50_7]], [[SUM_NEXT_6]] -; CHECK-NEXT: [[INDVARS_IV_NEXT_7]] = add nuw nsw i64 [[INDVARS_IV]], 8 -; CHECK-NEXT: [[NITER_NEXT_7]] = add i64 [[NITER]], 8 -; CHECK-NEXT: [[NITER_NCMP_7:%.*]] = icmp eq i64 [[NITER_NEXT_7]], [[UNROLL_ITER]] -; CHECK-NEXT: br i1 [[NITER_NCMP_7]], label [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT:%.*]], label [[FOR_BODY]] -; CHECK: for.cond.cleanup.unr-lcssa.loopexit: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] -; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_7]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM_UNR_PH:%.*]] = phi i32 [ [[SUM_NEXT_7]], [[FOR_BODY]] ] -; CHECK-NEXT: br label [[FOR_COND_CLEANUP_UNR_LCSSA]] -; CHECK: for.cond.cleanup.unr-lcssa: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[SUM_NEXT_LCSSA_PH_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT]] ] -; CHECK-NEXT: [[INDVARS_IV_UNR:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_UNR_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT]] ] -; CHECK-NEXT: [[SUM_UNR:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_UNR_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA_LOOPEXIT]] ] -; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i64 [[XTRAITER]], 0 -; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[FOR_BODY_EPIL_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] -; CHECK: for.body.epil.preheader: -; CHECK-NEXT: br label [[FOR_BODY_EPIL:%.*]] -; CHECK: for.body.epil: -; CHECK-NEXT: [[INDVARS_IV_EPIL:%.*]] = phi i64 [ [[INDVARS_IV_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[INDVARS_IV_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[SUM_EPIL:%.*]] = phi i32 [ [[SUM_UNR]], [[FOR_BODY_EPIL_PREHEADER]] ], [ [[SUM_NEXT_EPIL:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[EPIL_ITER:%.*]] = phi i64 [ 0, [[FOR_BODY_EPIL_PREHEADER]] ], [ [[EPIL_ITER_NEXT:%.*]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: [[ARRAYIDX_EPIL:%.*]] = getelementptr inbounds i32, ptr [[ARY]], i64 [[INDVARS_IV_EPIL]] -; CHECK-NEXT: [[VAL_EPIL:%.*]] = load i32, ptr [[ARRAYIDX_EPIL]], align 4 -; CHECK-NEXT: [[DUMMY1_EPIL:%.*]] = mul i32 [[VAL_EPIL]], [[VAL_EPIL]] -; CHECK-NEXT: [[DUMMY2_EPIL:%.*]] = mul i32 [[DUMMY1_EPIL]], [[DUMMY1_EPIL]] -; CHECK-NEXT: [[DUMMY3_EPIL:%.*]] = mul i32 [[DUMMY2_EPIL]], [[DUMMY2_EPIL]] -; CHECK-NEXT: [[DUMMY4_EPIL:%.*]] = mul i32 [[DUMMY3_EPIL]], [[DUMMY3_EPIL]] -; CHECK-NEXT: [[DUMMY5_EPIL:%.*]] = mul i32 [[DUMMY4_EPIL]], [[DUMMY4_EPIL]] -; CHECK-NEXT: [[DUMMY6_EPIL:%.*]] = mul i32 [[DUMMY5_EPIL]], [[DUMMY5_EPIL]] -; CHECK-NEXT: [[DUMMY7_EPIL:%.*]] = mul i32 [[DUMMY6_EPIL]], [[DUMMY6_EPIL]] -; CHECK-NEXT: [[DUMMY8_EPIL:%.*]] = mul i32 [[DUMMY7_EPIL]], [[DUMMY7_EPIL]] -; CHECK-NEXT: [[DUMMY9_EPIL:%.*]] = mul i32 [[DUMMY8_EPIL]], [[DUMMY8_EPIL]] -; CHECK-NEXT: [[DUMMY10_EPIL:%.*]] = mul i32 [[DUMMY9_EPIL]], [[DUMMY9_EPIL]] -; CHECK-NEXT: [[DUMMY11_EPIL:%.*]] = mul i32 [[DUMMY10_EPIL]], [[DUMMY10_EPIL]] -; CHECK-NEXT: [[DUMMY12_EPIL:%.*]] = mul i32 [[DUMMY11_EPIL]], [[DUMMY11_EPIL]] -; CHECK-NEXT: [[DUMMY13_EPIL:%.*]] = mul i32 [[DUMMY12_EPIL]], [[DUMMY12_EPIL]] -; CHECK-NEXT: [[DUMMY14_EPIL:%.*]] = mul i32 [[DUMMY13_EPIL]], [[DUMMY13_EPIL]] -; CHECK-NEXT: [[DUMMY15_EPIL:%.*]] = mul i32 [[DUMMY14_EPIL]], [[DUMMY14_EPIL]] -; CHECK-NEXT: [[DUMMY16_EPIL:%.*]] = mul i32 [[DUMMY15_EPIL]], [[DUMMY15_EPIL]] -; CHECK-NEXT: [[DUMMY17_EPIL:%.*]] = mul i32 [[DUMMY16_EPIL]], [[DUMMY16_EPIL]] -; CHECK-NEXT: [[DUMMY18_EPIL:%.*]] = mul i32 [[DUMMY17_EPIL]], [[DUMMY17_EPIL]] -; CHECK-NEXT: [[DUMMY19_EPIL:%.*]] = mul i32 [[DUMMY18_EPIL]], [[DUMMY18_EPIL]] -; CHECK-NEXT: [[DUMMY20_EPIL:%.*]] = mul i32 [[DUMMY19_EPIL]], [[DUMMY19_EPIL]] -; CHECK-NEXT: [[DUMMY21_EPIL:%.*]] = mul i32 [[DUMMY20_EPIL]], [[DUMMY20_EPIL]] -; CHECK-NEXT: [[DUMMY22_EPIL:%.*]] = mul i32 [[DUMMY21_EPIL]], [[DUMMY21_EPIL]] -; CHECK-NEXT: [[DUMMY23_EPIL:%.*]] = mul i32 [[DUMMY22_EPIL]], [[DUMMY22_EPIL]] -; CHECK-NEXT: [[DUMMY24_EPIL:%.*]] = mul i32 [[DUMMY23_EPIL]], [[DUMMY23_EPIL]] -; CHECK-NEXT: [[DUMMY25_EPIL:%.*]] = mul i32 [[DUMMY24_EPIL]], [[DUMMY24_EPIL]] -; CHECK-NEXT: [[DUMMY26_EPIL:%.*]] = mul i32 [[DUMMY25_EPIL]], [[DUMMY25_EPIL]] -; CHECK-NEXT: [[DUMMY27_EPIL:%.*]] = mul i32 [[DUMMY26_EPIL]], [[DUMMY26_EPIL]] -; CHECK-NEXT: [[DUMMY28_EPIL:%.*]] = mul i32 [[DUMMY27_EPIL]], [[DUMMY27_EPIL]] -; CHECK-NEXT: [[DUMMY29_EPIL:%.*]] = mul i32 [[DUMMY28_EPIL]], [[DUMMY28_EPIL]] -; CHECK-NEXT: [[DUMMY30_EPIL:%.*]] = mul i32 [[DUMMY29_EPIL]], [[DUMMY29_EPIL]] -; CHECK-NEXT: [[DUMMY31_EPIL:%.*]] = mul i32 [[DUMMY30_EPIL]], [[DUMMY30_EPIL]] -; CHECK-NEXT: [[DUMMY32_EPIL:%.*]] = mul i32 [[DUMMY31_EPIL]], [[DUMMY31_EPIL]] -; CHECK-NEXT: [[DUMMY33_EPIL:%.*]] = mul i32 [[DUMMY32_EPIL]], [[DUMMY32_EPIL]] -; CHECK-NEXT: [[DUMMY34_EPIL:%.*]] = mul i32 [[DUMMY33_EPIL]], [[DUMMY33_EPIL]] -; CHECK-NEXT: [[DUMMY35_EPIL:%.*]] = mul i32 [[DUMMY34_EPIL]], [[DUMMY34_EPIL]] -; CHECK-NEXT: [[DUMMY36_EPIL:%.*]] = mul i32 [[DUMMY35_EPIL]], [[DUMMY35_EPIL]] -; CHECK-NEXT: [[DUMMY37_EPIL:%.*]] = mul i32 [[DUMMY36_EPIL]], [[DUMMY36_EPIL]] -; CHECK-NEXT: [[DUMMY38_EPIL:%.*]] = mul i32 [[DUMMY37_EPIL]], [[DUMMY37_EPIL]] -; CHECK-NEXT: [[DUMMY39_EPIL:%.*]] = mul i32 [[DUMMY38_EPIL]], [[DUMMY38_EPIL]] -; CHECK-NEXT: [[DUMMY40_EPIL:%.*]] = mul i32 [[DUMMY39_EPIL]], [[DUMMY39_EPIL]] -; CHECK-NEXT: [[DUMMY41_EPIL:%.*]] = mul i32 [[DUMMY40_EPIL]], [[DUMMY40_EPIL]] -; CHECK-NEXT: [[DUMMY42_EPIL:%.*]] = mul i32 [[DUMMY41_EPIL]], [[DUMMY41_EPIL]] -; CHECK-NEXT: [[DUMMY43_EPIL:%.*]] = mul i32 [[DUMMY42_EPIL]], [[DUMMY42_EPIL]] -; CHECK-NEXT: [[DUMMY44_EPIL:%.*]] = mul i32 [[DUMMY43_EPIL]], [[DUMMY43_EPIL]] -; CHECK-NEXT: [[DUMMY45_EPIL:%.*]] = mul i32 [[DUMMY44_EPIL]], [[DUMMY44_EPIL]] -; CHECK-NEXT: [[DUMMY46_EPIL:%.*]] = mul i32 [[DUMMY45_EPIL]], [[DUMMY45_EPIL]] -; CHECK-NEXT: [[DUMMY47_EPIL:%.*]] = mul i32 [[DUMMY46_EPIL]], [[DUMMY46_EPIL]] -; CHECK-NEXT: [[DUMMY48_EPIL:%.*]] = mul i32 [[DUMMY47_EPIL]], [[DUMMY47_EPIL]] -; CHECK-NEXT: [[DUMMY49_EPIL:%.*]] = mul i32 [[DUMMY48_EPIL]], [[DUMMY48_EPIL]] -; CHECK-NEXT: [[DUMMY50_EPIL:%.*]] = mul i32 [[DUMMY49_EPIL]], [[DUMMY49_EPIL]] +; CHECK-NEXT: [[DUMMY50_EPIL:%.*]] = mul i32 [[DUMMY49]], [[DUMMY49]] ; CHECK-NEXT: [[SUM_NEXT_EPIL]] = add nsw i32 [[DUMMY50_EPIL]], [[SUM_EPIL]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_EPIL]] = add nuw nsw i64 [[INDVARS_IV_EPIL]], 1 ; CHECK-NEXT: [[EXITCOND_NOT_EPIL:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT_EPIL]], [[N]] -; CHECK-NEXT: [[EPIL_ITER_NEXT]] = add i64 [[EPIL_ITER]], 1 -; CHECK-NEXT: [[EPIL_ITER_CMP:%.*]] = icmp ne i64 [[EPIL_ITER_NEXT]], [[XTRAITER]] -; CHECK-NEXT: br i1 [[EPIL_ITER_CMP]], label [[FOR_BODY_EPIL]], label [[FOR_COND_CLEANUP_EPILOG_LCSSA:%.*]], !llvm.loop [[LOOP0:![0-9]+]] -; CHECK: for.cond.cleanup.epilog-lcssa: -; CHECK-NEXT: [[SUM_NEXT_LCSSA_PH1:%.*]] = phi i32 [ [[SUM_NEXT_EPIL]], [[FOR_BODY_EPIL]] ] -; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT_EPIL]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_LCSSA_PH]], [[FOR_COND_CLEANUP_UNR_LCSSA]] ], [ [[SUM_NEXT_LCSSA_PH1]], [[FOR_COND_CLEANUP_EPILOG_LCSSA]] ] +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_EPIL]], [[FOR_BODY]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] ; entry: From 93c02b7dc3bd07d3d62b56cb3299288901205f3a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 16 May 2024 15:47:39 +0200 Subject: [PATCH 040/576] [CodeGen][ARM64EC] Use MCSymbolRefExpr::VK_None for function aliases. (#92100) --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 2 +- llvm/test/CodeGen/AArch64/arm64ec-symbols.ll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 3ce766fc173c8e..bdc3fc630a4e3b 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1170,7 +1170,7 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() { auto emitFunctionAlias = [&](MCSymbol *Src, MCSymbol *Dst) { OutStreamer->emitSymbolAttribute(Src, MCSA_WeakAntiDep); OutStreamer->emitAssignment( - Src, MCSymbolRefExpr::create(Dst, MCSymbolRefExpr::VK_WEAKREF, + Src, MCSymbolRefExpr::create(Dst, MCSymbolRefExpr::VK_None, MMI->getContext())); }; diff --git a/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll b/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll index 389c36974beda2..b79dd7d61dd600 100644 --- a/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll +++ b/llvm/test/CodeGen/AArch64/arm64ec-symbols.ll @@ -10,12 +10,12 @@ define void @caller() nounwind { } ; CHECK: .weak_anti_dep caller -; CHECK-NEXT: .set caller, "#caller"@WEAKREF +; CHECK-NEXT: .set caller, "#caller"{{$}} ; CHECK: .weak_anti_dep func -; CHECK-NEXT: .set func, "#func"@WEAKREF +; CHECK-NEXT: .set func, "#func"{{$}} ; CHECK-NEXT: .weak_anti_dep "#func" -; CHECK-NEXT: .set "#func", "#func$exit_thunk"@WEAKREF +; CHECK-NEXT: .set "#func", "#func$exit_thunk"{{$}} ; SYM: [ 8](sec 4)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #caller ; SYM: [21](sec 7)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 #func$exit_thunk From c675a58edec6d1a876a0d0e7d261f74764855b38 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Thu, 16 May 2024 09:48:42 -0400 Subject: [PATCH 041/576] [TableGen][SubtargetEmitter] Early exit from loop in FindWriteResources and FindReadAdvance (#92202) This gives us a 30% speed improvement in our downstream. --- llvm/utils/TableGen/SubtargetEmitter.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index 9e32d2de19b2ce..323470940fec5c 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -902,14 +902,19 @@ SubtargetEmitter::FindWriteResources(const CodeGenSchedRW &SchedWrite, for (Record *WR : ProcModel.WriteResDefs) { if (!WR->isSubClassOf("WriteRes")) continue; - if (AliasDef == WR->getValueAsDef("WriteType") || - SchedWrite.TheDef == WR->getValueAsDef("WriteType")) { + Record *WRDef = WR->getValueAsDef("WriteType"); + if (AliasDef == WRDef || SchedWrite.TheDef == WRDef) { if (ResDef) { PrintFatalError(WR->getLoc(), "Resources are defined for both " "SchedWrite and its alias on processor " + ProcModel.ModelName); } ResDef = WR; + // If there is no AliasDef and we find a match, we can early exit since + // there is no need to verify whether there are resources defined for both + // SchedWrite and its alias. + if (!AliasDef) + break; } } // TODO: If ProcModel has a base model (previous generation processor), @@ -956,14 +961,19 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, for (Record *RA : ProcModel.ReadAdvanceDefs) { if (!RA->isSubClassOf("ReadAdvance")) continue; - if (AliasDef == RA->getValueAsDef("ReadType") || - SchedRead.TheDef == RA->getValueAsDef("ReadType")) { + Record *RADef = RA->getValueAsDef("ReadType"); + if (AliasDef == RADef || SchedRead.TheDef == RADef) { if (ResDef) { PrintFatalError(RA->getLoc(), "Resources are defined for both " "SchedRead and its alias on processor " + ProcModel.ModelName); } ResDef = RA; + // If there is no AliasDef and we find a match, we can early exit since + // there is no need to verify whether there are resources defined for both + // SchedRead and its alias. + if (!AliasDef) + break; } } // TODO: If ProcModel has a base model (previous generation processor), From 6c7ec6e1e6646fb334064bda6f301fdb52390d9b Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 16 May 2024 15:26:11 +0100 Subject: [PATCH 042/576] [mlir][ArmSME] Remove empty line in test (NFC) (#92404) --- .../ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir | 1 - 1 file changed, 1 deletion(-) diff --git a/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir b/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir index 27757e29c1e2f6..752e6b61b08348 100644 --- a/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir +++ b/mlir/test/Dialect/ArmSME/tile-allocation-spills-with-mixed-tile-types.mlir @@ -1,4 +1,3 @@ - // RUN: mlir-opt %s -test-arm-sme-tile-allocation -split-input-file | FileCheck %s // CHECK-LABEL: @always_spill_larger_or_equal_tile_type From 74a87548e5b62881108e6cd1fd63b45580fc3097 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Thu, 16 May 2024 15:27:59 +0100 Subject: [PATCH 043/576] [flang][MLIR][OpenMP] make reduction by-ref toggled per variable (#92244) Fixes #88935 Toggling reduction by-ref broke when multiple reduction clauses were used. Decisions made for the by-ref status for later clauses could then invalidate decisions for earlier clauses. For example, ``` reduction(+:scalar,scalar2) reduction(+:array) ``` The first clause would choose by value reduction and generate by-value reduction regions, but then after this the second clause would force by-ref to support the array argument. But by the time the second clause is processed, the first clause has already had the wrong kind of reduction regions generated. This is solved by toggling whether a variable should be reduced by reference per variable. In the above example, this allows only `array` to be reduced by ref. --- flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 12 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 6 - flang/lib/Lower/OpenMP/ReductionProcessor.cpp | 29 ++-- flang/lib/Lower/OpenMP/ReductionProcessor.h | 4 +- .../test/Fir/omp-reduction-embox-codegen.fir | 2 +- .../Lower/OpenMP/default-clause-byref.f90 | 2 +- .../delayed-privatization-reduction-byref.f90 | 2 +- .../OpenMP/parallel-reduction-add-byref.f90 | 6 +- .../parallel-reduction-allocatable-array.f90 | 2 +- .../OpenMP/parallel-reduction-array-lb.f90 | 2 +- .../Lower/OpenMP/parallel-reduction-array.f90 | 2 +- .../OpenMP/parallel-reduction-array2.f90 | 2 +- .../Lower/OpenMP/parallel-reduction-byref.f90 | 2 +- .../test/Lower/OpenMP/parallel-reduction3.f90 | 2 +- .../parallel-wsloop-reduction-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-add-byref.f90 | 14 +- .../wsloop-reduction-add-hlfir-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-allocatable.f90 | 2 +- .../wsloop-reduction-array-assumed-shape.f90 | 2 +- .../Lower/OpenMP/wsloop-reduction-array.f90 | 2 +- .../Lower/OpenMP/wsloop-reduction-array2.f90 | 2 +- .../OpenMP/wsloop-reduction-iand-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-ieor-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-ior-byref.f90 | 2 +- .../wsloop-reduction-logical-and-byref.f90 | 6 +- .../wsloop-reduction-logical-eqv-byref.f90 | 6 +- .../wsloop-reduction-logical-neqv-byref.f90 | 6 +- .../wsloop-reduction-logical-or-byref.f90 | 6 +- .../OpenMP/wsloop-reduction-max-2-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-max-byref.f90 | 6 +- .../wsloop-reduction-max-hlfir-byref.f90 | 2 +- .../OpenMP/wsloop-reduction-min-byref.f90 | 6 +- .../OpenMP/wsloop-reduction-mul-byref.f90 | 14 +- .../wsloop-reduction-multiple-clauses.f90 | 164 ++++++++++++++++++ .../llvm/Frontend/OpenMP/OMPIRBuilder.h | 2 +- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 19 +- .../Frontend/OpenMPIRBuilderTest.cpp | 12 +- .../Dialect/OpenMP/OpenMPClauseOperands.h | 2 +- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 59 +++---- .../Conversion/SCFToOpenMP/SCFToOpenMP.cpp | 7 + mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 126 +++++++++----- .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 43 +++-- mlir/test/Dialect/OpenMP/invalid.mlir | 19 ++ mlir/test/Dialect/OpenMP/ops.mlir | 38 ++++ .../openmp-parallel-reduction-cleanup.mlir | 2 +- .../Target/LLVMIR/openmp-reduction-byref.mlir | 2 +- .../LLVMIR/openmp-reduction-init-arg.mlir | 2 +- .../openmp-wsloop-reduction-cleanup.mlir | 2 +- 48 files changed, 464 insertions(+), 196 deletions(-) create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 40d66460a69848..875599098b3dcb 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -917,20 +917,18 @@ bool ClauseProcessor::processReduction( llvm::SmallVectorImpl *outReductionSyms) const { return findRepeatableClause( [&](const omp::clause::Reduction &clause, const parser::CharBlock &) { - // Use local lists of reductions to prevent variables from other - // already-processed reduction clauses from impacting this reduction. - // For example, the whole `reductionVars` array is queried to decide - // whether to do the reduction byref. llvm::SmallVector reductionVars; + llvm::SmallVector reduceVarByRef; llvm::SmallVector reductionDeclSymbols; llvm::SmallVector reductionSyms; ReductionProcessor rp; - rp.addDeclareReduction(currentLocation, converter, clause, - reductionVars, reductionDeclSymbols, - outReductionSyms ? &reductionSyms : nullptr); + rp.addDeclareReduction( + currentLocation, converter, clause, reductionVars, reduceVarByRef, + reductionDeclSymbols, outReductionSyms ? &reductionSyms : nullptr); // Copy local lists into the output. llvm::copy(reductionVars, std::back_inserter(result.reductionVars)); + llvm::copy(reduceVarByRef, std::back_inserter(result.reduceVarByRef)); llvm::copy(reductionDeclSymbols, std::back_inserter(result.reductionDeclSymbols)); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index af27c59eb9937c..4ae1fe6d99020e 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -984,8 +984,6 @@ static void genParallelClauses( if (processReduction) { cp.processReduction(loc, clauseOps, &reductionTypes, &reductionSyms); - if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) - clauseOps.reductionByRefAttr = converter.getFirOpBuilder().getUnitAttr(); } } @@ -1173,7 +1171,6 @@ static void genWsloopClauses( mlir::Location loc, mlir::omp::WsloopClauseOps &clauseOps, llvm::SmallVectorImpl &reductionTypes, llvm::SmallVectorImpl &reductionSyms) { - fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); ClauseProcessor cp(converter, semaCtx, clauses); cp.processNowait(clauseOps); cp.processOrdered(clauseOps); @@ -1181,9 +1178,6 @@ static void genWsloopClauses( cp.processSchedule(stmtCtx, clauseOps); // TODO Support delayed privatization. - if (ReductionProcessor::doReductionByRef(clauseOps.reductionVars)) - clauseOps.reductionByRefAttr = firOpBuilder.getUnitAttr(); - cp.processTODO( loc, llvm::omp::Directive::OMPD_do); } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index be6dcd6f5569a1..1a63e316ef0684 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -657,25 +657,17 @@ mlir::omp::DeclareReductionOp ReductionProcessor::createDeclareReduction( return decl; } -// TODO: By-ref vs by-val reductions are currently toggled for the whole -// operation (possibly effecting multiple reduction variables). -// This could cause a problem with openmp target reductions because -// by-ref trivial types may not be supported. -bool ReductionProcessor::doReductionByRef( - const llvm::SmallVectorImpl &reductionVars) { - if (reductionVars.empty()) - return false; +static bool doReductionByRef(mlir::Value reductionVar) { if (forceByrefReduction) return true; - for (mlir::Value reductionVar : reductionVars) { - if (auto declare = - mlir::dyn_cast(reductionVar.getDefiningOp())) - reductionVar = declare.getMemref(); + if (auto declare = + mlir::dyn_cast(reductionVar.getDefiningOp())) + reductionVar = declare.getMemref(); + + if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) + return true; - if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) - return true; - } return false; } @@ -683,6 +675,7 @@ void ReductionProcessor::addDeclareReduction( mlir::Location currentLocation, lower::AbstractConverter &converter, const omp::clause::Reduction &reduction, llvm::SmallVectorImpl &reductionVars, + llvm::SmallVectorImpl &reduceVarByRef, llvm::SmallVectorImpl &reductionDeclSymbols, llvm::SmallVectorImpl *reductionSymbols) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -761,8 +754,8 @@ void ReductionProcessor::addDeclareReduction( "reduction input var is a reference"); reductionVars.push_back(symVal); + reduceVarByRef.push_back(doReductionByRef(symVal)); } - const bool isByRef = doReductionByRef(reductionVars); if (const auto &redDefinedOp = std::get_if(&redOperator.u)) { @@ -784,7 +777,7 @@ void ReductionProcessor::addDeclareReduction( break; } - for (mlir::Value symVal : reductionVars) { + for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) { auto redType = mlir::cast(symVal.getType()); const auto &kindMap = firOpBuilder.getKindMap(); if (mlir::isa(redType.getEleTy())) @@ -808,7 +801,7 @@ void ReductionProcessor::addDeclareReduction( *reductionIntrinsic)) { ReductionProcessor::ReductionIdentifier redId = ReductionProcessor::getReductionType(*reductionIntrinsic); - for (mlir::Value symVal : reductionVars) { + for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) { auto redType = mlir::cast(symVal.getType()); if (!redType.getEleTy().isIntOrIndexOrFloat()) TODO(currentLocation, diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.h b/flang/lib/Lower/OpenMP/ReductionProcessor.h index 2852abad003690..0ed5782e5da1b7 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.h +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.h @@ -73,9 +73,6 @@ class ReductionProcessor { static const semantics::SourceName getRealName(const omp::clause::ProcedureDesignator &pd); - static bool - doReductionByRef(const llvm::SmallVectorImpl &reductionVars); - static std::string getReductionName(llvm::StringRef name, const fir::KindMapping &kindMap, mlir::Type ty, bool isByRef); @@ -127,6 +124,7 @@ class ReductionProcessor { mlir::Location currentLocation, lower::AbstractConverter &converter, const omp::clause::Reduction &reduction, llvm::SmallVectorImpl &reductionVars, + llvm::SmallVectorImpl &reduceVarByRef, llvm::SmallVectorImpl &reductionDeclSymbols, llvm::SmallVectorImpl *reductionSymbols = nullptr); diff --git a/flang/test/Fir/omp-reduction-embox-codegen.fir b/flang/test/Fir/omp-reduction-embox-codegen.fir index 7602012ebc5c9f..1645e1a407ad41 100644 --- a/flang/test/Fir/omp-reduction-embox-codegen.fir +++ b/flang/test/Fir/omp-reduction-embox-codegen.fir @@ -25,7 +25,7 @@ omp.declare_reduction @test_reduction : !fir.ref> init { func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { %4 = fir.alloca !fir.box - omp.parallel byref reduction(@test_reduction %4 -> %arg0 : !fir.ref>) { + omp.parallel reduction(byref @test_reduction %4 -> %arg0 : !fir.ref>) { omp.terminator } return diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 index 7cc2bc2e0c710a..7893c4d7d57323 100644 --- a/flang/test/Lower/OpenMP/default-clause-byref.f90 +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -351,7 +351,7 @@ subroutine skipped_default_clause_checks() type(it)::iii !CHECK: omp.parallel { -!CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref) { +!CHECK: omp.wsloop reduction(byref @min_byref_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref) { !CHECK-NEXT: omp.loop_nest (%[[ARG:.*]]) {{.*}} { !CHECK: omp.yield !CHECK: } diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 index 49d1142ea4b6aa..72e91680a43104 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 @@ -26,5 +26,5 @@ subroutine red_and_delayed_private ! CHECK-LABEL: _QPred_and_delayed_private ! CHECK: omp.parallel -! CHECK-SAME: reduction(@[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref) +! CHECK-SAME: reduction(byref @[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref) ! CHECK-SAME: private(@[[PRIVATIZER_SYM]] %{{.*}} -> %arg1 : !fir.ref) { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 index 2a1d26407b27e9..7347d9324feac8 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 @@ -40,7 +40,7 @@ !CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFsimple_int_addEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[I_START:.*]] = arith.constant 0 : i32 !CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref -!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { +!CHECK: omp.parallel reduction(byref @[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { !CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref !CHECK: %[[I_INCR:.*]] = arith.constant 1 : i32 @@ -65,7 +65,7 @@ subroutine simple_int_add !CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFsimple_real_addEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 !CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref -!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { +!CHECK: omp.parallel reduction(byref @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { !CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref !CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 @@ -94,7 +94,7 @@ subroutine simple_real_add !CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref !CHECK: %[[I_START:.*]] = arith.constant 0 : i32 !CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref -!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref, @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref) { +!CHECK: omp.parallel reduction(byref @[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref, byref @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref) { !CHECK: %[[IP_DECL:.+]]:2 = hlfir.declare %[[IPRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[RP_DECL:.+]]:2 = hlfir.declare %[[RPRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 diff --git a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 index 28216ef91c3a32..f6d3b0b73f7384 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-allocatable-array.f90 @@ -95,7 +95,7 @@ program reduce ! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_Uxi32 %[[VAL_3]]#0 -> %[[VAL_17:.*]] : !fir.ref>>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_heap_Uxi32 %[[VAL_3]]#0 -> %[[VAL_17:.*]] : !fir.ref>>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_18:.*]]) : i32 = (%[[VAL_14]]) to (%[[VAL_15]]) inclusive step (%[[VAL_16]]) { ! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_17]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) ! CHECK: fir.store %[[VAL_18]] to %[[VAL_13]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 index 8202e6d897157d..b44fe4c1f4cc28 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90 @@ -77,7 +77,7 @@ program reduce ! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFEi"} : (!fir.ref>, !fir.shapeshift<2>) -> (!fir.box>, !fir.ref>) ! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_6]]#0 to %[[VAL_7]] : !fir.ref>> -! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3x2xi32 %[[VAL_7]] -> %[[VAL_8:.*]] : !fir.ref>>) { +! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3x2xi32 %[[VAL_7]] -> %[[VAL_8:.*]] : !fir.ref>>) { ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFEi"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: %[[VAL_10:.*]] = arith.constant 3 : i32 ! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref>> diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 index 34f4ee0a9eb3a5..60b21c9b1ebbe0 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 @@ -70,7 +70,7 @@ program reduce ! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref>> -! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref>>) { +! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref>>) { ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref>> diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 index aa14092554eda2..5d4c86d1d76e84 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 @@ -69,7 +69,7 @@ program reduce ! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref>> -! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref>>) { +! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref>>) { ! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref>> ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : index diff --git a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 index fdcdf0c0b8d955..5685e2c584ace7 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 @@ -21,7 +21,7 @@ !CHECK: %[[RED_ACCUM_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[RED_ACCUM_REF]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32 !CHECK: hlfir.assign %[[C0]] to %[[RED_ACCUM_DECL]]#0 : i32, !fir.ref -!CHECK: omp.parallel byref reduction(@[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref) { +!CHECK: omp.parallel reduction(byref @[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref) { !CHECK: %[[PRIVATE_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[PRIVATE_RED]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[C1:[_a-z0-9]+]] = arith.constant 1 : i32 !CHECK: hlfir.assign %[[C1]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref diff --git a/flang/test/Lower/OpenMP/parallel-reduction3.f90 b/flang/test/Lower/OpenMP/parallel-reduction3.f90 index 17d805c0d142b4..47b743a558b498 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction3.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction3.f90 @@ -74,7 +74,7 @@ ! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_19:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_12]]#0 to %[[VAL_19]] : !fir.ref>> -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_Uxi32 %[[VAL_19]] -> %[[VAL_20:.*]] : !fir.ref>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_Uxi32 %[[VAL_19]] -> %[[VAL_20:.*]] : !fir.ref>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_21:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { ! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFsEc"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: fir.store %[[VAL_21]] to %[[VAL_15]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 index 66c80c31917ba8..32caac39778dee 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 @@ -4,7 +4,7 @@ ! RUN: flang-new -fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s ! CHECK: omp.parallel { -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 subroutine sb integer :: x x = 0 diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 index c9d03435d9e18c..cc4d055b3ea1f6 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 @@ -82,7 +82,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -125,7 +125,7 @@ subroutine simple_int_reduction ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -169,7 +169,7 @@ subroutine simple_real_reduction ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -211,7 +211,7 @@ subroutine simple_int_reduction_switch_order ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -262,7 +262,7 @@ subroutine simple_real_reduction_switch_order ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @add_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, byref @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, byref @add_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) @@ -326,7 +326,7 @@ subroutine multiple_int_reductions_same_type ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @add_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @add_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, byref @add_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, byref @add_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) @@ -397,7 +397,7 @@ subroutine multiple_real_reductions_same_type ! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, @add_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, @add_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, @add_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, byref @add_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, byref @add_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, byref @add_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { ! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 index 6a09fece80ae9d..ec9abba41db0e6 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 @@ -31,7 +31,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 index 8310aeb23df088..ccf186cf9908df 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90 @@ -80,7 +80,7 @@ program reduce ! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_12:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_i32 %[[VAL_5]]#0 -> %[[VAL_14:.*]] : !fir.ref>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_heap_i32 %[[VAL_5]]#0 -> %[[VAL_14:.*]] : !fir.ref>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_15:.*]]) : i32 = (%[[VAL_11]]) to (%[[VAL_12]]) inclusive step (%[[VAL_13]]) { ! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_14]] {fortran_attrs = {{.*}}, uniq_name = "_QFEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: fir.store %[[VAL_15]] to %[[VAL_10]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 index 197800486c39e8..be1e3ec0cb9d92 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 @@ -84,7 +84,7 @@ subroutine reduce(r) ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_3]]#1 to %[[VAL_9]] : !fir.ref>> -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_Uxf64 %[[VAL_9]] -> %[[VAL_10:.*]] : !fir.ref>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_Uxf64 %[[VAL_9]] -> %[[VAL_10:.*]] : !fir.ref>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {fortran_attrs = {{.*}}, uniq_name = "_QFFreduceEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_5]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 index 7aecf870cf800a..add422f5d95640 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 @@ -79,7 +79,7 @@ program reduce ! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#0(%[[VAL_4]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> ! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref>> -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { ! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 index d1d8a2c599444a..e988567fc3371e 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 @@ -79,7 +79,7 @@ program reduce ! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#0(%[[VAL_4]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> ! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box> ! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref>> -! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref>>) { +! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref>>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { ! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 index df07a906533156..bcc71415f1dd12 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 @@ -35,7 +35,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@iand_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @iand_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 index 50cec61b602bc6..6825800b2cd87c 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 @@ -28,7 +28,7 @@ !CHECK: omp.parallel !CHECK: %[[I_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} !CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFreduction_ieorEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) -!CHECK: omp.wsloop byref reduction(@ieor_byref_i32 %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) +!CHECK: omp.wsloop reduction(byref @ieor_byref_i32 %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) !CHECK-NEXT: omp.loop_nest !CHECK: %[[PRV_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: fir.store %{{.*}} to %[[I_DECL]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 index d847bba89782d2..00f4552917aa37 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 @@ -33,7 +33,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@ior_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @ior_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 index 69789e4c751e09..331232a08e624d 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 @@ -42,7 +42,7 @@ ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -92,7 +92,7 @@ end subroutine simple_reduction ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -151,7 +151,7 @@ subroutine simple_reduction_switch_order(y) ! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, byref @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, byref @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { ! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 index 54175994ecd8a8..d1cb7b05f0af5a 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 @@ -42,7 +42,7 @@ ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -91,7 +91,7 @@ subroutine simple_reduction(y) ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -150,7 +150,7 @@ subroutine simple_reduction_switch_order(y) ! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, byref @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, byref @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { ! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 index c0a82476c7b189..64c056c9c6bd23 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 @@ -42,7 +42,7 @@ ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -92,7 +92,7 @@ subroutine simple_reduction(y) ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -153,7 +153,7 @@ subroutine simple_reduction_switch_order(y) ! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, byref @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, byref @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { ! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 index 0af9e0d5c9fd2c..1e5f91de801c49 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 @@ -41,7 +41,7 @@ ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -90,7 +90,7 @@ subroutine simple_reduction(y) ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { ! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref @@ -149,7 +149,7 @@ subroutine simple_reduction_switch_order(y) ! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { +! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, byref @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, byref @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { ! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 index 5358806cdcdec2..28c70899e6ccc6 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s -! CHECK: omp.wsloop byref reduction(@max_byref_i32 +! CHECK: omp.wsloop reduction(byref @max_byref_i32 ! CHECK: arith.cmpi sgt ! CHECK: arith.select diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 index 11d039f9226ccf..399afa1065560e 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -46,7 +46,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref @@ -77,7 +77,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref @@ -98,7 +98,7 @@ ! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { ! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 index a352cb195c25dc..2f3aee9f1300a7 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 @@ -33,7 +33,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 index d168b2a89295f7..ccab017a1b0c63 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -46,7 +46,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @min_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref @@ -77,7 +77,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref @@ -100,7 +100,7 @@ ! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { ! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 index 7c538cdd470f8b..762d9dd4f254f4 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 @@ -85,7 +85,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -123,7 +123,7 @@ subroutine simple_int_reduction ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -162,7 +162,7 @@ subroutine simple_real_reduction ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -200,7 +200,7 @@ subroutine simple_int_reduction_switch_order ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref @@ -247,7 +247,7 @@ subroutine simple_real_reduction_switch_order ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @multiply_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, byref @multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, byref @multiply_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) @@ -307,7 +307,7 @@ subroutine multiple_int_reductions_same_type ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @multiply_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @multiply_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, byref @multiply_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, byref @multiply_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) @@ -374,7 +374,7 @@ subroutine multiple_real_reductions_same_type ! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_17:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, @multiply_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, @multiply_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, @multiply_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) { +! CHECK: omp.wsloop reduction(byref @multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, byref @multiply_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, byref @multiply_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, byref @multiply_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) { ! CHECK-NEXT: omp.loop_nest (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { ! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 new file mode 100644 index 00000000000000..ed462b58bbf882 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-multiple-clauses.f90 @@ -0,0 +1,164 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +program main + implicit none + + integer:: i + REAL(8) :: scalar + REAL(8) :: array(3,3) + + scalar = 0 + array = 0 + + !$omp parallel do reduction(+:scalar) reduction(+:array) + do i=1,10 + scalar = i + array(1, 1) = i + 1 + array(2, 2) = i + 2 + array(3, 3) = i + 3 + enddo + + print *,scalar + print *,array + +endprogram + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3x3xf64 : !fir.ref>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): +! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box> +! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_4]], %[[VAL_5]] : (index, index) -> !fir.shape<2> +! CHECK: %[[VAL_7:.*]] = fir.allocmem !fir.array<3x3xf64> {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_6]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<2>) -> (!fir.heap>, !fir.heap>) +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_10]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_13:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_12]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_14:.*]] = fir.shape_shift %[[VAL_11]]#0, %[[VAL_11]]#1, %[[VAL_13]]#0, %[[VAL_13]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_9]]#0(%[[VAL_14]]) : (!fir.heap>, !fir.shapeshift<2>) -> !fir.box> +! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_15]] : f64, !fir.box> +! CHECK: fir.store %[[VAL_15]] to %[[VAL_3]] : !fir.ref>> +! CHECK: omp.yield(%[[VAL_3]] : !fir.ref>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>, %[[VAL_1:.*]]: !fir.ref>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_7:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_6]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_8:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1, %[[VAL_7]]#0, %[[VAL_7]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_10:.*]] = %[[VAL_9]] to %[[VAL_7]]#1 step %[[VAL_9]] unordered { +! CHECK: fir.do_loop %[[VAL_11:.*]] = %[[VAL_9]] to %[[VAL_5]]#1 step %[[VAL_9]] unordered { +! CHECK: %[[VAL_12:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_8]]) %[[VAL_11]], %[[VAL_10]] : (!fir.box>, !fir.shapeshift<2>, index, index) -> !fir.ref +! CHECK: %[[VAL_13:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_8]]) %[[VAL_11]], %[[VAL_10]] : (!fir.box>, !fir.shapeshift<2>, index, index) -> !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]] : !fir.ref +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_13]] : !fir.ref +! CHECK: %[[VAL_16:.*]] = arith.addf %[[VAL_14]], %[[VAL_15]] fastmath : f64 +! CHECK: fir.store %[[VAL_16]] to %[[VAL_12]] : !fir.ref +! CHECK: } +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref>>) + +! CHECK-LABEL: } cleanup { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): +! CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref>> +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box>) -> !fir.ref> +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref>) -> i64 +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i64 +! CHECK: %[[VAL_5:.*]] = arith.cmpi ne, %[[VAL_3]], %[[VAL_4]] : i64 +! CHECK: fir.if %[[VAL_5]] { +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_2]] : (!fir.ref>) -> !fir.heap> +! CHECK: fir.freemem %[[VAL_6]] : !fir.heap> +! CHECK: } +! CHECK: omp.yield +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_f64 : f64 init { +! CHECK: ^bb0(%[[VAL_0:.*]]: f64): +! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: omp.yield(%[[VAL_1]] : f64) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: f64, %[[VAL_1:.*]]: f64): +! CHECK: %[[VAL_2:.*]] = arith.addf %[[VAL_0]], %[[VAL_1]] fastmath : f64 +! CHECK: omp.yield(%[[VAL_2]] : f64) +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEarray) : !fir.ref> +! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_2:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "_QFEarray"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = fir.alloca f64 {bindc_name = "scalar", uniq_name = "_QFEscalar"} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFEscalar"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_8]]#0 : f64, !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_4]]#0 : f64, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_16:.*]] = fir.embox %[[VAL_4]]#0(%[[VAL_3]]) : (!fir.ref>, !fir.shape<2>) -> !fir.box> +! CHECK: %[[VAL_17:.*]] = fir.alloca !fir.box> +! CHECK: fir.store %[[VAL_16]] to %[[VAL_17]] : !fir.ref>> +! CHECK: omp.wsloop reduction(@add_reduction_f64 %[[VAL_8]]#0 -> %[[VAL_18:.*]] : !fir.ref, byref @add_reduction_byref_box_3x3xf64 %[[VAL_17]] -> %[[VAL_19:.*]] : !fir.ref>>) { +! CHECK: omp.loop_nest (%[[VAL_20:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFEscalar"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFEarray"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: fir.store %[[VAL_20]] to %[[VAL_12]]#1 : !fir.ref +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (i32) -> f64 +! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_21]]#0 : f64, !fir.ref +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_26:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_27:.*]] = arith.addi %[[VAL_25]], %[[VAL_26]] : i32 +! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_27]] : (i32) -> f64 +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref>> +! CHECK: %[[VAL_30:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_31:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_29]] (%[[VAL_30]], %[[VAL_31]]) : (!fir.box>, index, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_32]] : f64, !fir.ref +! CHECK: %[[VAL_33:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_34:.*]] = arith.constant 2 : i32 +! CHECK: %[[VAL_35:.*]] = arith.addi %[[VAL_33]], %[[VAL_34]] : i32 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_35]] : (i32) -> f64 +! CHECK: %[[VAL_37:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref>> +! CHECK: %[[VAL_38:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_39:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_37]] (%[[VAL_38]], %[[VAL_39]]) : (!fir.box>, index, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_36]] to %[[VAL_40]] : f64, !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_42:.*]] = arith.constant 3 : i32 +! CHECK: %[[VAL_43:.*]] = arith.addi %[[VAL_41]], %[[VAL_42]] : i32 +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (i32) -> f64 +! CHECK: %[[VAL_45:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref>> +! CHECK: %[[VAL_46:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_47:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_48:.*]] = hlfir.designate %[[VAL_45]] (%[[VAL_46]], %[[VAL_47]]) : (!fir.box>, index, index) -> !fir.ref +! CHECK: hlfir.assign %[[VAL_44]] to %[[VAL_48]] : f64, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: omp.terminator +! CHECK: } + +! CHECK-LABEL: fir.global internal @_QFEarray : !fir.array<3x3xf64> { +! CHECK: %[[VAL_0:.*]] = fir.zero_bits !fir.array<3x3xf64> +! CHECK: fir.has_value %[[VAL_0]] : !fir.array<3x3xf64> +! CHECK: } +! CHECK: func.func private @_FortranAioBeginExternalListOutput(i32, !fir.ref, i32) -> !fir.ref attributes {fir.io, fir.runtime} diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index c9ee0c25194c23..e54ec4f2b1d72d 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -1344,7 +1344,7 @@ class OpenMPIRBuilder { InsertPointTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef ReductionInfos, - bool IsNoWait = false, bool IsByRef = false); + ArrayRef IsByRef, bool IsNoWait = false); ///} diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index 391a4947877a6c..cb4de9c8876dcc 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -2121,9 +2121,12 @@ Function *getFreshReductionFunc(Module &M) { ".omp.reduction.func", &M); } -OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( - const LocationDescription &Loc, InsertPointTy AllocaIP, - ArrayRef ReductionInfos, bool IsNoWait, bool IsByRef) { +OpenMPIRBuilder::InsertPointTy +OpenMPIRBuilder::createReductions(const LocationDescription &Loc, + InsertPointTy AllocaIP, + ArrayRef ReductionInfos, + ArrayRef IsByRef, bool IsNoWait) { + assert(ReductionInfos.size() == IsByRef.size()); for (const ReductionInfo &RI : ReductionInfos) { (void)RI; assert(RI.Variable && "expected non-null variable"); @@ -2213,7 +2216,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( // We have one less load for by-ref case because that load is now inside of // the reduction region Value *RedValue = nullptr; - if (!IsByRef) { + if (!IsByRef[En.index()]) { RedValue = Builder.CreateLoad(ValueType, RI.Variable, "red.value." + Twine(En.index())); } @@ -2221,7 +2224,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( Builder.CreateLoad(ValueType, RI.PrivateVariable, "red.private.value." + Twine(En.index())); Value *Reduced; - if (IsByRef) { + if (IsByRef[En.index()]) { Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), RI.Variable, PrivateRedValue, Reduced)); } else { @@ -2231,7 +2234,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( if (!Builder.GetInsertBlock()) return InsertPointTy(); // for by-ref case, the load is inside of the reduction region - if (!IsByRef) + if (!IsByRef[En.index()]) Builder.CreateStore(Reduced, RI.Variable); } Function *EndReduceFunc = getOrCreateRuntimeFunctionPtr( @@ -2244,7 +2247,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( // function. There are no loads/stores here because they will be happening // inside the atomic elementwise reduction. Builder.SetInsertPoint(AtomicRedBlock); - if (CanGenerateAtomic && !IsByRef) { + if (CanGenerateAtomic && llvm::none_of(IsByRef, [](bool P) { return P; })) { for (const ReductionInfo &RI : ReductionInfos) { Builder.restoreIP(RI.AtomicReductionGen(Builder.saveIP(), RI.ElementType, RI.Variable, RI.PrivateVariable)); @@ -2283,7 +2286,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( if (!Builder.GetInsertBlock()) return InsertPointTy(); // store is inside of the reduction region when using by-ref - if (!IsByRef) + if (!IsByRef[En.index()]) Builder.CreateStore(Reduced, LHSPtr); } Builder.CreateRetVoid(); diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp index 8344bca08404e4..3ed3034f489ce7 100644 --- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -4982,8 +4982,10 @@ TEST_F(OpenMPIRBuilderTest, CreateReductions) { OpenMPIRBuilder::ReductionInfo ReductionInfos[] = { {SumType, SumReduced, SumPrivatized, sumReduction, sumAtomicReduction}, {XorType, XorReduced, XorPrivatized, xorReduction, xorAtomicReduction}}; + bool ReduceVariableByRef[] = {false, false}; - OMPBuilder.createReductions(BodyIP, BodyAllocaIP, ReductionInfos); + OMPBuilder.createReductions(BodyIP, BodyAllocaIP, ReductionInfos, + ReduceVariableByRef); Builder.restoreIP(AfterIP); Builder.CreateRetVoid(); @@ -5230,12 +5232,16 @@ TEST_F(OpenMPIRBuilderTest, CreateTwoReductions) { /* NumThreads */ nullptr, OMP_PROC_BIND_default, /* IsCancellable */ false); + bool ReduceVariableByRef[] = {false}; + OMPBuilder.createReductions( FirstBodyIP, FirstBodyAllocaIP, - {{SumType, SumReduced, SumPrivatized, sumReduction, sumAtomicReduction}}); + {{SumType, SumReduced, SumPrivatized, sumReduction, sumAtomicReduction}}, + ReduceVariableByRef); OMPBuilder.createReductions( SecondBodyIP, SecondBodyAllocaIP, - {{XorType, XorReduced, XorPrivatized, xorReduction, xorAtomicReduction}}); + {{XorType, XorReduced, XorPrivatized, xorReduction, xorAtomicReduction}}, + ReduceVariableByRef); Builder.restoreIP(AfterIP); Builder.CreateRetVoid(); diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h index 244cee1dd635b6..de7959db489e9d 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauseOperands.h @@ -177,8 +177,8 @@ struct ProcBindClauseOps { struct ReductionClauseOps { llvm::SmallVector reductionVars; + llvm::SmallVector reduceVarByRef; llvm::SmallVector reductionDeclSymbols; - UnitAttr reductionByRefAttr; }; struct SafelenClauseOps { diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index f248be1639fe94..29c287cad06e9b 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -272,22 +272,21 @@ def ParallelOp : OpenMP_Op<"parallel", [ that specify the memory allocator to be used to obtain storage for private values. Reductions can be performed in a parallel construct by specifying reduction - accumulator variables in `reduction_vars` and symbols referring to reduction - declarations in the `reductions` attribute. Each reduction is identified - by the accumulator it uses and accumulators must not be repeated in the same - reduction. The `omp.reduction` operation accepts the accumulator and a - partial value which is considered to be produced by the thread for the - given reduction. If multiple values are produced for the same accumulator, - i.e. there are multiple `omp.reduction`s, the last value is taken. The - reduction declaration specifies how to combine the values from each thread - into the final value, which is available in the accumulator after all the - threads complete. + accumulator variables in `reduction_vars`, symbols referring to reduction + declarations in the `reductions` attribute, and whether the reduction + variable should be passed into the reduction region by value or by reference + in `reduction_vars_byref`. Each reduction is identified by the accumulator + it uses and accumulators must not be repeated in the same reduction. The + `omp.reduction` operation accepts the accumulator and a partial value which + is considered to be produced by the thread for the given reduction. If + multiple values are produced for the same accumulator, i.e. there are + multiple `omp.reduction`s, the last value is taken. The reduction + declaration specifies how to combine the values from each thread into the + final value, which is available in the accumulator after all the threads + complete. The optional $proc_bind_val attribute controls the thread affinity for the execution of the parallel region. - - The optional byref attribute controls whether reduction arguments are passed by - reference or by value. }]; let arguments = (ins Optional:$if_expr_var, @@ -295,11 +294,11 @@ def ParallelOp : OpenMP_Op<"parallel", [ Variadic:$allocate_vars, Variadic:$allocators_vars, Variadic:$reduction_vars, + OptionalAttr:$reduction_vars_byref, OptionalAttr:$reductions, OptionalAttr:$proc_bind_val, Variadic:$private_vars, - OptionalAttr:$privatizers, - UnitAttr:$byref); + OptionalAttr:$privatizers); let regions = (region AnyRegion:$region); @@ -321,10 +320,9 @@ def ParallelOp : OpenMP_Op<"parallel", [ $allocators_vars, type($allocators_vars) ) `)` | `proc_bind` `(` custom($proc_bind_val) `)` - | `byref` $byref ) custom($region, $reduction_vars, type($reduction_vars), - $reductions, $private_vars, type($private_vars), - $privatizers) attr-dict + $reduction_vars_byref, $reductions, $private_vars, + type($private_vars), $privatizers) attr-dict }]; let hasVerifier = 1; } @@ -649,14 +647,15 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, elements. Reductions can be performed in a worksharing-loop by specifying reduction - accumulator variables in `reduction_vars` and symbols referring to reduction - declarations in the `reductions` attribute. Each reduction is identified - by the accumulator it uses and accumulators must not be repeated in the same - reduction. A private variable corresponding to the accumulator is used in - place of the accumulator inside the body of the worksharing-loop. The - reduction declaration specifies how to combine the values from each - iteration into the final value, which is available in the accumulator after - the loop completes. + accumulator variables in `reduction_vars`, symbols referring to reduction + declarations in the `reductions` attribute, and whether the reduction + variable should be passed by reference or value in `reduction_vars_byref`. + Each reduction is identified by the accumulator it uses and accumulators + must not be repeated in the same reduction. A private variable corresponding + to the accumulator is used in place of the accumulator inside the body of + the worksharing-loop. The reduction declaration specifies how to combine the + values from each iteration into the final value, which is available in the + accumulator after the loop completes. The optional `schedule_val` attribute specifies the loop schedule for this loop, determining how the loop is distributed across the parallel threads. @@ -677,21 +676,18 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, The optional `order` attribute specifies which order the iterations of the associate loops are executed in. Currently the only option for this attribute is "concurrent". - - The optional `byref` attribute indicates that reduction arguments should be - passed by reference. }]; let arguments = (ins Variadic:$linear_vars, Variadic:$linear_step_vars, Variadic:$reduction_vars, + OptionalAttr:$reduction_vars_byref, OptionalAttr:$reductions, OptionalAttr:$schedule_val, Optional:$schedule_chunk_var, OptionalAttr:$schedule_modifier, UnitAttr:$simd_modifier, UnitAttr:$nowait, - UnitAttr:$byref, ConfinedAttr, [IntMinValue<0>]>:$ordered_val, OptionalAttr:$order_val); @@ -716,11 +712,10 @@ def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, $schedule_val, $schedule_modifier, $simd_modifier, $schedule_chunk_var, type($schedule_chunk_var)) `)` |`nowait` $nowait - |`byref` $byref |`ordered` `(` $ordered_val `)` |`order` `(` custom($order_val) `)` ) custom($region, $reduction_vars, type($reduction_vars), - $reductions) attr-dict + $reduction_vars_byref, $reductions) attr-dict }]; let hasVerifier = 1; } diff --git a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp index d6f85451ee5d30..60c62131752f61 100644 --- a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp +++ b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp @@ -449,6 +449,7 @@ struct ParallelOpLowering : public OpRewritePattern { /* allocate_vars = */ llvm::SmallVector{}, /* allocators_vars = */ llvm::SmallVector{}, /* reduction_vars = */ llvm::SmallVector{}, + /* reduction_vars_isbyref = */ DenseBoolArrayAttr{}, /* reductions = */ ArrayAttr{}, /* proc_bind_val = */ omp::ClauseProcBindKindAttr{}, /* private_vars = */ ValueRange(), @@ -467,6 +468,12 @@ struct ParallelOpLowering : public OpRewritePattern { wsloopOp.setReductionsAttr( ArrayAttr::get(rewriter.getContext(), reductionDeclSymbols)); wsloopOp.getReductionVarsMutable().append(reductionVariables); + llvm::SmallVector byRefVec; + // false because these reductions always reduce scalars and so do + // not need to pass by reference + byRefVec.resize(reductionVariables.size(), false); + wsloopOp.setReductionVarsByref( + DenseBoolArrayAttr::get(rewriter.getContext(), byRefVec)); } rewriter.create(loc); // omp.parallel terminator. diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 61073af2aa4d60..24a6d5b5d68499 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -15,11 +15,13 @@ #include "mlir/Dialect/LLVMIR/LLVMTypes.h" #include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h" #include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/OperationSupport.h" #include "mlir/Interfaces/FoldInterfaces.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" @@ -435,25 +437,30 @@ static void printScheduleClause(OpAsmPrinter &p, Operation *op, // Parser, printer and verifier for ReductionVarList //===----------------------------------------------------------------------===// -ParseResult parseClauseWithRegionArgs( +static ParseResult parseClauseWithRegionArgs( OpAsmParser &parser, Region ®ion, SmallVectorImpl &operands, - SmallVectorImpl &types, ArrayAttr &symbols, + SmallVectorImpl &types, DenseBoolArrayAttr &isByRef, + ArrayAttr &symbols, SmallVectorImpl ®ionPrivateArgs) { SmallVector reductionVec; + SmallVector isByRefVec; unsigned regionArgOffset = regionPrivateArgs.size(); if (failed( parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren, [&]() { + ParseResult optionalByref = parser.parseOptionalKeyword("byref"); if (parser.parseAttribute(reductionVec.emplace_back()) || parser.parseOperand(operands.emplace_back()) || parser.parseArrow() || parser.parseArgument(regionPrivateArgs.emplace_back()) || parser.parseColonType(types.emplace_back())) return failure(); + isByRefVec.push_back(optionalByref.succeeded()); return success(); }))) return failure(); + isByRef = DenseBoolArrayAttr::get(parser.getContext(), isByRefVec); auto *argsBegin = regionPrivateArgs.begin(); MutableArrayRef argsSubrange(argsBegin + regionArgOffset, @@ -469,15 +476,18 @@ ParseResult parseClauseWithRegionArgs( static void printClauseWithRegionArgs(OpAsmPrinter &p, Operation *op, ValueRange argsSubrange, StringRef clauseName, ValueRange operands, - TypeRange types, ArrayAttr symbols) { + TypeRange types, DenseBoolArrayAttr byRef, + ArrayAttr symbols) { if (!clauseName.empty()) p << clauseName << "("; - llvm::interleaveComma( - llvm::zip_equal(symbols, operands, argsSubrange, types), p, [&p](auto t) { - auto [sym, op, arg, type] = t; - p << sym << " " << op << " -> " << arg << " : " << type; - }); + llvm::interleaveComma(llvm::zip_equal(symbols, operands, argsSubrange, types, + byRef.asArrayRef()), + p, [&p](auto t) { + auto [sym, op, arg, type, isByRef] = t; + p << (isByRef ? "byref " : "") << sym << " " << op + << " -> " << arg << " : " << type; + }); if (!clauseName.empty()) p << ") "; @@ -486,7 +496,8 @@ static void printClauseWithRegionArgs(OpAsmPrinter &p, Operation *op, static ParseResult parseParallelRegion( OpAsmParser &parser, Region ®ion, SmallVectorImpl &reductionVarOperands, - SmallVectorImpl &reductionVarTypes, ArrayAttr &reductionSymbols, + SmallVectorImpl &reductionVarTypes, + DenseBoolArrayAttr &reductionByRef, ArrayAttr &reductionSymbols, llvm::SmallVectorImpl &privateVarOperands, llvm::SmallVectorImpl &privateVarsTypes, ArrayAttr &privatizerSymbols) { @@ -494,16 +505,23 @@ static ParseResult parseParallelRegion( if (succeeded(parser.parseOptionalKeyword("reduction"))) { if (failed(parseClauseWithRegionArgs(parser, region, reductionVarOperands, - reductionVarTypes, reductionSymbols, - regionPrivateArgs))) + reductionVarTypes, reductionByRef, + reductionSymbols, regionPrivateArgs))) return failure(); } if (succeeded(parser.parseOptionalKeyword("private"))) { + auto privateByRef = DenseBoolArrayAttr::get(parser.getContext(), {}); if (failed(parseClauseWithRegionArgs(parser, region, privateVarOperands, - privateVarsTypes, privatizerSymbols, - regionPrivateArgs))) + privateVarsTypes, privateByRef, + privatizerSymbols, regionPrivateArgs))) return failure(); + if (llvm::any_of(privateByRef.asArrayRef(), + [](bool byref) { return byref; })) { + parser.emitError(parser.getCurrentLocation(), + "private clause cannot have byref attributes"); + return failure(); + } } return parser.parseRegion(region, regionPrivateArgs); @@ -512,6 +530,7 @@ static ParseResult parseParallelRegion( static void printParallelRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange reductionVarOperands, TypeRange reductionVarTypes, + DenseBoolArrayAttr reductionVarIsByRef, ArrayAttr reductionSymbols, ValueRange privateVarOperands, TypeRange privateVarTypes, @@ -522,7 +541,7 @@ static void printParallelRegion(OpAsmPrinter &p, Operation *op, Region ®ion, argsBegin + reductionVarTypes.size()); printClauseWithRegionArgs(p, op, argsSubrange, "reduction", reductionVarOperands, reductionVarTypes, - reductionSymbols); + reductionVarIsByRef, reductionSymbols); } if (privatizerSymbols) { @@ -530,8 +549,13 @@ static void printParallelRegion(OpAsmPrinter &p, Operation *op, Region ®ion, MutableArrayRef argsSubrange(argsBegin + reductionVarOperands.size(), argsBegin + reductionVarOperands.size() + privateVarTypes.size()); + mlir::SmallVector isByRefVec; + isByRefVec.resize(privateVarTypes.size(), false); + DenseBoolArrayAttr isByRef = + DenseBoolArrayAttr::get(op->getContext(), isByRefVec); + printClauseWithRegionArgs(p, op, argsSubrange, "private", - privateVarOperands, privateVarTypes, + privateVarOperands, privateVarTypes, isByRef, privatizerSymbols); } @@ -575,14 +599,22 @@ static void printReductionVarList(OpAsmPrinter &p, Operation *op, } /// Verifies Reduction Clause -static LogicalResult verifyReductionVarList(Operation *op, - std::optional reductions, - OperandRange reductionVars) { +static LogicalResult +verifyReductionVarList(Operation *op, std::optional reductions, + OperandRange reductionVars, + std::optional> byRef = std::nullopt) { if (!reductionVars.empty()) { if (!reductions || reductions->size() != reductionVars.size()) return op->emitOpError() << "expected as many reduction symbol references " "as reduction variables"; + if (mlir::isa(op)) + assert(byRef); + else + assert(!byRef); // TODO: support byref reductions on other operations + if (byRef && byRef->size() != reductionVars.size()) + return op->emitError() << "expected as many reduction variable by " + "reference attributes as reduction variables"; } else { if (reductions) return op->emitOpError() << "unexpected reduction symbol references"; @@ -1163,9 +1195,14 @@ static void printPrivateList(OpAsmPrinter &p, Operation *op, MutableArrayRef argsSubrange(argsBegin + targetOp.getMapOperands().size(), argsBegin + targetOp.getMapOperands().size() + privateVarTypes.size()); + mlir::SmallVector isByRefVec; + isByRefVec.resize(privateVarTypes.size(), false); + DenseBoolArrayAttr isByRef = + DenseBoolArrayAttr::get(op->getContext(), isByRefVec); + printClauseWithRegionArgs( p, op, argsSubrange, /*clauseName=*/llvm::StringRef{}, privateVarOperands, - privateVarTypes, privatizerSymbols); + privateVarTypes, isByRef, privatizerSymbols); } static void printCaptureType(OpAsmPrinter &p, Operation *op, @@ -1402,21 +1439,24 @@ void ParallelOp::build(OpBuilder &builder, OperationState &state, ParallelOp::build( builder, state, /*if_expr_var=*/nullptr, /*num_threads_var=*/nullptr, /*allocate_vars=*/ValueRange(), /*allocators_vars=*/ValueRange(), - /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, + /*reduction_vars=*/ValueRange(), /*reduction_vars_byref=*/nullptr, + /*reductions=*/nullptr, /*proc_bind_val=*/nullptr, /*private_vars=*/ValueRange(), - /*privatizers=*/nullptr, /*byref=*/false); + /*privatizers=*/nullptr); state.addAttributes(attributes); } void ParallelOp::build(OpBuilder &builder, OperationState &state, const ParallelClauseOps &clauses) { MLIRContext *ctx = builder.getContext(); - ParallelOp::build( - builder, state, clauses.ifVar, clauses.numThreadsVar, - clauses.allocateVars, clauses.allocatorVars, clauses.reductionVars, - makeArrayAttr(ctx, clauses.reductionDeclSymbols), - clauses.procBindKindAttr, clauses.privateVars, - makeArrayAttr(ctx, clauses.privatizers), clauses.reductionByRefAttr); + + ParallelOp::build(builder, state, clauses.ifVar, clauses.numThreadsVar, + clauses.allocateVars, clauses.allocatorVars, + clauses.reductionVars, + DenseBoolArrayAttr::get(ctx, clauses.reduceVarByRef), + makeArrayAttr(ctx, clauses.reductionDeclSymbols), + clauses.procBindKindAttr, clauses.privateVars, + makeArrayAttr(ctx, clauses.privatizers)); } template @@ -1488,7 +1528,8 @@ LogicalResult ParallelOp::verify() { if (failed(verifyPrivateVarList(*this))) return failure(); - return verifyReductionVarList(*this, getReductions(), getReductionVars()); + return verifyReductionVarList(*this, getReductions(), getReductionVars(), + getReductionVarsByref()); } //===----------------------------------------------------------------------===// @@ -1609,13 +1650,13 @@ ParseResult parseWsloop(OpAsmParser &parser, Region ®ion, SmallVectorImpl &reductionOperands, SmallVectorImpl &reductionTypes, - ArrayAttr &reductionSymbols) { + DenseBoolArrayAttr &reductionByRef, ArrayAttr &reductionSymbols) { // Parse an optional reduction clause llvm::SmallVector privates; if (succeeded(parser.parseOptionalKeyword("reduction"))) { if (failed(parseClauseWithRegionArgs(parser, region, reductionOperands, - reductionTypes, reductionSymbols, - privates))) + reductionTypes, reductionByRef, + reductionSymbols, privates))) return failure(); } return parser.parseRegion(region, privates); @@ -1623,11 +1664,11 @@ parseWsloop(OpAsmParser &parser, Region ®ion, void printWsloop(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange reductionOperands, TypeRange reductionTypes, - ArrayAttr reductionSymbols) { + DenseBoolArrayAttr isByRef, ArrayAttr reductionSymbols) { if (reductionSymbols) { auto reductionArgs = region.front().getArguments(); printClauseWithRegionArgs(p, op, reductionArgs, "reduction", - reductionOperands, reductionTypes, + reductionOperands, reductionTypes, isByRef, reductionSymbols); } p.printRegion(region, /*printEntryBlockArgs=*/false); @@ -1637,9 +1678,10 @@ void WsloopOp::build(OpBuilder &builder, OperationState &state, ArrayRef attributes) { build(builder, state, /*linear_vars=*/ValueRange(), /*linear_step_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), + /*reduction_vars_byref=*/nullptr, /*reductions=*/nullptr, /*schedule_val=*/nullptr, /*schedule_chunk_var=*/nullptr, /*schedule_modifier=*/nullptr, - /*simd_modifier=*/false, /*nowait=*/false, /*byref=*/false, + /*simd_modifier=*/false, /*nowait=*/false, /*ordered_val=*/nullptr, /*order_val=*/nullptr); state.addAttributes(attributes); } @@ -1649,12 +1691,13 @@ void WsloopOp::build(OpBuilder &builder, OperationState &state, MLIRContext *ctx = builder.getContext(); // TODO: Store clauses in op: allocateVars, allocatorVars, privateVars, // privatizers. - WsloopOp::build( - builder, state, clauses.linearVars, clauses.linearStepVars, - clauses.reductionVars, makeArrayAttr(ctx, clauses.reductionDeclSymbols), - clauses.scheduleValAttr, clauses.scheduleChunkVar, - clauses.scheduleModAttr, clauses.scheduleSimdAttr, clauses.nowaitAttr, - clauses.reductionByRefAttr, clauses.orderedAttr, clauses.orderAttr); + WsloopOp::build(builder, state, clauses.linearVars, clauses.linearStepVars, + clauses.reductionVars, + DenseBoolArrayAttr::get(ctx, clauses.reduceVarByRef), + makeArrayAttr(ctx, clauses.reductionDeclSymbols), + clauses.scheduleValAttr, clauses.scheduleChunkVar, + clauses.scheduleModAttr, clauses.scheduleSimdAttr, + clauses.nowaitAttr, clauses.orderedAttr, clauses.orderAttr); } LogicalResult WsloopOp::verify() { @@ -1668,7 +1711,8 @@ LogicalResult WsloopOp::verify() { return emitError() << "only supported nested wrapper is 'omp.simd'"; } - return verifyReductionVarList(*this, getReductions(), getReductionVars()); + return verifyReductionVarList(*this, getReductions(), getReductionVars(), + getReductionVarsByref()); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index ed9fb44cf08ed5..8576be67f04a8e 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -22,6 +22,7 @@ #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "mlir/Transforms/RegionUtils.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/TypeSwitch.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -813,13 +814,16 @@ static void allocByValReductionVars( llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, SmallVectorImpl &reductionDecls, SmallVectorImpl &privateReductionVariables, - DenseMap &reductionVariableMap) { + DenseMap &reductionVariableMap, + llvm::ArrayRef isByRefs) { llvm::IRBuilderBase::InsertPointGuard guard(builder); builder.restoreIP(allocaIP); auto args = loop.getRegion().getArguments().take_back(loop.getNumReductionVars()); for (std::size_t i = 0; i < loop.getNumReductionVars(); ++i) { + if (isByRefs[i]) + continue; llvm::Value *var = builder.CreateAlloca( moduleTranslation.convertType(reductionDecls[i].getType())); moduleTranslation.mapValue(args[i], var); @@ -919,13 +923,21 @@ inlineOmpRegionCleanup(llvm::SmallVectorImpl &cleanupRegions, return success(); } +static ArrayRef getIsByRef(std::optional> attr) { + if (!attr) + return {}; + return *attr; +} + /// Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder. static LogicalResult convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { auto wsloopOp = cast(opInst); auto loopOp = cast(wsloopOp.getWrappedLoop()); - const bool isByRef = wsloopOp.getByref(); + + llvm::ArrayRef isByRef = getIsByRef(wsloopOp.getReductionVarsByref()); + assert(isByRef.size() == wsloopOp.getNumReductionVars()); // TODO: this should be in the op verifier instead. if (loopOp.getLowerBound().empty()) @@ -952,11 +964,9 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, SmallVector privateReductionVariables; DenseMap reductionVariableMap; - if (!isByRef) { - allocByValReductionVars(wsloopOp, builder, moduleTranslation, allocaIP, - reductionDecls, privateReductionVariables, - reductionVariableMap); - } + allocByValReductionVars(wsloopOp, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap, isByRef); // Before the loop, store the initial values of reductions into reduction // variables. Although this could be done after allocas, we don't want to mess @@ -974,7 +984,7 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, return failure(); assert(phis.size() == 1 && "expected one value to be yielded from the " "reduction neutral element declaration region"); - if (isByRef) { + if (isByRef[i]) { // Allocate reduction variable (which is a pointer to the real reduction // variable allocated in the inlined region) llvm::Value *var = builder.CreateAlloca( @@ -1108,7 +1118,7 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, builder.SetInsertPoint(tempTerminator); llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos, - wsloopOp.getNowait(), isByRef); + isByRef, wsloopOp.getNowait()); if (!contInsertPoint.getBlock()) return wsloopOp->emitOpError() << "failed to convert reductions"; auto nextInsertionPoint = @@ -1170,7 +1180,8 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; OmpParallelOpConversionManager raii(opInst); - const bool isByRef = opInst.getByref(); + ArrayRef isByRef = getIsByRef(opInst.getReductionVarsByref()); + assert(isByRef.size() == opInst.getNumReductionVars()); // TODO: support error propagation in OpenMPIRBuilder and use it instead of // relying on captured variables. @@ -1185,11 +1196,9 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { // Allocate reduction vars DenseMap reductionVariableMap; - if (!isByRef) { - allocByValReductionVars(opInst, builder, moduleTranslation, allocaIP, - reductionDecls, privateReductionVariables, - reductionVariableMap); - } + allocByValReductionVars(opInst, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap, isByRef); // Initialize reduction vars builder.restoreIP(allocaIP); @@ -1210,7 +1219,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, "reduction neutral element declaration region"); builder.restoreIP(allocaIP); - if (isByRef) { + if (isByRef[i]) { // Allocate reduction variable (which is a pointer to the real reduciton // variable allocated in the inlined region) llvm::Value *var = builder.CreateAlloca( @@ -1269,7 +1278,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, - reductionInfos, false, isByRef); + reductionInfos, isByRef, false); if (!contInsertPoint.getBlock()) { bodyGenStatus = opInst->emitOpError() << "failed to convert reductions"; return; diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index aee79264313eff..db016fe8e7ba8b 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -2272,3 +2272,22 @@ func.func @undefined_privatizer(%arg0: !llvm.ptr) { }) : (!llvm.ptr) -> () return } + +// ----- + +omp.private {type = private} @var1.privatizer : !llvm.ptr alloc { +^bb0(%arg0: !llvm.ptr): + omp.yield(%arg0 : !llvm.ptr) +} copy { +^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): + omp.yield(%arg0 : !llvm.ptr) +} + +func.func @byref_in_private(%arg0: index) { + // expected-error @below {{private clause cannot have byref attributes}} + omp.parallel private(byref @var1.privatizer %arg0 -> %arg2 : index) { + omp.terminator + } + + return +} diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index fc6d1c3165316f..0d5fd9383a92fc 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -869,6 +869,28 @@ func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) { return } +// CHECK-LABEL: func @wsloop_reduction_byref +func.func @wsloop_reduction_byref(%lb : index, %ub : index, %step : index) { + %c1 = arith.constant 1 : i32 + %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr + // CHECK: reduction(byref @add_f32 %{{.+}} -> %[[PRV:.+]] : !llvm.ptr) + omp.wsloop reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) { + omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) { + // CHECK: %[[CST:.+]] = arith.constant 2.0{{.*}} : f32 + %cst = arith.constant 2.0 : f32 + // CHECK: %[[LPRV:.+]] = llvm.load %[[PRV]] : !llvm.ptr -> f32 + %lprv = llvm.load %prv : !llvm.ptr -> f32 + // CHECK: %[[RES:.+]] = llvm.fadd %[[LPRV]], %[[CST]] : f32 + %res = llvm.fadd %lprv, %cst: f32 + // CHECK: llvm.store %[[RES]], %[[PRV]] : f32, !llvm.ptr + llvm.store %res, %prv : f32, !llvm.ptr + omp.yield + } + omp.terminator + } + return +} + // CHECK-LABEL: func @parallel_reduction func.func @parallel_reduction() { %c1 = arith.constant 1 : i32 @@ -885,6 +907,22 @@ func.func @parallel_reduction() { return } +// CHECK-LABEL: func @parallel_reduction_byref +func.func @parallel_reduction_byref() { + %c1 = arith.constant 1 : i32 + %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr + // CHECK: omp.parallel reduction(byref @add_f32 {{.+}} -> {{.+}} : !llvm.ptr) + omp.parallel reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) { + %1 = arith.constant 2.0 : f32 + %2 = llvm.load %prv : !llvm.ptr -> f32 + // CHECK: llvm.fadd %{{.*}}, %{{.*}} : f32 + %3 = llvm.fadd %1, %2 : f32 + llvm.store %3, %prv : f32, !llvm.ptr + omp.terminator + } + return +} + // CHECK: func @parallel_wsloop_reduction func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) { %c1 = arith.constant 1 : i32 diff --git a/mlir/test/Target/LLVMIR/openmp-parallel-reduction-cleanup.mlir b/mlir/test/Target/LLVMIR/openmp-parallel-reduction-cleanup.mlir index b7f71f438e56b0..84a487cb8c98f2 100644 --- a/mlir/test/Target/LLVMIR/openmp-parallel-reduction-cleanup.mlir +++ b/mlir/test/Target/LLVMIR/openmp-parallel-reduction-cleanup.mlir @@ -27,7 +27,7 @@ %0 = llvm.mlir.constant(-1 : i32) : i32 %1 = llvm.mlir.addressof @i : !llvm.ptr %2 = llvm.mlir.addressof @j : !llvm.ptr - omp.parallel byref reduction(@add_reduction_i_32 %1 -> %arg0 : !llvm.ptr, @add_reduction_i_32 %2 -> %arg1 : !llvm.ptr) { + omp.parallel reduction(byref @add_reduction_i_32 %1 -> %arg0 : !llvm.ptr, byref @add_reduction_i_32 %2 -> %arg1 : !llvm.ptr) { llvm.store %0, %arg0 : i32, !llvm.ptr llvm.store %0, %arg1 : i32, !llvm.ptr omp.terminator diff --git a/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir index e720969e82c112..ef1284547a88a7 100644 --- a/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir +++ b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir @@ -20,7 +20,7 @@ llvm.func @main() { %0 = llvm.mlir.constant(-1 : i32) : i32 %1 = llvm.mlir.addressof @i : !llvm.ptr - omp.parallel byref reduction(@add_reduction_i_32 %1 -> %arg0 : !llvm.ptr) { + omp.parallel reduction(byref @add_reduction_i_32 %1 -> %arg0 : !llvm.ptr) { llvm.store %0, %arg0 : i32, !llvm.ptr omp.terminator } diff --git a/mlir/test/Target/LLVMIR/openmp-reduction-init-arg.mlir b/mlir/test/Target/LLVMIR/openmp-reduction-init-arg.mlir index 5dd31c425566c1..f4b77cbf413d49 100644 --- a/mlir/test/Target/LLVMIR/openmp-reduction-init-arg.mlir +++ b/mlir/test/Target/LLVMIR/openmp-reduction-init-arg.mlir @@ -24,7 +24,7 @@ module { %87 = llvm.alloca %86 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> : (i64) -> !llvm.ptr // test multiple reduction variables to ensure they don't intefere with eachother // when inlining the reduction init region multiple times - omp.parallel byref reduction(@add_reduction_byref_box_Uxf64 %84 -> %arg3 : !llvm.ptr, @add_reduction_byref_box_Uxf64 %87 -> %arg4 : !llvm.ptr) { + omp.parallel reduction(byref @add_reduction_byref_box_Uxf64 %84 -> %arg3 : !llvm.ptr, byref @add_reduction_byref_box_Uxf64 %87 -> %arg4 : !llvm.ptr) { omp.terminator } llvm.return diff --git a/mlir/test/Target/LLVMIR/openmp-wsloop-reduction-cleanup.mlir b/mlir/test/Target/LLVMIR/openmp-wsloop-reduction-cleanup.mlir index 7a1a31830ce9bc..0b28294dc1cedc 100644 --- a/mlir/test/Target/LLVMIR/openmp-wsloop-reduction-cleanup.mlir +++ b/mlir/test/Target/LLVMIR/openmp-wsloop-reduction-cleanup.mlir @@ -30,7 +30,7 @@ %loop_ub = llvm.mlir.constant(9 : i32) : i32 %loop_lb = llvm.mlir.constant(0 : i32) : i32 %loop_step = llvm.mlir.constant(1 : i32) : i32 - omp.wsloop byref reduction(@add_reduction_i_32 %1 -> %arg0 : !llvm.ptr, @add_reduction_i_32 %2 -> %arg1 : !llvm.ptr) { + omp.wsloop reduction(byref @add_reduction_i_32 %1 -> %arg0 : !llvm.ptr, byref @add_reduction_i_32 %2 -> %arg1 : !llvm.ptr) { omp.loop_nest (%loop_cnt) : i32 = (%loop_lb) to (%loop_ub) inclusive step (%loop_step) { llvm.store %0, %arg0 : i32, !llvm.ptr llvm.store %0, %arg1 : i32, !llvm.ptr From d94582eea410a04f9f84e39a54276a8418aa2dbb Mon Sep 17 00:00:00 2001 From: NimishMishra <42909663+NimishMishra@users.noreply.github.com> Date: Thu, 16 May 2024 07:28:40 -0700 Subject: [PATCH 044/576] [flang][OpenMP] Add test for checking overloaded operator in atomic update (#88471) Atomic update expression does not allow overloaded user-defined operators. This PR adds a test case for the same; the semantic check is already existent. --- .../OpenMP/atomic-update-overloaded-ops.f90 | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 flang/test/Semantics/OpenMP/atomic-update-overloaded-ops.f90 diff --git a/flang/test/Semantics/OpenMP/atomic-update-overloaded-ops.f90 b/flang/test/Semantics/OpenMP/atomic-update-overloaded-ops.f90 new file mode 100644 index 00000000000000..21a9b87d263459 --- /dev/null +++ b/flang/test/Semantics/OpenMP/atomic-update-overloaded-ops.f90 @@ -0,0 +1,31 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp + +module new_operator + implicit none + + interface operator(.MYOPERATOR.) + module procedure myprocedure + end interface +contains + pure integer function myprocedure(param1, param2) + integer, intent(in) :: param1, param2 + myprocedure = param1 + param2 + end function +end module + +program sample + use new_operator + implicit none + integer :: x, y + + !$omp atomic update + x = x / y + + !$omp atomic update + !ERROR: Invalid or missing operator in atomic update statement + x = x .MYOPERATOR. y + + !$omp atomic + !ERROR: Invalid or missing operator in atomic update statement + x = x .MYOPERATOR. y +end program From f579dcf816b5626724e9eae5feea594008b5c863 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 18:34:22 +0400 Subject: [PATCH 045/576] [lldb] Fixed an invalid error message in the DAP disconnect response (#92345) The `disconnect` response contains the `error` message with invalid characters (a junk data). To reproduce this issue it is enough to run the `TestDAP_commands` test on Windows host and Linux target. The test will fail to run ELF file on Windows and dap_server will be disconnected unexpectedly. Note dap_server hangs if read_packet() cannot decode JSON with invalid characters. read_packet() must return None in this case instead of an exception. But dap_server does not require any fix after this patch. --- lldb/tools/lldb-dap/lldb-dap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 96da458be21d11..170fa88f1e8b84 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -977,7 +977,7 @@ void request_disconnect(const llvm::json::Object &request) { g_dap.debugger.SetAsync(false); lldb::SBError error = terminateDebuggee ? process.Kill() : process.Detach(); if (!error.Success()) - response.try_emplace("error", error.GetCString()); + EmplaceSafeString(response, "error", error.GetCString()); g_dap.debugger.SetAsync(true); break; } From d665d51c9296fc0b57945bb67e06040e26cd03c5 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 18:34:58 +0400 Subject: [PATCH 046/576] [lldb] Fixed the DAP tests in case of a remote target (#92398) These tests failed in case of Windows host and Linux target, because dap_server tried to run ELF file on Windows. --- lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py | 2 ++ .../API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py | 1 + 2 files changed, 3 insertions(+) diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py index 226b9385fe719a..bfdf9ef2897b2b 100644 --- a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py +++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py @@ -7,6 +7,7 @@ class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase): + @skipIfRemote def test_command_directive_quiet_on_success(self): program = self.getBuildArtifact("a.out") command_quiet = ( @@ -60,6 +61,7 @@ def test_command_directive_abort_on_error_launch_commands(self): def test_command_directive_abort_on_error_pre_run_commands(self): self.do_test_abort_on_error(use_pre_run_commands=True) + @skipIfRemote def test_command_directive_abort_on_error_post_run_commands(self): self.do_test_abort_on_error(use_post_run_commands=True) diff --git a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py index fd48e69cae5e25..7700c65f862dc1 100644 --- a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py +++ b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py @@ -11,6 +11,7 @@ class TestDAP_startDebugging(lldbdap_testcase.DAPTestCaseBase): + @skipIfRemote def test_startDebugging(self): """ Tests the "startDebugging" reverse request. It makes sure that the IDE can From d1f96d4cfe25770827b5f819b6a9de6fef142c9c Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Thu, 16 May 2024 17:51:59 +0300 Subject: [PATCH 047/576] [clang][NFC] Claim support for P3106R1 since Clang 17 Test for this paper were added in https://github.com/llvm/llvm-project/pull/91435 --- clang/www/cxx_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 6e2fd745e666cb..a11bf9a06f9f4d 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -172,7 +172,7 @@

    C++2c implementation status

    Clarifying rules for brace elision in aggregate initialization P3106R1 (DR) - No + Clang 17 Attributes for Structured Bindings From 5ac34358181b21135851979c1c949632be5a9d32 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 16 May 2024 11:01:08 -0400 Subject: [PATCH 048/576] Respect the [[clang::unsafe_buffer_usage]] attribute for constructors (#91777) The -Wunsafe-buffer-usage warning should fire on any call to a function annotated with [[clang::unsafe_buffer_usage]], however it omitted calls to constructors, since the expression is a CXXConstructExpr which does not subclass CallExpr. Thus the matcher on callExpr() does not find these expressions. Add a new WarningGadget that matches cxxConstructExpr that are calling a CXXConstructDecl annotated by [[clang::unsafe_buffer_usage]] and fires the warning. The new UnsafeBufferUsageCtorAttrGadget gadget explicitly avoids matching against the std::span(ptr, size) constructor because that is handled by SpanTwoParamConstructorGadget and we never want two gadgets to match the same thing (and this is guarded by asserts). The gadgets themselves do not report the warnings, instead each gadget's Stmt is passed to the UnsafeBufferUsageHandler (implemented by UnsafeBufferUsageReporter). The Reporter is previously hardcoded that a CXXConstructExpr statement must be a match for std::span(ptr, size), but that is no longer the case. We want the Reporter to generate different warnings (in the -Wunsafe-buffer-usage-in-container subgroup) for the span contructor. And we will want it to report more warnings for other std-container-specific gadgets in the future. To handle this we allow the gadget to control if the warning is general (it calls handleUnsafeBufferUsage()) or is a std-container-specific warning (it calls handleUnsafeOperationInContainer()). Then the WarningGadget grows a virtual method to dispatch to the appropriate path in the UnsafeBufferUsageHandler. By doing so, we no longer need getBaseStmt in the Gadget interface. The only use of it for FixableGadgets was to get the SourceLocation, so we make an explicit virtual method for that on Gadget. Then the handleUnsafeOperation() dispatcher can be a virtual method that is only in WarningGadget. The SpanTwoParamConstructorGadget gadget dispatches to handleUnsafeOperationInContainer() while the other WarningGadgets all dispatch to the original handleUnsafeBufferUsage(). Tests are added for annotated constructors, conversion operattors, call operators, fold expressions, and regular methods. Issue #80482 --- .../Analysis/Analyses/UnsafeBufferUsage.h | 5 + .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 166 ++++++++++++------ clang/lib/Sema/AnalysisBasedWarnings.cpp | 25 ++- ...warn-unsafe-buffer-usage-function-attr.cpp | 38 ++++ 5 files changed, 178 insertions(+), 57 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 5d16dcc824c50c..228b4ae1e3e115 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -106,6 +106,11 @@ class UnsafeBufferUsageHandler { virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl, ASTContext &Ctx) = 0; + /// Invoked when an unsafe operation with a std container is found. + virtual void handleUnsafeOperationInContainer(const Stmt *Operation, + bool IsRelatedToDecl, + ASTContext &Ctx) = 0; + /// Invoked when a fix is suggested against a variable. This function groups /// all variables that must be fixed together (i.e their types must be changed /// to the same target type to prevent type mismatches) into a single fixit. diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 3273c642eed517..242ad763ba62b9 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) WARNING_GADGET(UnsafeBufferUsageAttr) +WARNING_GADGET(UnsafeBufferUsageCtorAttr) WARNING_GADGET(DataInvocation) WARNING_CONTAINER_GADGET(SpanTwoParamConstructor) // Uses of `std::span(arg0, arg1)` FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index c42e70d5b95ac1..866222380974b6 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -492,7 +492,9 @@ class Gadget { #endif virtual bool isWarningGadget() const = 0; - virtual const Stmt *getBaseStmt() const = 0; + // TODO remove this method from WarningGadget interface. It's only used for + // debug prints in FixableGadget. + virtual SourceLocation getSourceLoc() const = 0; /// Returns the list of pointer-type variables on which this gadget performs /// its operation. Typically, there's only one variable. This isn't a list @@ -513,6 +515,10 @@ class WarningGadget : public Gadget { static bool classof(const Gadget *G) { return G->isWarningGadget(); } bool isWarningGadget() const final { return true; } + + virtual void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const = 0; }; /// Fixable gadgets correspond to code patterns that aren't always unsafe but @@ -572,7 +578,12 @@ class IncrementGadget : public WarningGadget { .bind(OpTag)); } - const UnaryOperator *getBaseStmt() const override { return Op; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { SmallVector Uses; @@ -607,7 +618,12 @@ class DecrementGadget : public WarningGadget { .bind(OpTag)); } - const UnaryOperator *getBaseStmt() const override { return Op; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -648,7 +664,12 @@ class ArraySubscriptGadget : public WarningGadget { // clang-format on } - const ArraySubscriptExpr *getBaseStmt() const override { return ASE; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(ASE, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return ASE->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -696,7 +717,12 @@ class PointerArithmeticGadget : public WarningGadget { .bind(PointerArithmeticTag)); } - const Stmt *getBaseStmt() const override { return PA; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(PA, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return PA->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = dyn_cast(Ptr->IgnoreParenImpCasts())) { @@ -734,7 +760,12 @@ class SpanTwoParamConstructorGadget : public WarningGadget { .bind(SpanTwoParamConstructorTag)); } - const Stmt *getBaseStmt() const override { return Ctor; } + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperationInContainer(Ctor, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Ctor->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { // If the constructor call is of the form `std::span{var, n}`, `var` is @@ -780,11 +811,8 @@ class PointerInitGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This needs to be the entire DeclStmt, assuming that this method - // makes sense at all on a FixableGadget. - return PtrInitRHS; + SourceLocation getSourceLoc() const override { + return PtrInitRHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { @@ -833,12 +861,7 @@ class PtrToPtrAssignmentGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This should be the binary operator, assuming that this method - // makes sense at all on a FixableGadget. - return PtrLHS; - } + SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrLHS, PtrRHS}; @@ -888,12 +911,7 @@ class CArrayToPtrAssignmentGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { - // FIXME: This should be the binary operator, assuming that this method - // makes sense at all on a FixableGadget. - return PtrLHS; - } + SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrLHS, PtrRHS}; @@ -921,10 +939,53 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget { } static Matcher matcher() { - return stmt(callExpr(callee(functionDecl(hasAttr(attr::UnsafeBufferUsage)))) - .bind(OpTag)); + auto HasUnsafeFnDecl = + callee(functionDecl(hasAttr(attr::UnsafeBufferUsage))); + return stmt(callExpr(HasUnsafeFnDecl).bind(OpTag)); + } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); } - const Stmt *getBaseStmt() const override { return Op; } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } + + DeclUseList getClaimedVarUseSites() const override { return {}; } +}; + +/// A call of a constructor that performs unchecked buffer operations +/// over one of its pointer parameters, or constructs a class object that will +/// perform buffer operations that depend on the correctness of the parameters. +class UnsafeBufferUsageCtorAttrGadget : public WarningGadget { + constexpr static const char *const OpTag = "cxx_construct_expr"; + const CXXConstructExpr *Op; + +public: + UnsafeBufferUsageCtorAttrGadget(const MatchFinder::MatchResult &Result) + : WarningGadget(Kind::UnsafeBufferUsageCtorAttr), + Op(Result.Nodes.getNodeAs(OpTag)) {} + + static bool classof(const Gadget *G) { + return G->getKind() == Kind::UnsafeBufferUsageCtorAttr; + } + + static Matcher matcher() { + auto HasUnsafeCtorDecl = + hasDeclaration(cxxConstructorDecl(hasAttr(attr::UnsafeBufferUsage))); + // std::span(ptr, size) ctor is handled by SpanTwoParamConstructorGadget. + auto HasTwoParamSpanCtorDecl = SpanTwoParamConstructorGadget::matcher(); + return stmt( + cxxConstructExpr(HasUnsafeCtorDecl, unless(HasTwoParamSpanCtorDecl)) + .bind(OpTag)); + } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } }; @@ -953,7 +1014,13 @@ class DataInvocationGadget : public WarningGadget { explicitCastExpr(anyOf(has(callExpr), has(parenExpr(has(callExpr))))) .bind(OpTag)); } - const Stmt *getBaseStmt() const override { return Op; } + + void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, + bool IsRelatedToDecl, + ASTContext &Ctx) const override { + Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx); + } + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } }; @@ -990,8 +1057,7 @@ class ULCArraySubscriptGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { if (const auto *DRE = @@ -1031,8 +1097,7 @@ class UPCStandalonePointerGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {Node}; } }; @@ -1070,10 +1135,9 @@ class PointerDereferenceGadget : public FixableGadget { return {BaseDeclRefExpr}; } - virtual const Stmt *getBaseStmt() const final { return Op; } - virtual std::optional getFixits(const FixitStrategy &S) const override; + SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } }; // Represents expressions of the form `&DRE[any]` in the Unspecified Pointer @@ -1108,8 +1172,7 @@ class UPCAddressofArraySubscriptGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { const auto *ArraySubst = cast(Node->getSubExpr()); @@ -1218,8 +1281,7 @@ class UPCPreIncrementGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {dyn_cast(Node->getSubExpr())}; @@ -1264,8 +1326,7 @@ class UUCAddAssignGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &S) const override; - - virtual const Stmt *getBaseStmt() const override { return Node; } + SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); } virtual DeclUseList getClaimedVarUseSites() const override { return {dyn_cast(Node->getLHS())}; @@ -1315,9 +1376,9 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget { virtual std::optional getFixits(const FixitStrategy &s) const final; - - // TODO remove this method from FixableGadget interface - virtual const Stmt *getBaseStmt() const final { return nullptr; } + SourceLocation getSourceLoc() const override { + return DerefOp->getBeginLoc(); + } virtual DeclUseList getClaimedVarUseSites() const final { return {BaseDeclRefExpr}; @@ -2070,7 +2131,7 @@ UUCAddAssignGadget::getFixits(const FixitStrategy &S) const { if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; - const Stmt *AddAssignNode = getBaseStmt(); + const Stmt *AddAssignNode = Node; StringRef varName = VD->getName(); const ASTContext &Ctx = VD->getASTContext(); @@ -2112,7 +2173,6 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const { if (S.lookup(VD) == FixitStrategy::Kind::Span) { FixItList Fixes; std::stringstream SS; - const Stmt *PreIncNode = getBaseStmt(); StringRef varName = VD->getName(); const ASTContext &Ctx = VD->getASTContext(); @@ -2120,12 +2180,12 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const { SS << "(" << varName.data() << " = " << varName.data() << ".subspan(1)).data()"; std::optional PreIncLocation = - getEndCharLoc(PreIncNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + getEndCharLoc(Node, Ctx.getSourceManager(), Ctx.getLangOpts()); if (!PreIncLocation) return std::nullopt; Fixes.push_back(FixItHint::CreateReplacement( - SourceRange(PreIncNode->getBeginLoc(), *PreIncLocation), SS.str())); + SourceRange(Node->getBeginLoc(), *PreIncLocation), SS.str())); return Fixes; } } @@ -2856,7 +2916,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const FixitStrategy &S, } #ifndef NDEBUG Handler.addDebugNoteForVar( - VD, F->getBaseStmt()->getBeginLoc(), + VD, F->getSourceLoc(), ("gadget '" + F->getDebugName() + "' refused to produce a fix") .str()); #endif @@ -3008,8 +3068,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, // every problematic operation and consider it done. No need to deal // with fixable gadgets, no need to group operations by variable. for (const auto &G : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false, + D->getASTContext()); } // This return guarantees that most of the machine doesn't run when @@ -3251,8 +3311,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, Tracker, Handler, VarGrpMgr); for (const auto &G : UnsafeOps.noVar) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false, + D->getASTContext()); } for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) { @@ -3263,8 +3323,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, : FixItList{}, D, NaiveStrategy); for (const auto &G : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true, - D->getASTContext()); + G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/true, + D->getASTContext()); } } } diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6992ba9ad9a756..b9d0b59ef1db73 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2256,11 +2256,8 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler { Range = UO->getSubExpr()->getSourceRange(); MsgParam = 1; } - } else if (const auto *CtorExpr = dyn_cast(Operation)) { - S.Diag(CtorExpr->getLocation(), - diag::warn_unsafe_buffer_usage_in_container); } else { - if (isa(Operation)) { + if (isa(Operation) || isa(Operation)) { // note_unsafe_buffer_operation doesn't have this mode yet. assert(!IsRelatedToDecl && "Not implemented yet!"); MsgParam = 3; @@ -2295,6 +2292,26 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler { } } + void handleUnsafeOperationInContainer(const Stmt *Operation, + bool IsRelatedToDecl, + ASTContext &Ctx) override { + SourceLocation Loc; + SourceRange Range; + unsigned MsgParam = 0; + + // This function only handles SpanTwoParamConstructorGadget so far, which + // always gives a CXXConstructExpr. + const auto *CtorExpr = cast(Operation); + Loc = CtorExpr->getLocation(); + + S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container); + if (IsRelatedToDecl) { + assert(!SuggestSuggestions && + "Variables blamed for unsafe buffer usage without suggestions!"); + S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range; + } + } + void handleUnsafeVariableGroup(const VarDecl *Variable, const VariableGroupsManager &VarGrpMgr, FixItList &&Fixes, const Decl *D, diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp index 7df01c46438c79..bfc34b55c1f667 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp @@ -85,3 +85,41 @@ void testInheritance() { BC->func(); // expected-warning{{function introduces unsafe buffer manipulation}} BC->func1(); } + +class UnsafeMembers { +public: + UnsafeMembers() {} + + [[clang::unsafe_buffer_usage]] + UnsafeMembers(int) {} + + [[clang::unsafe_buffer_usage]] + explicit operator int() { return 0; } + + [[clang::unsafe_buffer_usage]] + void Method() {} + + [[clang::unsafe_buffer_usage]] + void operator()() {} + + [[clang::unsafe_buffer_usage]] + int operator+(UnsafeMembers) { return 0; } +}; + +template +int testFoldExpression(Vs&&... v) { + return (... + v); // expected-warning{{function introduces unsafe buffer manipulation}} +} + +// https://github.com/llvm/llvm-project/issues/80482 +void testClassMembers() { + UnsafeMembers(3); // expected-warning{{function introduces unsafe buffer manipulation}} + + (void)static_cast(UnsafeMembers()); // expected-warning{{function introduces unsafe buffer manipulation}} + + UnsafeMembers().Method(); // expected-warning{{function introduces unsafe buffer manipulation}} + + UnsafeMembers()(); // expected-warning{{function introduces unsafe buffer manipulation}} + + testFoldExpression(UnsafeMembers(), UnsafeMembers()); +} From ee407e17a3a4986bab49272665abc9973d78691d Mon Sep 17 00:00:00 2001 From: Renaud Kauffmann <50748669+Renaud-K@users.noreply.github.com> Date: Thu, 16 May 2024 08:49:44 -0700 Subject: [PATCH 049/576] [flang] AliasAnalysis: More formally define and distinguish between data and non-data (#91020) This PR is an implementation for changes proposed in https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759 Test updates were made when the query was on the wrong reference. So, it is my hope that this will clear ambiguity on the nature of the queries from here on. There are also some TODOs that were addressed. It also partly implements what https://github.com/llvm/llvm-project/pull/87723 is attempting to accomplish. At least, on a point-to-point query between references, the distinction is made. To apply it to TBAA, would be another PR. Note that, the changes were minimal in the TBAA code to retain the current results. --- .../flang/Optimizer/Analysis/AliasAnalysis.h | 95 ++++++++++- .../lib/Optimizer/Analysis/AliasAnalysis.cpp | 157 +++++++----------- .../lib/Optimizer/Transforms/AddAliasTags.cpp | 17 +- .../AliasAnalysis/alias-analysis-2.fir | 37 +++-- .../AliasAnalysis/alias-analysis-3.fir | 4 +- .../AliasAnalysis/alias-analysis-9.fir | 59 +++++++ 6 files changed, 248 insertions(+), 121 deletions(-) create mode 100644 flang/test/Analysis/AliasAnalysis/alias-analysis-9.fir diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h index dfcafe88fee1b5..40fd1705115a06 100644 --- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h +++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h @@ -36,9 +36,6 @@ struct AliasAnalysis { /// Represents memory allocated outside of a function /// and passed to the function via host association tuple. HostAssoc, - /// Represents direct memory access whose source cannot be further - /// determined - Direct, /// Represents memory allocated by unknown means and /// with the memory address defined by a memory reading /// operation (e.g. fir::LoadOp). @@ -50,12 +47,85 @@ struct AliasAnalysis { /// Attributes of the memory source object. ENUM_CLASS(Attribute, Target, Pointer, IntentIn); + // See + // https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759/1 + // + // It is possible, while following the source of a memory reference through + // the use-def chain, to arrive at the same origin, even though the starting + // points were known to not alias. + // + // clang-format off + // Example: + // ------------------- test.f90 -------------------- + // module top + // real, pointer :: a(:) + // end module + // + // subroutine test() + // use top + // a(1) = 1 + // end subroutine + // ------------------------------------------------- + // + // flang-new -fc1 -emit-fir test.f90 -o test.fir + // + // ------------------- test.fir -------------------- + // fir.global @_QMtopEa : !fir.box>> + // + // func.func @_QPtest() { + // %c1 = arith.constant 1 : index + // %cst = arith.constant 1.000000e+00 : f32 + // %0 = fir.address_of(@_QMtopEa) : !fir.ref>>> + // %1 = fir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMtopEa"} : (!fir.ref>>>) -> !fir.ref>>> + // %2 = fir.load %1 : !fir.ref>>> + // ... + // %5 = fir.array_coor %2 %c1 : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref + // fir.store %cst to %5 : !fir.ref + // return + // } + // ------------------------------------------------- + // + // With high level operations, such as fir.array_coor, it is possible to + // reach into the data wrapped by the box (the descriptor). Therefore when + // asking about the memory source of %5, we are really asking about the + // source of the data of box %2. + // + // When asking about the source of %0 which is the address of the box, we + // reach the same source as in the first case: the global @_QMtopEa. Yet one + // source refers to the data while the other refers to the address of the box + // itself. + // + // To distinguish between the two, the isData flag has been added, whereby + // data is defined as any memory reference that is not a box reference. + // Additionally, because it is relied on in HLFIR lowering, we allow querying + // on a box SSA value, which is interpreted as querying on its data. + // + // So in the above example, !fir.ref and !fir.box>> is data, + // while !fir.ref>>> is not data. + + // This also applies to function arguments. In the example below, %arg0 + // is data, %arg1 is not data but a load of %arg1 is. + // + // func.func @_QFPtest2(%arg0: !fir.ref, %arg1: !fir.ref>> ) { + // %0 = fir.load %arg1 : !fir.ref>> + // ... } + // + // clang-format on + struct Source { using SourceUnion = llvm::PointerUnion; using Attributes = Fortran::common::EnumSet; - /// Source definition of a value. - SourceUnion u; + struct SourceOrigin { + /// Source definition of a value. + SourceUnion u; + + /// Whether the source was reached following data or box reference + bool isData{false}; + }; + + SourceOrigin origin; + /// Kind of the memory source. SourceKind kind; /// Value type of the source definition. @@ -77,6 +147,12 @@ struct AliasAnalysis { /// attribute. bool isRecordWithPointerComponent() const; + bool isDummyArgument() const; + bool isData() const; + bool isBoxData() const; + + mlir::Type getType() const; + /// Return true, if `ty` is a reference type to a boxed /// POINTER object or a raw fir::PointerType. static bool isPointerReference(mlir::Type ty); @@ -95,6 +171,15 @@ struct AliasAnalysis { Source getSource(mlir::Value); }; +inline bool operator==(const AliasAnalysis::Source::SourceOrigin &lhs, + const AliasAnalysis::Source::SourceOrigin &rhs) { + return lhs.u == rhs.u && lhs.isData == rhs.isData; +} +inline bool operator!=(const AliasAnalysis::Source::SourceOrigin &lhs, + const AliasAnalysis::Source::SourceOrigin &rhs) { + return !(lhs == rhs); +} + inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const AliasAnalysis::Source &op) { op.print(os); diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index ed1101dc5e8d88..9d0d706a85c5e1 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -33,11 +33,9 @@ static bool isDummyArgument(mlir::Value v) { if (!blockArg) return false; - mlir::Block *owner = blockArg.getOwner(); - if (!owner->isEntryBlock() || - !mlir::isa(owner->getParentOp())) - return false; - return true; + auto *owner{blockArg.getOwner()}; + return owner->isEntryBlock() && + mlir::isa(owner->getParentOp()); } /// Temporary function to skip through all the no op operations @@ -58,12 +56,17 @@ static mlir::Value getOriginalDef(mlir::Value v) { namespace fir { void AliasAnalysis::Source::print(llvm::raw_ostream &os) const { - if (auto v = llvm::dyn_cast(u)) + if (auto v = llvm::dyn_cast(origin.u)) os << v; - else if (auto gbl = llvm::dyn_cast(u)) + else if (auto gbl = llvm::dyn_cast(origin.u)) os << gbl; os << " SourceKind: " << EnumToString(kind); os << " Type: " << valueType << " "; + if (origin.isData) { + os << " following data "; + } else { + os << " following box reference "; + } attributes.Dump(os, EnumToString); } @@ -80,6 +83,19 @@ bool AliasAnalysis::Source::isTargetOrPointer() const { attributes.test(Attribute::Target); } +bool AliasAnalysis::Source::isDummyArgument() const { + if (auto v = origin.u.dyn_cast()) { + return ::isDummyArgument(v); + } + return false; +} + +bool AliasAnalysis::Source::isData() const { return origin.isData; } +bool AliasAnalysis::Source::isBoxData() const { + return mlir::isa(fir::unwrapRefType(valueType)) && + origin.isData; +} + bool AliasAnalysis::Source::isRecordWithPointerComponent() const { auto eleTy = fir::dyn_cast_ptrEleTy(valueType); if (!eleTy) @@ -92,70 +108,35 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) { auto lhsSrc = getSource(lhs); auto rhsSrc = getSource(rhs); bool approximateSource = lhsSrc.approximateSource || rhsSrc.approximateSource; - LLVM_DEBUG(llvm::dbgs() << "AliasAnalysis::alias\n"; + LLVM_DEBUG(llvm::dbgs() << "\nAliasAnalysis::alias\n"; llvm::dbgs() << " lhs: " << lhs << "\n"; llvm::dbgs() << " lhsSrc: " << lhsSrc << "\n"; llvm::dbgs() << " rhs: " << rhs << "\n"; - llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n"; - llvm::dbgs() << "\n";); + llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n";); // Indirect case currently not handled. Conservatively assume // it aliases with everything - if (lhsSrc.kind > SourceKind::Direct || rhsSrc.kind > SourceKind::Direct) { + if (lhsSrc.kind >= SourceKind::Indirect || + rhsSrc.kind >= SourceKind::Indirect) { return AliasResult::MayAlias; } - // SourceKind::Direct is set for the addresses wrapped in a global boxes. - // ie: fir.global @_QMpointersEp : !fir.box> - // Though nothing is known about them, they would only alias with targets or - // pointers - bool directSourceToNonTargetOrPointer = false; - if (lhsSrc.u != rhsSrc.u || lhsSrc.kind != rhsSrc.kind) { - if ((lhsSrc.kind == SourceKind::Direct && !rhsSrc.isTargetOrPointer()) || - (rhsSrc.kind == SourceKind::Direct && !lhsSrc.isTargetOrPointer())) - directSourceToNonTargetOrPointer = true; - } - - if (lhsSrc.kind == SourceKind::Direct || - rhsSrc.kind == SourceKind::Direct) { - if (!directSourceToNonTargetOrPointer) - return AliasResult::MayAlias; - } - if (lhsSrc.kind == rhsSrc.kind) { - if (lhsSrc.u == rhsSrc.u) { + if (lhsSrc.origin == rhsSrc.origin) { + LLVM_DEBUG(llvm::dbgs() + << " aliasing because same source kind and origin\n"); if (approximateSource) return AliasResult::MayAlias; return AliasResult::MustAlias; } // Two host associated accesses may overlap due to an equivalence. - if (lhsSrc.kind == SourceKind::HostAssoc) + if (lhsSrc.kind == SourceKind::HostAssoc) { + LLVM_DEBUG(llvm::dbgs() << " aliasing because of host association\n"); return AliasResult::MayAlias; - - // Allocate and global memory address cannot physically alias - if (lhsSrc.kind == SourceKind::Allocate || - lhsSrc.kind == SourceKind::Global) - return AliasResult::NoAlias; - - // Dummy TARGET/POINTER arguments may alias. - if (lhsSrc.isTargetOrPointer() && rhsSrc.isTargetOrPointer()) - return AliasResult::MayAlias; - - // Box for POINTER component inside an object of a derived type - // may alias box of a POINTER object, as well as boxes for POINTER - // components inside two objects of derived types may alias. - if ((lhsSrc.isRecordWithPointerComponent() && rhsSrc.isTargetOrPointer()) || - (rhsSrc.isRecordWithPointerComponent() && lhsSrc.isTargetOrPointer()) || - (lhsSrc.isRecordWithPointerComponent() && - rhsSrc.isRecordWithPointerComponent())) - return AliasResult::MayAlias; - - return AliasResult::NoAlias; + } } - assert(lhsSrc.kind != rhsSrc.kind && "memory source kinds must be different"); - Source *src1, *src2; if (lhsSrc.kind < rhsSrc.kind) { src1 = &lhsSrc; @@ -186,8 +167,11 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) { } // Dummy TARGET/POINTER argument may alias with a global TARGET/POINTER. - if (src1->isTargetOrPointer() && src2->isTargetOrPointer()) + if (src1->isTargetOrPointer() && src2->isTargetOrPointer() && + src1->isData() == src2->isData()) { + LLVM_DEBUG(llvm::dbgs() << " aliasing because of target or pointer\n"); return AliasResult::MayAlias; + } // Box for POINTER component inside an object of a derived type // may alias box of a POINTER object, as well as boxes for POINTER @@ -195,8 +179,10 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) { if ((src1->isRecordWithPointerComponent() && src2->isTargetOrPointer()) || (src2->isRecordWithPointerComponent() && src1->isTargetOrPointer()) || (src1->isRecordWithPointerComponent() && - src2->isRecordWithPointerComponent())) + src2->isRecordWithPointerComponent())) { + LLVM_DEBUG(llvm::dbgs() << " aliasing because of pointer components\n"); return AliasResult::MayAlias; + } return AliasResult::NoAlias; } @@ -262,7 +248,10 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { mlir::Type ty; bool breakFromLoop{false}; bool approximateSource{false}; - bool followBoxAddr{mlir::isa(v.getType())}; + bool followBoxData{mlir::isa(v.getType())}; + bool isBoxRef{fir::isa_ref_type(v.getType()) && + mlir::isa(fir::unwrapRefType(v.getType()))}; + bool followingData = !isBoxRef; mlir::SymbolRefAttr global; Source::Attributes attributes; while (defOp && !breakFromLoop) { @@ -282,34 +271,32 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { v = op->getOperand(0); defOp = v.getDefiningOp(); if (mlir::isa(v.getType())) - followBoxAddr = true; + followBoxData = true; }) .Case([&](auto op) { v = op->getOperand(0); defOp = v.getDefiningOp(); if (mlir::isa(v.getType())) - followBoxAddr = true; + followBoxData = true; approximateSource = true; }) .Case([&](auto op) { - if (followBoxAddr) { + if (followBoxData) { v = op->getOperand(0); defOp = v.getDefiningOp(); } else breakFromLoop = true; }) .Case([&](auto op) { - if (followBoxAddr && mlir::isa(op.getType())) { - // For now, support the load of an argument or fir.address_of - // TODO: generalize to all operations (in particular fir.alloca and - // fir.allocmem) - auto def = getOriginalDef(op.getMemref()); - if (isDummyArgument(def) || - def.template getDefiningOp()) { - v = def; - defOp = v.getDefiningOp(); - return; - } + // If the load is from a leaf source, return the leaf. Do not track + // through indirections otherwise. + // TODO: Add support to fir.alloca and fir.allocmem + auto def = getOriginalDef(op.getMemref()); + if (isDummyArgument(def) || + def.template getDefiningOp()) { + v = def; + defOp = v.getDefiningOp(); + return; } // No further tracking for addresses loaded from memory for now. type = SourceKind::Indirect; @@ -318,24 +305,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { .Case([&](auto op) { // Address of a global scope object. ty = v.getType(); - - // When the global is a - // fir.global @_QMpointersEp : !fir.box> - // or - // fir.global @_QMpointersEp : !fir.box> - // - // and when following through the wrapped address, capture - // the fact that there is nothing known about it. Therefore setting - // the source to Direct. - // - // When not following the wrapped address, then consider the address - // of the box, which has nothing to do with the wrapped address and - // lies in the global memory space. - if (followBoxAddr && - mlir::isa(fir::unwrapRefType(ty))) - type = SourceKind::Direct; - else - type = SourceKind::Global; + type = SourceKind::Global; auto globalOpName = mlir::OperationName( fir::GlobalOp::getOperationName(), defOp->getContext()); @@ -343,11 +313,10 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { v, fir::GlobalOp::getTargetAttrName(globalOpName))) attributes.set(Attribute::Target); - // TODO: Take followBoxAddr into account when setting the pointer + // TODO: Take followBoxData into account when setting the pointer // attribute if (Source::isPointerReference(ty)) attributes.set(Attribute::Pointer); - global = llvm::cast(op).getSymbol(); breakFromLoop = true; }) @@ -393,7 +362,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { // MustAlias after going through a designate operation approximateSource = true; if (mlir::isa(v.getType())) - followBoxAddr = true; + followBoxData = true; }) .Default([&](auto op) { defOp = nullptr; @@ -412,10 +381,10 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) { attributes.set(Attribute::Pointer); } - if (type == SourceKind::Global || type == SourceKind::Direct) - return {global, type, ty, attributes, approximateSource}; - - return {v, type, ty, attributes, approximateSource}; + if (type == SourceKind::Global) { + return {{global, followingData}, type, ty, attributes, approximateSource}; + } + return {{v, followingData}, type, ty, attributes, approximateSource}; } } // namespace fir diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp index 3642a812096db4..caece93840043d 100644 --- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp +++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp @@ -145,7 +145,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, source.kind == fir::AliasAnalysis::SourceKind::Argument) { LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to dummy argument at " << *op << "\n"); - std::string name = getFuncArgName(source.u.get()); + std::string name = getFuncArgName(source.origin.u.get()); if (!name.empty()) tag = state.getFuncTree(func).dummyArgDataTree.getTag(name); else @@ -155,8 +155,9 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, // TBAA for global variables } else if (enableGlobals && - source.kind == fir::AliasAnalysis::SourceKind::Global) { - mlir::SymbolRefAttr glbl = source.u.get(); + source.kind == fir::AliasAnalysis::SourceKind::Global && + !source.isBoxData()) { + mlir::SymbolRefAttr glbl = source.origin.u.get(); const char *name = glbl.getRootReference().data(); LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to global " << name << " at " << *op << "\n"); @@ -164,9 +165,10 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, // TBAA for SourceKind::Direct } else if (enableDirect && - source.kind == fir::AliasAnalysis::SourceKind::Direct) { - if (source.u.is()) { - mlir::SymbolRefAttr glbl = source.u.get(); + source.kind == fir::AliasAnalysis::SourceKind::Global && + source.isBoxData()) { + if (source.origin.u.is()) { + mlir::SymbolRefAttr glbl = source.origin.u.get(); const char *name = glbl.getRootReference().data(); LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to direct " << name << " at " << *op << "\n"); @@ -182,7 +184,8 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, } else if (enableLocalAllocs && source.kind == fir::AliasAnalysis::SourceKind::Allocate) { std::optional name; - mlir::Operation *sourceOp = source.u.get().getDefiningOp(); + mlir::Operation *sourceOp = + source.origin.u.get().getDefiningOp(); if (auto alloc = mlir::dyn_cast_or_null(sourceOp)) name = alloc.getUniqName(); else if (auto alloc = mlir::dyn_cast_or_null(sourceOp)) diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir index 31459ef21d947c..d03348efd2a68c 100644 --- a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir @@ -37,14 +37,14 @@ // arg2 is a reference to a pointer. Modifying arg2 could // modify a target with a pointer component -// CHECK-DAG: func.region0#0 <-> func.region0#2: MayAlias -// CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias +// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias +// CHECK-DAG: arg2.load#0 <-> func.region0#1: MayAlias // However, the address wrapped by arg2, can alias with any target or // pointer arguments // CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias // CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias -// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MustAlias +// CHECK-DAG: arg2.load#0 <-> arg2.addr#0: MustAlias // CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias func.func @_QFPtest(%arg0: !fir.ref {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref {fir.bindc_name = "v2", fir.target}, %arg2: !fir.ref>> ) attributes {test.ptr = "func"} { @@ -80,7 +80,7 @@ func.func @_QFPtest(%arg0: !fir.ref {fir.bindc_name = "v1", fir.target}, %a %14 = fir.box_addr %13 : (!fir.box>) -> !fir.ptr fir.store %14 to %4 : !fir.ref> - %15 = fir.load %arg2 : !fir.ref>> + %15 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref>> %16 = fir.box_addr %15 {test.ptr = "arg2.addr"} : (!fir.box>) -> !fir.ptr return } @@ -99,10 +99,12 @@ func.func @_QFPtest(%arg0: !fir.ref {fir.bindc_name = "v1", fir.target}, %a // CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias // They can also modify targets that have pointer components -// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias -// CHECK-DAG: func.region0#0 <-> func.region0#2: MayAlias +// CHECK-DAG: arg1.load#0 <-> func.region0#0: MayAlias +// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias func.func @_QFPtest2(%arg0: !fir.ref {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref>>, %arg2: !fir.ref>> ) attributes {test.ptr = "func"} { + %0 = fir.load %arg1 {test.ptr = "arg1.load"} : !fir.ref>> + %1 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref>> return } @@ -141,14 +143,14 @@ func.func @_QFPtest2(%arg0: !fir.ref {fir.bindc_name = "v1", fir.target}, % // alias with the wrapped scalar _QFEvar2. We meant box_addr of _QMpointersEp // CHECK-DAG: p#0 <-> box.addr#0: NoAlias -// TODO: Still need to handle more gracefully the difference between !fir.ref> and !fir.box<> -// CHECK-DAG: box.addr#0 <-> func.region0#0: MayAlias +// Handling gracefully the difference between !fir.ref> and !fir.box<> +// CHECK-DAG: box.addr#0 <-> func.region0#0: NoAlias // var2, although it is a target, cannot alias with p // A modification of p would only make them point to a new target but not modify it // CHECK-DAG: var2#0 <-> p#0: NoAlias // It can alias with p1, if p1 is a pointer component -// CHECK-DAG: var2#0 <-> func.region0#0: MayAlias +// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias // It is the same as box.addr // CHECK-DAG: var2#0 <-> box.addr#0: MustAlias @@ -173,6 +175,7 @@ fir.global internal @_QFEvar2 target : f32 { } func.func @_QFPtest3(%arg0: !fir.ref>> {fir.bindc_name = "p1"}, %arg1: !fir.ref) attributes {test.ptr = "func"} { + %3 = fir.load %arg0 {test.ptr = "arg0.load"}: !fir.ref>> %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref %5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref>> %6 = fir.embox %4 : (!fir.ref) -> !fir.box> @@ -214,10 +217,17 @@ func.func @_QFPtest3(%arg0: !fir.ref>> {fir.bindc_name = // CHECK-DAG: var2_hlfir#1 <-> p_hlfir#0: NoAlias // CHECK-DAG: var2_hlfir#1 <-> p_hlfir#1: NoAlias -// CHECK-DAG: var2#0 <-> func.region0#0: MayAlias -// CHECK-DAG: var2_fir#0 <-> func.region0#0: MayAlias -// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: MayAlias -// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: MayAlias +// The data cannot alias with the box references +// CHECK-DAG: var2#0 <-> func.region0#0: NoAlias +// CHECK-DAG: var2_fir#0 <-> func.region0#0: NoAlias +// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: NoAlias +// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: NoAlias + +// But it can alias with the box's own data +// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias +// CHECK-DAG: arg0.load#0 <-> var2_fir#0: MayAlias +// CHECK-DAG: arg0.load#0 <-> var2_hlfir#0: MayAlias +// CHECK-DAG: arg0.load#0 <-> var2_hlfir#1: MayAlias // CHECK-DAG: var2#0 <-> box.addr#0: MustAlias // CHECK-DAG: var2#0 <-> box.addr_fir#0: MustAlias @@ -255,6 +265,7 @@ fir.global internal @_QFEvar2 target : f32 { } func.func @_QFPtest4(%arg0: !fir.ref>> {fir.bindc_name = "p1"}, %arg1: !fir.ref) attributes {test.ptr = "func"} { + %3 = fir.load %arg0 {test.ptr = "arg0.load"} : !fir.ref>> %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref %fir_decl_var2 = fir.declare %4 {uniq_name = "var2_fir", test.ptr = "var2_fir"}: (!fir.ref) -> !fir.ref %hlfir_decl_var2:2 = hlfir.declare %4 {uniq_name = "var2_hlfir", test.ptr = "var2_hlfir"}: (!fir.ref) -> (!fir.ref, !fir.ref) diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-3.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-3.fir index d7bd970b51907f..91829a461dc72a 100644 --- a/flang/test/Analysis/AliasAnalysis/alias-analysis-3.fir +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-3.fir @@ -23,8 +23,8 @@ // FIXME: a's box cannot alias with raw reference to f32 (x), so MayAlias below must be NoAlias: // CHECK: a#0 <-> func.region0#1: MayAlias -// FIXME: pointer_dummy's box cannot alias with raw reference to f32 (x), so MayAlias below must be NoAlias: -// CHECK: func.region0#0 <-> func.region0#1: MayAlias +// pointer_dummy's box cannot alias with raw reference to f32 (x) +// CHECK: func.region0#0 <-> func.region0#1: NoAlias fir.global @_QMmEa : !fir.type<_QMmTt{pointer_component:!fir.box>}> { %0 = fir.undefined !fir.type<_QMmTt{pointer_component:!fir.box>}> diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-9.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-9.fir new file mode 100644 index 00000000000000..df24a6d32aa596 --- /dev/null +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-9.fir @@ -0,0 +1,59 @@ +// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' 2>&1 | FileCheck %s + + +// module m +// type t +// type(t), pointer :: next +// integer :: i +// end type +// contains +// subroutine foo(x, y) +// type(t) :: x, y +// integer :: i1, i2 +// i1 = x%next%i +// x = y +// i2 = x%next%i +// end subroutine +// end module + +// CHECK-LABEL: Testing : "_QMmPfoo" +// TODO: x and y are non pointer, non target argument and therefore do not alias. +// CHECK-DAG: x#0 <-> y#0: MayAlias + +// TODO: y is not a pointer object and therefore does not alias with the x%next component. +// Also assigning x to y would not modify x.next +// CHECK-DAG: y#0 <-> xnext1#0: MayAlias +// CHECK-DAG: y#0 <-> xnext2#0: MayAlias + +// We need to catch the fact that assigning y to x will modify xnext. +// The only side-effect between the 2 loads of x.next is the assignment to x, +// therefore x needs to alias with x.next to prevent the loads from being merged. +// CHECK-DAG: x#0 <-> xnext1#0: MayAlias +// CHECK-DAG: x#0 <-> xnext2#0: MayAlias + +// TODO: xnext1#0 <-> xnext2#0 are the same and therefore MustAlias but +// we are currently not comparing operands involved in offset computations +// CHECK-DAG: xnext1#0 <-> xnext2#0: MayAlias + +func.func @_QMmPfoo(%arg0: !fir.ref>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>,i:i32}>> {fir.bindc_name = "y"}) { + %0 = fir.alloca i32 {bindc_name = "i1", uniq_name = "_QMmFfooEi1"} + %1:2 = hlfir.declare %0 {uniq_name = "_QMmFfooEi1"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %2 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QMmFfooEi2"} + %3:2 = hlfir.declare %2 {uniq_name = "_QMmFfooEi2"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %4:2 = hlfir.declare %arg0 {uniq_name = "_QMmFfooEx", test.ptr = "x"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) + %5:2 = hlfir.declare %arg1 {uniq_name = "_QMmFfooEy", test.ptr = "y"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) + %6 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs, test.ptr = "xnext1"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> + %7 = fir.load %6 : !fir.ref>>,i:i32}>>>> + %8 = fir.box_addr %7 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> + %9 = hlfir.designate %8{"i"} : (!fir.ptr>>,i:i32}>>) -> !fir.ref + %10 = fir.load %9 : !fir.ref + hlfir.assign %10 to %1#0 : i32, !fir.ref + hlfir.assign %5#0 to %4#0 : !fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>> + %11 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs, test.ptr = "xnext2"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> + %12 = fir.load %11 : !fir.ref>>,i:i32}>>>> + %13 = fir.box_addr %12 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> + %14 = hlfir.designate %13{"i"} : (!fir.ptr>>,i:i32}>>) -> !fir.ref + %15 = fir.load %14 : !fir.ref + hlfir.assign %15 to %3#0 : i32, !fir.ref + return +} From cdb41e416adcd49a783f0d3d28d1e3fafb6f5429 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 16 May 2024 17:54:26 +0200 Subject: [PATCH 050/576] PlaceSafepoints: Fix using default constructed TargetLibraryInfo (#92411) --- llvm/include/llvm/Analysis/TargetLibraryInfo.h | 4 ++++ llvm/lib/Analysis/TargetLibraryInfo.cpp | 4 ++++ llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp | 2 ++ llvm/test/Transforms/PlaceSafepoints/libcall.ll | 7 +++++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h index 46f31f918e7b61..f5da222d11f55c 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -633,6 +633,10 @@ class TargetLibraryInfoWrapperPass : public ImmutablePass { explicit TargetLibraryInfoWrapperPass(const Triple &T); explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); + // FIXME: This should be removed when PlaceSafepoints is fixed to not create a + // PassManager inside a pass. + explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfo &TLI); + TargetLibraryInfo &getTLI(const Function &F) { FunctionAnalysisManager DummyFAM; TLI = TLA.run(F, DummyFAM); diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index c62d9daa13ef01..684b0759f3157d 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1383,6 +1383,10 @@ TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass( initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); } +TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass( + const TargetLibraryInfo &TLIOther) + : TargetLibraryInfoWrapperPass(*TLIOther.Impl) {} + AnalysisKey TargetLibraryAnalysis::Key; // Register the basic pass. diff --git a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp index 77d155d7e78e3d..dcdea6e7b62ae7 100644 --- a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -288,6 +288,8 @@ bool PlaceSafepointsPass::runImpl(Function &F, const TargetLibraryInfo &TLI) { // with for the moment. legacy::FunctionPassManager FPM(F.getParent()); bool CanAssumeCallSafepoints = enableCallSafepoints(F); + + FPM.add(new TargetLibraryInfoWrapperPass(TLI)); auto *PBS = new PlaceBackedgeSafepointsLegacyPass(CanAssumeCallSafepoints); FPM.add(PBS); FPM.run(F); diff --git a/llvm/test/Transforms/PlaceSafepoints/libcall.ll b/llvm/test/Transforms/PlaceSafepoints/libcall.ll index 89090ba1b243cc..6e26f924a5ba3d 100644 --- a/llvm/test/Transforms/PlaceSafepoints/libcall.ll +++ b/llvm/test/Transforms/PlaceSafepoints/libcall.ll @@ -1,4 +1,6 @@ -; RUN: opt -S -passes=place-safepoints < %s | FileCheck %s +; RUN: opt -S -passes=place-safepoints < %s | FileCheck -check-prefixes=CHECK,WITHLDEXPF %s +; RUN: opt -S -passes=place-safepoints -disable-builtin=ldexp < %s | FileCheck %s + ; Libcalls will not contain a safepoint poll, so check that we insert ; a safepoint in a loop containing a libcall. @@ -17,7 +19,8 @@ loop: ; CHECK-NEXT: %x_loop = phi double [ %x, %entry ], [ %x_exp, %loop ] ; CHECK-NEXT: %x_exp = call double @ldexp(double %x_loop, i32 5) ; CHECK-NEXT: %done = fcmp ogt double %x_exp, 1.5 -; CHECK-NEXT: call void @do_safepoint +; WITHLDEXPF-NEXT: call void @do_safepoint +; CHECK-NEXT: br %x_loop = phi double [ %x, %entry ], [ %x_exp, %loop ] %x_exp = call double @ldexp(double %x_loop, i32 5) nounwind readnone %done = fcmp ogt double %x_exp, 1.5 From 309a881dccb82bf1f101cf138bee3e7400968ed8 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 16 May 2024 16:54:38 +0100 Subject: [PATCH 051/576] [VPlan] Address remaining comments for #85689. Address comments missed when landing https://github.com/llvm/llvm-project/pull/85689. --- llvm/docs/VectorizationPlan.rst | 4 ++-- llvm/docs/conf.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/docs/VectorizationPlan.rst b/llvm/docs/VectorizationPlan.rst index 6496263cf8d97d..73e9e6098175a4 100644 --- a/llvm/docs/VectorizationPlan.rst +++ b/llvm/docs/VectorizationPlan.rst @@ -289,5 +289,5 @@ References .. [9] "Extending LoopVectorizer: OpenMP4.5 SIMD and Outer Loop Auto-Vectorization", Intel Vectorizer Team, LLVM Developers' Meeting 2016. -.. [10] "VPlan: Status Update and Future Roadmap", Florian Hahn, LLVM - Developers' Meeting 2023, https://www.youtube.com/watch?v=SzGP4PgMuLE +.. [10] "VPlan: Status Update and Future Roadmap", Ayal Zaks and Florian Hahn, + LLVM Developers' Meeting 2023, https://www.youtube.com/watch?v=SzGP4PgMuLE diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py index 270f5b33e98552..7f2ed5309606b5 100644 --- a/llvm/docs/conf.py +++ b/llvm/docs/conf.py @@ -222,6 +222,8 @@ # If false, no module index is generated. # latex_domain_indices = True +# If true, figures, tables and code-blocks are automatically numbered if they +# have a caption. numfig = True # -- Options for manual page output -------------------------------------------- From 117d755b1b84c7d379ea5c3d93f8c2ab9bfcde82 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 16 May 2024 17:04:30 +0100 Subject: [PATCH 052/576] [DAG] SimplifyDemandedBits - use ComputeKnownBits instead of getValidShiftAmountConstant to check for constant shift amounts. (#92412) This allows us to handle cases where the constant has already been type legalized behind a bitcast Despite calling ComputeKnownBits I'm not seeing any notable change in compile time. --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 39 ++++++++------- llvm/test/CodeGen/AArch64/sadd_sat_vec.ll | 10 ++-- llvm/test/CodeGen/AArch64/ssub_sat_vec.ll | 10 ++-- llvm/test/CodeGen/PowerPC/pr44183.ll | 9 +--- .../CodeGen/RISCV/rvv/bitreverse-sdnode.ll | 49 ++++++++----------- ...vector_splat-const-shift-of-constmasked.ll | 3 +- 6 files changed, 52 insertions(+), 68 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 38583de03d9c80..3ec6b9b795079d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1732,9 +1732,9 @@ bool TargetLowering::SimplifyDemandedBits( SDValue Op1 = Op.getOperand(1); EVT ShiftVT = Op1.getValueType(); - if (const APInt *SA = - TLO.DAG.getValidShiftAmountConstant(Op, DemandedElts)) { - unsigned ShAmt = SA->getZExtValue(); + KnownBits KnownSA = TLO.DAG.computeKnownBits(Op1, DemandedElts, Depth + 1); + if (KnownSA.isConstant() && KnownSA.getConstant().ult(BitWidth)) { + unsigned ShAmt = KnownSA.getConstant().getZExtValue(); if (ShAmt == 0) return TLO.CombineTo(Op, Op0); @@ -1744,9 +1744,10 @@ bool TargetLowering::SimplifyDemandedBits( // TODO - support non-uniform vector amounts. if (Op0.getOpcode() == ISD::SRL) { if (!DemandedBits.intersects(APInt::getLowBitsSet(BitWidth, ShAmt))) { - if (const APInt *SA2 = - TLO.DAG.getValidShiftAmountConstant(Op0, DemandedElts)) { - unsigned C1 = SA2->getZExtValue(); + KnownBits InnerSA = TLO.DAG.computeKnownBits(Op0.getOperand(1), + DemandedElts, Depth + 1); + if (InnerSA.isConstant() && InnerSA.getConstant().ult(BitWidth)) { + unsigned C1 = InnerSA.getConstant().getZExtValue(); unsigned Opc = ISD::SHL; int Diff = ShAmt - C1; if (Diff < 0) { @@ -1912,9 +1913,9 @@ bool TargetLowering::SimplifyDemandedBits( DemandedElts, Depth + 1)) return TLO.CombineTo(Op, AVG); - if (const APInt *SA = - TLO.DAG.getValidShiftAmountConstant(Op, DemandedElts)) { - unsigned ShAmt = SA->getZExtValue(); + KnownBits KnownSA = TLO.DAG.computeKnownBits(Op1, DemandedElts, Depth + 1); + if (KnownSA.isConstant() && KnownSA.getConstant().ult(BitWidth)) { + unsigned ShAmt = KnownSA.getConstant().getZExtValue(); if (ShAmt == 0) return TLO.CombineTo(Op, Op0); @@ -1924,9 +1925,10 @@ bool TargetLowering::SimplifyDemandedBits( // TODO - support non-uniform vector amounts. if (Op0.getOpcode() == ISD::SHL) { if (!DemandedBits.intersects(APInt::getHighBitsSet(BitWidth, ShAmt))) { - if (const APInt *SA2 = - TLO.DAG.getValidShiftAmountConstant(Op0, DemandedElts)) { - unsigned C1 = SA2->getZExtValue(); + KnownBits InnerSA = TLO.DAG.computeKnownBits(Op0.getOperand(1), + DemandedElts, Depth + 1); + if (InnerSA.isConstant() && InnerSA.getConstant().ult(BitWidth)) { + unsigned C1 = InnerSA.getConstant().getZExtValue(); unsigned Opc = ISD::SRL; int Diff = ShAmt - C1; if (Diff < 0) { @@ -2018,24 +2020,25 @@ bool TargetLowering::SimplifyDemandedBits( DemandedElts, Depth + 1)) return TLO.CombineTo(Op, AVG); - if (const APInt *SA = - TLO.DAG.getValidShiftAmountConstant(Op, DemandedElts)) { - unsigned ShAmt = SA->getZExtValue(); + KnownBits KnownSA = TLO.DAG.computeKnownBits(Op1, DemandedElts, Depth + 1); + if (KnownSA.isConstant() && KnownSA.getConstant().ult(BitWidth)) { + unsigned ShAmt = KnownSA.getConstant().getZExtValue(); if (ShAmt == 0) return TLO.CombineTo(Op, Op0); // fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target // supports sext_inreg. if (Op0.getOpcode() == ISD::SHL) { - if (const APInt *InnerSA = - TLO.DAG.getValidShiftAmountConstant(Op0, DemandedElts)) { + KnownBits InnerSA = TLO.DAG.computeKnownBits(Op0.getOperand(1), + DemandedElts, Depth + 1); + if (InnerSA.isConstant() && InnerSA.getConstant().ult(BitWidth)) { unsigned LowBits = BitWidth - ShAmt; EVT ExtVT = EVT::getIntegerVT(*TLO.DAG.getContext(), LowBits); if (VT.isVector()) ExtVT = EVT::getVectorVT(*TLO.DAG.getContext(), ExtVT, VT.getVectorElementCount()); - if (*InnerSA == ShAmt) { + if (InnerSA.getConstant() == ShAmt) { if (!TLO.LegalOperations() || getOperationAction(ISD::SIGN_EXTEND_INREG, ExtVT) == Legal) return TLO.CombineTo( diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll index 8a0e7661883f21..49ed9897667460 100644 --- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll @@ -149,12 +149,12 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr s0, [x0] ; CHECK-SD-NEXT: ldr s1, [x1] -; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 -; CHECK-SD-NEXT: sshll v1.8h, v1.8b, #0 +; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-SD-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-SD-NEXT: shl v1.4h, v1.4h, #8 ; CHECK-SD-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-SD-NEXT: sqadd v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: ushr v0.4h, v0.4h, #8 ; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: str s0, [x2] ; CHECK-SD-NEXT: ret @@ -364,10 +364,6 @@ define void @v1i16(ptr %px, ptr %py, ptr %pz) nounwind { define <16 x i4> @v16i4(<16 x i4> %x, <16 x i4> %y) nounwind { ; CHECK-LABEL: v16i4: ; CHECK: // %bb.0: -; CHECK-NEXT: shl v0.16b, v0.16b, #4 -; CHECK-NEXT: shl v1.16b, v1.16b, #4 -; CHECK-NEXT: sshr v0.16b, v0.16b, #4 -; CHECK-NEXT: sshr v1.16b, v1.16b, #4 ; CHECK-NEXT: shl v1.16b, v1.16b, #4 ; CHECK-NEXT: shl v0.16b, v0.16b, #4 ; CHECK-NEXT: sqadd v0.16b, v0.16b, v1.16b diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll index a8c1276eadc4fa..f6b58023da1f33 100644 --- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll @@ -150,12 +150,12 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr s0, [x0] ; CHECK-SD-NEXT: ldr s1, [x1] -; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 -; CHECK-SD-NEXT: sshll v1.8h, v1.8b, #0 +; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-SD-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-SD-NEXT: shl v1.4h, v1.4h, #8 ; CHECK-SD-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-SD-NEXT: sqsub v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: ushr v0.4h, v0.4h, #8 ; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: str s0, [x2] ; CHECK-SD-NEXT: ret @@ -365,10 +365,6 @@ define void @v1i16(ptr %px, ptr %py, ptr %pz) nounwind { define <16 x i4> @v16i4(<16 x i4> %x, <16 x i4> %y) nounwind { ; CHECK-LABEL: v16i4: ; CHECK: // %bb.0: -; CHECK-NEXT: shl v0.16b, v0.16b, #4 -; CHECK-NEXT: shl v1.16b, v1.16b, #4 -; CHECK-NEXT: sshr v0.16b, v0.16b, #4 -; CHECK-NEXT: sshr v1.16b, v1.16b, #4 ; CHECK-NEXT: shl v1.16b, v1.16b, #4 ; CHECK-NEXT: shl v0.16b, v0.16b, #4 ; CHECK-NEXT: sqsub v0.16b, v0.16b, v1.16b diff --git a/llvm/test/CodeGen/PowerPC/pr44183.ll b/llvm/test/CodeGen/PowerPC/pr44183.ll index e3dca138090351..4d2c81c35b7fe0 100644 --- a/llvm/test/CodeGen/PowerPC/pr44183.ll +++ b/llvm/test/CodeGen/PowerPC/pr44183.ll @@ -22,13 +22,8 @@ define void @_ZN1m1nEv(ptr %this) local_unnamed_addr nounwind align 2 { ; CHECK-NEXT: rlwimi r4, r3, 0, 0, 0 ; CHECK-NEXT: bl _ZN1llsE1d ; CHECK-NEXT: nop -; CHECK-NEXT: ld r3, 16(r30) -; CHECK-NEXT: ld r4, 8(r30) -; CHECK-NEXT: rldicl r4, r4, 60, 4 -; CHECK-NEXT: sldi r3, r3, 60 -; CHECK-NEXT: or r3, r3, r4 -; CHECK-NEXT: sldi r3, r3, 31 -; CHECK-NEXT: rlwinm r4, r3, 0, 0, 0 +; CHECK-NEXT: ld r3, 8(r30) +; CHECK-NEXT: rlwinm r4, r3, 27, 0, 0 ; CHECK-NEXT: bl _ZN1llsE1d ; CHECK-NEXT: nop ; CHECK-NEXT: addi r1, r1, 48 diff --git a/llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll index 19ae26d2424260..94e945f8032059 100644 --- a/llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll @@ -8,10 +8,9 @@ define @bitreverse_nxv1i8( %va) { ; CHECK-LABEL: bitreverse_nxv1i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf8, ta, ma -; CHECK-NEXT: vsrl.vi v9, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v9, v8 +; CHECK-NEXT: vsll.vi v9, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vsrl.vi v9, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v9, v9, a0 @@ -40,10 +39,9 @@ define @bitreverse_nxv2i8( %va) { ; CHECK-LABEL: bitreverse_nxv2i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma -; CHECK-NEXT: vsrl.vi v9, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v9, v8 +; CHECK-NEXT: vsll.vi v9, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vsrl.vi v9, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v9, v9, a0 @@ -72,10 +70,9 @@ define @bitreverse_nxv4i8( %va) { ; CHECK-LABEL: bitreverse_nxv4i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma -; CHECK-NEXT: vsrl.vi v9, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v9, v8 +; CHECK-NEXT: vsll.vi v9, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vsrl.vi v9, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v9, v9, a0 @@ -104,10 +101,9 @@ define @bitreverse_nxv8i8( %va) { ; CHECK-LABEL: bitreverse_nxv8i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma -; CHECK-NEXT: vsrl.vi v9, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v9, v8 +; CHECK-NEXT: vsll.vi v9, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v9 ; CHECK-NEXT: vsrl.vi v9, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v9, v9, a0 @@ -136,10 +132,9 @@ define @bitreverse_nxv16i8( %va) { ; CHECK-LABEL: bitreverse_nxv16i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma -; CHECK-NEXT: vsrl.vi v10, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v10, v8 +; CHECK-NEXT: vsll.vi v10, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v10 ; CHECK-NEXT: vsrl.vi v10, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v10, v10, a0 @@ -168,10 +163,9 @@ define @bitreverse_nxv32i8( %va) { ; CHECK-LABEL: bitreverse_nxv32i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma -; CHECK-NEXT: vsrl.vi v12, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v12, v8 +; CHECK-NEXT: vsll.vi v12, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v12 ; CHECK-NEXT: vsrl.vi v12, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v12, v12, a0 @@ -200,10 +194,9 @@ define @bitreverse_nxv64i8( %va) { ; CHECK-LABEL: bitreverse_nxv64i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m8, ta, ma -; CHECK-NEXT: vsrl.vi v16, v8, 4 -; CHECK-NEXT: vand.vi v8, v8, 15 -; CHECK-NEXT: vsll.vi v8, v8, 4 -; CHECK-NEXT: vor.vv v8, v16, v8 +; CHECK-NEXT: vsll.vi v16, v8, 4 +; CHECK-NEXT: vsrl.vi v8, v8, 4 +; CHECK-NEXT: vor.vv v8, v8, v16 ; CHECK-NEXT: vsrl.vi v16, v8, 2 ; CHECK-NEXT: li a0, 51 ; CHECK-NEXT: vand.vx v16, v16, a0 diff --git a/llvm/test/CodeGen/X86/vector_splat-const-shift-of-constmasked.ll b/llvm/test/CodeGen/X86/vector_splat-const-shift-of-constmasked.ll index c3e9a2b6841ae2..b39e2bb620d6f4 100644 --- a/llvm/test/CodeGen/X86/vector_splat-const-shift-of-constmasked.ll +++ b/llvm/test/CodeGen/X86/vector_splat-const-shift-of-constmasked.ll @@ -3176,7 +3176,8 @@ define <2 x i64> @test_128_i64_x_2_18446744065119617024_mask_ashr_32(<2 x i64> % ; ; X86-AVX2-LABEL: test_128_i64_x_2_18446744065119617024_mask_ashr_32: ; X86-AVX2: # %bb.0: -; X86-AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0, %xmm0 +; X86-AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [4294967294,4294967294,4294967294,4294967294] +; X86-AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 ; X86-AVX2-NEXT: vpsrad $31, %xmm0, %xmm1 ; X86-AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] ; X86-AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3] From 3abd3d6e597cba5161f37fa0478382fc93a8c9fd Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 11:13:50 -0500 Subject: [PATCH 053/576] [Libomptarget] Remove requires information from plugin (#80345) Summary: Currently this is only used for the zero-copy handling. However, this can easily be moved into `libomptarget` so that we do not need to bother setting the requires flags in the plugin. The advantage here is that we no longer need to do this for every device redundently. Additionally, these requires flags are specifically OpenMP related, so they should live in `libomptarget`. --- .../common/include/PluginInterface.h | 15 +-------------- .../common/src/PluginInterface.cpp | 10 ---------- offload/src/device.cpp | 12 +++--------- 3 files changed, 4 insertions(+), 33 deletions(-) diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h index c396099ac62526..d8d71e3e65a4a0 100644 --- a/offload/plugins-nextgen/common/include/PluginInterface.h +++ b/offload/plugins-nextgen/common/include/PluginInterface.h @@ -958,8 +958,7 @@ struct GenericPluginTy { /// Construct a plugin instance. GenericPluginTy(Triple::ArchType TA) - : RequiresFlags(OMP_REQ_UNDEFINED), GlobalHandler(nullptr), JIT(TA), - RPCServer(nullptr) {} + : GlobalHandler(nullptr), JIT(TA), RPCServer(nullptr) {} virtual ~GenericPluginTy() {} @@ -1028,12 +1027,6 @@ struct GenericPluginTy { return *RPCServer; } - /// Get the OpenMP requires flags set for this plugin. - int64_t getRequiresFlags() const { return RequiresFlags; } - - /// Set the OpenMP requires flags for this plugin. - void setRequiresFlag(int64_t Flags) { RequiresFlags = Flags; } - /// Initialize a device within the plugin. Error initDevice(int32_t DeviceId); @@ -1074,9 +1067,6 @@ struct GenericPluginTy { /// Return the number of devices this plugin can support. int32_t number_of_devices(); - /// Initializes the OpenMP register requires information. - int64_t init_requires(int64_t RequiresFlags); - /// Returns non-zero if the data can be exchanged between the two devices. int32_t is_data_exchangable(int32_t SrcDeviceId, int32_t DstDeviceId); @@ -1203,9 +1193,6 @@ struct GenericPluginTy { /// device was not initialized yet. llvm::SmallVector Devices; - /// OpenMP requires flags. - int64_t RequiresFlags; - /// Pointer to the global handler for this plugin. GenericGlobalHandlerTy *GlobalHandler; diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index 737a8b2a4064f4..253acacc3a9dc8 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -1618,11 +1618,6 @@ int32_t GenericPluginTy::init_device(int32_t DeviceId) { int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); } -int64_t GenericPluginTy::init_requires(int64_t RequiresFlags) { - setRequiresFlag(RequiresFlags); - return OFFLOAD_SUCCESS; -} - int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId, int32_t DstDeviceId) { return isDataExchangable(SrcDeviceId, DstDeviceId); @@ -1964,11 +1959,6 @@ int32_t GenericPluginTy::set_device_offset(int32_t DeviceIdOffset) { } int32_t GenericPluginTy::use_auto_zero_copy(int32_t DeviceId) { - // Automatic zero-copy only applies to programs that did - // not request unified_shared_memory and are deployed on an - // APU with XNACK enabled. - if (getRequiresFlags() & OMP_REQ_UNIFIED_SHARED_MEMORY) - return false; return getDevice(DeviceId).useAutoZeroCopy(); } diff --git a/offload/src/device.cpp b/offload/src/device.cpp index 749b4c567f8e46..943c7782787306 100644 --- a/offload/src/device.cpp +++ b/offload/src/device.cpp @@ -77,15 +77,7 @@ DeviceTy::~DeviceTy() { } llvm::Error DeviceTy::init() { - // Make call to init_requires if it exists for this plugin. - int32_t Ret = 0; - Ret = RTL->init_requires(PM->getRequirements()); - if (Ret != OFFLOAD_SUCCESS) - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "Failed to initialize requirements for device %d\n", DeviceID); - - Ret = RTL->init_device(RTLDeviceID); + int32_t Ret = RTL->init_device(RTLDeviceID); if (Ret != OFFLOAD_SUCCESS) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Failed to initialize device %d\n", @@ -285,5 +277,7 @@ void DeviceTy::dumpOffloadEntries() { } bool DeviceTy::useAutoZeroCopy() { + if (PM->getRequirements() & OMP_REQ_UNIFIED_SHARED_MEMORY) + return false; return RTL->use_auto_zero_copy(RTLDeviceID); } From b28766eb3f20354d1d7a34ea83b9d915c3715032 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 16 May 2024 09:15:17 -0700 Subject: [PATCH 054/576] [Arm64EC] Correctly handle sret in entry thunks. (#92326) I accidentally left out the code to transfer sret attributes to entry thunks, so values weren't being passed in the right registers, and the sret pointer wasn't returned in the correct register. Fixes #90229 --- .../AArch64/AArch64Arm64ECCallLowering.cpp | 9 ++++- .../CodeGen/AArch64/arm64ec-entry-thunks.ll | 36 +++++++++++-------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp index dddc181b031444..0ec15d34cd4a90 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -512,7 +512,14 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) { // Call the function passed to the thunk. Value *Callee = Thunk->getArg(0); Callee = IRB.CreateBitCast(Callee, PtrTy); - Value *Call = IRB.CreateCall(Arm64Ty, Callee, Args); + CallInst *Call = IRB.CreateCall(Arm64Ty, Callee, Args); + + auto SRetAttr = F->getAttributes().getParamAttr(0, Attribute::StructRet); + auto InRegAttr = F->getAttributes().getParamAttr(0, Attribute::InReg); + if (SRetAttr.isValid() && !InRegAttr.isValid()) { + Thunk->addParamAttr(1, SRetAttr); + Call->addParamAttr(0, SRetAttr); + } Value *RetVal = Call; if (TransformDirectToSRet) { diff --git a/llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll b/llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll index c00c9bfe127e8a..e9556b9d5cbeef 100644 --- a/llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll +++ b/llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll @@ -222,12 +222,12 @@ define i8 @matches_has_sret() nounwind { } %TSRet = type { i64, i64 } -define void @has_aligned_sret(ptr align 32 sret(%TSRet)) nounwind { -; CHECK-LABEL: .def $ientry_thunk$cdecl$m16$v; -; CHECK: .section .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m16$v +define void @has_aligned_sret(ptr align 32 sret(%TSRet), i32) nounwind { +; CHECK-LABEL: .def $ientry_thunk$cdecl$m16$i8; +; CHECK: .section .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m16$i8 ; CHECK: // %bb.0: -; CHECK-NEXT: stp q6, q7, [sp, #-176]! // 32-byte Folded Spill -; CHECK-NEXT: .seh_save_any_reg_px q6, 176 +; CHECK-NEXT: stp q6, q7, [sp, #-192]! // 32-byte Folded Spill +; CHECK-NEXT: .seh_save_any_reg_px q6, 192 ; CHECK-NEXT: stp q8, q9, [sp, #32] // 32-byte Folded Spill ; CHECK-NEXT: .seh_save_any_reg_p q8, 32 ; CHECK-NEXT: stp q10, q11, [sp, #64] // 32-byte Folded Spill @@ -236,17 +236,25 @@ define void @has_aligned_sret(ptr align 32 sret(%TSRet)) nounwind { ; CHECK-NEXT: .seh_save_any_reg_p q12, 96 ; CHECK-NEXT: stp q14, q15, [sp, #128] // 32-byte Folded Spill ; CHECK-NEXT: .seh_save_any_reg_p q14, 128 -; CHECK-NEXT: stp x29, x30, [sp, #160] // 16-byte Folded Spill -; CHECK-NEXT: .seh_save_fplr 160 -; CHECK-NEXT: add x29, sp, #160 -; CHECK-NEXT: .seh_add_fp 160 +; CHECK-NEXT: str x19, [sp, #160] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x19, 160 +; CHECK-NEXT: stp x29, x30, [sp, #168] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 168 +; CHECK-NEXT: add x29, sp, #168 +; CHECK-NEXT: .seh_add_fp 168 ; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x19, x0 +; CHECK-NEXT: mov x8, x0 +; CHECK-NEXT: mov x0, x1 ; CHECK-NEXT: blr x9 ; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_ret ; CHECK-NEXT: ldr x0, [x8, :lo12:__os_arm64x_dispatch_ret] +; CHECK-NEXT: mov x8, x19 ; CHECK-NEXT: .seh_startepilogue -; CHECK-NEXT: ldp x29, x30, [sp, #160] // 16-byte Folded Reload -; CHECK-NEXT: .seh_save_fplr 160 +; CHECK-NEXT: ldp x29, x30, [sp, #168] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 168 +; CHECK-NEXT: ldr x19, [sp, #160] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x19, 160 ; CHECK-NEXT: ldp q14, q15, [sp, #128] // 32-byte Folded Reload ; CHECK-NEXT: .seh_save_any_reg_p q14, 128 ; CHECK-NEXT: ldp q12, q13, [sp, #96] // 32-byte Folded Reload @@ -255,8 +263,8 @@ define void @has_aligned_sret(ptr align 32 sret(%TSRet)) nounwind { ; CHECK-NEXT: .seh_save_any_reg_p q10, 64 ; CHECK-NEXT: ldp q8, q9, [sp, #32] // 32-byte Folded Reload ; CHECK-NEXT: .seh_save_any_reg_p q8, 32 -; CHECK-NEXT: ldp q6, q7, [sp], #176 // 32-byte Folded Reload -; CHECK-NEXT: .seh_save_any_reg_px q6, 176 +; CHECK-NEXT: ldp q6, q7, [sp], #192 // 32-byte Folded Reload +; CHECK-NEXT: .seh_save_any_reg_px q6, 192 ; CHECK-NEXT: .seh_endepilogue ; CHECK-NEXT: br x0 ; CHECK-NEXT: .seh_endfunclet @@ -457,7 +465,7 @@ define %T2 @simple_struct(%T1 %0, %T2 %1, %T3, %T4) nounwind { ; CHECK-NEXT: .symidx $ientry_thunk$cdecl$i8$v ; CHECK-NEXT: .word 1 ; CHECK-NEXT: .symidx "#has_aligned_sret" -; CHECK-NEXT: .symidx $ientry_thunk$cdecl$m16$v +; CHECK-NEXT: .symidx $ientry_thunk$cdecl$m16$i8 ; CHECK-NEXT: .word 1 ; CHECK-NEXT: .symidx "#small_array" ; CHECK-NEXT: .symidx $ientry_thunk$cdecl$m2$m2F8 From b82fd5d75cff87f7480a24d4a16ea8400cc35c86 Mon Sep 17 00:00:00 2001 From: pvanhout Date: Thu, 16 May 2024 18:15:55 +0200 Subject: [PATCH 055/576] [GlobalISel] Initialize variables in IndexedLoadStoreMatchInfo --- llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index ecaece8b683423..87cff154b4eb50 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -56,9 +56,9 @@ struct IndexedLoadStoreMatchInfo { Register Addr; Register Base; Register Offset; - bool RematOffset; // True if Offset is a constant that needs to be - // rematerialized before the new load/store. - bool IsPre; + bool RematOffset = false; // True if Offset is a constant that needs to be + // rematerialized before the new load/store. + bool IsPre = false; }; struct PtrAddChain { From e8692b88bec1d43325804d75166d9483d6c17fc7 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 16 May 2024 18:18:37 +0200 Subject: [PATCH 056/576] [NewPM] Add pass options for InternalizePass to preserve GVs (reland) (#92383) Reland of https://github.com/llvm/llvm-project/pull/91334, which broke the gcc7 buildbot and was reverted in https://github.com/llvm/llvm-project/pull/92321. Work around the failure by being explicit about returning an `Expected`. cc @joker-eph --- llvm/lib/Passes/PassBuilder.cpp | 18 ++++++++++++++++++ llvm/lib/Passes/PassRegistry.def | 15 ++++++++++++++- llvm/test/Transforms/Internalize/lists.ll | 5 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e4131706aba015..734ca4d5deec98 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1142,6 +1142,24 @@ Expected parseGlobalMergeOptions(StringRef Params) { return Result; } +Expected> parseInternalizeGVs(StringRef Params) { + SmallVector PreservedGVs; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName.consume_front("preserve-gv=")) { + PreservedGVs.push_back(ParamName.str()); + } else { + return make_error( + formatv("invalid Internalize pass parameter '{0}' ", ParamName).str(), + inconvertibleErrorCode()); + } + } + + return Expected>(std::move(PreservedGVs)); +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index e5ce6cb7da649f..50682ca4970f19 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -78,7 +78,6 @@ MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass()) MODULE_PASS("instrorderfile", InstrOrderFilePass()) MODULE_PASS("instrprof", InstrProfilingLoweringPass()) MODULE_PASS("ctx-instr-lower", PGOCtxProfLoweringPass()) -MODULE_PASS("internalize", InternalizePass()) MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) MODULE_PASS("iroutliner", IROutlinerPass()) MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass()) @@ -175,6 +174,20 @@ MODULE_PASS_WITH_PARAMS( "hwasan", "HWAddressSanitizerPass", [](HWAddressSanitizerOptions Opts) { return HWAddressSanitizerPass(Opts); }, parseHWASanPassOptions, "kernel;recover") +MODULE_PASS_WITH_PARAMS( + "internalize", "InternalizePass", + [](SmallVector PreservedGVs) { + if (PreservedGVs.empty()) + return InternalizePass(); + auto MustPreserveGV = [=](const GlobalValue &GV) { + for (auto &PreservedGV : PreservedGVs) + if (GV.getName() == PreservedGV) + return true; + return false; + }; + return InternalizePass(MustPreserveGV); + }, + parseInternalizeGVs, "preserve-gv=GV") MODULE_PASS_WITH_PARAMS( "ipsccp", "IPSCCPPass", [](IPSCCPOptions Opts) { return IPSCCPPass(Opts); }, parseIPSCCPOptions, "no-func-spec;func-spec") diff --git a/llvm/test/Transforms/Internalize/lists.ll b/llvm/test/Transforms/Internalize/lists.ll index df408f906b7806..83dad03d75eae1 100644 --- a/llvm/test/Transforms/Internalize/lists.ll +++ b/llvm/test/Transforms/Internalize/lists.ll @@ -13,6 +13,11 @@ ; -file and -list options should be merged, the apifile contains foo and j ; RUN: opt < %s -passes=internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s +; specifying through pass builder option +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_J %s +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_AND_BAR %s +; RUN: opt < %s -passes='internalize' -S | FileCheck --check-prefix=FOO_J_AND_BAR %s + ; ALL: @i = internal global ; FOO_AND_J: @i = internal global ; FOO_AND_BAR: @i = internal global From ce67fcf15f4ffac00a715cf724bc72e37f063064 Mon Sep 17 00:00:00 2001 From: SunilKuravinakop <98882378+SunilKuravinakop@users.noreply.github.com> Date: Thu, 16 May 2024 21:55:53 +0530 Subject: [PATCH 057/576] Avoid unevaluated implicit private (#92055) For every variable used under `#pragma omp task` directive (`DeclRefExpr`) an ImplicitPrivateVariable is created in the AST, if `private` or `shared` clauses are not present. If the variable has the property of `non_odr_use_unevaluated` e.g. for statements which use `sizeof( i )` `i` will have `non_odr_use_unevaluated` . In such cases CodeGen was asserting by avoiding emitting of LLVM IR for such variables. To prevent this assertion this checkin avoids adding the ImplicitPrivateVariable for variables with `non_odr_use_unevaluated`. --------- Authored-by: Sunil Kuravinakop --- clang/lib/Sema/SemaOpenMP.cpp | 3 +- clang/test/OpenMP/task_ast_print.cpp | 41 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7d00cf6fb5b6a1..6110e5229b076c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3757,7 +3757,8 @@ class DSAAttrChecker final : public StmtVisitor { void VisitDeclRefExpr(DeclRefExpr *E) { if (TryCaptureCXXThisMembers || E->isTypeDependent() || E->isValueDependent() || E->containsUnexpandedParameterPack() || - E->isInstantiationDependent()) + E->isInstantiationDependent() || + E->isNonOdrUse() == clang::NOUR_Unevaluated) return; if (auto *VD = dyn_cast(E->getDecl())) { // Check the datasharing rules for the expressions in the clauses. diff --git a/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp index 12923e6ab42441..2a6b8908a1e2dc 100644 --- a/clang/test/OpenMP/task_ast_print.cpp +++ b/clang/test/OpenMP/task_ast_print.cpp @@ -5,6 +5,7 @@ // RUN: %clang_cc1 -verify -Wno-vla -fopenmp-simd -ast-print %s | FileCheck %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -ast-dump %s | FileCheck %s --check-prefix=DUMP // expected-no-diagnostics #ifndef HEADER @@ -208,4 +209,44 @@ int main(int argc, char **argv) { extern template int S::TS; extern template long S::TS; +// DUMP-LABEL: FunctionDecl {{.*}} implicit_firstprivate +void +implicit_firstprivate() { + +#pragma omp parallel num_threads(1) + { + int i = 0; + // DUMP: OMPTaskDirective + // DUMP-NEXT: OMPFirstprivateClause + // DUMP-NOT: DeclRefExpr {{.+}} 'i' {{.+}} non_odr_use_unevaluated + // DUMP: DeclRefExpr {{.+}} 'i' 'int' refers_to_enclosing_variable_or_capture + // DUMP: CapturedStmt + // DUMP: BinaryOperator {{.+}} 'int' lvalue '=' + // DUMP-NEXT: DeclRefExpr {{.+}} 'j' 'int' + // DUMP: DeclRefExpr {{.+}} 'i' {{.+}} non_odr_use_unevaluated + #pragma omp task + { + int j = sizeof(i); + j = i; + } + } +} + +// DUMP-LABEL: FunctionDecl {{.*}} no_implicit_firstprivate +void +no_implicit_firstprivate() { + +#pragma omp parallel num_threads(1) + { + int i = 0; + // DUMP: OMPTaskDirective + // DUMP-NEXT: CapturedStmt + // DUMP: DeclRefExpr {{.+}} 'i' {{.+}} non_odr_use_unevaluated refers_to_enclosing_variable_or_capture + #pragma omp task + { + int j = sizeof(i); + } + } +} + #endif From 033fa81480a7e8d0a6cf2f72b52232275145d105 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 11:47:57 -0500 Subject: [PATCH 058/576] [Offload][NFC] Remove unused files following static plugins Summary: Forgot to remove these when I landed the initial patch, they are no longer used. --- offload/include/Shared/PluginAPI.h | 232 --------------------------- offload/include/Shared/PluginAPI.inc | 51 ------ 2 files changed, 283 deletions(-) delete mode 100644 offload/include/Shared/PluginAPI.h delete mode 100644 offload/include/Shared/PluginAPI.inc diff --git a/offload/include/Shared/PluginAPI.h b/offload/include/Shared/PluginAPI.h deleted file mode 100644 index ecf669c774f142..00000000000000 --- a/offload/include/Shared/PluginAPI.h +++ /dev/null @@ -1,232 +0,0 @@ -//===-- Shared/PluginAPI.h - Target independent plugin API ------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines an interface between target independent OpenMP offload -// runtime library libomptarget and target dependent plugin. -// -//===----------------------------------------------------------------------===// - -#ifndef OMPTARGET_SHARED_PLUGIN_API_H -#define OMPTARGET_SHARED_PLUGIN_API_H - -#include -#include - -#include "Shared/APITypes.h" - -extern "C" { - -// First method called on the plugin -int32_t __tgt_rtl_init_plugin(); - -// Return the number of available devices of the type supported by the -// target RTL. -int32_t __tgt_rtl_number_of_devices(void); - -// Return an integer different from zero if the provided device image can be -// supported by the runtime. The functionality is similar to comparing the -// result of __tgt__rtl__load__binary to NULL. However, this is meant to be a -// lightweight query to determine if the RTL is suitable for an image without -// having to load the library, which can be expensive. -int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image); - -// Return an integer other than zero if the data can be exchaned from SrcDevId -// to DstDevId. If it is data exchangable, the device plugin should provide -// function to move data from source device to destination device directly. -int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDevId, int32_t DstDevId); - -// Initialize the requires flags for the device. -int64_t __tgt_rtl_init_requires(int64_t RequiresFlags); - -// Initialize the specified device. In case of success return 0; otherwise -// return an error code. -int32_t __tgt_rtl_init_device(int32_t ID); - -// Pass an executable image section described by image to the specified -// device and prepare an address table of target entities. In case of error, -// return NULL. Otherwise, return a pointer to the built address table. -// Individual entries in the table may also be NULL, when the corresponding -// offload region is not supported on the target device. -int32_t __tgt_rtl_load_binary(int32_t ID, __tgt_device_image *Image, - __tgt_device_binary *Binary); - -// Look up the device address of the named symbol in the given binary. Returns -// non-zero on failure. -int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, - const char *Name, void **DevicePtr); - -// Look up the device address of the named kernel in the given binary. Returns -// non-zero on failure. -int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, - void **DevicePtr); - -// Allocate data on the particular target device, of the specified size. -// HostPtr is a address of the host data the allocated target data -// will be associated with (HostPtr may be NULL if it is not known at -// allocation time, like for example it would be for target data that -// is allocated by omp_target_alloc() API). Return address of the -// allocated data on the target that will be used by libomptarget.so to -// initialize the target data mapping structures. These addresses are -// used to generate a table of target variables to pass to -// __tgt_rtl_run_region(). The __tgt_rtl_data_alloc() returns NULL in -// case an error occurred on the target device. Kind dictates what allocator -// to use (e.g. shared, host, device). -void *__tgt_rtl_data_alloc(int32_t ID, int64_t Size, void *HostPtr, - int32_t Kind); - -// Pass the data content to the target device using the target address. In case -// of success, return zero. Otherwise, return an error code. -int32_t __tgt_rtl_data_submit(int32_t ID, void *TargetPtr, void *HostPtr, - int64_t Size); - -int32_t __tgt_rtl_data_submit_async(int32_t ID, void *TargetPtr, void *HostPtr, - int64_t Size, __tgt_async_info *AsyncInfo); - -// Retrieve the data content from the target device using its address. In case -// of success, return zero. Otherwise, return an error code. -int32_t __tgt_rtl_data_retrieve(int32_t ID, void *HostPtr, void *TargetPtr, - int64_t Size); - -// Asynchronous version of __tgt_rtl_data_retrieve -int32_t __tgt_rtl_data_retrieve_async(int32_t ID, void *HostPtr, - void *TargetPtr, int64_t Size, - __tgt_async_info *AsyncInfo); - -// Copy the data content from one target device to another target device using -// its address. This operation does not need to copy data back to host and then -// from host to another device. In case of success, return zero. Otherwise, -// return an error code. -int32_t __tgt_rtl_data_exchange(int32_t SrcID, void *SrcPtr, int32_t DstID, - void *DstPtr, int64_t Size); - -// Asynchronous version of __tgt_rtl_data_exchange -int32_t __tgt_rtl_data_exchange_async(int32_t SrcID, void *SrcPtr, - int32_t DesID, void *DstPtr, int64_t Size, - __tgt_async_info *AsyncInfo); - -// De-allocate the data referenced by target ptr on the device. In case of -// success, return zero. Otherwise, return an error code. Kind dictates what -// allocator to use (e.g. shared, host, device). -int32_t __tgt_rtl_data_delete(int32_t ID, void *TargetPtr, int32_t Kind); - -// Transfer control to the offloaded entry Entry on the target device. -// Args and Offsets are arrays of NumArgs size of target addresses and -// offsets. An offset should be added to the target address before passing it -// to the outlined function on device side. If AsyncInfo is nullptr, it is -// synchronous; otherwise it is asynchronous. However, AsyncInfo may be -// ignored on some platforms, like x86_64. In that case, it is synchronous. In -// case of success, return zero. Otherwise, return an error code. -int32_t __tgt_rtl_run_target_region(int32_t ID, void *Entry, void **Args, - ptrdiff_t *Offsets, int32_t NumArgs); - -// Asynchronous version of __tgt_rtl_run_target_region -int32_t __tgt_rtl_run_target_region_async(int32_t ID, void *Entry, void **Args, - ptrdiff_t *Offsets, int32_t NumArgs, - __tgt_async_info *AsyncInfo); - -// Similar to __tgt_rtl_run_target_region, but additionally specify the -// number of teams to be created and a number of threads in each team. If -// AsyncInfo is nullptr, it is synchronous; otherwise it is asynchronous. -// However, AsyncInfo may be ignored on some platforms, like x86_64. In that -// case, it is synchronous. -int32_t __tgt_rtl_run_target_team_region(int32_t ID, void *Entry, void **Args, - ptrdiff_t *Offsets, int32_t NumArgs, - int32_t NumTeams, int32_t ThreadLimit, - uint64_t LoopTripcount); - -// Asynchronous version of __tgt_rtl_run_target_team_region -int32_t __tgt_rtl_run_target_team_region_async( - int32_t ID, void *Entry, void **Args, ptrdiff_t *Offsets, int32_t NumArgs, - int32_t NumTeams, int32_t ThreadLimit, uint64_t LoopTripcount, - __tgt_async_info *AsyncInfo); - -// Device synchronization. In case of success, return zero. Otherwise, return an -// error code. -int32_t __tgt_rtl_synchronize(int32_t ID, __tgt_async_info *AsyncInfo); - -// Queries for the completion of asynchronous operations. Instead of blocking -// the calling thread as __tgt_rtl_synchronize, the progress of the operations -// stored in AsyncInfo->Queue is queried in a non-blocking manner, partially -// advancing their execution. If all operations are completed, AsyncInfo->Queue -// is set to nullptr. If there are still pending operations, AsyncInfo->Queue is -// kept as a valid queue. In any case of success (i.e., successful query -// with/without completing all operations), return zero. Otherwise, return an -// error code. -int32_t __tgt_rtl_query_async(int32_t ID, __tgt_async_info *AsyncInfo); - -// Set plugin's internal information flag externally. -void __tgt_rtl_set_info_flag(uint32_t); - -// Print the device information -void __tgt_rtl_print_device_info(int32_t ID); - -// Event related interfaces. It is expected to use the interfaces in the -// following way: -// 1) Create an event on the target device (__tgt_rtl_create_event). -// 2) Record the event based on the status of \p AsyncInfo->Queue at the moment -// of function call to __tgt_rtl_record_event. An event becomes "meaningful" -// once it is recorded, such that others can depend on it. -// 3) Call __tgt_rtl_wait_event to set dependence on the event. Whether the -// operation is blocking or non-blocking depends on the target. It is expected -// to be non-blocking, just set dependence and return. -// 4) Call __tgt_rtl_sync_event to sync the event. It is expected to block the -// thread calling the function. -// 5) Destroy the event (__tgt_rtl_destroy_event). -// { -int32_t __tgt_rtl_create_event(int32_t ID, void **Event); - -int32_t __tgt_rtl_record_event(int32_t ID, void *Event, - __tgt_async_info *AsyncInfo); - -int32_t __tgt_rtl_wait_event(int32_t ID, void *Event, - __tgt_async_info *AsyncInfo); - -int32_t __tgt_rtl_sync_event(int32_t ID, void *Event); - -int32_t __tgt_rtl_destroy_event(int32_t ID, void *Event); -// } - -int32_t __tgt_rtl_init_async_info(int32_t ID, __tgt_async_info **AsyncInfoPtr); -int32_t __tgt_rtl_init_device_info(int32_t ID, __tgt_device_info *DeviceInfoPtr, - const char **ErrStr); - -// lock/pin host memory -int32_t __tgt_rtl_data_lock(int32_t ID, void *HstPtr, int64_t Size, - void **LockedPtr); - -// unlock/unpin host memory -int32_t __tgt_rtl_data_unlock(int32_t ID, void *HstPtr); - -// Notify the plugin about a new mapping starting at the host address \p HstPtr -// and \p Size bytes. The plugin may lock/pin that buffer to achieve optimal -// memory transfers involving that buffer. -int32_t __tgt_rtl_data_notify_mapped(int32_t ID, void *HstPtr, int64_t Size); - -// Notify the plugin about an existing mapping being unmapped, starting at the -// host address \p HstPtr and \p Size bytes. -int32_t __tgt_rtl_data_notify_unmapped(int32_t ID, void *HstPtr); - -// Set the global device identifier offset, such that the plugin may determine a -// unique device number. -int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset); - -int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, - void **TgtArgs, ptrdiff_t *TgtOffsets, - KernelArgsTy *KernelArgs, - __tgt_async_info *AsyncInfoPtr); - -int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, - void *VAddr, bool isRecord, - bool SaveOutput, - uint64_t &ReqPtrArgOffset); - -// Returns true if the device \p DeviceId suggests to use auto zero-copy. -int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId); -} - -#endif // OMPTARGET_SHARED_PLUGIN_API_H diff --git a/offload/include/Shared/PluginAPI.inc b/offload/include/Shared/PluginAPI.inc deleted file mode 100644 index e445da6852f7b4..00000000000000 --- a/offload/include/Shared/PluginAPI.inc +++ /dev/null @@ -1,51 +0,0 @@ -//===-- Shared/PluginAPI.inc - Target independent plugin API ----*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// -// -// This file defines the names of the interface functions between target -// independent offload runtime library and target dependent plugins. -// -//===----------------------------------------------------------------------===// - -// No include guards! - -PLUGIN_API_HANDLE(init_plugin); -PLUGIN_API_HANDLE(is_valid_binary); -PLUGIN_API_HANDLE(is_data_exchangable); -PLUGIN_API_HANDLE(number_of_devices); -PLUGIN_API_HANDLE(init_device); -PLUGIN_API_HANDLE(load_binary); -PLUGIN_API_HANDLE(get_global); -PLUGIN_API_HANDLE(get_function); -PLUGIN_API_HANDLE(data_alloc); -PLUGIN_API_HANDLE(data_submit); -PLUGIN_API_HANDLE(data_submit_async); -PLUGIN_API_HANDLE(data_retrieve); -PLUGIN_API_HANDLE(data_retrieve_async); -PLUGIN_API_HANDLE(data_exchange); -PLUGIN_API_HANDLE(data_exchange_async); -PLUGIN_API_HANDLE(data_delete); -PLUGIN_API_HANDLE(launch_kernel); -PLUGIN_API_HANDLE(init_requires); -PLUGIN_API_HANDLE(synchronize); -PLUGIN_API_HANDLE(query_async); -PLUGIN_API_HANDLE(set_info_flag); -PLUGIN_API_HANDLE(print_device_info); -PLUGIN_API_HANDLE(create_event); -PLUGIN_API_HANDLE(record_event); -PLUGIN_API_HANDLE(wait_event); -PLUGIN_API_HANDLE(sync_event); -PLUGIN_API_HANDLE(destroy_event); -PLUGIN_API_HANDLE(init_async_info); -PLUGIN_API_HANDLE(init_device_info); -PLUGIN_API_HANDLE(data_lock); -PLUGIN_API_HANDLE(data_unlock); -PLUGIN_API_HANDLE(data_notify_mapped); -PLUGIN_API_HANDLE(data_notify_unmapped); -PLUGIN_API_HANDLE(set_device_offset); -PLUGIN_API_HANDLE(initialize_record_replay); -PLUGIN_API_HANDLE(use_auto_zero_copy); From 224116ab9f4d97acb0cca76dc63c1d3d4a253078 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Thu, 16 May 2024 09:34:24 -0700 Subject: [PATCH 059/576] Revert "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (#87933)" This reverts commit 17daa204feadf9c28fc13b7daa69c3cbe865b238. Multiple examples on the PR https://github.com/llvm/llvm-project/pull/87933 show regressions, so reverting until they can be fixed in the followup. --- .../clang/Basic/DiagnosticSemaKinds.td | 6 ++++ clang/lib/Sema/SemaExpr.cpp | 31 +++++------------ clang/lib/Sema/SemaInit.cpp | 19 ++++++++++- clang/test/AST/ast-dump-default-init-json.cpp | 6 ++-- clang/test/AST/ast-dump-default-init.cpp | 2 +- .../Analysis/lifetime-extended-regions.cpp | 9 +++-- clang/test/CXX/drs/cwg16xx.cpp | 2 ++ clang/test/CXX/drs/cwg18xx.cpp | 25 +++++--------- clang/test/CXX/special/class.temporary/p6.cpp | 34 ------------------- clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +-- clang/test/SemaCXX/eval-crashes.cpp | 6 ++-- clang/www/cxx_dr_status.html | 2 +- 12 files changed, 57 insertions(+), 89 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e648b503ac0348..3be9d34b36b063 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10037,6 +10037,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_unsupported_lifetime_extension : Warning< + "lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using a default member initializer " + "is not yet supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 151cda5d68b016..274e1fb1835341 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5618,9 +5618,10 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isUsable()) - Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); + if (Res.isInvalid()) + return ExprError(); + Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -5656,7 +5657,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); + EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -5691,35 +5692,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - - // CWG1815 - // Support lifetime extension of temporary created by aggregate - // initialization using a default member initializer. We should always rebuild - // the initializer if it contains any temporaries (if the initializer - // expression is an ExprWithCleanups). Then make sure the normal lifetime - // extension code recurses into the default initializer and does lifetime - // extension when warranted. - bool ContainsAnyTemporaries = - isa_and_present(Field->getInClassInitializer()); - if (V.HasImmediateCalls || InLifetimeExtendingContext || - ContainsAnyTemporaries) { + if (V.HasImmediateCalls) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; - // Pass down lifetime extending flag, and collect temporaries in - // CreateMaterializeTemporaryExpr when we rewrite the call argument. - keepInLifetimeExtendingContext(); + EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; - - // Rebuild CXXDefaultInitExpr might cause diagnostics. - SFINAETrap Trap(*this); runWithSufficientStackSpace(Loc, [&] { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); - if (Res.isUsable()) + if (!Res.isInvalid()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 708286e192f9c1..2177972f3af2c2 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8066,6 +8066,11 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, enum PathLifetimeKind { /// Lifetime-extend along this path. Extend, + /// We should lifetime-extend, but we don't because (due to technical + /// limitations) we can't. This happens for default member initializers, + /// which we don't clone for every use, so we don't have a unique + /// MaterializeTemporaryExpr to update. + ShouldExtend, /// Do not lifetime extend along this path. NoExtend }; @@ -8077,7 +8082,7 @@ shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) - Kind = PathLifetimeKind::Extend; + Kind = PathLifetimeKind::ShouldExtend; else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) return PathLifetimeKind::NoExtend; } @@ -8197,6 +8202,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, ExtendingEntity->allocateManglingNumber()); // Also visit the temporaries lifetime-extended by this initializer. return true; + + case PathLifetimeKind::ShouldExtend: + // We're supposed to lifetime-extend the temporary along this path (per + // the resolution of DR1815), but we don't support that yet. + // + // FIXME: Properly handle this situation. Perhaps the easiest approach + // would be to clone the initializer expression on each use that would + // lifetime extend its temporaries. + Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) + << RK << DiagRange; + break; + case PathLifetimeKind::NoExtend: // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. diff --git a/clang/test/AST/ast-dump-default-init-json.cpp b/clang/test/AST/ast-dump-default-init-json.cpp index f4949a9c9eedf4..1058b4e3ea4d93 100644 --- a/clang/test/AST/ast-dump-default-init-json.cpp +++ b/clang/test/AST/ast-dump-default-init-json.cpp @@ -789,10 +789,10 @@ void test() { // CHECK-NEXT: "valueCategory": "lvalue", // CHECK-NEXT: "extendingDecl": { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "VarDecl", -// CHECK-NEXT: "name": "b", +// CHECK-NEXT: "kind": "FieldDecl", +// CHECK-NEXT: "name": "a", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "B" +// CHECK-NEXT: "qualType": "const A &" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "storageDuration": "automatic", diff --git a/clang/test/AST/ast-dump-default-init.cpp b/clang/test/AST/ast-dump-default-init.cpp index 26864fbf15424d..15b29f04bf21bf 100644 --- a/clang/test/AST/ast-dump-default-init.cpp +++ b/clang/test/AST/ast-dump-default-init.cpp @@ -13,7 +13,7 @@ void test() { } // CHECK: -CXXDefaultInitExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue has rewritten init // CHECK-NEXT: `-ExprWithCleanups 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue -// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Var 0x{{[^ ]*}} 'b' 'B' +// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Field 0x{{[^ ]*}} 'a' 'const A &' // CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <{{.*}}> 'const A' // CHECK-NEXT: `-CXXFunctionalCastExpr 0x{{[^ ]*}} <{{.*}}> 'A' functional cast to A // CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'A' diff --git a/clang/test/Analysis/lifetime-extended-regions.cpp b/clang/test/Analysis/lifetime-extended-regions.cpp index 4458ad294af7cb..4e98bd4b0403eb 100644 --- a/clang/test/Analysis/lifetime-extended-regions.cpp +++ b/clang/test/Analysis/lifetime-extended-regions.cpp @@ -120,11 +120,10 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference); // expected-warning-re {{&lifetime_extended_object{RefAggregate, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.rx); // expected-warning-re {{&lifetime_extended_object{int, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.ry); // expected-warning-re {{&lifetime_extended_object{Composite, viaReference, S{{[0-9]+}}} }} - - // FIXME: clang currently support extending lifetime of object bound to reference members of aggregates, - // that are created from default member initializer. But CFG and ExprEngine need to be updated to address this change. - // The following expect warning: {{&lifetime_extended_object{Composite, defaultInitExtended, S{{[0-9]+}}} }} - RefAggregate defaultInitExtended{i}; + + // clang does not currently implement extending lifetime of object bound to reference members of aggregates, + // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) + RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }} } diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp index 82ef871939d2c4..cf6b45ceabf2cc 100644 --- a/clang/test/CXX/drs/cwg16xx.cpp +++ b/clang/test/CXX/drs/cwg16xx.cpp @@ -483,6 +483,8 @@ namespace cwg1696 { // cwg1696: 7 const A &a = A(); // #cwg1696-D1-a }; D1 d1 = {}; // #cwg1696-d1 + // since-cxx14-warning@-1 {{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported; lifetime of temporary will end at the end of the full-expression}} + // since-cxx14-note@#cwg1696-D1-a {{initializing field 'a' with default member initializer}} struct D2 { const A &a = A(); // #cwg1696-D2-a diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 89adc283849048..35615076a62880 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -56,7 +56,7 @@ namespace cwg1804 { // cwg1804: 2.7 template struct A { void f1(); - + template void f2(V); @@ -73,7 +73,7 @@ struct A { template struct A { void f1(); - + template void f2(V); @@ -97,7 +97,7 @@ class D { template struct A { void f1(); - + template void f2(V); @@ -206,28 +206,19 @@ namespace cwg1814 { // cwg1814: yes #endif } -namespace cwg1815 { // cwg1815: 19 +namespace cwg1815 { // cwg1815: no #if __cplusplus >= 201402L - struct A { int &&r = 0; }; + // FIXME: needs codegen test + struct A { int &&r = 0; }; // #cwg1815-A A a = {}; + // since-cxx14-warning@-1 {{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported; lifetime of temporary will end at the end of the full-expression}} FIXME + // since-cxx14-note@#cwg1815-A {{initializing field 'r' with default member initializer}} struct B { int &&r = 0; }; // #cwg1815-B // since-cxx14-error@-1 {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} // since-cxx14-note@#cwg1815-B {{initializing field 'r' with default member initializer}} // since-cxx14-note@#cwg1815-b {{in implicit default constructor for 'cwg1815::B' first required here}} B b; // #cwg1815-b - -#if __cplusplus >= 201703L - struct C { const int &r = 0; }; - constexpr C c = {}; // OK, since cwg1815 - static_assert(c.r == 0); - - constexpr int f() { - A a = {}; // OK, since cwg1815 - return a.r; - } - static_assert(f() == 0); -#endif #endif } diff --git a/clang/test/CXX/special/class.temporary/p6.cpp b/clang/test/CXX/special/class.temporary/p6.cpp index a6d2adfd1fd2c5..5554363cc69abb 100644 --- a/clang/test/CXX/special/class.temporary/p6.cpp +++ b/clang/test/CXX/special/class.temporary/p6.cpp @@ -269,40 +269,6 @@ void init_capture_init_list() { // CHECK: } } -void check_dr1815() { // dr1815: yes -#if __cplusplus >= 201402L - - struct A { - int &&r = 0; - ~A() {} - }; - - struct B { - A &&a = A{}; - ~B() {} - }; - B a = {}; - - // CHECK: call {{.*}}block_scope_begin_function - extern void block_scope_begin_function(); - extern void block_scope_end_function(); - block_scope_begin_function(); - { - // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev - // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev - B b = {}; - } - // CHECK: call {{.*}}block_scope_end_function - block_scope_end_function(); - - // CHECK: call {{.*}}some_other_function - extern void some_other_function(); - some_other_function(); - // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev - // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev -#endif -} - namespace P2718R0 { namespace basic { template using T2 = std::list; diff --git a/clang/test/SemaCXX/constexpr-default-arg.cpp b/clang/test/SemaCXX/constexpr-default-arg.cpp index 901123bfb359ff..ec9b2927880bdf 100644 --- a/clang/test/SemaCXX/constexpr-default-arg.cpp +++ b/clang/test/SemaCXX/constexpr-default-arg.cpp @@ -32,8 +32,8 @@ void test_default_arg2() { } // Check that multiple CXXDefaultInitExprs don't cause an assertion failure. -struct A { int &&r = 0; }; +struct A { int &&r = 0; }; // expected-note 2{{default member initializer}} struct B { A x, y; }; -B b = {}; // expected-no-diagnostics +B b = {}; // expected-warning 2{{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported}} } diff --git a/clang/test/SemaCXX/eval-crashes.cpp b/clang/test/SemaCXX/eval-crashes.cpp index a06f60f71e9c7e..017df977b26b7b 100644 --- a/clang/test/SemaCXX/eval-crashes.cpp +++ b/clang/test/SemaCXX/eval-crashes.cpp @@ -25,9 +25,11 @@ namespace pr33140_0b { } namespace pr33140_2 { - struct A { int &&r = 0; }; + // FIXME: The declaration of 'b' below should lifetime-extend two int + // temporaries. + struct A { int &&r = 0; }; // expected-note 2{{initializing field 'r' with default member initializer}} struct B { A x, y; }; - B b = {}; + B b = {}; // expected-warning 2{{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported}} } namespace pr33140_3 { diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index abf5d4ae4676da..2ed79fa21db261 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -10698,7 +10698,7 @@

    C++ defect report implementation status

    1815 CD4 Lifetime extension in aggregate initialization - Clang 19 + No 1816 From bd6c358d01f6ebc3851996e2c29c47b08e992525 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 16 May 2024 09:53:47 -0700 Subject: [PATCH 060/576] [lldb-dap] Update repository in package.json Use https://github.com/llvm/vscode-lldb instead of the monorepo, for consistency with the other two extensions (mlir, clangd). --- lldb/tools/lldb-dap/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index aeb24445551c1e..45fcb83cf81d89 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -8,7 +8,7 @@ "license": "Apache 2.0 License with LLVM exceptions", "repository": { "type": "git", - "url": "https://github.com/llvm/llvm-project.git" + "url": "https://github.com/llvm/vscode-lldb.git" }, "bugs": { "url": "https://github.com/llvm/llvm-project/issues" From f03430f5e37e8eb64878dc538b05210adea2d80f Mon Sep 17 00:00:00 2001 From: Xiaoyang Liu Date: Thu, 16 May 2024 13:25:04 -0400 Subject: [PATCH 061/576] [libc++] LWG3672: `common_iterator::operator->()` should return by value (#87899) ## Abstract This pull request implements LWG3672: `common_iterator::operator->()` should return by value. The current implementation specifies that this function should return the underlying pointer by reference (`T* const&`), but it would be more intuitive to return it by value (`T*`). ## Reference - [Draft C++ Standard: [common.iter.access]](https://eel.is/c++draft/common.iter.access) - [LWG3672](https://cplusplus.github.io/LWG/issue3672) --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- libcxx/include/__iterator/common_iterator.h | 2 +- .../iterators.common/arrow.pass.cpp | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index 04f6e23375acdf..d421feef8db972 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -165,7 +165,7 @@ "`3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","July 2022","|Complete|","15.0" "`3670 `__","``Cpp17InputIterators`` don't have integer-class difference types","July 2022","","","|ranges|" "`3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","","" -"`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|" +"`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","|Complete|","19.0","|ranges|" "`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" "`3687 `__","``expected`` move constructor should move","July 2022","|Complete|","16.0" "`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|" diff --git a/libcxx/include/__iterator/common_iterator.h b/libcxx/include/__iterator/common_iterator.h index 7b3f4610d5319a..199de2cc7337b0 100644 --- a/libcxx/include/__iterator/common_iterator.h +++ b/libcxx/include/__iterator/common_iterator.h @@ -124,7 +124,7 @@ class common_iterator { } template - _LIBCPP_HIDE_FROM_ABI decltype(auto) operator->() const + _LIBCPP_HIDE_FROM_ABI auto operator->() const requires indirectly_readable && (requires(const _I2& __i) { __i.operator->(); } || is_reference_v> || constructible_from, iter_reference_t<_I2>>) diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp index ec992eb98b4bc8..ee7628b3e4dbb6 100644 --- a/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp @@ -8,7 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// decltype(auto) operator->() const +// auto operator->() const // requires see below; #include @@ -28,11 +28,11 @@ void test() { using Common = std::common_iterator>; Common common(iter); - std::same_as auto result = common.operator->(); + std::same_as decltype(auto) result = common.operator->(); assert(base(result) == buffer); Common const ccommon(iter); - std::same_as auto cresult = ccommon.operator->(); + std::same_as decltype(auto) cresult = ccommon.operator->(); assert(base(cresult) == buffer); }; @@ -48,11 +48,11 @@ void test() { using Common = std::common_iterator>; Common common(iter); - std::same_as auto result = common.operator->(); + std::same_as decltype(auto) result = common.operator->(); assert(result == buffer); Common const ccommon(iter); - std::same_as auto cresult = ccommon.operator->(); + std::same_as decltype(auto) cresult = ccommon.operator->(); assert(cresult == buffer); }; @@ -72,14 +72,14 @@ void test() { using Common = std::common_iterator>; Common common(iter); - auto proxy = common.operator->(); - std::same_as auto result = proxy.operator->(); + auto proxy = common.operator->(); + std::same_as decltype(auto) result = proxy.operator->(); assert(result != buffer); // we copied to a temporary proxy assert(*result == *buffer); Common const ccommon(iter); - auto cproxy = ccommon.operator->(); - std::same_as auto cresult = cproxy.operator->(); + auto cproxy = ccommon.operator->(); + std::same_as decltype(auto) cresult = cproxy.operator->(); assert(cresult != buffer); // we copied to a temporary proxy assert(*cresult == *buffer); }; From c7ae8c6639370ccbc583dca019bbb78761ce423d Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Thu, 16 May 2024 21:30:31 +0400 Subject: [PATCH 062/576] [lldb] Fixed the DAP tests in case of a remote target (#92416) These tests are based on dap_server which runs locally. These tests failed in case of Windows host and Linux target. --- lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py | 1 + lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py | 1 + 2 files changed, 2 insertions(+) diff --git a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py index 2b3ec656c107a5..3250a5093cac47 100644 --- a/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py +++ b/lldb/test/API/tools/lldb-dap/completions/TestDAP_completions.py @@ -19,6 +19,7 @@ def verify_completions(self, actual_list, expected_list, not_expected_list=[]): self.assertNotIn(not_expected_item, actual_list) @skipIfWindows + @skipIfRemote @skipIf(compiler="clang", compiler_version=["<", "17.0"]) def test_completions(self): """ diff --git a/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py b/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py index 8c2c0154ba65c0..58a67d8164368d 100644 --- a/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py +++ b/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py @@ -9,6 +9,7 @@ class TestDAP_exception(lldbdap_testcase.DAPTestCaseBase): + @skipIfRemote @skipIfWindows def test_stopped_description(self): """ From 0dc80e4b2640f80a5b421e6e636d2a7243150917 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 16 May 2024 10:35:45 -0700 Subject: [PATCH 063/576] [memprof] Group MemProf data structures into a struct (NFC) (#92360) This patch groups the three Memprof data structures into a struct named IndexedMemProfData and teaches InstrProfWriter to use it. This way, we can pass IndexedMemProfData to writeMemProf and its helpers instead of individual data structures. As a follow-up, we can use the new struct in MemProfReader also. That in turn allows loadInput in llvm-profdata to move the MemProf data into the writer context, saving a few seconds for a large MemProf profile. --- .../llvm/ProfileData/InstrProfWriter.h | 14 +-- llvm/include/llvm/ProfileData/MemProf.h | 14 +++ llvm/lib/ProfileData/InstrProfWriter.cpp | 86 ++++++++----------- 3 files changed, 50 insertions(+), 64 deletions(-) diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h index 08db8fa6e7ef2c..1714f3b6cf3ae3 100644 --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -51,18 +51,8 @@ class InstrProfWriter { SmallVector TemporalProfTraces; std::mt19937 RNG; - // A map to hold memprof data per function. The lower 64 bits obtained from - // the md5 hash of the function name is used to index into the map. - llvm::MapVector - MemProfRecordData; - // A map to hold frame id to frame mappings. The mappings are used to - // convert IndexedMemProfRecord to MemProfRecords with frame information - // inline. - llvm::MapVector MemProfFrameData; - - // A map to hold call stack id to call stacks. - llvm::MapVector> - MemProfCallStackData; + // The MemProf data. + memprof::IndexedMemProfData MemProfData; // List of binary ids. std::vector BinaryIds; diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 60bff76d0e4649..66a99f16cdb638 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -833,6 +833,20 @@ template struct CallStackIdConverter { } }; +struct IndexedMemProfData { + // A map to hold memprof data per function. The lower 64 bits obtained from + // the md5 hash of the function name is used to index into the map. + llvm::MapVector RecordData; + + // A map to hold frame id to frame mappings. The mappings are used to + // convert IndexedMemProfRecord to MemProfRecords with frame information + // inline. + llvm::MapVector FrameData; + + // A map to hold call stack id to call stacks. + llvm::MapVector> CallStackData; +}; + // Verify that each CallStackId is computed with hashCallStack. This function // is intended to help transition from CallStack to CSId in // IndexedAllocationInfo. diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index c941b9d89df388..aeafd429e8badd 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -273,7 +273,7 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash, void InstrProfWriter::addMemProfRecord( const Function::GUID Id, const memprof::IndexedMemProfRecord &Record) { - auto [Iter, Inserted] = MemProfRecordData.insert({Id, Record}); + auto [Iter, Inserted] = MemProfData.RecordData.insert({Id, Record}); // If we inserted a new record then we are done. if (Inserted) { return; @@ -285,7 +285,7 @@ void InstrProfWriter::addMemProfRecord( bool InstrProfWriter::addMemProfFrame(const memprof::FrameId Id, const memprof::Frame &Frame, function_ref Warn) { - auto [Iter, Inserted] = MemProfFrameData.insert({Id, Frame}); + auto [Iter, Inserted] = MemProfData.FrameData.insert({Id, Frame}); // If a mapping already exists for the current frame id and it does not // match the new mapping provided then reset the existing contents and bail // out. We don't support the merging of memprof data whose Frame -> Id @@ -302,7 +302,7 @@ bool InstrProfWriter::addMemProfCallStack( const memprof::CallStackId CSId, const llvm::SmallVector &CallStack, function_ref Warn) { - auto [Iter, Inserted] = MemProfCallStackData.insert({CSId, CallStack}); + auto [Iter, Inserted] = MemProfData.CallStackData.insert({CSId, CallStack}); // If a mapping already exists for the current call stack id and it does not // match the new mapping provided then reset the existing contents and bail // out. We don't support the merging of memprof data whose CallStack -> Id @@ -389,22 +389,22 @@ void InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW, addTemporalProfileTraces(IPW.TemporalProfTraces, IPW.TemporalProfTraceStreamSize); - MemProfFrameData.reserve(IPW.MemProfFrameData.size()); - for (auto &[FrameId, Frame] : IPW.MemProfFrameData) { + MemProfData.FrameData.reserve(IPW.MemProfData.FrameData.size()); + for (auto &[FrameId, Frame] : IPW.MemProfData.FrameData) { // If we weren't able to add the frame mappings then it doesn't make sense // to try to merge the records from this profile. if (!addMemProfFrame(FrameId, Frame, Warn)) return; } - MemProfCallStackData.reserve(IPW.MemProfCallStackData.size()); - for (auto &[CSId, CallStack] : IPW.MemProfCallStackData) { + MemProfData.CallStackData.reserve(IPW.MemProfData.CallStackData.size()); + for (auto &[CSId, CallStack] : IPW.MemProfData.CallStackData) { if (!addMemProfCallStack(CSId, CallStack, Warn)) return; } - MemProfRecordData.reserve(IPW.MemProfRecordData.size()); - for (auto &[GUID, Record] : IPW.MemProfRecordData) { + MemProfData.RecordData.reserve(IPW.MemProfData.RecordData.size()); + for (auto &[GUID, Record] : IPW.MemProfData.RecordData) { addMemProfRecord(GUID, Record); } } @@ -499,11 +499,8 @@ static uint64_t writeMemProfCallStacks( return CallStackTableGenerator.Emit(OS.OS); } -static Error writeMemProfV0( - ProfOStream &OS, - llvm::MapVector - &MemProfRecordData, - llvm::MapVector &MemProfFrameData) { +static Error writeMemProfV0(ProfOStream &OS, + memprof::IndexedMemProfData &MemProfData) { uint64_t HeaderUpdatePos = OS.tell(); OS.write(0ULL); // Reserve space for the memprof record table offset. OS.write(0ULL); // Reserve space for the memprof frame payload offset. @@ -512,11 +509,11 @@ static Error writeMemProfV0( auto Schema = memprof::getFullSchema(); writeMemProfSchema(OS, Schema); - uint64_t RecordTableOffset = - writeMemProfRecords(OS, MemProfRecordData, &Schema, memprof::Version0); + uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData, + &Schema, memprof::Version0); uint64_t FramePayloadOffset = OS.tell(); - uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfFrameData); + uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData); uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset}; OS.patch({{HeaderUpdatePos, Header, std::size(Header)}}); @@ -524,11 +521,8 @@ static Error writeMemProfV0( return Error::success(); } -static Error writeMemProfV1( - ProfOStream &OS, - llvm::MapVector - &MemProfRecordData, - llvm::MapVector &MemProfFrameData) { +static Error writeMemProfV1(ProfOStream &OS, + memprof::IndexedMemProfData &MemProfData) { OS.write(memprof::Version1); uint64_t HeaderUpdatePos = OS.tell(); OS.write(0ULL); // Reserve space for the memprof record table offset. @@ -538,11 +532,11 @@ static Error writeMemProfV1( auto Schema = memprof::getFullSchema(); writeMemProfSchema(OS, Schema); - uint64_t RecordTableOffset = - writeMemProfRecords(OS, MemProfRecordData, &Schema, memprof::Version1); + uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData, + &Schema, memprof::Version1); uint64_t FramePayloadOffset = OS.tell(); - uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfFrameData); + uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData); uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset}; OS.patch({{HeaderUpdatePos, Header, std::size(Header)}}); @@ -550,14 +544,9 @@ static Error writeMemProfV1( return Error::success(); } -static Error writeMemProfV2( - ProfOStream &OS, - llvm::MapVector - &MemProfRecordData, - llvm::MapVector &MemProfFrameData, - llvm::MapVector> - &MemProfCallStackData, - bool MemProfFullSchema) { +static Error writeMemProfV2(ProfOStream &OS, + memprof::IndexedMemProfData &MemProfData, + bool MemProfFullSchema) { OS.write(memprof::Version2); uint64_t HeaderUpdatePos = OS.tell(); OS.write(0ULL); // Reserve space for the memprof record table offset. @@ -571,15 +560,15 @@ static Error writeMemProfV2( Schema = memprof::getFullSchema(); writeMemProfSchema(OS, Schema); - uint64_t RecordTableOffset = - writeMemProfRecords(OS, MemProfRecordData, &Schema, memprof::Version2); + uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData, + &Schema, memprof::Version2); uint64_t FramePayloadOffset = OS.tell(); - uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfFrameData); + uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData); uint64_t CallStackPayloadOffset = OS.tell(); uint64_t CallStackTableOffset = - writeMemProfCallStacks(OS, MemProfCallStackData); + writeMemProfCallStacks(OS, MemProfData.CallStackData); uint64_t Header[] = { RecordTableOffset, FramePayloadOffset, FrameTableOffset, @@ -603,23 +592,17 @@ static Error writeMemProfV2( // uint64_t Schema entry N - 1 // OnDiskChainedHashTable MemProfRecordData // OnDiskChainedHashTable MemProfFrameData -static Error writeMemProf( - ProfOStream &OS, - llvm::MapVector - &MemProfRecordData, - llvm::MapVector &MemProfFrameData, - llvm::MapVector> - &MemProfCallStackData, - memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema) { - +static Error writeMemProf(ProfOStream &OS, + memprof::IndexedMemProfData &MemProfData, + memprof::IndexedVersion MemProfVersionRequested, + bool MemProfFullSchema) { switch (MemProfVersionRequested) { case memprof::Version0: - return writeMemProfV0(OS, MemProfRecordData, MemProfFrameData); + return writeMemProfV0(OS, MemProfData); case memprof::Version1: - return writeMemProfV1(OS, MemProfRecordData, MemProfFrameData); + return writeMemProfV1(OS, MemProfData); case memprof::Version2: - return writeMemProfV2(OS, MemProfRecordData, MemProfFrameData, - MemProfCallStackData, MemProfFullSchema); + return writeMemProfV2(OS, MemProfData, MemProfFullSchema); } return make_error( @@ -737,8 +720,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { uint64_t MemProfSectionStart = 0; if (static_cast(ProfileKind & InstrProfKind::MemProf)) { MemProfSectionStart = OS.tell(); - if (auto E = writeMemProf(OS, MemProfRecordData, MemProfFrameData, - MemProfCallStackData, MemProfVersionRequested, + if (auto E = writeMemProf(OS, MemProfData, MemProfVersionRequested, MemProfFullSchema)) return E; } From 525bd66fc29fd056ef18118dfff3c9cc05fdd5e3 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 16 May 2024 10:41:06 -0700 Subject: [PATCH 064/576] [lldb-dap] Separate user and developer documentation (#92428) The README.md is what users see when they look for the extension in the Marketplace [1]. Right now, it's a mix of developer documentation (for us) and user documentation. This commit moves the developer docs into `docs` and the lldb website and refocuses the README on using the extension. [1] https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap --- lldb/docs/index.rst | 1 + lldb/docs/resources/lldbdap.md | 97 ++++++++++++++++++++ lldb/tools/lldb-dap/README.md | 156 +++++---------------------------- 3 files changed, 119 insertions(+), 135 deletions(-) create mode 100644 lldb/docs/resources/lldbdap.md diff --git a/lldb/docs/index.rst b/lldb/docs/index.rst index 7a27f6914fa89d..1e7d69002dd3eb 100644 --- a/lldb/docs/index.rst +++ b/lldb/docs/index.rst @@ -161,6 +161,7 @@ interesting areas to contribute to lldb. resources/lldbplatformpackets resources/caveats resources/projects + resources/lldbdap Public C++ API Private C++ API diff --git a/lldb/docs/resources/lldbdap.md b/lldb/docs/resources/lldbdap.md new file mode 100644 index 00000000000000..2d345e26b7e57c --- /dev/null +++ b/lldb/docs/resources/lldbdap.md @@ -0,0 +1,97 @@ +# LLDB-DAP + +The `lldb-dap` tool (formerly `lldb-vscode`) is a command line tool that +implements the [Debug Adapter +Protocol](https://microsoft.github.io/debug-adapter-protocol/). It can be +installed as an extension for Visual Studio Code and other IDEs supporting DAP. +The protocol is easy to run remotely and also can allow other tools and IDEs to +get a full featured debugger with a well defined protocol. + +## Local Installation for Visual Studio Code + +Installing the plug-in is very straightforward and involves just a few steps. + +### Pre-requisites + +- Install a modern version of node (e.g. `v20.0.0`). +- On VS Code, execute the command `Install 'code' command in PATH`. You need to + do it only once. This enables the command `code` in the PATH. + +### Packaging and installation + +```bash +cd /path/to/lldb/tools/lldb-dap +npm install +npm run package # This also compiles the extension. +npm run vscode-install +``` + +On VS Code, set the setting `lldb-dap.executable-path` to the path of your local +build of `lldb-dap`. + +And then you are ready! + +### Updating the extension + +*Note: It's not necessary to update the extension if there has been changes +to `lldb-dap`. The extension needs to be updated only if the TypesScript code +has changed.* + +Updating the extension is pretty much the same process as installing it from +scratch. However, VS Code expects the version number of the upgraded extension +to be greater than the previous one, otherwise the installation step might have +no effect. + +```bash +# Bump version in package.json +cd /path/to/lldb/tools/lldb-dap +npm install +npm run package +npm run vscode-install +``` + +Another way upgrade without bumping the extension version is to first uninstall +the extension, then reload VS Code, and then install it again. This is +an unfortunate limitation of the editor. + +```bash +cd /path/to/lldb/tools/lldb-dap +npm run vscode-uninstall +# Then reload VS Code: reopen the IDE or execute the `Developer: Reload Window` +# command. +npm run package +npm run vscode-install +``` + +### Deploying for Visual Studio Code + +The easiest way to deploy the extension for execution on other machines requires +copying `lldb-dap` and its dependencies into a`./bin` subfolder and then create a +standalone VSIX package. + +```bash +cd /path/to/lldb/tools/lldb-dap +mkdir -p ./bin +cp /path/to/a/built/lldb-dap ./bin/ +cp /path/to/a/built/liblldb.so ./bin/ +npm run package +``` + +This will produce the file `./out/lldb-dap.vsix` that can be distributed. In +this type of installation, users don't need to manually set the path to +`lldb-dap`. The extension will automatically look for it in the `./bin` +subfolder. + +*Note: It's not possible to use symlinks to `lldb-dap`, as the packaging tool +forcefully performs a deep copy of all symlinks.* + +*Note: It's possible to use this kind flow for local installations, but it's +not recommended because updating `lldb-dap` requires rebuilding the extension.* + +## Formatting the Typescript code + +This is also very simple, just run: + +```bash +npm run format +``` diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md index 16ce4672be71c3..8ecbaf7ce98163 100644 --- a/lldb/tools/lldb-dap/README.md +++ b/lldb/tools/lldb-dap/README.md @@ -1,133 +1,19 @@ +# LLDB DAP -# Table of Contents - -- [Table of Contents](#table-of-contents) -- [Introduction](#introduction) -- [Local Installation for Visual Studio Code](#local-installation-for-visual-studio-code) - - [Pre-requisites](#pre-requisites) - - [Packaging and installation](#packaging-and-installation) - - [Updating the extension](#updating-the-extension) - - [Deploying for Visual Studio Code](#deploying-for-visual-studio-code) -- [Formatting the Typescript code](#formatting-the-typescript-code) -- [Configurations](#configurations) - - [Launch Configuration Settings](#launch-configuration-settings) - - [Attaching Settings](#attaching-settings) - - [Example configurations](#example-configurations) - - [Launching](#launching) - - [Attach using PID](#attach-using-pid) - - [Attach by Name](#attach-by-name) - - [Loading a Core File](#loading-a-core-file) - - [Connect to a Debug Server on the Current Machine](#connect-to-a-debug-server-on-the-current-machine) - - [Connect to a Debug Server on Another Machine](#connect-to-a-debug-server-on-another-machine) -- [Custom debugger commands](#custom-debugger-commands) - - [startDebugging](#startdebugging) - - [repl-mode](#repl-mode) - -# Introduction - -The `lldb-dap` tool (formerly `lldb-vscode`) creates a command line tool that -implements the [Debug Adapter -Protocol](https://microsoft.github.io/debug-adapter-protocol/). It can be -installed as an extension for Visual Studio Code and other IDEs supporting DAP. +## `lldb-dap` Configurations + +The extension requires the `lldb-dap` (formerly `lldb-vscode`) binary. It is a +command line tool that implements the [Debug Adapter +Protocol](https://microsoft.github.io/debug-adapter-protocol/). It is used to power the Visual Studio Code extension but can also be used with other IDEs and editors that support DAP. The protocol is easy to run remotely and also can allow other tools and IDEs to get a full featured debugger with a well defined protocol. -# Local Installation for Visual Studio Code - -Installing the plug-in is very straightforward and involves just a few steps. - -## Pre-requisites - -- Install a modern version of node (e.g. `v20.0.0`). -- On VS Code, execute the command `Install 'code' command in PATH`. You need to - do it only once. This enables the command `code` in the PATH. - -## Packaging and installation - -```bash -cd /path/to/lldb/tools/lldb-dap -npm install -npm run package # This also compiles the extension. -npm run vscode-install -``` - -On VS Code, set the setting `lldb-dap.executable-path` to the path of your local -build of `lldb-dap`. - -And then you are ready! - -## Updating the extension - -*Note: It's not necessary to update the extension if there has been changes -to `lldb-dap`. The extension needs to be updated only if the TypesScript code -has changed.* - -Updating the extension is pretty much the same process as installing it from -scratch. However, VS Code expects the version number of the upgraded extension -to be greater than the previous one, otherwise the installation step might have -no effect. - -```bash -# Bump version in package.json -cd /path/to/lldb/tools/lldb-dap -npm install -npm run package -npm run vscode-install -``` - -Another way upgrade without bumping the extension version is to first uninstall -the extension, then reload VS Code, and then install it again. This is -an unfortunate limitation of the editor. - -```bash -cd /path/to/lldb/tools/lldb-dap -npm run vscode-uninstall -# Then reload VS Code: reopen the IDE or execute the `Developer: Reload Window` -# command. -npm run package -npm run vscode-install -``` - -## Deploying for Visual Studio Code - -The easiest way to deploy the extension for execution on other machines requires -copying `lldb-dap` and its dependencies into a`./bin` subfolder and then create a -standalone VSIX package. - -```bash -cd /path/to/lldb/tools/lldb-dap -mkdir -p ./bin -cp /path/to/a/built/lldb-dap ./bin/ -cp /path/to/a/built/liblldb.so ./bin/ -npm run package -``` - -This will produce the file `./out/lldb-dap.vsix` that can be distributed. In -this type of installation, users don't need to manually set the path to -`lldb-dap`. The extension will automatically look for it in the `./bin` -subfolder. - -*Note: It's not possible to use symlinks to `lldb-dap`, as the packaging tool -forcefully performs a deep copy of all symlinks.* - -*Note: It's possible to use this kind flow for local installations, but it's -not recommended because updating `lldb-dap` requires rebuilding the extension.* - -# Formatting the Typescript code - -This is also very simple, just run: - -```bash -npm run format -``` - -# Configurations +## Launching & Attaching Configuration -Launching to attaching require you to create a [launch configuration](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations). This file -defines arguments that get passed to `lldb-dap` and the configuration settings -control how the launch or attach happens. +Launching to attaching require you to create a [launch configuration](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations). +This file defines arguments that get passed to `lldb-dap` and the configuration settings control how the launch or attach happens. -## Launch Configuration Settings +### Launch Configuration Settings When you launch a program with Visual Studio Code you will need to create a [launch.json](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations) file that defines how your program will be run. The JSON configuration file can contain the following `lldb-dap` specific launch key/value pairs: @@ -151,7 +37,7 @@ file that defines how your program will be run. The JSON configuration file can |**sourceMap** |[string[2]]| | Specify an array of path re-mappings. Each element in the array must be a two element array containing a source and destination pathname. |**debuggerRoot** | string| |Specify a working directory to use when launching lldb-dap. If the debug information in your executable contains relative paths, this option can be used so that `lldb-dap` can find source files and object files that have relative paths. -## Attaching Settings +### Attaching Settings When attaching to a process using LLDB you can attach in a few ways @@ -177,9 +63,9 @@ The JSON configuration file can contain the following `lldb-dap` specific launch |**terminateCommands** |[string]| | LLDB commands executed when the debugging session ends. Commands and command output will be sent to the debugger console when they are executed. |**attachCommands** |[string]| | LLDB commands that will be executed after **preRunCommands** which take place of the code that normally does the attach. The commands can create a new target and attach or launch it however desired. This allows custom launch and attach configurations. Core files can use `target create --core /path/to/core` to attach to core files. -## Example configurations +### Example configurations -### Launching +#### Launching This will launch `/tmp/a.out` with arguments `one`, `two`, and `three` and adds `FOO=1` and `bar` to the environment: @@ -195,7 +81,7 @@ adds `FOO=1` and `bar` to the environment: } ``` -### Attach using PID +#### Attach using PID This will attach to a process `a.out` whose process ID is 123: @@ -209,7 +95,7 @@ This will attach to a process `a.out` whose process ID is 123: } ``` -### Attach by Name +#### Attach by Name This will attach to an existing process whose base name matches `a.out`. All we have to do is leave the `pid` value out of the @@ -240,7 +126,7 @@ to be launched you can add the "waitFor" key value pair: This will work as long as the architecture, vendor and OS supports waiting for processes. Currently MacOS is the only platform that supports this. -### Loading a Core File +#### Loading a Core File This loads the coredump file `/cores/123.core` associated with the program `/tmp/a.out`: @@ -255,7 +141,7 @@ This loads the coredump file `/cores/123.core` associated with the program } ``` -### Connect to a Debug Server on the Current Machine +#### Connect to a Debug Server on the Current Machine This connects to a debug server (e.g. `lldb-server`, `gdbserver`) on the current machine, that is debugging the program `/tmp/a.out` and listening @@ -271,7 +157,7 @@ locally on port `2345`. } ``` -### Connect to a Debug Server on Another Machine +#### Connect to a Debug Server on Another Machine This connects to a debug server running on another machine with hostname `hostnmame`. Which is debugging the program `/tmp/a.out` and listening on @@ -287,12 +173,12 @@ port `5678` of that other machine. } ``` -# Custom debugger commands +## Custom debugger commands The `lldb-dap` tool includes additional custom commands to support the Debug Adapter Protocol features. -## startDebugging +### startDebugging Using the command `lldb-dap startDebugging` it is possible to trigger a reverse request to the client requesting a child debug session with the @@ -317,7 +203,7 @@ This will launch a server and then request a child debug session for a client. } ``` -## repl-mode +### repl-mode Inspect or adjust the behavior of lldb-dap repl evaluation requests. The supported modes are `variable`, `command` and `auto`. From 80a0a067fb8cc3122f53083fd2fe20f9d5dfc5bf Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sat, 30 Mar 2024 21:38:23 -0500 Subject: [PATCH 065/576] [ValueTracking] Add tests for computing knownbits from `(icmp upred (add/sub nuw X, Y), C)`; NFC --- .../test/Transforms/InstCombine/known-bits.ll | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index cb404c0b7f889f..c00bdb78709539 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1698,5 +1698,281 @@ define i32 @test_none(float nofpclass(all) %x) { ret i32 %and } +define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_add( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_ADD:%.*]] = add nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_ADD]], 32 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_add = add nuw i8 %n, %n2 + %cmp = icmp ult i8 %n_add, 32 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_add_fail_nsw(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_add_fail_nsw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_ADD:%.*]] = add nsw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_ADD]], 32 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_add = add nsw i8 %n, %n2 + %cmp = icmp ult i8 %n_add, 32 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_add2(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_add2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_ADD:%.*]] = add nuw nsw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_ADD]], 14 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; +entry: + %n_add = add nsw nuw i8 %n, %n2 + %cmp = icmp uge i8 %n_add, 15 + br i1 %cmp, label %if.then, label %if.else + +if.then: + ret i8 %other +if.else: + %r = and i8 %n, 32 + ret i8 %r + +} + +define i8 @test_icmp_add_fail_bad_range(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_add_fail_bad_range( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_ADD:%.*]] = add nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_ADD]], 33 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_add = add nuw i8 %n, %n2 + %cmp = icmp ule i8 %n_add, 32 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_add_fail_bad_pred(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_add_fail_bad_pred( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_ADD:%.*]] = add nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_ADD]], 32 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_add = add nuw i8 %n, %n2 + %cmp = icmp ugt i8 %n_add, 32 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_sub(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_SUB]], -33 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_sub = sub nuw i8 %n, %n2 + %cmp = icmp ugt i8 %n_sub, 223 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_sub_fail_wrong_arg(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub_fail_wrong_arg( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_SUB]], -33 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N2]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_sub = sub nuw i8 %n, %n2 + %cmp = icmp ugt i8 %n_sub, 223 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n2, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_sub2(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_SUB]], -31 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; +entry: + %n_sub = sub nuw i8 %n, %n2 + %cmp = icmp ule i8 %n_sub, 224 + br i1 %cmp, label %if.then, label %if.else + +if.then: + ret i8 %other +if.else: + %r = and i8 %n, 32 + ret i8 %r + +} + +define i8 @test_icmp_sub2_fail_nsw(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub2_fail_nsw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nsw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_SUB]], -31 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; +entry: + %n_sub = sub nsw i8 %n, %n2 + %cmp = icmp ule i8 %n_sub, 224 + br i1 %cmp, label %if.then, label %if.else + +if.then: + ret i8 %other +if.else: + %r = and i8 %n, 32 + ret i8 %r + +} + + +define i8 @test_icmp_sub_fail_bad_range(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub_fail_bad_range( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_SUB]], -34 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_sub = sub nuw i8 %n, %n2 + %cmp = icmp uge i8 %n_sub, 223 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + +define i8 @test_icmp_sub_fail_bad_pred(i8 %n, i8 %n2, i8 %other) { +; CHECK-LABEL: @test_icmp_sub_fail_bad_pred( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_SUB:%.*]] = sub nuw i8 [[N:%.*]], [[N2:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[N_SUB]], 31 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 +; CHECK-NEXT: ret i8 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i8 [[OTHER:%.*]] +; +entry: + %n_sub = sub nuw i8 %n, %n2 + %cmp = icmp sge i8 %n_sub, 32 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = and i8 %n, 32 + ret i8 %r + +if.else: + ret i8 %other +} + declare void @use(i1) declare void @sink(i8) From 05347f8c2fde0cde2fd12f1ec3611eeaf666ece0 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sat, 30 Mar 2024 21:39:36 -0500 Subject: [PATCH 066/576] [ValueTracking] Compute knownbits from `(icmp upred (add/sub nuw X, Y), C)` `(icmp ule/ult (add nuw X, Y), C)` implies both `(icmp ule/ult X, C)` and `(icmp ule/ult Y, C)`. We can use this to deduce leading zeros in `X`/`Y`. `(icmp uge/ugt (sub nuw X, Y), C)` implies `(icmp uge/uge X, C)` . We can use this to deduce leading ones in `X`. Proofs: https://alive2.llvm.org/ce/z/sc5k22 Closes #87180 --- llvm/lib/Analysis/ValueTracking.cpp | 47 ++++++++++++------- .../test/Transforms/InstCombine/known-bits.ll | 12 ++--- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index e07d14ccbb85c4..e8c5f9b3dc25d3 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -706,17 +706,22 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred, LHSRange = LHSRange.sub(*Offset); Known = Known.unionWith(LHSRange.toKnownBits()); } - // X & Y u> C -> X u> C && Y u> C - if ((Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) && - match(LHS, m_c_And(m_V, m_Value()))) { - Known.One.setHighBits( - (*C + (Pred == ICmpInst::ICMP_UGT)).countLeadingOnes()); + if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) { + // X & Y u> C -> X u> C && Y u> C + // X nuw- Y u> C -> X u> C + if (match(LHS, m_c_And(m_V, m_Value())) || + match(LHS, m_NUWSub(m_V, m_Value()))) + Known.One.setHighBits( + (*C + (Pred == ICmpInst::ICMP_UGT)).countLeadingOnes()); } - // X | Y u< C -> X u< C && Y u< C - if ((Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) && - match(LHS, m_c_Or(m_V, m_Value()))) { - Known.Zero.setHighBits( - (*C - (Pred == ICmpInst::ICMP_ULT)).countLeadingZeros()); + if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) { + // X | Y u< C -> X u< C && Y u< C + // X nuw+ Y u< C -> X u< C && Y u< C + if (match(LHS, m_c_Or(m_V, m_Value())) || + match(LHS, m_c_NUWAdd(m_V, m_Value()))) { + Known.Zero.setHighBits( + (*C - (Pred == ICmpInst::ICMP_ULT)).countLeadingZeros()); + } } } break; @@ -9576,14 +9581,20 @@ void llvm::findValuesAffectedByCondition( if (match(A, m_AddLike(m_Value(X), m_ConstantInt()))) AddAffected(X); - Value *Y; - // X & Y u> C -> X >u C && Y >u C - // X | Y u< C -> X u< C && Y u< C - if (ICmpInst::isUnsigned(Pred) && - (match(A, m_And(m_Value(X), m_Value(Y))) || - match(A, m_Or(m_Value(X), m_Value(Y))))) { - AddAffected(X); - AddAffected(Y); + if (ICmpInst::isUnsigned(Pred)) { + Value *Y; + // X & Y u> C -> X >u C && Y >u C + // X | Y u< C -> X u< C && Y u< C + // X nuw+ Y u< C -> X u< C && Y u< C + if (match(A, m_And(m_Value(X), m_Value(Y))) || + match(A, m_Or(m_Value(X), m_Value(Y))) || + match(A, m_NUWAdd(m_Value(X), m_Value(Y)))) { + AddAffected(X); + AddAffected(Y); + } + // X nuw- Y u> C -> X u> C + if (match(A, m_NUWSub(m_Value(X), m_Value()))) + AddAffected(X); } } diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index c00bdb78709539..82cd24027e4e1b 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1705,8 +1705,7 @@ define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) { ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[N_ADD]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: ; CHECK-NEXT: ret i8 [[OTHER:%.*]] ; @@ -1757,8 +1756,7 @@ define i8 @test_icmp_add2(i8 %n, i8 %n2, i8 %other) { ; CHECK: if.then: ; CHECK-NEXT: ret i8 [[OTHER:%.*]] ; CHECK: if.else: -; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; entry: %n_add = add nsw nuw i8 %n, %n2 @@ -1830,8 +1828,7 @@ define i8 @test_icmp_sub(i8 %n, i8 %n2, i8 %other) { ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_SUB]], -33 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 32 ; CHECK: if.else: ; CHECK-NEXT: ret i8 [[OTHER:%.*]] ; @@ -1882,8 +1879,7 @@ define i8 @test_icmp_sub2(i8 %n, i8 %n2, i8 %other) { ; CHECK: if.then: ; CHECK-NEXT: ret i8 [[OTHER:%.*]] ; CHECK: if.else: -; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], 32 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 32 ; entry: %n_sub = sub nuw i8 %n, %n2 From ebbf484e1c62a312d88c7f6482af11a58d40f52d Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 7 Apr 2024 14:01:15 -0500 Subject: [PATCH 067/576] [InstCombine] Add tests for folding `(icmp pred (trunc nuw/nsw X), C)`; NFC --- .../test/Transforms/InstCombine/icmp-trunc.ll | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-trunc.ll b/llvm/test/Transforms/InstCombine/icmp-trunc.ll index b2de9dddb21947..c49c6a36823b29 100644 --- a/llvm/test/Transforms/InstCombine/icmp-trunc.ll +++ b/llvm/test/Transforms/InstCombine/icmp-trunc.ll @@ -555,3 +555,195 @@ define i1 @shl1_trunc_sgt4(i32 %a) { %r = icmp sgt i16 %t, 4 ret i1 %r } + +define i1 @eq_nuw(i32 %x) { +; DL64-LABEL: @eq_nuw( +; DL64-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 255 +; DL64-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 123 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @eq_nuw( +; DL8-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp eq i8 [[T]], 123 +; DL8-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp eq i8 %t, 123 + ret i1 %r +} + +define i1 @ult_nuw(i32 %x) { +; CHECK-LABEL: @ult_nuw( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 45 +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp ult i8 %t, 45 + ret i1 %r +} + +define i1 @ule_nuw(i32 %x) { +; CHECK-LABEL: @ule_nuw( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 46 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp ule i8 %t, 45 + call void @use(i8 %t) + ret i1 %r +} + +define i1 @ugt_nuw(i32 %x) { +; CHECK-LABEL: @ugt_nuw( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 12 +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp ugt i8 %t, 12 + ret i1 %r +} + +define i1 @uge_nuw(i32 %x) { +; CHECK-LABEL: @uge_nuw( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 98 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp uge i8 %t, 99 + call void @use(i8 %t) + ret i1 %r +} + +define i1 @uge_nuw_i48(i48 %x) { +; CHECK-LABEL: @uge_nuw_i48( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i48 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 98 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i48 %x to i8 + %r = icmp uge i8 %t, 99 + call void @use(i8 %t) + ret i1 %r +} + +define i1 @sgt_nuw_fail(i32 %x) { +; CHECK-LABEL: @sgt_nuw_fail( +; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], 12 +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nuw i32 %x to i8 + %r = icmp sgt i8 %t, 12 + ret i1 %r +} + +define i1 @ne_nsw(i32 %x) { +; DL64-LABEL: @ne_nsw( +; DL64-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 255 +; DL64-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 133 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @ne_nsw( +; DL8-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp ne i8 [[T]], -123 +; DL8-NEXT: ret i1 [[R]] +; + %t = trunc nsw i32 %x to i8 + %r = icmp ne i8 %t, -123 + ret i1 %r +} + +define i1 @slt_nsw(i32 %x) { +; CHECK-LABEL: @slt_nsw( +; CHECK-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 45 +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nsw i32 %x to i8 + %r = icmp slt i8 %t, 45 + ret i1 %r +} + +define i1 @sle_nsw(i16 %x) { +; CHECK-LABEL: @sle_nsw( +; CHECK-NEXT: [[T:%.*]] = trunc nsw i16 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 46 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nsw i16 %x to i8 + %r = icmp sle i8 %t, 45 + call void @use(i8 %t) + ret i1 %r +} + +define i1 @sgt_nsw(i32 %x) { +; CHECK-LABEL: @sgt_nsw( +; CHECK-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], -12 +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nsw i32 %x to i8 + %r = icmp sgt i8 %t, -12 + ret i1 %r +} + +define i1 @sge_nsw(i64 %x) { +; CHECK-LABEL: @sge_nsw( +; CHECK-NEXT: [[T:%.*]] = trunc nsw i64 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], 98 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nsw i64 %x to i8 + %r = icmp sge i8 %t, 99 + call void @use(i8 %t) + ret i1 %r +} + + + +define i1 @sge_nsw_i48(i48 %x) { +; CHECK-LABEL: @sge_nsw_i48( +; CHECK-NEXT: [[T:%.*]] = trunc nsw i48 [[X:%.*]] to i8 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], 98 +; CHECK-NEXT: call void @use(i8 [[T]]) +; CHECK-NEXT: ret i1 [[R]] +; + %t = trunc nsw i48 %x to i8 + %r = icmp sge i8 %t, 99 + call void @use(i8 %t) + ret i1 %r +} + + +define <2 x i1> @uge_nsw(<2 x i32> %x) { +; CHECK-LABEL: @uge_nsw( +; CHECK-NEXT: [[T:%.*]] = trunc nsw <2 x i32> [[X:%.*]] to <2 x i8> +; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[T]], +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %t = trunc nsw <2 x i32> %x to <2 x i8> + %r = icmp uge <2 x i8> %t, + ret <2 x i1> %r +} + + +define <2 x i1> @uge_nsw_non_splat(<2 x i32> %x) { +; CHECK-LABEL: @uge_nsw_non_splat( +; CHECK-NEXT: [[T:%.*]] = trunc nsw <2 x i32> [[X:%.*]] to <2 x i8> +; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[T]], +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %t = trunc nsw <2 x i32> %x to <2 x i8> + %r = icmp uge <2 x i8> %t, + ret <2 x i1> %r +} + From 23f1047daac9702876ca99b53e8fe649fca569fa Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 7 Apr 2024 14:01:29 -0500 Subject: [PATCH 068/576] [InstCombine] Fold `(icmp pred (trunc nuw/nsw X), C)` -> `(icmp pred X, (zext/sext C))` This is valid as long as the sign of the wrap flag doesn't differ from the sign of the `pred`. Proofs: https://alive2.llvm.org/ce/z/35NsrR NB: The online Alive2 hasn't been updated with `trunc nuw/nsw` support, so the proofs must be reproduced locally. Closes #87935 --- .../InstCombine/InstCombineCompares.cpp | 17 ++- .../test/Transforms/InstCombine/icmp-trunc.ll | 118 ++++++++++++------ 2 files changed, 91 insertions(+), 44 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9883d02c87a323..542a1c82b127a0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1409,6 +1409,19 @@ Instruction *InstCombinerImpl::foldICmpTruncConstant(ICmpInst &Cmp, const APInt &C) { ICmpInst::Predicate Pred = Cmp.getPredicate(); Value *X = Trunc->getOperand(0); + Type *SrcTy = X->getType(); + unsigned DstBits = Trunc->getType()->getScalarSizeInBits(), + SrcBits = SrcTy->getScalarSizeInBits(); + + // Match (icmp pred (trunc nuw/nsw X), C) + // Which we can convert to (icmp pred X, (sext/zext C)) + if (shouldChangeType(Trunc->getType(), SrcTy)) { + if (Trunc->hasNoSignedWrap()) + return new ICmpInst(Pred, X, ConstantInt::get(SrcTy, C.sext(SrcBits))); + if (!Cmp.isSigned() && Trunc->hasNoUnsignedWrap()) + return new ICmpInst(Pred, X, ConstantInt::get(SrcTy, C.zext(SrcBits))); + } + if (C.isOne() && C.getBitWidth() > 1) { // icmp slt trunc(signum(V)) 1 --> icmp slt V, 1 Value *V = nullptr; @@ -1417,10 +1430,6 @@ Instruction *InstCombinerImpl::foldICmpTruncConstant(ICmpInst &Cmp, ConstantInt::get(V->getType(), 1)); } - Type *SrcTy = X->getType(); - unsigned DstBits = Trunc->getType()->getScalarSizeInBits(), - SrcBits = SrcTy->getScalarSizeInBits(); - // TODO: Handle any shifted constant by subtracting trailing zeros. // TODO: Handle non-equality predicates. Value *Y; diff --git a/llvm/test/Transforms/InstCombine/icmp-trunc.ll b/llvm/test/Transforms/InstCombine/icmp-trunc.ll index c49c6a36823b29..4de64d85bbf25a 100644 --- a/llvm/test/Transforms/InstCombine/icmp-trunc.ll +++ b/llvm/test/Transforms/InstCombine/icmp-trunc.ll @@ -558,8 +558,7 @@ define i1 @shl1_trunc_sgt4(i32 %a) { define i1 @eq_nuw(i32 %x) { ; DL64-LABEL: @eq_nuw( -; DL64-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 255 -; DL64-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 123 +; DL64-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 123 ; DL64-NEXT: ret i1 [[R]] ; ; DL8-LABEL: @eq_nuw( @@ -573,10 +572,14 @@ define i1 @eq_nuw(i32 %x) { } define i1 @ult_nuw(i32 %x) { -; CHECK-LABEL: @ult_nuw( -; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 45 -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @ult_nuw( +; DL64-NEXT: [[R:%.*]] = icmp ult i32 [[X:%.*]], 45 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @ult_nuw( +; DL8-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 45 +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nuw i32 %x to i8 %r = icmp ult i8 %t, 45 @@ -584,11 +587,17 @@ define i1 @ult_nuw(i32 %x) { } define i1 @ule_nuw(i32 %x) { -; CHECK-LABEL: @ule_nuw( -; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 46 -; CHECK-NEXT: call void @use(i8 [[T]]) -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @ule_nuw( +; DL64-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL64-NEXT: [[R:%.*]] = icmp ult i32 [[X]], 46 +; DL64-NEXT: call void @use(i8 [[T]]) +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @ule_nuw( +; DL8-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp ult i8 [[T]], 46 +; DL8-NEXT: call void @use(i8 [[T]]) +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nuw i32 %x to i8 %r = icmp ule i8 %t, 45 @@ -597,10 +606,14 @@ define i1 @ule_nuw(i32 %x) { } define i1 @ugt_nuw(i32 %x) { -; CHECK-LABEL: @ugt_nuw( -; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 12 -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @ugt_nuw( +; DL64-NEXT: [[R:%.*]] = icmp ugt i32 [[X:%.*]], 12 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @ugt_nuw( +; DL8-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 12 +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nuw i32 %x to i8 %r = icmp ugt i8 %t, 12 @@ -608,11 +621,17 @@ define i1 @ugt_nuw(i32 %x) { } define i1 @uge_nuw(i32 %x) { -; CHECK-LABEL: @uge_nuw( -; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 98 -; CHECK-NEXT: call void @use(i8 [[T]]) -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @uge_nuw( +; DL64-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL64-NEXT: [[R:%.*]] = icmp ugt i32 [[X]], 98 +; DL64-NEXT: call void @use(i8 [[T]]) +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @uge_nuw( +; DL8-NEXT: [[T:%.*]] = trunc nuw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp ugt i8 [[T]], 98 +; DL8-NEXT: call void @use(i8 [[T]]) +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nuw i32 %x to i8 %r = icmp uge i8 %t, 99 @@ -646,8 +665,7 @@ define i1 @sgt_nuw_fail(i32 %x) { define i1 @ne_nsw(i32 %x) { ; DL64-LABEL: @ne_nsw( -; DL64-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 255 -; DL64-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 133 +; DL64-NEXT: [[R:%.*]] = icmp ne i32 [[X:%.*]], -123 ; DL64-NEXT: ret i1 [[R]] ; ; DL8-LABEL: @ne_nsw( @@ -661,10 +679,14 @@ define i1 @ne_nsw(i32 %x) { } define i1 @slt_nsw(i32 %x) { -; CHECK-LABEL: @slt_nsw( -; CHECK-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 45 -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @slt_nsw( +; DL64-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 45 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @slt_nsw( +; DL8-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 45 +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nsw i32 %x to i8 %r = icmp slt i8 %t, 45 @@ -672,11 +694,17 @@ define i1 @slt_nsw(i32 %x) { } define i1 @sle_nsw(i16 %x) { -; CHECK-LABEL: @sle_nsw( -; CHECK-NEXT: [[T:%.*]] = trunc nsw i16 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 46 -; CHECK-NEXT: call void @use(i8 [[T]]) -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @sle_nsw( +; DL64-NEXT: [[T:%.*]] = trunc nsw i16 [[X:%.*]] to i8 +; DL64-NEXT: [[R:%.*]] = icmp slt i16 [[X]], 46 +; DL64-NEXT: call void @use(i8 [[T]]) +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @sle_nsw( +; DL8-NEXT: [[T:%.*]] = trunc nsw i16 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp slt i8 [[T]], 46 +; DL8-NEXT: call void @use(i8 [[T]]) +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nsw i16 %x to i8 %r = icmp sle i8 %t, 45 @@ -685,10 +713,14 @@ define i1 @sle_nsw(i16 %x) { } define i1 @sgt_nsw(i32 %x) { -; CHECK-LABEL: @sgt_nsw( -; CHECK-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], -12 -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @sgt_nsw( +; DL64-NEXT: [[R:%.*]] = icmp sgt i32 [[X:%.*]], -12 +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @sgt_nsw( +; DL8-NEXT: [[T:%.*]] = trunc nsw i32 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], -12 +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nsw i32 %x to i8 %r = icmp sgt i8 %t, -12 @@ -696,11 +728,17 @@ define i1 @sgt_nsw(i32 %x) { } define i1 @sge_nsw(i64 %x) { -; CHECK-LABEL: @sge_nsw( -; CHECK-NEXT: [[T:%.*]] = trunc nsw i64 [[X:%.*]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], 98 -; CHECK-NEXT: call void @use(i8 [[T]]) -; CHECK-NEXT: ret i1 [[R]] +; DL64-LABEL: @sge_nsw( +; DL64-NEXT: [[T:%.*]] = trunc nsw i64 [[X:%.*]] to i8 +; DL64-NEXT: [[R:%.*]] = icmp sgt i64 [[X]], 98 +; DL64-NEXT: call void @use(i8 [[T]]) +; DL64-NEXT: ret i1 [[R]] +; +; DL8-LABEL: @sge_nsw( +; DL8-NEXT: [[T:%.*]] = trunc nsw i64 [[X:%.*]] to i8 +; DL8-NEXT: [[R:%.*]] = icmp sgt i8 [[T]], 98 +; DL8-NEXT: call void @use(i8 [[T]]) +; DL8-NEXT: ret i1 [[R]] ; %t = trunc nsw i64 %x to i8 %r = icmp sge i8 %t, 99 From da928c6d6e0e2f619fdaef71cea8747d9aef188d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 16 May 2024 14:10:46 -0400 Subject: [PATCH 069/576] [Clang][Sema] ASTContext::getUnconstrainedType propagates dependence (#92425) When the argument passed to `ASTContext::getUnconstrainedType` is an unconstrained `AutoType`, will return the argument unchanged. However, when called with a constrained `AutoType`, an unconstrained, non-dependent `AutoType` will be returned even if the argument was dependent. Consider the following: ``` template concept C = sizeof(T) == sizeof(int); template struct A; template struct A; // error: class template partial specialization is not more specialized than the primary template ``` When comparing the template parameters for equivalence, `ASTContext::getUnconstrainedType` is used to remove the constraints per [temp.over.link] p6 sentence 2. For the template parameter `N` of the class template, it returns a dependent `AutoType`. For the template parameter `N` of the class template partial specialization, it returns a non-dependent `AutoType`. We subsequently compare the adjusted types and find they are not equivalent, thus we consider the partial specialization to not be more specialized than the primary template per [temp.func.order] p6.2.2. This patch changes `ASTContext::getUnconstrainedType` such that the dependence of a constrained `AutoType` will propagate to the returned unconstrained `AutoType`. This causes the above example to be correctly accepted, fixing #77377. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ASTContext.cpp | 3 ++- .../temp/temp.decls/temp.fct/temp.func.order/p2.cpp | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321f..2d2928e4186237 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -723,6 +723,7 @@ Bug Fixes to C++ Support - Clang now ignores template parameters only used within the exception specification of candidate function templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4475f399a120b2..8fc2bb8c401c2f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5910,7 +5910,8 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs()) { if (!AT->isConstrained()) return T; - return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, + return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), + AT->isDependentType(), AT->containsUnexpandedParameterPack()), T.getQualifiers()); } diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp new file mode 100644 index 00000000000000..df1bbd5fe81288 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +namespace GH77377 { + template + concept C = sizeof(T) == sizeof(int); + + template + struct A; + + template + struct A; +} From 9a7f54ba4878c4e66c99430b52d8c014ab7b2a03 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 16 May 2024 11:53:15 -0700 Subject: [PATCH 070/576] [clang-fuzzer-dictionary] Skip EmptySpellingName after #89358 The dictionary entry `=""` is invalid. --- clang/tools/clang-fuzzer/dictionary/dictionary.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/tools/clang-fuzzer/dictionary/dictionary.c b/clang/tools/clang-fuzzer/dictionary/dictionary.c index 90490477f70c8a..de1defb236accb 100644 --- a/clang/tools/clang-fuzzer/dictionary/dictionary.c +++ b/clang/tools/clang-fuzzer/dictionary/dictionary.c @@ -21,6 +21,8 @@ static void emit(const char *Name, const char *Spelling) { static char Hex[] = "0123456789abcdef"; + // Skip EmptySpellingName for IsDeducible. + if (!Name[0]) return; printf("%s=\"", Name); unsigned char C; From a383b3cca3383128123b33bc73ffc0199ec573e4 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 16 May 2024 20:57:58 +0200 Subject: [PATCH 071/576] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (#92389) Fixes https://github.com/llvm/llvm-project/issues/92225 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaConcept.cpp | 7 +++++++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 7 +++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3be9d34b36b063..7e487b70b03dca 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3003,6 +3003,8 @@ def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note< "%select{and|because}0 %1 does not satisfy %2">; def note_atomic_constraint_evaluated_to_false_elaborated : Note< "%select{and|because}0 '%1' (%2 %3 %4) evaluated to false">; +def note_is_deducible_constraint_evaluated_to_false : Note< + "cannot deduce template arguments for %0 from %1">; def err_constrained_virtual_method : Error< "virtual function cannot have a requires clause">; def err_trailing_requires_clause_on_deduction_guide : Error< diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 7bfec4e11f7aab..202dd86c67f622 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1162,6 +1162,13 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, break; } return; + } else if (auto *TTE = dyn_cast(SubstExpr); + TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { + assert(TTE->getNumArgs() == 2); + S.Diag(SubstExpr->getSourceRange().getBegin(), + diag::note_is_deducible_constraint_evaluated_to_false) + << TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); + return; } S.Diag(SubstExpr->getSourceRange().getBegin(), diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 7c186dc379c7b1..21b2b8bff50029 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -111,7 +111,7 @@ struct Foo { template using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ - // expected-note {{because '__is_deducible}} + // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo'}} Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }} @@ -138,7 +138,7 @@ template struct Foo { T c; }; template using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \ - // expected-note {{because '__is_deducible(AFoo, Foo)' evaluated to false}} \ + // expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo'}} \ // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} @@ -196,10 +196,9 @@ template struct Foo { Foo(T); }; template using AFoo = Foo; template concept False = false; -// FIXME: emit a more descriptive diagnostic for "__is_deducible" constraint failure. template using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ - // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ + // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo'}} \ // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} int i = 0; AFoo a1(&i); // OK, deduce Foo From 476f7f65f9f17fab7e78f395b83dcb7b0bbd5215 Mon Sep 17 00:00:00 2001 From: weltschildkroete <65237298+weltschildkroete@users.noreply.github.com> Date: Thu, 16 May 2024 21:15:25 +0200 Subject: [PATCH 072/576] [clang][Sema] Emit more specific diagnostic for auto in lambda before C++14 (#46059) (#68540) Namely, we specify that `auto` in a lambda parameter is a C++14 extension in the error message, which now reads: `'auto' not allowed in lambda parameter before C++14` This does not change the behavior for `decltype(auto)` and `__auto_type` though. --------- Co-authored-by: cor3ntin --- clang/docs/ReleaseNotes.rst | 3 +++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 +++- clang/lib/Sema/SemaType.cpp | 10 +++++++--- clang/test/SemaCXX/auto-cxx0x.cpp | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e4186237..65d191b6161a45 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -494,6 +494,9 @@ Improvements to Clang's diagnostics Improvements to Clang's time-trace ---------------------------------- +- Clang now specifies that using ``auto`` in a lambda parameter is a C++14 extension when + appropriate. (`#46059: `_). + Bug Fixes in This Version ------------------------- - Clang's ``-Wundefined-func-template`` no longer warns on pure virtual diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7e487b70b03dca..9372c862a36cb7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2433,7 +2433,9 @@ def err_auto_not_allowed : Error< "|in template parameter|in friend declaration|in function prototype that is " "not a function declaration|in requires expression parameter" "|in array declaration" - "|in declaration of conversion function template}1">; + "|in declaration of conversion function template" + "|in lambda parameter before C++14}1">; + def err_dependent_deduced_tst : Error< "typename specifier refers to " "%select{class template|function template|variable template|alias template|" diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index eb67546d048ae0..9c002d56b5bd9e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3257,9 +3257,13 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Info = &SemaRef.InventedParameterInfos.back(); } else { // In C++14, generic lambdas allow 'auto' in their parameters. - if (!SemaRef.getLangOpts().CPlusPlus14 || !Auto || - Auto->getKeyword() != AutoTypeKeyword::Auto) { - Error = 16; + if (!SemaRef.getLangOpts().CPlusPlus14 && Auto && + Auto->getKeyword() == AutoTypeKeyword::Auto) { + Error = 25; // auto not allowed in lambda parameter (before C++14) + break; + } else if (!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto) { + Error = 16; // __auto_type or decltype(auto) not allowed in lambda + // parameter break; } Info = SemaRef.getCurLambda(); diff --git a/clang/test/SemaCXX/auto-cxx0x.cpp b/clang/test/SemaCXX/auto-cxx0x.cpp index b4da3f9330c104..07687b6066790f 100644 --- a/clang/test/SemaCXX/auto-cxx0x.cpp +++ b/clang/test/SemaCXX/auto-cxx0x.cpp @@ -12,7 +12,7 @@ thread_local auto x; // expected-error {{requires an initializer}} void g() { [](auto){}(0); #if __cplusplus == 201103L - // expected-error@-2 {{'auto' not allowed in lambda parameter}} + // expected-error@-2 {{'auto' not allowed in lambda parameter before C++14}} #endif } @@ -20,6 +20,6 @@ void rdar47689465() { int x = 0; [](auto __attribute__((noderef)) *){}(&x); #if __cplusplus == 201103L - // expected-error@-2 {{'auto' not allowed in lambda parameter}} + // expected-error@-2 {{'auto' not allowed in lambda parameter before C++14}} #endif } From 174cdeced0fe0da07a03d0d118bd70b93badfbb1 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Thu, 16 May 2024 12:17:22 -0700 Subject: [PATCH 073/576] [nfc] Clarify when the various PGO instrumentation passes run (#92330) The code seems easier to read if it's centered on what the user wants rather than combinations of whatever internal variables. --- llvm/include/llvm/Passes/PassBuilder.h | 1 + llvm/lib/Passes/PassBuilderPipelines.cpp | 57 ++++++++++++++---------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 9b4da1c466f57d..8de0f024a4b115 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -723,6 +723,7 @@ class PassBuilder { bool AtomicCounterUpdate, std::string ProfileFile, std::string ProfileRemappingFile, IntrusiveRefCntPtr FS); + void addPostPGOLoopRotation(ModulePassManager &MPM, OptimizationLevel Level); // Extension Point callbacks SmallVector, 2> diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 72f273972f2f72..682bdefbd52436 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -803,6 +803,20 @@ void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM, MPM.addPass(GlobalDCEPass()); } +void PassBuilder::addPostPGOLoopRotation(ModulePassManager &MPM, + OptimizationLevel Level) { + if (EnablePostPGOLoopRotation) { + // Disable header duplication in loop rotation at -Oz. + MPM.addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor( + LoopRotatePass(EnableLoopHeaderDuplication || + Level != OptimizationLevel::Oz), + /*UseMemorySSA=*/false, + /*UseBlockFrequencyInfo=*/false), + PTO.EagerlyInvalidateAnalyses)); + } +} + void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, OptimizationLevel Level, bool RunProfileGen, bool IsCS, bool AtomicCounterUpdate, @@ -824,17 +838,7 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, // Perform PGO instrumentation. MPM.addPass(PGOInstrumentationGen(IsCS)); - if (EnablePostPGOLoopRotation) { - // Disable header duplication in loop rotation at -Oz. - MPM.addPass(createModuleToFunctionPassAdaptor( - createFunctionToLoopPassAdaptor( - LoopRotatePass(EnableLoopHeaderDuplication || - Level != OptimizationLevel::Oz), - /*UseMemorySSA=*/false, - /*UseBlockFrequencyInfo=*/false), - PTO.EagerlyInvalidateAnalyses)); - } - + addPostPGOLoopRotation(MPM, Level); if (PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) { MPM.addPass(PGOCtxProfLoweringPass()); return; @@ -1145,29 +1149,34 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM), PTO.EagerlyInvalidateAnalyses)); - // Invoke the pre-inliner passes for instrumentation PGO or MemProf. - if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && - (PGOOpt->Action == PGOOptions::IRInstr || - PGOOpt->Action == PGOOptions::IRUse || !PGOOpt->MemoryProfile.empty())) + // We already asserted this happens in non-FullLTOPostLink earlier. + const bool IsPreLink = Phase != ThinOrFullLTOPhase::ThinLTOPostLink; + const bool IsPGOPreLink = PGOOpt && IsPreLink; + const bool IsPGOInstrGen = + IsPGOPreLink && PGOOpt->Action == PGOOptions::IRInstr; + const bool IsPGOInstrUse = + IsPGOPreLink && PGOOpt->Action == PGOOptions::IRUse; + const bool IsMemprofUse = IsPGOPreLink && !PGOOpt->MemoryProfile.empty(); + + if (IsPGOInstrGen || IsPGOInstrUse || IsMemprofUse) addPreInlinerPasses(MPM, Level, Phase); // Add all the requested passes for instrumentation PGO, if requested. - if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && - (PGOOpt->Action == PGOOptions::IRInstr || - PGOOpt->Action == PGOOptions::IRUse)) { + if (IsPGOInstrGen || IsPGOInstrUse) { addPGOInstrPasses(MPM, Level, - /*RunProfileGen=*/PGOOpt->Action == PGOOptions::IRInstr, + /*RunProfileGen=*/IsPGOInstrGen, /*IsCS=*/false, PGOOpt->AtomicCounterUpdate, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, PGOOpt->FS); - MPM.addPass(PGOIndirectCallPromotion(false, false)); } - if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && - PGOOpt->CSAction == PGOOptions::CSIRInstr) + + if (IsPGOInstrGen || IsPGOInstrUse) + MPM.addPass(PGOIndirectCallPromotion(false, false)); + + if (IsPGOPreLink && PGOOpt->CSAction == PGOOptions::CSIRInstr) MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile)); - if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && - !PGOOpt->MemoryProfile.empty()) + if (IsMemprofUse) MPM.addPass(MemProfUsePass(PGOOpt->MemoryProfile, PGOOpt->FS)); // Synthesize function entry counts for non-PGO compilation. From b5f6cc9eb4f661816ef264ad41cb703004380636 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Thu, 16 May 2024 12:31:37 -0700 Subject: [PATCH 074/576] Unittest for Error forwarding, follow-up to PR #92208 (#92314) Added a unittest demonstrating Error -> Expected forwarding. --- llvm/unittests/Support/ErrorTest.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp index 1229282cf0def5..5d866a67c0eaae 100644 --- a/llvm/unittests/Support/ErrorTest.cpp +++ b/llvm/unittests/Support/ErrorTest.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Testing/Support/Error.h" +#include "gmock/gmock.h" #include "gtest/gtest-spi.h" #include "gtest/gtest.h" #include @@ -1158,4 +1159,21 @@ TEST(Error, BadAllocFatalErrorHandlersInteraction) { remove_bad_alloc_error_handler(); } +TEST(Error, ForwardToExpected) { + auto ErrorReturningFct = [](bool Fail) { + return Fail ? make_error(llvm::errc::invalid_argument, + "Some Error") + : Error::success(); + }; + auto ExpectedReturningFct = [&](bool Fail) -> Expected { + auto Err = ErrorReturningFct(Fail); + if (Err) + return Err; + return 42; + }; + std::optional MaybeV; + EXPECT_THAT_ERROR(ExpectedReturningFct(true).moveInto(MaybeV), Failed()); + EXPECT_THAT_ERROR(ExpectedReturningFct(false).moveInto(MaybeV), Succeeded()); + EXPECT_EQ(*MaybeV, 42); +} } // namespace From 9144553207052a868efc5a8ce61a0afbb0eaf236 Mon Sep 17 00:00:00 2001 From: Evgenii Stepanov Date: Thu, 16 May 2024 12:34:13 -0700 Subject: [PATCH 075/576] Revert "[RISCV] Remove unneeded casts from int64_t to uint64_t in RISCVMatInt.cpp. NFC" LLVM is built with C++17, where left shift of any negative value is still UB. Detected with UBSan on the buildbot. This reverts commit 0647d1035cb208195e002b38089b82004b6f7b92. --- .../Target/RISCV/MCTargetDesc/RISCVMatInt.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index fca3362f9a8b27..0a857eb96935ea 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -115,29 +115,30 @@ static void generateInstSeqImpl(int64_t Val, const MCSubtargetInfo &STI, Val >>= ShiftAmount; // If the remaining bits don't fit in 12 bits, we might be able to reduce - // the shift amount in order to use LUI which will zero the lower 12 bits. + // the // shift amount in order to use LUI which will zero the lower 12 + // bits. if (ShiftAmount > 12 && !isInt<12>(Val)) { - if (isInt<32>(Val << 12)) { + if (isInt<32>((uint64_t)Val << 12)) { // Reduce the shift amount and add zeros to the LSBs so it will match // LUI. ShiftAmount -= 12; - Val = Val << 12; - } else if (isUInt<32>(Val << 12) && + Val = (uint64_t)Val << 12; + } else if (isUInt<32>((uint64_t)Val << 12) && STI.hasFeature(RISCV::FeatureStdExtZba)) { // Reduce the shift amount and add zeros to the LSBs so it will match // LUI, then shift left with SLLI.UW to clear the upper 32 set bits. ShiftAmount -= 12; - Val = SignExtend64<32>(Val << 12); + Val = ((uint64_t)Val << 12) | (0xffffffffull << 32); Unsigned = true; } } // Try to use SLLI_UW for Val when it is uint32 but not int32. - if (isUInt<32>(Val) && !isInt<32>(Val) && + if (isUInt<32>((uint64_t)Val) && !isInt<32>((uint64_t)Val) && STI.hasFeature(RISCV::FeatureStdExtZba)) { - // Use LUI+ADDI(W) or LUI to compose, then clear the upper 32 bits with + // Use LUI+ADDI or LUI to compose, then clear the upper 32 bits with // SLLI_UW. - Val = SignExtend64<32>(Val); + Val = ((uint64_t)Val) | (0xffffffffull << 32); Unsigned = true; } } From f42f57b52dd279e6ae19270d063aeb8d59e3f11c Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 14:58:46 -0500 Subject: [PATCH 076/576] [Libomptarget] Rework Record & Replay to be a plugin member (#88928) (#89097) Summary: Previously, the R&R support was global state initialized by a global constructor. This is bad because it prevents us from adequately constraining the lifetime of the library. Additionally, we want to minimize the amount of global state floating around. This patch moves the R&R support into a plugin member like everything else. This means there will be multiple copies of the R&R implementation floating around, but this was already the case given the fact that we currently handle everything with dynamic libraries. --- .../common/include/PluginInterface.h | 13 ++++++- .../common/src/PluginInterface.cpp | 34 +++++++++++++------ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h index d8d71e3e65a4a0..83f6e8d76fec75 100644 --- a/offload/plugins-nextgen/common/include/PluginInterface.h +++ b/offload/plugins-nextgen/common/include/PluginInterface.h @@ -54,6 +54,7 @@ namespace plugin { struct GenericPluginTy; struct GenericKernelTy; struct GenericDeviceTy; +struct RecordReplayTy; /// Class that wraps the __tgt_async_info to simply its usage. In case the /// object is constructed without a valid __tgt_async_info, the object will use @@ -958,7 +959,8 @@ struct GenericPluginTy { /// Construct a plugin instance. GenericPluginTy(Triple::ArchType TA) - : GlobalHandler(nullptr), JIT(TA), RPCServer(nullptr) {} + : GlobalHandler(nullptr), JIT(TA), RPCServer(nullptr), + RecordReplay(nullptr) {} virtual ~GenericPluginTy() {} @@ -1027,6 +1029,12 @@ struct GenericPluginTy { return *RPCServer; } + /// Get a reference to the record and replay interface for the plugin. + RecordReplayTy &getRecordReplay() { + assert(RecordReplay && "RR interface not initialized"); + return *RecordReplay; + } + /// Initialize a device within the plugin. Error initDevice(int32_t DeviceId); @@ -1204,6 +1212,9 @@ struct GenericPluginTy { /// The interface between the plugin and the GPU for host services. RPCServerTy *RPCServer; + + /// The interface between the plugin and the GPU for host services. + RecordReplayTy *RecordReplay; }; namespace Plugin { diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index 253acacc3a9dc8..550ebc9c28b250 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -39,6 +39,7 @@ using namespace target; using namespace plugin; // TODO: Fix any thread safety issues for multi-threaded kernel recording. +namespace llvm::omp::target::plugin { struct RecordReplayTy { // Describes the state of the record replay mechanism. @@ -358,8 +359,7 @@ struct RecordReplayTy { } } }; - -static RecordReplayTy RecordReplay; +} // namespace llvm::omp::target::plugin // Extract the mapping of host function pointers to device function pointers // from the entry table. Functions marked as 'indirect' in OpenMP will have @@ -470,7 +470,7 @@ GenericKernelTy::getKernelLaunchEnvironment( // Ctor/Dtor have no arguments, replaying uses the original kernel launch // environment. Older versions of the compiler do not generate a kernel // launch environment. - if (RecordReplay.isReplaying() || + if (GenericDevice.Plugin.getRecordReplay().isReplaying() || Version < OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR) return nullptr; @@ -559,6 +559,7 @@ Error GenericKernelTy::launch(GenericDeviceTy &GenericDevice, void **ArgPtrs, // Record the kernel description after we modified the argument count and num // blocks/threads. + RecordReplayTy &RecordReplay = GenericDevice.Plugin.getRecordReplay(); if (RecordReplay.isRecording()) { RecordReplay.saveImage(getName(), getImage()); RecordReplay.saveKernelInput(getName(), getImage()); @@ -833,6 +834,7 @@ Error GenericDeviceTy::deinit(GenericPluginTy &Plugin) { delete MemoryManager; MemoryManager = nullptr; + RecordReplayTy &RecordReplay = Plugin.getRecordReplay(); if (RecordReplay.isRecordingOrReplaying()) RecordReplay.deinit(); @@ -886,7 +888,8 @@ GenericDeviceTy::loadBinary(GenericPluginTy &Plugin, return std::move(Err); // Setup the global device memory pool if needed. - if (!RecordReplay.isReplaying() && shouldSetupDeviceMemoryPool()) { + if (!Plugin.getRecordReplay().isReplaying() && + shouldSetupDeviceMemoryPool()) { uint64_t HeapSize; auto SizeOrErr = getDeviceHeapSize(HeapSize); if (SizeOrErr) { @@ -1301,8 +1304,8 @@ Expected GenericDeviceTy::dataAlloc(int64_t Size, void *HostPtr, TargetAllocTy Kind) { void *Alloc = nullptr; - if (RecordReplay.isRecordingOrReplaying()) - return RecordReplay.alloc(Size); + if (Plugin.getRecordReplay().isRecordingOrReplaying()) + return Plugin.getRecordReplay().alloc(Size); switch (Kind) { case TARGET_ALLOC_DEFAULT: @@ -1338,7 +1341,7 @@ Expected GenericDeviceTy::dataAlloc(int64_t Size, void *HostPtr, Error GenericDeviceTy::dataDelete(void *TgtPtr, TargetAllocTy Kind) { // Free is a noop when recording or replaying. - if (RecordReplay.isRecordingOrReplaying()) + if (Plugin.getRecordReplay().isRecordingOrReplaying()) return Plugin::success(); int Res; @@ -1405,7 +1408,8 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs, KernelArgsTy &KernelArgs, __tgt_async_info *AsyncInfo) { AsyncInfoWrapperTy AsyncInfoWrapper( - *this, RecordReplay.isRecordingOrReplaying() ? nullptr : AsyncInfo); + *this, + Plugin.getRecordReplay().isRecordingOrReplaying() ? nullptr : AsyncInfo); GenericKernelTy &GenericKernel = *reinterpret_cast(EntryPtr); @@ -1416,6 +1420,7 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs, // 'finalize' here to guarantee next record-replay actions are in-sync AsyncInfoWrapper.finalize(Err); + RecordReplayTy &RecordReplay = Plugin.getRecordReplay(); if (RecordReplay.isRecordingOrReplaying() && RecordReplay.isSaveOutputEnabled()) RecordReplay.saveKernelOutputInfo(GenericKernel.getName()); @@ -1503,6 +1508,9 @@ Error GenericPluginTy::init() { RPCServer = new RPCServerTy(*this); assert(RPCServer && "Invalid RPC server"); + RecordReplay = new RecordReplayTy(); + assert(RecordReplay && "Invalid RR interface"); + return Plugin::success(); } @@ -1523,6 +1531,9 @@ Error GenericPluginTy::deinit() { if (RPCServer) delete RPCServer; + if (RecordReplay) + delete RecordReplay; + // Perform last deinitializations on the plugin. return deinitImpl(); } @@ -1633,12 +1644,12 @@ int32_t GenericPluginTy::initialize_record_replay(int32_t DeviceId, isRecord ? RecordReplayTy::RRStatusTy::RRRecording : RecordReplayTy::RRStatusTy::RRReplaying; - if (auto Err = RecordReplay.init(&Device, MemorySize, VAddr, Status, - SaveOutput, ReqPtrArgOffset)) { + if (auto Err = RecordReplay->init(&Device, MemorySize, VAddr, Status, + SaveOutput, ReqPtrArgOffset)) { REPORT("WARNING RR did not intialize RR-properly with %lu bytes" "(Error: %s)\n", MemorySize, toString(std::move(Err)).data()); - RecordReplay.setStatus(RecordReplayTy::RRStatusTy::RRDeactivated); + RecordReplay->setStatus(RecordReplayTy::RRStatusTy::RRDeactivated); if (!isRecord) { return OFFLOAD_FAIL; @@ -1982,6 +1993,7 @@ int32_t GenericPluginTy::get_global(__tgt_device_binary Binary, uint64_t Size, assert(DevicePtr && "Invalid device global's address"); // Save the loaded globals if we are recording. + RecordReplayTy &RecordReplay = Device.Plugin.getRecordReplay(); if (RecordReplay.isRecording()) RecordReplay.addEntry(Name, Size, *DevicePtr); From 9d0a8eda0baca51ce61fd5ce7c59864b2b57dcf8 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 15:13:24 -0500 Subject: [PATCH 077/576] [libc][NFC] Replace address space with constant GPU utility Summary: This was written before we had the address space helpers. Using numerical address spaces is bad so this should be removed. --- libc/src/time/gpu/time_utils.cpp | 4 ++-- libc/src/time/gpu/time_utils.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libc/src/time/gpu/time_utils.cpp b/libc/src/time/gpu/time_utils.cpp index 300a72b102360a..53a1b2121f7c69 100644 --- a/libc/src/time/gpu/time_utils.cpp +++ b/libc/src/time/gpu/time_utils.cpp @@ -15,8 +15,8 @@ namespace LIBC_NAMESPACE { // insufficient. // TODO: Once we have another use-case for this we should put it in a common // device environment struct. -extern "C" [[gnu::visibility("protected")]] uint64_t - [[clang::address_space(4)]] __llvm_libc_clock_freq = clock_freq; +extern "C" [[gnu::visibility("protected")]] gpu::Constant + __llvm_libc_clock_freq = clock_freq; #endif } // namespace LIBC_NAMESPACE diff --git a/libc/src/time/gpu/time_utils.h b/libc/src/time/gpu/time_utils.h index 3f1fd11c1791c1..e7e0e526a532ba 100644 --- a/libc/src/time/gpu/time_utils.h +++ b/libc/src/time/gpu/time_utils.h @@ -23,8 +23,8 @@ constexpr uint64_t clock_freq = 100000000UL; // We provide an externally visible symbol such that the runtime can set // this to the correct value. -extern "C" [[gnu::visibility("protected")]] uint64_t - [[clang::address_space(4)]] __llvm_libc_clock_freq; +extern "C" [[gnu::visibility("protected")]] gpu::Constant + __llvm_libc_clock_freq; #define GPU_CLOCKS_PER_SEC static_cast(__llvm_libc_clock_freq) #elif defined(LIBC_TARGET_ARCH_IS_NVPTX) From 61565abcdc4d864a8c7aa7ad23ed441a3762b77d Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 15:24:23 -0500 Subject: [PATCH 078/576] [libc] Fix constant variable initializer --- libc/src/time/gpu/time_utils.cpp | 4 ++-- libc/src/time/gpu/time_utils.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libc/src/time/gpu/time_utils.cpp b/libc/src/time/gpu/time_utils.cpp index 53a1b2121f7c69..67fe5b4861acc6 100644 --- a/libc/src/time/gpu/time_utils.cpp +++ b/libc/src/time/gpu/time_utils.cpp @@ -15,8 +15,8 @@ namespace LIBC_NAMESPACE { // insufficient. // TODO: Once we have another use-case for this we should put it in a common // device environment struct. -extern "C" [[gnu::visibility("protected")]] gpu::Constant - __llvm_libc_clock_freq = clock_freq; +extern "C" [[gnu::visibility("protected")]] uint64_t __llvm_libc_clock_freq = + clock_freq; #endif } // namespace LIBC_NAMESPACE diff --git a/libc/src/time/gpu/time_utils.h b/libc/src/time/gpu/time_utils.h index e7e0e526a532ba..da713886b6434f 100644 --- a/libc/src/time/gpu/time_utils.h +++ b/libc/src/time/gpu/time_utils.h @@ -23,8 +23,7 @@ constexpr uint64_t clock_freq = 100000000UL; // We provide an externally visible symbol such that the runtime can set // this to the correct value. -extern "C" [[gnu::visibility("protected")]] gpu::Constant - __llvm_libc_clock_freq; +extern "C" [[gnu::visibility("protected")]] uint64_t __llvm_libc_clock_freq; #define GPU_CLOCKS_PER_SEC static_cast(__llvm_libc_clock_freq) #elif defined(LIBC_TARGET_ARCH_IS_NVPTX) From 479f4a7b68a8b1eb8da7fc3f28638045eaa7dc25 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 16 May 2024 13:26:13 -0700 Subject: [PATCH 079/576] [memprof] Update comments for writeMemProf and its helpers (#92446) This patch adds comments for writeMemProf{V0,V1,V2} in a version-specific manner. The mostly repetitive nature of the comments is somewhat unfortunate but intentional to make it easy to retire older versions. Without this patch, the comment just before writeMemProf documents the Version1 format, which is very confusing. --- llvm/lib/ProfileData/InstrProfWriter.cpp | 52 ++++++++++++++++++------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index aeafd429e8badd..b5b13550b057fb 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -499,6 +499,17 @@ static uint64_t writeMemProfCallStacks( return CallStackTableGenerator.Emit(OS.OS); } +// Write out MemProf Version0 as follows: +// uint64_t RecordTableOffset = RecordTableGenerator.Emit +// uint64_t FramePayloadOffset = Offset for the frame payload +// uint64_t FrameTableOffset = FrameTableGenerator.Emit +// uint64_t Num schema entries +// uint64_t Schema entry 0 +// uint64_t Schema entry 1 +// .... +// uint64_t Schema entry N - 1 +// OnDiskChainedHashTable MemProfRecordData +// OnDiskChainedHashTable MemProfFrameData static Error writeMemProfV0(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData) { uint64_t HeaderUpdatePos = OS.tell(); @@ -521,6 +532,18 @@ static Error writeMemProfV0(ProfOStream &OS, return Error::success(); } +// Write out MemProf Version1 as follows: +// uint64_t Version (NEW in V1) +// uint64_t RecordTableOffset = RecordTableGenerator.Emit +// uint64_t FramePayloadOffset = Offset for the frame payload +// uint64_t FrameTableOffset = FrameTableGenerator.Emit +// uint64_t Num schema entries +// uint64_t Schema entry 0 +// uint64_t Schema entry 1 +// .... +// uint64_t Schema entry N - 1 +// OnDiskChainedHashTable MemProfRecordData +// OnDiskChainedHashTable MemProfFrameData static Error writeMemProfV1(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData) { OS.write(memprof::Version1); @@ -544,6 +567,21 @@ static Error writeMemProfV1(ProfOStream &OS, return Error::success(); } +// Write out MemProf Version2 as follows: +// uint64_t Version +// uint64_t RecordTableOffset = RecordTableGenerator.Emit +// uint64_t FramePayloadOffset = Offset for the frame payload +// uint64_t FrameTableOffset = FrameTableGenerator.Emit +// uint64_t CallStackPayloadOffset = Offset for the call stack payload (NEW V2) +// uint64_t CallStackTableOffset = CallStackTableGenerator.Emit (NEW in V2) +// uint64_t Num schema entries +// uint64_t Schema entry 0 +// uint64_t Schema entry 1 +// .... +// uint64_t Schema entry N - 1 +// OnDiskChainedHashTable MemProfRecordData +// OnDiskChainedHashTable MemProfFrameData +// OnDiskChainedHashTable MemProfCallStackData (NEW in V2) static Error writeMemProfV2(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData, bool MemProfFullSchema) { @@ -579,19 +617,7 @@ static Error writeMemProfV2(ProfOStream &OS, return Error::success(); } -// The MemProf profile data includes a simple schema -// with the format described below followed by the hashtable: -// uint64_t Version -// uint64_t RecordTableOffset = RecordTableGenerator.Emit -// uint64_t FramePayloadOffset = Stream offset before emitting the frame table -// uint64_t FrameTableOffset = FrameTableGenerator.Emit -// uint64_t Num schema entries -// uint64_t Schema entry 0 -// uint64_t Schema entry 1 -// .... -// uint64_t Schema entry N - 1 -// OnDiskChainedHashTable MemProfRecordData -// OnDiskChainedHashTable MemProfFrameData +// Write out the MemProf data in a requested version. static Error writeMemProf(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData, memprof::IndexedVersion MemProfVersionRequested, From f05c068429a86ef2187eae094354c73e8339baa2 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Thu, 16 May 2024 15:40:02 -0500 Subject: [PATCH 080/576] [InstrProf] Remove unused argv in llvm-profdata.cpp (#92435) https://github.com/llvm/llvm-project/pull/71328 refactored `llvm-profdata.cpp` to use subcommands (which is super nice), but left many unused `argv` variables. This opts to use `ProgName` where necessary, and removes `argv` otherwise. --- llvm/tools/llvm-profdata/llvm-profdata.cpp | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index ec046ebfab130b..4126b55576ddc3 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -1654,7 +1654,7 @@ static void parseInputFilenamesFile(MemoryBuffer *Buffer, } } -static int merge_main(int argc, const char *argv[]) { +static int merge_main(StringRef ProgName) { WeightedFileVector WeightedInputs; for (StringRef Filename : InputFilenames) addWeightedInput(WeightedInputs, {std::string(Filename), 1}); @@ -1667,8 +1667,7 @@ static int merge_main(int argc, const char *argv[]) { parseInputFilenamesFile(Buffer.get(), WeightedInputs); if (WeightedInputs.empty()) - exitWithError("no input files specified. See " + - sys::path::filename(argv[0]) + " " + argv[1] + " -help"); + exitWithError("no input files specified. See " + ProgName + " merge -help"); if (DumpInputFileList) { for (auto &WF : WeightedInputs) @@ -2654,7 +2653,7 @@ void overlapSampleProfile(const std::string &BaseFilename, OverlapAggr.dumpFuncSimilarity(OS); } -static int overlap_main(int argc, const char *argv[]) { +static int overlap_main() { std::error_code EC; raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF); if (EC) @@ -3231,15 +3230,16 @@ static int showDebugInfoCorrelation(const std::string &Filename, return 0; } -static int show_main(int argc, const char *argv[]) { +static int show_main(StringRef ProgName) { if (Filename.empty() && DebugInfoFilename.empty()) exitWithError( "the positional argument '' is required unless '--" + DebugInfoFilename.ArgStr + "' is provided"); if (Filename == OutputFilename) { - errs() << sys::path::filename(argv[0]) << " " << argv[1] - << ": Input file name cannot be the same as the output file name!\n"; + errs() << ProgName + << " show: Input file name cannot be the same as the output file " + "name!\n"; return 1; } if (JsonFormat) @@ -3263,7 +3263,7 @@ static int show_main(int argc, const char *argv[]) { return showMemProfProfile(SFormat, OS); } -static int order_main(int argc, const char *argv[]) { +static int order_main() { std::error_code EC; raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF); if (EC) @@ -3314,16 +3314,16 @@ int llvm_profdata_main(int argc, char **argvNonConst, cl::ParseCommandLineOptions(argc, argv, "LLVM profile data\n"); if (ShowSubcommand) - return show_main(argc, argv); + return show_main(ProgName); if (OrderSubcommand) - return order_main(argc, argv); + return order_main(); if (OverlapSubcommand) - return overlap_main(argc, argv); + return overlap_main(); if (MergeSubcommand) - return merge_main(argc, argv); + return merge_main(ProgName); errs() << ProgName << ": Unknown command. Run llvm-profdata --help for usage.\n"; From 1ede503910d3133ea1af8c084fee96ca98c66464 Mon Sep 17 00:00:00 2001 From: Hugo Trachino Date: Thu, 16 May 2024 21:40:56 +0100 Subject: [PATCH 081/576] [MLIR][Vector] Implement TransferReadOfExtractSliceOp as MaskableOpRewritePattern (#91960) Split of https://github.com/llvm/llvm-project/pull/90835 Adds support for `TransferReadOfExtractSliceOpFolder` when the `TransferReadOp` is inside a `MaskOp`. --- .../Dialect/Tensor/Transforms/CMakeLists.txt | 1 + .../Tensor/Transforms/FoldTensorSubsetOps.cpp | 29 ++++++++++++------- ...nsor-subset-ops-into-vector-transfers.mlir | 15 ++++++++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt index c6ef6ed86e0d9d..0aabdaf667b9d8 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt @@ -39,5 +39,6 @@ add_mlir_dialect_library(MLIRTensorTransforms MLIRTilingInterface MLIRTransforms MLIRVectorDialect + MLIRVectorUtils MLIRValueBoundsOpInterface ) diff --git a/mlir/lib/Dialect/Tensor/Transforms/FoldTensorSubsetOps.cpp b/mlir/lib/Dialect/Tensor/Transforms/FoldTensorSubsetOps.cpp index 3b8d3708bb7314..5396531922aab3 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/FoldTensorSubsetOps.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/FoldTensorSubsetOps.cpp @@ -18,6 +18,7 @@ #include "mlir/Dialect/Tensor/Transforms/Transforms.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" @@ -48,12 +49,14 @@ static Value getTensorOperand(tensor::InsertSliceOp op) { namespace { /// Merge extract_slice operation with load/transferRead operation. class TransferReadOfExtractSliceOpFolder final - : public OpRewritePattern { + : public vector::MaskableOpRewritePattern { public: - using OpRewritePattern::OpRewritePattern; + using MaskableOpRewritePattern::MaskableOpRewritePattern; - LogicalResult matchAndRewrite(vector::TransferReadOp readOp, - PatternRewriter &rewriter) const override; + FailureOr + matchAndRewriteMaskableOp(vector::TransferReadOp readOp, + vector::MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override; }; /// Merge insert_slice operation with store/transferWriteOp operation. @@ -84,8 +87,10 @@ static LogicalResult preconditionsFoldExtractOrInsertWithTransferOp( return success(); } -LogicalResult TransferReadOfExtractSliceOpFolder::matchAndRewrite( - vector::TransferReadOp readOp, PatternRewriter &rewriter) const { +FailureOr +TransferReadOfExtractSliceOpFolder::matchAndRewriteMaskableOp( + vector::TransferReadOp readOp, vector::MaskingOpInterface maskOp, + PatternRewriter &rewriter) const { auto extractSliceOp = getTensorOperand(readOp).getDefiningOp(); if (!extractSliceOp) @@ -95,7 +100,7 @@ LogicalResult TransferReadOfExtractSliceOpFolder::matchAndRewrite( preconditionsFoldExtractOrInsertWithTransferOp(rewriter, readOp, extractSliceOp); if (failed(preconditionResult)) - return preconditionResult; + return rewriter.notifyMatchFailure(readOp, "Failed preconditions"); SmallVector indices(readOp.getIndices().begin(), readOp.getIndices().end()); @@ -105,15 +110,17 @@ LogicalResult TransferReadOfExtractSliceOpFolder::matchAndRewrite( extractSliceOp.getMixedStrides(), extractSliceOp.getDroppedDims(), indices, sourceIndices); - rewriter.replaceOpWithNewOp( - readOp, readOp.getVectorType(), extractSliceOp.getSource(), sourceIndices, + Operation *newOp = rewriter.create( + readOp.getLoc(), readOp.getVectorType(), extractSliceOp.getSource(), + sourceIndices, AffineMapAttr::get(expandDimsToRank( readOp.getPermutationMap(), extractSliceOp.getSourceType().getRank(), extractSliceOp.getDroppedDims())), readOp.getPadding(), /*mask=*/Value(), readOp.getInBoundsAttr()); - - return success(); + if (maskOp) + newOp = mlir::vector::maskOperation(rewriter, newOp, maskOp.getMask()); + return newOp->getResults()[0]; } LogicalResult InsertSliceOfTransferWriteOpFolder::matchAndRewrite( diff --git a/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir b/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir index 6213db3956f9a1..e562cf8efc3567 100644 --- a/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir +++ b/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir @@ -75,6 +75,21 @@ func.func @transfer_read_of_extract_slice_non_leading_rank_reduction(%t : tensor return %1 : vector<5x6xf32> } +// CHECK-LABEL: func @masked_transfer_read_of_extract_slice +// CHECK-SAME: %[[t:.*]]: tensor, %[[s1:.*]]: index, %[[s2:.*]]: index +// CHECK-DAG: %[[m:.*]] = vector.create_mask{{.*}} : vector<5x6xi1> +// CHECK-DAG: %[[a:.*]] = affine.apply {{.*}}[[s1]] +// CHECK: vector.mask %[[m]] { vector.transfer_read %[[t]]{{.*}}: tensor, vector<5x6xf32> } : vector<5x6xi1> -> vector<5x6xf32> +func.func @masked_transfer_read_of_extract_slice(%t : tensor, %s1 : index, %s2 : index) -> vector<5x6xf32> { + %c3 = arith.constant 3 : index + %c4 = arith.constant 4 : index + %cst = arith.constant 0.0 : f32 + %0 = tensor.extract_slice %t[5, %s1] [10, %s2] [1, 1] : tensor to tensor<10x?xf32> + %mask = vector.create_mask %c3, %c4 : vector<5x6xi1> + %1 = vector.mask %mask {vector.transfer_read %0[%c3, %c4], %cst {in_bounds = [true, true]} : tensor<10x?xf32>, vector<5x6xf32>} : vector<5x6xi1> -> vector<5x6xf32> + return %1 : vector<5x6xf32> +} + // CHECK-LABEL: func @insert_slice_of_transfer_write( // CHECK-SAME: %[[t1:.*]]: tensor, %[[v:.*]]: vector<5x6xf32>, %[[s:.*]]: index // CHECK: %[[c3:.*]] = arith.constant 3 : index From d311a62e2f1ae34a0329c3812f2969cedac93561 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Thu, 16 May 2024 13:41:36 -0700 Subject: [PATCH 082/576] [ctx_profile] Decouple ctx instrumentation from PGOOpt (#92445) We currently don't support passing files and don't need frontend involvement either. --- llvm/lib/Passes/PassBuilderPipelines.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 682bdefbd52436..1892e16a06528c 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -839,10 +839,6 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, MPM.addPass(PGOInstrumentationGen(IsCS)); addPostPGOLoopRotation(MPM, Level); - if (PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) { - MPM.addPass(PGOCtxProfLoweringPass()); - return; - } // Add the profile lowering pass. InstrProfOptions Options; if (!ProfileFile.empty()) @@ -1157,8 +1153,17 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, const bool IsPGOInstrUse = IsPGOPreLink && PGOOpt->Action == PGOOptions::IRUse; const bool IsMemprofUse = IsPGOPreLink && !PGOOpt->MemoryProfile.empty(); - - if (IsPGOInstrGen || IsPGOInstrUse || IsMemprofUse) + // We don't want to mix pgo ctx gen and pgo gen; we also don't currently + // enable ctx profiling from the frontend. + assert( + !(IsPGOInstrGen && PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) && + "Enabling both instrumented FDO and contextual instrumentation is not " + "supported."); + // Enable contextual profiling instrumentation. + const bool IsCtxProfGen = !IsPGOInstrGen && IsPreLink && + PGOCtxProfLoweringPass::isContextualIRPGOEnabled(); + + if (IsPGOInstrGen || IsPGOInstrUse || IsMemprofUse || IsCtxProfGen) addPreInlinerPasses(MPM, Level, Phase); // Add all the requested passes for instrumentation PGO, if requested. @@ -1168,9 +1173,13 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, /*IsCS=*/false, PGOOpt->AtomicCounterUpdate, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, PGOOpt->FS); + } else if (IsCtxProfGen) { + MPM.addPass(PGOInstrumentationGen(false)); + addPostPGOLoopRotation(MPM, Level); + MPM.addPass(PGOCtxProfLoweringPass()); } - if (IsPGOInstrGen || IsPGOInstrUse) + if (IsPGOInstrGen || IsPGOInstrUse || IsCtxProfGen) MPM.addPass(PGOIndirectCallPromotion(false, false)); if (IsPGOPreLink && PGOOpt->CSAction == PGOOptions::CSIRInstr) From 6d2219acabc1882508d695e23d444d3e1cae4ff3 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 16 May 2024 16:06:20 -0500 Subject: [PATCH 083/576] [Libomptarget] Pass '-Werror=global-constructors' to the libomptarget build (#88531) Summary: A runtime library should not have global constructors. Everything is now expected to go through the init methods. This patch ensures that global constructors will not accidentally be introduced. --- offload/CMakeLists.txt | 5 +++++ offload/src/CMakeLists.txt | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt index 1d8cab240924e2..e2a4c2597636ef 100644 --- a/offload/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -136,6 +136,8 @@ include(LibomptargetGetDependencies) # Set up testing infrastructure. include(OpenMPTesting) +check_cxx_compiler_flag(-Werror=global-constructors OFFLOAD_HAVE_WERROR_CTOR) + # LLVM source tree is required at build time for libomptarget if (NOT LIBOMPTARGET_LLVM_INCLUDE_DIRS) message(FATAL_ERROR "Missing definition for LIBOMPTARGET_LLVM_INCLUDE_DIRS") @@ -207,6 +209,9 @@ set(offload_compile_flags -fno-exceptions) if(NOT LLVM_ENABLE_RTTI) set(offload_compile_flags ${offload_compile_flags} -fno-rtti) endif() +if(OFFLOAD_HAVE_WERROR_CTOR) + list(APPEND offload_compile_flags -Werror=global-constructors) +endif() # TODO: Consider enabling LTO by default if supported. # https://cmake.org/cmake/help/latest/module/CheckIPOSupported.html can be used diff --git a/offload/src/CMakeLists.txt b/offload/src/CMakeLists.txt index b474f29ea0be21..c5338130297fea 100644 --- a/offload/src/CMakeLists.txt +++ b/offload/src/CMakeLists.txt @@ -69,8 +69,8 @@ foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD) target_link_libraries(omptarget PRIVATE omptarget.rtl.${plugin}) endforeach() -target_compile_options(omptarget PUBLIC ${offload_compile_flags}) -target_link_options(omptarget PUBLIC ${offload_link_flags}) +target_compile_options(omptarget PRIVATE ${offload_compile_flags}) +target_link_options(omptarget PRIVATE ${offload_link_flags}) # libomptarget.so needs to be aware of where the plugins live as they # are now separated in the build directory. From 47d80ec1802d70082c8fd32b4396c98db2c4dba2 Mon Sep 17 00:00:00 2001 From: Jacob Lalonde Date: Thu, 16 May 2024 14:17:19 -0700 Subject: [PATCH 084/576] [LLDB/Coredump] Only take the Pthread from stack start to the stackpointer + red_zone (#92002) Currently in Core dumps, the entire pthread is copied, including the unused space beyond the stack pointer. This causes large amounts of core dump inflation when the number of threads is high, but the stack usage is low. Such as when an application is using a thread pool. This change will optimize for these situations in addition to generally improving the core dump performance for all of lldb. --- .../Minidump/MinidumpFileBuilder.cpp | 12 ++ lldb/source/Target/Process.cpp | 109 ++++++++++-------- .../TestProcessSaveCoreMinidump.py | 65 +++++++++-- 3 files changed, 131 insertions(+), 55 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp index 601f11d51d4282..7231433619ffb2 100644 --- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp +++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/Section.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -491,6 +492,17 @@ findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp) { std::errc::not_supported, "unable to load stack segment of the process"); + // This is a duplicate of the logic in + // Process::SaveOffRegionsWithStackPointers but ultimately, we need to only + // save up from the start of the stack down to the stack pointer + const addr_t range_end = range_info.GetRange().GetRangeEnd(); + const addr_t red_zone = process_sp->GetABI()->GetRedZoneSize(); + const addr_t stack_head = rsp - red_zone; + if (stack_head > range_info.GetRange().GetRangeEnd()) { + range_info.GetRange().SetRangeBase(stack_head); + range_info.GetRange().SetByteSize(range_end - stack_head); + } + const addr_t addr = range_info.GetRange().GetRangeBase(); const addr_t size = range_info.GetRange().GetByteSize(); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 25afade9a82752..216d2f21abfef0 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3857,8 +3857,8 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { // case we should tell it to stop doing that. Normally, we don't NEED // to do that because we will next close the communication to the stub // and that will get it to shut down. But there are remote debugging - // cases where relying on that side-effect causes the shutdown to be - // flakey, so we should send a positive signal to interrupt the wait. + // cases where relying on that side-effect causes the shutdown to be + // flakey, so we should send a positive signal to interrupt the wait. Status error = HaltPrivate(); BroadcastEvent(eBroadcastBitInterrupt, nullptr); } else if (StateIsRunningState(m_last_broadcast_state)) { @@ -6335,30 +6335,65 @@ static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages, ranges.push_back(CreateCoreFileMemoryRange(region)); } +static void SaveOffRegionsWithStackPointers( + Process &process, const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges, std::set &stack_ends) { + const bool try_dirty_pages = true; + + // Before we take any dump, we want to save off the used portions of the + // stacks and mark those memory regions as saved. This prevents us from saving + // the unused portion of the stack below the stack pointer. Saving space on + // the dump. + for (lldb::ThreadSP thread_sp : process.GetThreadList().Threads()) { + if (!thread_sp) + continue; + StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0); + if (!frame_sp) + continue; + RegisterContextSP reg_ctx_sp = frame_sp->GetRegisterContext(); + if (!reg_ctx_sp) + continue; + const addr_t sp = reg_ctx_sp->GetSP(); + const size_t red_zone = process.GetABI()->GetRedZoneSize(); + lldb_private::MemoryRegionInfo sp_region; + if (process.GetMemoryRegionInfo(sp, sp_region).Success()) { + const size_t stack_head = (sp - red_zone); + const size_t stack_size = sp_region.GetRange().GetRangeEnd() - stack_head; + sp_region.GetRange().SetRangeBase(stack_head); + sp_region.GetRange().SetByteSize(stack_size); + stack_ends.insert(sp_region.GetRange().GetRangeEnd()); + AddRegion(sp_region, try_dirty_pages, ranges); + } + } +} + // Save all memory regions that are not empty or have at least some permissions // for a full core file style. static void GetCoreFileSaveRangesFull(Process &process, const MemoryRegionInfos ®ions, - Process::CoreFileMemoryRanges &ranges) { + Process::CoreFileMemoryRanges &ranges, + std::set &stack_ends) { // Don't add only dirty pages, add full regions. const bool try_dirty_pages = false; for (const auto ®ion : regions) - AddRegion(region, try_dirty_pages, ranges); + if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0) + AddRegion(region, try_dirty_pages, ranges); } // Save only the dirty pages to the core file. Make sure the process has at // least some dirty pages, as some OS versions don't support reporting what // pages are dirty within an memory region. If no memory regions have dirty // page information fall back to saving out all ranges with write permissions. -static void -GetCoreFileSaveRangesDirtyOnly(Process &process, - const MemoryRegionInfos ®ions, - Process::CoreFileMemoryRanges &ranges) { +static void GetCoreFileSaveRangesDirtyOnly( + Process &process, const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges, std::set &stack_ends) { + // Iterate over the regions and find all dirty pages. bool have_dirty_page_info = false; for (const auto ®ion : regions) { - if (AddDirtyPages(region, ranges)) + if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0 && + AddDirtyPages(region, ranges)) have_dirty_page_info = true; } @@ -6367,7 +6402,8 @@ GetCoreFileSaveRangesDirtyOnly(Process &process, // plug-in so fall back to any region with write access permissions. const bool try_dirty_pages = false; for (const auto ®ion : regions) - if (region.GetWritable() == MemoryRegionInfo::eYes) + if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0 && + region.GetWritable() == MemoryRegionInfo::eYes) AddRegion(region, try_dirty_pages, ranges); } } @@ -6380,43 +6416,18 @@ GetCoreFileSaveRangesDirtyOnly(Process &process, // dirty regions as this will make the core file smaller. If the process // doesn't support dirty regions, then it will fall back to adding the full // stack region. -static void -GetCoreFileSaveRangesStackOnly(Process &process, - const MemoryRegionInfos ®ions, - Process::CoreFileMemoryRanges &ranges) { +static void GetCoreFileSaveRangesStackOnly( + Process &process, const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges, std::set &stack_ends) { + const bool try_dirty_pages = true; // Some platforms support annotating the region information that tell us that // it comes from a thread stack. So look for those regions first. - // Keep track of which stack regions we have added - std::set stack_bases; - - const bool try_dirty_pages = true; for (const auto ®ion : regions) { - if (region.IsStackMemory() == MemoryRegionInfo::eYes) { - stack_bases.insert(region.GetRange().GetRangeBase()); + // Save all the stack memory ranges not associated with a stack pointer. + if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0 && + region.IsStackMemory() == MemoryRegionInfo::eYes) AddRegion(region, try_dirty_pages, ranges); - } - } - - // Also check with our threads and get the regions for their stack pointers - // and add those regions if not already added above. - for (lldb::ThreadSP thread_sp : process.GetThreadList().Threads()) { - if (!thread_sp) - continue; - StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0); - if (!frame_sp) - continue; - RegisterContextSP reg_ctx_sp = frame_sp->GetRegisterContext(); - if (!reg_ctx_sp) - continue; - const addr_t sp = reg_ctx_sp->GetSP(); - lldb_private::MemoryRegionInfo sp_region; - if (process.GetMemoryRegionInfo(sp, sp_region).Success()) { - // Only add this region if not already added above. If our stack pointer - // is pointing off in the weeds, we will want this range. - if (stack_bases.count(sp_region.GetRange().GetRangeBase()) == 0) - AddRegion(sp_region, try_dirty_pages, ranges); - } } } @@ -6428,23 +6439,27 @@ Status Process::CalculateCoreFileSaveRanges(lldb::SaveCoreStyle core_style, return err; if (regions.empty()) return Status("failed to get any valid memory regions from the process"); + if (core_style == eSaveCoreUnspecified) + return Status("callers must set the core_style to something other than " + "eSaveCoreUnspecified"); + + std::set stack_ends; + SaveOffRegionsWithStackPointers(*this, regions, ranges, stack_ends); switch (core_style) { case eSaveCoreUnspecified: - err = Status("callers must set the core_style to something other than " - "eSaveCoreUnspecified"); break; case eSaveCoreFull: - GetCoreFileSaveRangesFull(*this, regions, ranges); + GetCoreFileSaveRangesFull(*this, regions, ranges, stack_ends); break; case eSaveCoreDirtyOnly: - GetCoreFileSaveRangesDirtyOnly(*this, regions, ranges); + GetCoreFileSaveRangesDirtyOnly(*this, regions, ranges, stack_ends); break; case eSaveCoreStackOnly: - GetCoreFileSaveRangesStackOnly(*this, regions, ranges); + GetCoreFileSaveRangesStackOnly(*this, regions, ranges, stack_ends); break; } diff --git a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py index 9fe5e89142987d..1e171e726fb6b3 100644 --- a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py +++ b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py @@ -2,7 +2,6 @@ Test saving a mini dump. """ - import os import lldb from lldbsuite.test.decorators import * @@ -12,7 +11,12 @@ class ProcessSaveCoreMinidumpTestCase(TestBase): def verify_core_file( - self, core_path, expected_pid, expected_modules, expected_threads + self, + core_path, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sps_map, ): # To verify, we'll launch with the mini dump target = self.dbg.CreateTarget(None) @@ -36,17 +40,36 @@ def verify_core_file( self.assertEqual(module_file_name, expected_file_name) self.assertEqual(module.GetUUIDString(), expected.GetUUIDString()) + red_zone = process.GetTarget().GetStackRedZoneSize() for thread_idx in range(process.GetNumThreads()): thread = process.GetThreadAtIndex(thread_idx) self.assertTrue(thread.IsValid()) thread_id = thread.GetThreadID() self.assertIn(thread_id, expected_threads) + frame = thread.GetFrameAtIndex(0) + sp_region = lldb.SBMemoryRegionInfo() + sp = frame.GetSP() + err = process.GetMemoryRegionInfo(sp, sp_region) + self.assertTrue(err.Success(), err.GetCString()) + error = lldb.SBError() + # Ensure thread_id is in the saved map + self.assertIn(thread_id, stacks_to_sps_map) + # Ensure the SP is correct + self.assertEqual(stacks_to_sps_map[thread_id], sp) + # Try to read at the end of the stack red zone and succeed + process.ReadMemory(sp - red_zone, 1, error) + self.assertTrue(error.Success(), error.GetCString()) + # Try to read just past the red zone and fail + process.ReadMemory(sp - red_zone - 1, 1, error) + self.assertTrue(error.Fail(), "No failure when reading past the red zone") + self.dbg.DeleteTarget(target) @skipUnlessArch("x86_64") @skipUnlessPlatform(["linux"]) def test_save_linux_mini_dump(self): """Test that we can save a Linux mini dump.""" + self.build() exe = self.getBuildArtifact("a.out") core_stack = self.getBuildArtifact("core.stack.dmp") @@ -69,30 +92,44 @@ def test_save_linux_mini_dump(self): expected_modules = target.modules expected_number_of_threads = process.GetNumThreads() expected_threads = [] + stacks_to_sp_map = {} for thread_idx in range(process.GetNumThreads()): thread = process.GetThreadAtIndex(thread_idx) thread_id = thread.GetThreadID() expected_threads.append(thread_id) + stacks_to_sp_map[thread_id] = thread.GetFrameAtIndex(0).GetSP() # save core and, kill process and verify corefile existence base_command = "process save-core --plugin-name=minidump " self.runCmd(base_command + " --style=stack '%s'" % (core_stack)) self.assertTrue(os.path.isfile(core_stack)) self.verify_core_file( - core_stack, expected_pid, expected_modules, expected_threads + core_stack, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) self.runCmd(base_command + " --style=modified-memory '%s'" % (core_dirty)) self.assertTrue(os.path.isfile(core_dirty)) self.verify_core_file( - core_dirty, expected_pid, expected_modules, expected_threads + core_dirty, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) self.runCmd(base_command + " --style=full '%s'" % (core_full)) self.assertTrue(os.path.isfile(core_full)) self.verify_core_file( - core_full, expected_pid, expected_modules, expected_threads + core_full, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) # validate saving via SBProcess @@ -100,14 +137,22 @@ def test_save_linux_mini_dump(self): self.assertTrue(error.Success()) self.assertTrue(os.path.isfile(core_sb_stack)) self.verify_core_file( - core_sb_stack, expected_pid, expected_modules, expected_threads + core_sb_stack, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) error = process.SaveCore(core_sb_dirty, "minidump", lldb.eSaveCoreDirtyOnly) self.assertTrue(error.Success()) self.assertTrue(os.path.isfile(core_sb_dirty)) self.verify_core_file( - core_sb_dirty, expected_pid, expected_modules, expected_threads + core_sb_dirty, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) # Minidump can now save full core files, but they will be huge and @@ -116,7 +161,11 @@ def test_save_linux_mini_dump(self): self.assertTrue(error.Success()) self.assertTrue(os.path.isfile(core_sb_full)) self.verify_core_file( - core_sb_full, expected_pid, expected_modules, expected_threads + core_sb_full, + expected_pid, + expected_modules, + expected_threads, + stacks_to_sp_map, ) self.assertSuccess(process.Kill()) From e5e562361555fc96c768b1dd3dd99f403f500838 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 16 May 2024 14:33:39 -0700 Subject: [PATCH 085/576] [bazel] Port #91960 (#92458) --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 62ac56f8b46e99..f7495a202669c5 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -2156,7 +2156,7 @@ cc_library( ":ArmSMEOpInterfacesIncGen", ":ArmSMEOpsIncGen", ":BytecodeOpInterface", - ":FunctionInterfaces", + ":FunctionInterfaces", ":IR", ":LLVMDialect", ":MemRefDialect", @@ -2173,7 +2173,7 @@ cc_library( hdrs = glob(["include/mlir/Dialect/ArmSME/Transforms/*.h"]), includes = ["include"], deps = [ - ":Analysis", + ":Analysis", ":ArithUtils", ":ArmSMEDialect", ":ArmSMETransformsPassIncGen", @@ -2181,7 +2181,7 @@ cc_library( ":DialectUtils", ":FuncDialect", ":FuncTransforms", - ":FunctionInterfaces", + ":FunctionInterfaces", ":IR", ":LLVMCommonConversion", ":LLVMDialect", @@ -2220,7 +2220,7 @@ cc_library( ":ControlFlowDialect", ":ConversionPassIncGen", ":FuncDialect", - ":FunctionInterfaces", + ":FunctionInterfaces", ":LLVMCommonConversion", ":LLVMDialect", ":MemRefDialect", @@ -7487,6 +7487,7 @@ cc_library( ":TransformUtils", ":ValueBoundsOpInterface", ":VectorDialect", + ":VectorUtils", "//llvm:Support", ], ) From 997eae3673dcd635b60ac63031f01f5dded92f32 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 16 May 2024 14:41:19 -0700 Subject: [PATCH 086/576] [AsmPrinter] Increase upper bound for size in global structs This is part of the fixes to address #57353 https://reviews.llvm.org/D133845 Pull Request: https://github.com/llvm/llvm-project/pull/92334 --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/test/CodeGen/X86/big-array-init.ll | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/big-array-init.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 869670d43a1785..d50cdc4323ecfa 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -3501,7 +3501,7 @@ static void emitGlobalConstantStruct(const DataLayout &DL, const Constant *BaseCV, uint64_t Offset, AsmPrinter::AliasMapTy *AliasList) { // Print the fields in successive locations. Pad to align if needed! - unsigned Size = DL.getTypeAllocSize(CS->getType()); + uint64_t Size = DL.getTypeAllocSize(CS->getType()); const StructLayout *Layout = DL.getStructLayout(CS->getType()); uint64_t SizeSoFar = 0; for (unsigned I = 0, E = CS->getNumOperands(); I != E; ++I) { diff --git a/llvm/test/CodeGen/X86/big-array-init.ll b/llvm/test/CodeGen/X86/big-array-init.ll new file mode 100644 index 00000000000000..6b05f901ebea84 --- /dev/null +++ b/llvm/test/CodeGen/X86/big-array-init.ll @@ -0,0 +1,7 @@ +; RUN: llc < %s -mtriple=x86_64 | FileCheck %s + +; CHECK-LABEL: bad_int: +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .zero 4294967292 +; CHECK-NEXT: .size bad_int, 4294967296 +@bad_int = global <{ i32, [1073741823 x i32] }> <{ i32 1, [1073741823 x i32] zeroinitializer }>, align 16 From c86a53d75995d65601d5745b2fceb2d50a970645 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Thu, 16 May 2024 18:44:41 -0300 Subject: [PATCH 087/576] [clang] Implement provisional wording for CWG2398 regarding packs (#90820) This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. When performing template argument deduction, a template template parameter containing no packs should be more specialized than one that does. Given the following example: ```C++ template struct A; template class TT1, class T4> struct A>; // #1 template class TT2, class T6> struct A>; // #2 template struct B; template struct A>; ``` Prior to P0522, candidate `#2` would be more specialized. After P0522, neither is more specialized, so this becomes ambiguous. With this change, `#2` becomes more specialized again, maintaining compatibility with pre-P0522 implementations. The problem is that in P0522, candidates are at least as specialized when matching packs to fixed-size lists both ways, whereas before, a fixed-size list is more specialized. This patch keeps the original behavior when checking template arguments outside deduction, but restores this aspect of pre-P0522 matching during deduction. --- Since this changes provisional implementation of CWG2398 which has not been released yet, and already contains a changelog entry, we don't provide a changelog entry here. --- clang/include/clang/Sema/Sema.h | 5 +- clang/lib/Sema/SemaTemplate.cpp | 10 ++-- clang/lib/Sema/SemaTemplateDeduction.cpp | 67 +++++++++++++++++++----- clang/test/SemaTemplate/cwg2398.cpp | 15 ++---- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 66d5e2d4a4aded..873592a2d430a7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9133,7 +9133,7 @@ class Sema final : public SemaBase { CheckTemplateArgumentKind CTAK); bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, - TemplateArgumentLoc &Arg); + TemplateArgumentLoc &Arg, bool IsDeduced); void NoteTemplateLocation(const NamedDecl &Decl, std::optional ParamRange = {}); @@ -9612,7 +9612,8 @@ class Sema final : public SemaBase { sema::TemplateDeductionInfo &Info); bool isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc); + TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc, + bool IsDeduced); void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a5350ceb59cb7c..1b3f1e8bf80f4f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6554,7 +6554,8 @@ bool Sema::CheckTemplateArgument( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (CheckTemplateTemplateArgument(TempParm, Params, Arg)) + if (CheckTemplateTemplateArgument(TempParm, Params, Arg, + /*IsDeduced=*/CTAK != CTAK_Specified)) return true; SugaredConverted.push_back(Arg.getArgument()); @@ -8472,7 +8473,8 @@ static void DiagnoseTemplateParameterListArityMismatch( /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, - TemplateArgumentLoc &Arg) { + TemplateArgumentLoc &Arg, + bool IsDeduced) { TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern(); TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { @@ -8524,8 +8526,8 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, !Template->hasAssociatedConstraints()) return false; - if (isTemplateTemplateParameterAtLeastAsSpecializedAs(Params, Template, - Arg.getLocation())) { + if (isTemplateTemplateParameterAtLeastAsSpecializedAs( + Params, Template, Arg.getLocation(), IsDeduced)) { // P2113 // C++20[temp.func.order]p2 // [...] If both deductions succeed, the partial ordering selects the diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 4d89fcfc9b116f..d0b780c28eae9d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -139,13 +139,15 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( SmallVectorImpl &Deduced, unsigned TDF, bool PartialOrdering = false, bool DeducedFromArrayBound = false); +enum class PackFold { ParameterToArgument, ArgumentToParameter }; static TemplateDeductionResult DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, - bool NumberOfArgumentsMustMatch); + bool NumberOfArgumentsMustMatch, + PackFold PackFold = PackFold::ParameterToArgument); static void MarkUsedTemplateParameters(ASTContext &Ctx, const TemplateArgument &TemplateArg, @@ -2550,7 +2552,9 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, ArrayRef As, TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, - bool NumberOfArgumentsMustMatch) { + bool NumberOfArgumentsMustMatch, PackFold PackFold) { + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Ps, As); // C++0x [temp.deduct.type]p9: // If the template argument list of P contains a pack expansion that is not // the last template argument, the entire template argument list is a @@ -2581,8 +2585,11 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, return TemplateDeductionResult::MiscellaneousDeductionFailure; // Perform deduction for this Pi/Ai pair. - if (auto Result = DeduceTemplateArguments(S, TemplateParams, P, - As[ArgIdx], Info, Deduced); + TemplateArgument Pi = P, Ai = As[ArgIdx]; + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Pi, Ai); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, Pi, Ai, Info, Deduced); Result != TemplateDeductionResult::Success) return Result; @@ -2609,9 +2616,12 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, for (; hasTemplateArgumentForDeduction(As, ArgIdx) && PackScope.hasNextElement(); ++ArgIdx) { + TemplateArgument Pi = Pattern, Ai = As[ArgIdx]; + if (PackFold == PackFold::ArgumentToParameter) + std::swap(Pi, Ai); // Deduce template arguments from the pattern. - if (auto Result = DeduceTemplateArguments(S, TemplateParams, Pattern, - As[ArgIdx], Info, Deduced); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, Pi, Ai, Info, Deduced); Result != TemplateDeductionResult::Success) return Result; @@ -6299,7 +6309,8 @@ bool Sema::isMoreSpecializedThanPrimary( } bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) { + TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc, + bool IsDeduced) { // C++1z [temp.arg.template]p4: (DR 150) // A template template-parameter P is at least as specialized as a // template template-argument A if, given the following rewrite to two @@ -6309,11 +6320,10 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( // equivalent partial ordering by performing deduction directly on // the template parameter lists of the template template parameters. // - // Given an invented class template X with the template parameter list of - // A (including default arguments): - TemplateName X = Context.getCanonicalTemplateName(TemplateName(AArg)); TemplateParameterList *A = AArg->getTemplateParameters(); + // Given an invented class template X with the template parameter list of + // A (including default arguments): // - Each function template has a single function parameter whose type is // a specialization of X with template arguments corresponding to the // template parameters from the respective function template @@ -6356,14 +6366,43 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( return false; } - QualType AType = Context.getCanonicalTemplateSpecializationType(X, AArgs); - QualType PType = Context.getCanonicalTemplateSpecializationType(X, PArgs); + // Determine whether P1 is at least as specialized as P2. + TemplateDeductionInfo Info(Loc, A->getDepth()); + SmallVector Deduced; + Deduced.resize(A->size()); // ... the function template corresponding to P is at least as specialized // as the function template corresponding to A according to the partial // ordering rules for function templates. - TemplateDeductionInfo Info(Loc, A->getDepth()); - return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info); + + // Provisional resolution for CWG2398: Regarding temp.arg.template]p4, when + // applying the partial ordering rules for function templates on + // the rewritten template template parameters: + // - In a deduced context, the matching of packs versus fixed-size needs to + // be inverted between Ps and As. On non-deduced context, matching needs to + // happen both ways, according to [temp.arg.template]p3, but this is + // currently implemented as a special case elsewhere. + if (::DeduceTemplateArguments(*this, A, AArgs, PArgs, Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false, + IsDeduced ? PackFold::ArgumentToParameter + : PackFold::ParameterToArgument) != + TemplateDeductionResult::Success) + return false; + + SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); + Sema::InstantiatingTemplate Inst(*this, Info.getLocation(), AArg, DeducedArgs, + Info); + if (Inst.isInvalid()) + return false; + + bool AtLeastAsSpecialized; + runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = + ::FinishTemplateArgumentDeduction( + *this, AArg, /*IsPartialOrdering=*/true, PArgs, Deduced, Info) == + TemplateDeductionResult::Success; + }); + return AtLeastAsSpecialized; } namespace { diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index d163354b2e5fed..31686c4bc98050 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -62,25 +62,19 @@ namespace templ { namespace type_pack1 { template struct A; template class TT1, class T4> struct A> ; - // new-note@-1 {{partial specialization matches}} template class TT2, class T6> struct A> {}; - // new-note@-1 {{partial specialization matches}} template struct B; template struct A>; - // new-error@-1 {{ambiguous partial specialization}} } // namespace type_pack1 namespace type_pack2 { template struct A; template class TT1, class ...T4> struct A> ; - // new-note@-1 {{partial specialization matches}} template class TT2, class ...T6> struct A> {}; - // new-note@-1 {{partial specialization matches}} template struct B; template struct A>; - // new-error@-1 {{ambiguous partial specialization}} } // namespace type_pack2 namespace type_pack3 { @@ -140,13 +134,10 @@ namespace ttp_defaults { namespace ttp_only { template