<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/67747>67747</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [AArch64][SVE] 128-bit fixed length truncstore cannot be lowered (with a candidate fix)
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          MattPD
      </td>
    </tr>
</table>

<pre>
    Encountering an ICE after removing NEON preference in `useSVEForFixedLengthVectors` for 128-bit vector register size SVE code generation, i.e., when changing `256` to `128` in <https://github.com/llvm/llvm-project/blob/de85739ded2edddc568f287d4f94c2dc1ab97dd7/llvm/lib/Target/AArch64/AArch64Subtarget.h#L408>.

---

Candidate fix:

The good news is that I've been able to fix this by building on 2240409 to further restrict the fixed-length truncstore combine, avoiding introducing it entirely for the 128-bit vector size.

Similarly to 2240409, we can prevent the ICE by not folding FP_ROUND followed by a store into a truncating store when in the  mode compiling for 128-bit SVE subtarget as that would introduce an illegal ISD TRUNC node (which we cannot lower).

The idea is to add a check in addition to `hasValidElementTypeForFPTruncStore` specifically preventing the fold for the 128-bit vector size subtarget, e.g., either add an additional check `Subtarget->getMinSVEVectorSizeInBits() != 128` here: <https://github.com/llvm/llvm-project/commit/22404099c48cff1c118cd4f6fd9e1acf7ff0fefb#diff-6291e4657dea1f4fecdcb9dc96bfb014f79d4c617f080b2f033943e52732cf69R19334> or restrict the threshold in ` VT.getFixedSizeInBits() >= Subtarget->getMinSVEVectorSizeInBits()` to be instead 256 bits.

The lack of support for lowering this manifests as an ICE in `llvm::SelectionDAG::getNode(unsigned int, const llvm::SDLoc&, llvm::EVT, llvm::SDValue, llvm::SDNodeFlags)` with the following assertion violation: `Assertion VT.isInteger() && N1.getValueType().isInteger() && "Invalid TRUNCATE!" failed.`

---

Minimal reproducer:
```
$ cat Reduction.c
void copy_real_to_outtype(int num_elems, double inarray[], void *outarray) {
  float *_outarray = outarray;
  for (int i = 0; i < num_elems; i++)
    _outarray[i] = inarray[i];
}
```

ICE:
```
$ clang_with_relaxed_useSVEForFixedLengthVectors -Ofast -msve-vector-bits=128 -mcpu=neoverse-v2 -c Reduction.c

clang: /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:5744: llvm::SDValue llvm::SelectionDAG::getNode(unsigned int, const llvm::SDLoc&, llvm::EVT, llvm::SDValue, llvm::SDNodeFlags): Assertion `VT.isInteger() && N1.getValueType().isInteger() && "Invalid TRUNCATE!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /llvm_src/build_aarch64-release-asserts/bin/clang -Ofast -msve-vector-bits=128 -mcpu=neoverse-v2 -c Reduction.c
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'Reduction.c'.
4.      Running pass 'AArch64 Instruction Selection' on function '@copy_real_to_outtype'
 #0 0x0000ffffaab53560 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /llvm_src/llvm-project/llvm/lib/Support/Unix/Signals.inc:727:3
 #1 0x0000ffffaab51680 llvm::sys::RunSignalHandlers() /llvm_src/llvm-project/llvm/lib/Support/Signals.cpp:106:18
 #2 0x0000ffffaaa84388 HandleCrash /llvm_src/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:73:5
 #3 0x0000ffffaaa84388 CrashRecoverySignalHandler(int) /llvm_src/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:390:62
 #4 0x0000ffffb04847cc (linux-vdso.so.1+0x7cc)
 #5 0x0000ffffaa553500 raise (/lib64/libc.so.6+0x37500)
 #6 0x0000ffffaa5548a4 abort (/lib64/libc.so.6+0x388a4)
 #7 0x0000ffffaa54c9e8 __assert_fail_base (/lib64/libc.so.6+0x309e8)
 #8 0x0000ffffaa54ca64 (/lib64/libc.so.6+0x30a64)
 #9 0x0000ffffaa09bc10 llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::EVT, llvm::SDValue) /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:5565:7
#10 0x0000ffffa9f494f4 LegalizeStoreOps /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:652:15
#11 0x0000ffffa9f494f4 (anonymous namespace)::SelectionDAGLegalize::LegalizeOp(llvm::SDNode*) /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1367:28
#12 0x0000ffffa9f528fc llvm::SelectionDAG::Legalize() /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:5584:22
#13 0x0000ffffaa0d4064 llvm::TimeRegion::~TimeRegion() /llvm_src/llvm-project/llvm/include/llvm/Support/Timer.h:155:9
#14 0x0000ffffaa0d4064 llvm::NamedRegionTimer::~NamedRegionTimer() /llvm_src/llvm-project/llvm/include/llvm/Support/Timer.h:163:8
#15 0x0000ffffaa0d4064 llvm::SelectionDAGISel::CodeGenAndEmitDAG() /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:906:3
#16 0x0000ffffaa0d7600 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1707:33
#17 0x0000ffffaa0d90bc llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) /llvm_src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:483:22
#18 0x0000ffffadd1e588 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) /llvm_src/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:91:33
#19 0x0000ffffab5d51e4 llvm::FPPassManager::runOnFunction(llvm::Function&) /llvm_src/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1435:40
#20 0x0000ffffab5d53f8 llvm::ilist_node_base<true>::getNext() const /llvm_src/llvm-project/llvm/include/llvm/ADT/ilist_node_base.h:43:45
#21 0x0000ffffab5d53f8 llvm::ilist_node_impl<llvm::ilist_detail::node_options<llvm::Function, true, false, void>>::getNext() /llvm_src/llvm-project/llvm/include/llvm/ADT/ilist_node.h:67:66
#22 0x0000ffffab5d53f8 llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Function, true, false, void>, false, false>::operator++() /llvm_src/llvm-project/llvm/include/llvm/ADT/ilist_iterator.h:157:25
#23 0x0000ffffab5d53f8 llvm::FPPassManager::runOnModule(llvm::Module&) /llvm_src/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1480:22
#24 0x0000ffffab5d5c6c runOnModule /llvm_src/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1550:38
#25 0x0000ffffab5d5c6c llvm::legacy::PassManagerImpl::run(llvm::Module&) /llvm_src/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:535:55
#26 0x0000ffffae3e57c0 llvm::TimeTraceScope::~TimeTraceScope() /llvm_src/llvm-project/llvm/include/llvm/Support/TimeProfiler.h:155:37
#27 0x0000ffffae3e57c0 RunCodegenPipeline /llvm_src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp:1154:3
#28 0x0000ffffae3e57c0 EmitAssembly /llvm_src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp:1175:21
#29 0x0000ffffae3e57c0 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>) /llvm_src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp:1337:25
#30 0x0000ffffae7bf63c std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>::~unique_ptr() /opt/gcc/12.1.0/snos/include/g++/bits/unique_ptr.h:395:12
#31 0x0000ffffae7bf63c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) /llvm_src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:386:24
#32 0x0000ffffa8017b4c clang::ParseAST(clang::Sema&, bool, bool) /llvm_src/llvm-project/clang/lib/Parse/ParseAST.cpp:176:34
#33 0x0000ffffad09ddd4 clang::FrontendAction::Execute() /llvm_src/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1070:21
#34 0x0000ffffad036484 llvm::Error::getPtr() const /llvm_src/llvm-project/llvm/include/llvm/Support/Error.h:276:51
#35 0x0000ffffad036484 llvm::Error::operator bool() /llvm_src/llvm-project/llvm/include/llvm/Support/Error.h:239:22
#36 0x0000ffffad036484 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /llvm_src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1051:42
#37 0x0000ffffaef013a4 std::__shared_ptr<clang::FrontendOptions, (__gnu_cxx::_Lock_policy)2>::get() const /opt/gcc/12.1.0/snos/include/g++/bits/shared_ptr_base.h:1666:16
#38 0x0000ffffaef013a4 std::__shared_ptr_access<clang::FrontendOptions, (__gnu_cxx::_Lock_policy)2, false, false>::_M_get() const /opt/gcc/12.1.0/snos/include/g++/bits/shared_ptr_base.h:1363:69
#39 0x0000ffffaef013a4 std::__shared_ptr_access<clang::FrontendOptions, (__gnu_cxx::_Lock_policy)2, false, false>::operator*() const /opt/gcc/12.1.0/snos/include/g++/bits/shared_ptr_base.h:1349:2
#40 0x0000ffffaef013a4 clang::CompilerInvocation::getFrontendOpts() /llvm_src/llvm-project/clang/include/clang/Frontend/CompilerInvocation.h:247:48
#41 0x0000ffffaef013a4 clang::CompilerInstance::getFrontendOpts() /llvm_src/llvm-project/clang/include/clang/Frontend/CompilerInstance.h:291:39
#42 0x0000ffffaef013a4 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /llvm_src/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:273:29
#43 0x00000000004139bc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /llvm_src/llvm-project/clang/tools/driver/cc1_main.cpp:294:40
#44 0x000000000040cb44 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /llvm_src/llvm-project/clang/tools/driver/driver.cpp:366:20
#45 0x0000ffffacd60764 operator() /llvm_src/llvm-project/clang/lib/Driver/Job.cpp:440:32
#46 0x0000ffffacd60764 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) /llvm_src/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:52
#47 0x0000ffffaaa84504 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /llvm_src/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:10
#48 0x0000ffffacd60ed4 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) /llvm_src/llvm-project/clang/lib/Driver/Job.cpp:440:3
#49 0x0000ffffacd2dc18 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const /llvm_src/llvm-project/clang/lib/Driver/Compilation.cpp:199:22
#50 0x0000ffffacd2e370 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const /llvm_src/llvm-project/clang/lib/Driver/Compilation.cpp:253:5
#51 0x0000ffffacd3a77c llvm::SmallVectorBase<unsigned int>::empty() const /llvm_src/llvm-project/llvm/include/llvm/ADT/SmallVector.h:94:46
#52 0x0000ffffacd3a77c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) /llvm_src/llvm-project/clang/lib/Driver/Driver.cpp:1883:28
#53 0x0000000000411210 clang_main(int, char**, llvm::ToolContext const&) /llvm_src/llvm-project/clang/tools/driver/driver.cpp:542:39
#54 0x000000000040b4fc main /llvm_src/build_aarch64-release-asserts/tools/clang/tools/driver/clang-driver.cpp:16:1
#55 0x0000ffffaa53ffa0 __libc_start_main (/lib64/libc.so.6+0x23fa0)
#56 0x000000000040b538 _start /home/abuild/rpmbuild/BUILD/glibc-2.31/csu/../sysdeps/aarch64/start.S:95:0
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 18.0.0 (https://github.com/llvm/llvm-project.git da28593d71a8581bdcf6b99346e1cd625076aaff)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /llvm_src/build_aarch64-release-asserts/bin
clang: note: diagnostic msg:
********************
```

---

Reduced LLVM IR (note that the load(f64)-fptrunc(from_f64_to_f32)-store(f32) sequence occurs in a loop context):
```
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

define void @copy_real_to_outtype(i32 %num_elems, ptr %inarray, ptr %outarray) {
entry:
  br label %for.cond

for.cond:                                         ; preds = %for.body, %entry
  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
 %cmp = icmp slt i32 %i.0, %num_elems
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %idxprom = zext i32 %i.0 to i64
  %arrayidx = getelementptr double, ptr %inarray, i64 %idxprom
  %0 = load double, ptr %arrayidx, align 8
  %conv = fptrunc double %0 to float
  %arrayidx2 = getelementptr float, ptr %outarray, i64 %idxprom
  store float %conv, ptr %arrayidx2, align 4
  %inc = add i32 %i.0, 1
  br label %for.cond

for.end:                                          ; preds = %for.cond
  ret void
}
```

---

We can get more context by adding the following in `performSTORECombine` before the check involving `hasValidElementTypeForFPTruncStore`:

```
if (DCI.isBeforeLegalizeOps() && Value.getOpcode() == ISD::FP_ROUND &&
 Value.getNode()->hasOneUse() && ST->isUnindexed() &&
 Subtarget->useSVEForFixedLengthVectors())
{
LLVM_DEBUG(dbgs() << "ValueVT.getFixedSizeInBits(): " << ValueVT.getFixedSizeInBits() << '\n');
LLVM_DEBUG(dbgs() << "Subtarget->getMinSVEVectorSizeInBits(): " << Subtarget->getMinSVEVectorSizeInBits() << '\n');
}

```

Now, the difference is that with the 256-bit restriction we don't get past Subtarget->useSVEForFixedLengthVectors():
```
Combining: t58: ch = store<(store (s128) into %ir.scevgep26, align 4, !tbaa !20)> t0, t19, t30, undef:i64, Reduction.c:4:18
---
Combining: t33: ch = store<(store (s32) into %ir.lsr.iv, !tbaa !20)> t0, t7, t9, undef:i64, Reduction.c:4:18 at depth 1
```

In contrast, with 128-bit-only restriction we do get past `Subtarget->useSVEForFixedLengthVectors()` and introduce the aforementioned trunc node due to the fold:
```
Combining: t58: ch = store<(store (s128) into %ir.scevgep26, align 4, !tbaa !20)> t0, t19, t30, undef:i64, Reduction.c:4:18
ValueVT.getFixedSizeInBits(): 128
Subtarget->getMinSVEVectorSizeInBits(): 128
Combining: t33: ch = store<(store (s32) into %ir.lsr.iv, !tbaa !20)> t0, t7, t9, undef:i64, Reduction.c:4:18 at depth 1
ValueVT.getFixedSizeInBits(): 32
Subtarget->getMinSVEVectorSizeInBits(): 128
```

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkfFtz2rrX96dxbzQwtny-6AWBZP-zJ20zIe17yciSDHprJP8lmYR98Xz2ZyTZ2CaQhO50P6dOh4COv7W0TpK1jJRia07pZy--8uLFJ9TojZCfvyCt7xefCkH2n685Fg3XVDK-BoiD2_k1QKWmEki6FTtT-vX621dQS1pSSTmmgHHgJX6j6PLH9Y2QN-yZkjvK13rzg2ItpPISH5RCggBmk4JpsLPFQNI1U2Zkxf6iYPnjGmBBKFhTTiXSTHAPzgGb0qn5-7ShHOAN4msDwUt8GCdmXC3MjwBm5odBEs43WtfKC2cevPHgzZrpTVNMsdh68Kaqdt2fSS3F_6dYe_CmqEThwRtCszgNc0IJpIQQHCdZCbOURGUeYUhwgIo8JSQdjMNMv0ck19SMM5tJvEmi_tuyKbStnG48GN5FfuaF11PPX3j-zH1OJpPhzznihBGkKSjZsyFhUPe4oWAtBAGcPinAFNAbpMGtB9MdBQWlHKCiooYhJXsGesMUKPagaFhFDMsEBxBGfuTntkkj9cYuqtKSYQ30xs5JyaSySwe0bDhWWkgKsNgWjFOzDGgnmB2OcS0FabD9rgHlmkla7e06m7GO1tos8YjwJduyCslqb9C0wOw6U4ARN-K1o9zBMiJY7AEXGpTCEXNzv3r49v3rwhRU4okS0wABB5dxLQByBCBtmrtyK0KM2zHB1ogaFtuaVabFUDyNJKpu5QBqGf0kmoocyKZGN1hV0TWqwO1yAR4fvn-dA25G9WD2tGF409JicBuM0oP59HhBGaHIrqUAiBCAAN5Q_NOgRIQwowSthG-Q-oEqRq4ruqVcP-5ranTt_tFQuTT0GQVQNcWsZBhV1b7joSHPrq6oyGvL09Ns1oFO11bvKLNyYsH1oFDVAvUS_yDkEy-8XlP9hfHlj2un-kv2F73lV0wrD2YezIEHAy9cgFZfN1RSL5z9ktJisd0y86UVnhxHGS7LAAdBhklUJiXJaYBwmZalX9Ky8GBIWFlOEpgHNErilFAUlFFJMcFFTnCeFGXhB1GZ5iTCSZCWfuYXsPTDMI9CGsM0hLhM8ocgD8PIC6-BONIfvZFUbYQVE8MZ8ONxuqbaGsSXnAivDScu4V5r7woj4kpTRACME1AwrV7IVYXwTyBKoJq6FlLbdbdC6KSBKbBFnJVUaWUkvDX0DrbldzjzwtmSVhSb9V7M_nAla6q_CkI9mDXc-hKrEkZQsOBKg0HfxZ3AHkxMXV96_eNxXLBc_EBVQ48LzSQ3FVqrluwnZkySk-JKPFnnpBSVVkN2TFTOYRhZSvzZoebH45SpW67p2qhfK4GJBxPwNTBLY-c2uuQqzzX2ILzlO6N-Ts9nj9dGkCEEJWIVJVMv8V-x6l8YZ1tUAUlrZzxkb9oTv_3vfsIIYKTBAyWNZfwUuwpjdgEW9X4lKapWWqxEo7UDzrgGvNmuaEW3yjCSiMZ4AsaRlGjvfL0pt4N4cCYa7WoMhemVmwGAshJIm_pV1wAYCT20DvuWQoJ2Ymbb-F54Zb_OB0hMkQev7P-86wrAYXQvvmJevLAD9FhN0WEqL12c5pP9vJ1fv8rICvH1ykjOStIKPVOyeiVIAZNvJVIaTLZqRyfOLhoTqbxwEcAMTLa4brxwwanYUanoZAfBBL9cKfdp57bi6AzXSkn80oaNwoi5IPQPyj14M1K78c8prmsvnMVpFJnRX-gR-G-nvOEM9ProJf7vVkkPpgettEtxf3c9W1qPvmUaIFA0a6OJxipqAS72O0yphioP3gDEDf9w1RBqTROWSG1AgfBPLRG2XKmtymOqFCVAiUa6YtMTKSUwQ5oSIBsOFJas1i3kpTbmmzTb-iDf_hTYf_dSrCXaAiTXjQkE1EshsyHfCiEbgk4krShSdOLMpQFeMCNkVkI_SuiDFp0XzqkojW-skVQmbjChITGeqGQVdY1h23h-FO3byrCtfGg4N1a-RkoBD6Y3DbczgntT8AVxZEUiNXHtVpCmMnFXOgQG05ab0Zkh2yAd3HKlpesGDkrTDl1203ow9SL_tAVOW-PmwdAH_rPv-35ZliVCRRzGiT_QDbVX7su9ZFzbZX50spL1jSR6WgmlJUXbVgWtluYX2JKlc_sevPnO2bMpYGuOKjVlHHvhLIWpF87CHnZwBDtIspOwHxruRvoX4qSisg_rLkfWQXIWLfAT85n1mOAIE8qiMMuAm3duNe1XJrU9Hyg24ryfC67ps24RpKExrP384an5R_1HrHD-8FeZ8QquMPe9cJbAHlk0QFb4URalGBt_XDHePE92RImpEtPAg1f-c4px7309GMYjquI4jH0fSMSU3bc4ZHYLW7ECm2ESO0yYxr4_Gig5GijKUARQYczqqwNlGYpGA6XjgSKc0wysVs5erYwpXxXoLXh-TrPRqNnxqCiJ3hgCJWNg-WgIPy9w4P-ifz3yrM7fXuBfLxGqi-KIOImN6HdBUxiMDFheRnlURuDObHPZX9TuM7_V6iPQdGP2YJIYGhMQ92CCU2A8mCEu-H4rGgU42lJVWwuav1yWbg5X0_36Vo_MrYtXPDj7IDa_JCwIE2NvYdZTBseUxTAr8auydSDlUoN7Ac44zkxUCWGPc2wEfRL5STTA-ci29IGu3dbLC2f_MSh4P9A2iOoLertoxpPTjZULI6l5Dy16HdpXtKXEQbGDtABfFH80zMS4kcFKx6_DHC7K7ZJWrrRdtBkn11um7Xp91LIfT9iufW79b9jjTo5wp4l_zvr1uF3prKqukGL4qhL4pxop2yGM6y3g76QqSH0b6QzoSo_oyv3inOb1dMmGf-NfEN4wTjsSRnS9qGsJy6Y1knrq_14yoyw80tuR-yMkoHGWgbNwTUw9IPQkhR9O2gkMnSwGR2s28sRFTOKADnXo5t507vYEl9LxXuS3D63RxPvBdJ2gRaExT9Hh-CGE_jHosBwuAauY0isuCLXhjRfOtWyoPRXsYgn6rFu9d_vzXzJSs8WjKR7PZk1VZIQm6t0tDN6NmG3rygvnx3WEasRalbHtRG1YrUZN-wWYA0synIMSVYp2R1SWByfZ8CEMsLRbh5wkPe3wPbQzbfaqQv5W0odl7kvHDFG307eHah_Dk46o1svaSGUgFOHrjDmne1_snnxsI9uij9W7zB-bPhgdA8YJBgNMHzZ1HJupw97Xw_jU1D0DKjtSewDQj3drlanl3G_nWGwNVTxY4ZGnpyGNU-wfxXj2kGKJRU0Hcd6g8MOCqHspSlaNQr6w353A9BTUh4Ybr7Km_J7VtGL8jSV2Z7MvHdIVwj8pJ981O4QPQRyNoiKYnQJgYrSZUnRbVPuPmzo1xMOgnzs_NXd30Gy2j1um24G-NbpujNUcVC8YWnOhNMPqmq_t81y7_xw0-RdFhMolRRJvvjn7NdqqDpq22N9o5R6Nv9HoDvH1qSaDoExLxtcPtBwXd-oxOxqwZcLsYGv7Lrdcy0axHX2g5Zzrez225buyjYNuWEWXe6XptjXJShNX03D274au6qOeEj2t6ifJNF11R3eDToSWqKmMl6iopm90dO7vLX26QJTC8Mioj48paVqUSYj_eRKdKRnMdjAjojYkrrGhO4DTwESZN4oLNbIg684R3tgja3jTD2XtR5gbFQp63zA-5-zofik5c8FVc9gzugO-R4m4co8Zv3N2pFuz5WN7aPceY31u6bpdX3uC7U7_MrMvg1FPwyhSyfwgLaIRDfdIKjpbPo4RLukWtXpVCFH1fy_Casfu_s6Wj4dtlt08DkCOogbi54SQaAjyRhp2HXTU2a9nihv9LmcyRtUNNvg64mHgp_7Ylo6OUBHxwyTKhjuKaymFPESg9wfR_BtxeO_n7OBWQKHlWzzAFb8bVxcMtsv4EQ54ACzMx1HV-Li3AzbyB9vaOO5brjTimI6WtLPE2XkJuFhtBot-PPdh2WOzkYwGVIzjh9IPQhT1Jmy1UhskKWkt3wmwrZsy2uPBbLVa82aFn5_b7ncC_1zVomJ478EcDjcxx_Lziwaux9dv44IksY9O-s3M-PD7VTJXCGNqNv9_n9rz-5bVl9VvZkFoT92S_nRwfHj_X8-Cfus2-618iKzeHtgQ-afYcFJtdwKj3havqR6w4F2P-Tr17DF3JSdVtZvP2ZsotcdYPfDg3cCH9ub3w24tjAXtzql6oYvgG6Bbc3iC6SPT-IK2dzybOG0cH61vuDk7b2spoX32CQeUdP7b_YuCMC8wwDhYbREb71FnUqK9Cc3DOd4g2UXwszZuHpd1xxwXEKSFqIy8E8l2VJqKFkWHPY_GB29RNMbu4yKKQMeCeeB4MnwAtEVV5W4Bua34CUKONiRmjDbge_9J9lmK3Jcu4LPWHA7oGcUEmCR-mkSgNyiXRkuLbto_RdGdH0f2JGNgN5JTc9r7Yz0TursRK2lXv71dZh_DdmYPo6oqEP65KvnYvra0O3GfB3Ox3SJOjuPAk1J2MOLuhA2NDyL7rWK7jZoPrT5-fg4C96NAimGzH2EGk13yUWNTsNIS2cswrvpoOFRVRo3scWBXb5rM-uB6drD0rosH0wptC4I8mPasglklzAL9rcO85eNdd7yIqutnLZFyp7z2uGewtOnxvYbYH4aYp24i9Jc_UEmr_WhlXpeCj78OEdm7K8FAP7JjWaXjvcb_OVm75OHMe21Dz-58zG5IcJCdZbf1OOjFHq9bg5HbO-poGpw7Mnql6Wy0y33Xlu0MDwbgux1FfrQtiv0jZtAw9S9lxp-iUOc58aco7pjS507GXviug8jUiBlp6W54vpN5rVz9NhbCeHDNynAwGHMwRGmKTxN45R6Tje7WdI6Gbmu9_6iHZYM5rQl1EUa_v4rhKcxnOLwYfB_FYScCv3PS8g-u-q-Zi8Uwggky9zi6j-bj43AygEGrJl1A2QG2pnHWGrZ_JOCKIzgO4-PjALKISgwMzgsv2nbzng9lTcVkhCawe_key9F9vbAskQ9Wq4oVxqEgqVctsPM322BYov7unhk0OSYwDjPghjMkbsTW6ASy9HnwRtbb7uvV99u7hdmOmikmcBoGhgzVePBmOjW70r0itDZEtmwxZWbc6dIokolF_KMb8rQ903LyAMp26wJwK6TuMrfLAKHPTLsswSC0N8EaRcFkB7QAilLABhuqfDAN2FGpmOAgyKb-1DcdL7v3PV0zDQiCWZyHJA1QFmdBQXCZFHkeRgkNMElg7KcJQmV5mLtNDAxnoJORhv_k4olP3E3NNW-6jB1JEbE5aZVpXgvFntscB7MHrCpKFkz-2lXvMbe50DblihyeBoGtsiailY6_8f98psZRQoy9pk0JuLv78QXcPpj1MLhcop3eUFAJZIKD0t7InJS1zeUzBVJsV2USrbRYlSE0lTa3z1TZn0DRfzc2K1Vg3EhlM-lAJURtzIY7oM-9M0kjbcYfQRpVaC8abVNTPAjpxJghOmGZvdtltkoTFiSduppfifERSTRhAczsQ4dswkPoypamrIsa2km0ZHVFuwnOy8ch2LCfhJaM0zaR59x19IyFEHgwHuUE1Vqasi7Ppi85mQxEuZb7A5sAKCSoUEEr06EUcooFJ0Nch7JwBt77zwuvQC0pUS0T7MCFIHt32BY7DC0AA90obrgA9YYBS2F8BfxhW9CmOZkKSypua7uBbYPuem-Mt7VLPTJfVKVByzY27UbtGdizgQVtX-ufhjzpoI8K6Us-2XZ_l0_9AjjekOdaiq1t8ZfxkT0txjYa6ewb2-Vm5Nm2XlNNXUqpkQeXOXZaXpi9QN1NNRjPLYtR2Zf9u7ls1kvF1hxkg55Y8J3t3Gp4l7lmB9XCZaSdQA5PQHdtT8n1OeguK7jLerNgTiCHPfQhExnHFgQi5EhwgkuUhl6mM28Lg6TaHbG9I3_uyCr_P5d6bazT1qV9u3ir2Nu83z6NuE3AdNmiNZWlkNvl47eH63mbKJ74oKClGcPmRbUpzTtR7drk_XdlM3vj_PcjElhp3MZifjtl6spO1t_vVuNcMXuJfmovImB3P98l4C4MD2-Xi-4mU5tT7nq1DD30_XroOfHC6w1S3zj9ruh4puWjqWTqO2ec0GdKRtXtkKOU39dem-BOUQ6BW2ecjddcLa6vvv_hwYwU6z6jeO6FxnBBC_qV5GMXSMCux1vN-5FTL55ze3aVH3I034ZzUY7zGNplyeWvwexV4bxCfBVP9mrehgLCysP7Lbo3AHQ5yDBObPJ8l_xtIssnCojNGtNWgWqk9KULfSYqcUrFXPim48yGyhur_y72CecezJwxM18Cxwz7FgRjleRUYbpb09rtIjtTZl1coAuEzF_ouwM7oK0N04F9GYMO7a-GE1p64cy4ETgfZf-Fs2iQtnUwKGPMYfgWZhe7DSBXSk7Z7g2Qqf3M3wkRIA0IrfWms9Cnc4rt1XQtkbLOxK55-7KEieDV_uWi9-t9_DKEt5c88dss0u6tEka8kDFmxiwywSlx77Fwb5YgjX2_R_c2h_8FEvMeSxV0JwmX2pFDx_8R4vgeVnSPaH6ZE0eS8ol8Dkke5ugT_RwkeZyHeRLDT5vPBcniDBYE-VFUxomfFDHNE5QkGBKcR_QT-wx9GPo5zCCEfgynUQBjnxCIwyhCSQq9yKdbxKqp2a5OhVx_spnTn5M0jdJPNjBS9j1EEHL6BGyl2e3Ei0_ys917F81aeZFfMaVVP4pmurIvMOrethMvvPhq-ePaixeH15rYN9mAE2-yca9jKah7GQa1jyqsjiNTN3j3Dsw_NbL6_Ovp4ZbO_wwAAP__pDyIjA">