<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/110305>110305</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[Zen 3] Dead 32-byte constant accessed via `vbroadcasti128` not eliminated from assembly
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
Validark
</td>
</tr>
</table>
<pre>
I had this code: ([Godbolt link](https://zig.godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYgAzKVpMGoAF55gpJfWQE8Ayo3QBhVLQCuLBiADsBpwAyeAyYAHKeAEaYxCAAbKQADqgKhPYMrh5evgZJKXYCQSHhLFEx8daYtmlCBEzEBBme3n5WmDb5DDV1BIVhkdFxVrX1jVktCsM9wX0lA7EAlFao7sTI7BxoDBMA1BPo2wCkegAi2wACeCxJ9RAHAEx3e/d380cAQgcaAIKbOxHudDsDEOJ3Ol2uBFuD3%2BgOCz1eeg%2B30%2BX0wqgh2yowP4qAg6nOADVKkRiBA9HdSNt3AAOebzc4AFQAnglMAB5Kh4%2BkHHxIr7bAXbX4EbYAN0qIEZLPZnNU3NBaCudjYuwI6AAdCkWBriJhWUxIWcUqYZRAzszWRyuYtDgBWN5cWIHW3HGk8t7SAwUilcUi%2B/2kDSB4NB0MhnnHBF8wXbXUEFbA0UJBQIdxUCIQcXISmqEHYI7Yc4KBJGSGSOmHO5vIttYkQGk5kHHI6nM5MBRmi2muWUo0lg0QDR0ylJlNpjNZnM2tsd83Sq09ov9yFDunvFERjffLFi5Op9MQWoRcTbYxMgjSynBfBrBSSueWzlH%2BgVh%2Bm5%2BYbm8lExvBUbZmsErhKpcmAQBW7o/jGgqinUsaYAo7i0AQ95dla154Le8qnO4DBYDQIToOu3zQYK/DEABGjquqZwRIQQh4CaVpvuheGYQhFYAPTbLShw%2BM4eA8s4fHRqR0HCts15ok2klsbezpvIJLrEfyYkxrqiHIQpSmnC2kn/hAUm5gWekaKo1JDtsGjbG0SjbB%2B2l4dJ9y2gBtH0YxposU%2BTDHp%2B9LcbSzrNoiUGkZuyIkWJcYJvBmkECpMYRV8YVCgIOxsAQCAYAoMkTMQ7i2CJqUxmiBDRNiwJnM8tC0KKLDquZsTqkwoqqLaXB3Oqe5puqETqh1dzPGaRK2CQECxNIVK0r2o0khNU00q%2Bc3jZNlJLYlYllRVmJVTVdUNU1LVtV1PVUH1w1nCtpLkutM2EsS423dNy2PTdFIvZtpHbcQlXnPt9WNdSzUKKDmB6N1Y7nf1nXUpd10QI6d3TgjSMvfSV1vYj8SfaFUUCpueMpfj8Hxr9uwAO6EMgCBuWhPl%2BRB34kzGmNjaSa0vU2Bb6QBioJMqmCqhqDJ1MAmAEEDzVUJgBorJgQgSwAEu2EAwshwTqsgCTuOqMtyxplLHe1nURBTFaZdl6AKDRAOHcDxuDZD%2B59QNnXDR%2BV5yRxNm0HZZz83QODEMQ43PM4yhyPZYsS9sRjIAA1rliEJBi5G7lDESDfCpAlYKbPzc9S3c3ohZ/nzqAgSqezqqLxDi5LR362TCvK6r6tAlrOt67LLcKEbrWqC89KWzltsPLVgNHYPp1QxdDyHr59BezePu2ULAeVwkQfYCHYcPBHUfDA3cdMInyfuKnJAiuno77hEdy2k6DyLHnAoF%2BNaPFy2PPlxA/OC2FrXGOjcHbN3lorAgKsOwd01trXW4DDbbE1GDPQFsJZWxttVCeB0pYoKUBDM6rtYYeyXpgFe7EFD0nXucQO9Bd6h1JOHSO0d66x3jknXYl804kAzvfEhL9c4s0FDQn%2BpdaFbx3nvUkNcqAsElgA0CyhiDBEhM8AAkgwWCtA8D7DFp4RgIoLysm2AkdsSh9hED4eOSUkEfDNltM4Bgzwjbum8ovRmEZhypUJnyCMHBFi0E4LaXg3huC8FQJwAAWhYXYyxVhC3uHoPQvAUIcC0MOBAsssAxHAqQBOIBbQQy4FwDQ1IACcegn6xFKbEW0hhOCSF4CwCQGggxhK0KQSJHBeB3iDGkjJpA4CwCQHQ6I5BKBjJiKYAgBUGAJz4ICaId41aaF4HRZgxAmScB4KQDZdQmRsgiNoYkOzeCKjYIINkDBaDbPSbwLA/xgDODEH7M5pAsAsGMMAcQ9yPl4F1FUcUd4/lokqO4cq7zVFtDWYYPAERiAHNcFgWFszLjvPFMQCIyRMDHEwF8kwOiTBrMWFQIwwAFAEjwJgCmbJWRhN2fwQQIgxDsCkDIQQigVDqD%2BboX0RhiXmEsDoiId5ICLFQALNIIKAC0bJtgACVaztkwAAMXbCKGVx9Y5NQAPqTRlUS9wuYZUsHgS2UwWjogpK6ZilRWAxV5IqFUBwEAnCjG8FwakpBAjTGKKUEAkhfS5FSAID1EhvUho6L0f1Awg2tHaNUSY4avUJuJEm7oMb%2BgxHjRMboKbvV5vqFm2YOauCLAUPEtY%2BhAnBNCbC7p2whX2TmQnACuBCC8KSWg1JJLFhZKYDkygiwCmSGatSCptTJDJIqVUikQSOBNNIC00p7SG2cF6SAfpfaGkcDuPWv53Te33OHJilIDhJBAA%3D%3D%3D))
```zig
const std = @import("std");
const builtin = @import("builtin");
export fn foo(x: @Vector(32, u8)) @TypeOf(x) {
const vec: @TypeOf(x) = comptime std.simd.repeat(@sizeOf(@TypeOf(x)), [16]u8{4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0});
return vpshufb(vec, x >> @splat(4)) + @select(u8, x == @as(@TypeOf(x), @splat(0)), vpshufb(vec, x), @as(@TypeOf(x), @splat(0)));
}
fn vpshufb(table: anytype, indices: @TypeOf(table)) @TypeOf(table) {
if (@inComptime()) {
var result: @TypeOf(indices) = undefined;
for (0..@bitSizeOf(@TypeOf(indices)) / 8) |i| {
const index = indices[i];
result[i] = if (index >= 0x80) 0 else table[index % (@bitSizeOf(@TypeOf(table)) / 8)];
}
return result;
}
const methods = struct {
extern fn @"llvm.x86.avx512.pshuf.b.512"(@Vector(64, u8), @Vector(64, u8)) @Vector(64, u8);
extern fn @"llvm.x86.avx2.pshuf.b"(@Vector(32, u8), @Vector(32, u8)) @Vector(32, u8);
extern fn @"llvm.x86.ssse3.pshuf.b.128"(@Vector(16, u8), @Vector(16, u8)) @Vector(16, u8);
};
return switch (@TypeOf(table)) {
@Vector(64, u8) => if (comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx512bw)) methods.@"llvm.x86.avx512.pshuf.b.512"(table, indices) else @compileError("CPU target lacks support for vpshufb512"),
@Vector(32, u8) => if (comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) methods.@"llvm.x86.avx2.pshuf.b"(table, indices) else @compileError("CPU target lacks support for vpshufb256"),
@Vector(16, u8) => if (comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) methods.@"llvm.x86.ssse3.pshuf.b.128"(table, indices) else @compileError("CPU target lacks support for vpshufb128"),
else => @compileError(std.fmt.comptimePrint("Invalid argument type passed to vpshufb: {}\n", .{@TypeOf(table)})),
};
}
```
Produce this ASM:
```asm
.LCPI0_0:
.zero 32,15
.byte 4
.byte 3
.byte 2
.byte 2
.byte 1
.byte 1
.byte 1
.byte 1
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 4
.byte 3
.byte 2
.byte 2
.byte 1
.byte 1
.byte 1
.byte 1
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.LCPI0_2:
.byte 4
.byte 3
.byte 2
.byte 2
.byte 1
.byte 1
.byte 1
.byte 1
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
foo:
vbroadcasti128 ymm2, xmmword ptr [rip + .LCPI0_2]
vpsrlw ymm1, ymm0, 4
vpand ymm1, ymm1, ymmword ptr [rip + .LCPI0_0]
vpxor xmm3, xmm3, xmm3
vpcmpeqb ymm3, ymm0, ymm3
vpshufb ymm0, ymm2, ymm0
vpshufb ymm1, ymm2, ymm1
vpand ymm0, ymm3, ymm0
vpaddb ymm0, ymm0, ymm1
ret
```
Looks like `LCPI0_1` was sort of put there but our code ultimately decided to use `vbroadcasti128` instead so only the 16-byte version in `LCPI0_2` was necessary.
Interestingly, when I flip the `vpshufb(vec, x >> @splat(4)) + @select(u8, x == @as(@TypeOf(x), @splat(0)), vpshufb(vec, x), @as(@TypeOf(x), @splat(0)));` to be `@select(u8, x == @as(@TypeOf(x), @splat(0)), vpshufb(vec, x), @as(@TypeOf(x), @splat(0))) + vpshufb(vec, x >> @splat(4));`, the problem disappears:
```asm
.LCPI0_1:
.zero 32,15
.LCPI0_2:
.byte 4
.byte 3
.byte 2
.byte 2
.byte 1
.byte 1
.byte 1
.byte 1
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
.byte 0
foo:
vbroadcasti128 ymm2, xmmword ptr [rip + .LCPI0_2]
vpxor xmm1, xmm1, xmm1
vpcmpeqb ymm1, ymm0, ymm1
vpshufb ymm3, ymm2, ymm0
vpsrlw ymm0, ymm0, 4
vpand ymm0, ymm0, ymmword ptr [rip + .LCPI0_1]
vpand ymm1, ymm1, ymm3
vpshufb ymm0, ymm2, ymm0
vpaddb ymm0, ymm1, ymm0
ret
```
Here is a dump of the offending code via `zig build-obj ./src/llvm_code.zig -O ReleaseFast -target x86_64-linux -mcpu znver3 --verbose-llvm-ir -fstrip >llvm_code.ll 2>&1`
```llvm
; ModuleID = 'llvm_code'
source_filename = "llvm_code"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-musl"
%Target.Cpu.Feature.Set = type { [5 x i64] }
%Target.Cpu.Model = type { { ptr, i64 }, { ptr, i64 }, %Target.Cpu.Feature.Set }
%Target.Cpu = type { ptr, %Target.Cpu.Feature.Set, i6, [7 x i8] }
%Target.DynamicLinker = type { [255 x i8], i8 }
@builtin.zig_backend = internal unnamed_addr constant i64 2, align 8
@Target.Cpu.Feature.Set.empty = internal unnamed_addr constant %Target.Cpu.Feature.Set zeroinitializer, align 8
@Target.x86.cpu.znver3 = internal unnamed_addr constant %Target.Cpu.Model { { ptr, i64 } { ptr getelementptr inbounds (i8, ptr @__anon_225, i64 0), i64 6 }, { ptr, i64 } { ptr getelementptr inbounds (i8, ptr @__anon_225, i64 0), i64 6 }, %Target.Cpu.Feature.Set { [5 x i64] [i64 148023677034692784, i64 110359908924890900, i64 8266358215819756484, i64 0, i64 0] } }, align 8
@__anon_225 = internal unnamed_addr constant [7 x i8] c"znver3\00", align 1
@builtin.cpu = internal unnamed_addr constant %Target.Cpu { ptr getelementptr inbounds (i8, ptr @Target.x86.cpu.znver3, i64 0), %Target.Cpu.Feature.Set { [5 x i64] [i64 152527276662137072, i64 119367108179631892, i64 8842824431321580484, i64 0, i64 0] }, i6 -22, [7 x i8] undef }, align 8
@start.simplified_logic = internal unnamed_addr constant i1 false, align 1
@builtin.output_mode = internal unnamed_addr constant i2 -2, align 1
@Target.DynamicLinker.none = internal unnamed_addr constant %Target.DynamicLinker { [255 x i8] undef, i8 0 }, align 1
; Function Attrs: nounwind uwtable nosanitize_coverage skipprofile
define dso_local <32 x i8> @foo2(<32 x i8> %0) #0 {
1:
%2 = zext <32 x i3> <i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4, i3 -4> to <32 x i8>
%3 = lshr <32 x i8> %0, %2
%4 = call fastcc <32 x i8> @llvm_code.vpshufb__anon_1530(<32 x i8> <i8 4, i8 3, i8 2, i8 2, i8 1, i8 1, i8 1, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 4, i8 3, i8 2, i8 2, i8 1, i8 1, i8 1, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, <32 x i8> %3)
%5 = icmp eq <32 x i8> %0, zeroinitializer
%6 = call fastcc <32 x i8> @llvm_code.vpshufb__anon_1530(<32 x i8> <i8 4, i8 3, i8 2, i8 2, i8 1, i8 1, i8 1, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 4, i8 3, i8 2, i8 2, i8 1, i8 1, i8 1, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, <32 x i8> %0)
%7 = select <32 x i1> %5, <32 x i8> %6, <32 x i8> zeroinitializer
%8 = add nuw <32 x i8> %4, %7
ret <32 x i8> %8
}
; Function Attrs: nounwind uwtable nosanitize_coverage skipprofile
define internal fastcc <32 x i8> @llvm_code.vpshufb__anon_1530(<32 x i8> %0, <32 x i8> %1) unnamed_addr #0 {
2:
%3 = call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %0, <32 x i8> %1)
ret <32 x i8> %3
}
; Function Attrs: nounwind uwtable
declare <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %0, <32 x i8> %1) #1
attributes #0 = { nounwind uwtable nosanitize_coverage skipprofile "frame-pointer"="none" "target-cpu"="znver3" "target-features"="-16bit-mode,-32bit-mode,+64bit,+adx,+aes,+allow-light-256-bit,-amx-bf16,-amx-complex,-amx-fp16,-amx-int8,-amx-tile,+avx,-avx10.1-256,-avx10.1-512,+avx2,-avx512bf16,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512f,-avx512fp16,-avx512ifma,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vp2intersect,-avx512vpopcntdq,-avxifma,-avxneconvert,-avxvnni,-avxvnniint16,-avxvnniint8,+bmi,+bmi2,-branch-hint,+branchfusion,-ccmp,-cf,-cldemote,+clflushopt,+clwb,+clzero,+cmov,-cmpccxadd,+crc32,+cx16,+cx8,-egpr,-enqcmd,-ermsb,-evex512,+f16c,-false-deps-getmant,-false-deps-lzcnt-tzcnt,-false-deps-mulc,-false-deps-mullq,-false-deps-perm,-false-deps-popcnt,-false-deps-range,-fast-11bytenop,+fast-15bytenop,-fast-7bytenop,+fast-bextr,-fast-dpwssd,-fast-gather,-fast-hops,+fast-imm16,+fast-lzcnt,+fast-movbe,+fast-scalar-fsqrt,+fast-scalar-shift-masks,-fast-shld-rotate,-fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle,+fast-vector-fsqrt,-fast-vector-shift-masks,-faster-shift-than-shuffle,+fma,-fma4,+fsgsbase,+fsrm,+fxsr,-gfni,-harden-sls-ijmp,-harden-sls-ret,-hreset,-idivl-to-divb,+idivq-to-divl,-inline-asm-use-gpr32,+invpcid,-kl,-lea-sp,-lea-uses-ag,-lvi-cfi,-lvi-load-hardening,-lwp,+lzcnt,+macrofusion,+mmx,+movbe,-movdir64b,-movdiri,+mwaitx,-ndd,-nf,-no-bypass-delay,-no-bypass-delay-blend,-no-bypass-delay-mov,-no-bypass-delay-shuffle,+nopl,-pad-short-functions,+pclmul,-pconfig,+pku,+popcnt,-ppx,-prefer-128-bit,-prefer-256-bit,-prefer-mask-registers,-prefer-movmsk-over-vtest,-prefer-no-gather,-prefer-no-scatter,-prefetchi,+prfchw,-ptwrite,-push2pop2,-raoint,+rdpid,+rdpru,+rdrnd,+rdseed,-retpoline,-retpoline-external-thunk,-retpoline-indirect-branches,-retpoline-indirect-calls,-rtm,+sahf,+sbb-dep-breaking,-serialize,-seses,-sgx,+sha,-sha512,-shstk,-slow-3ops-lea,-slow-incdec,-slow-lea,-slow-pmaddwd,-slow-pmulld,+slow-shld,-slow-two-mem-ops,-slow-unaligned-mem-16,-slow-unaligned-mem-32,-sm3,-sm4,-soft-float,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,-sse-unaligned-mem,+ssse3,-tagged-globals,-tbm,-tsxldtrk,-tuning-fast-imm-vector-shift,-uintr,-use-glm-div-sqrt-costs,-use-slm-arith-costs,-usermsr,+vaes,+vpclmulqdq,+vzeroupper,-waitpkg,+wbnoinvd,-widekl,+x87,-xop,+xsave,+xsavec,+xsaveopt,+xsaves,-zu" }
attributes #1 = { nounwind uwtable "frame-pointer"="none" "target-cpu"="znver3" "target-features"="-16bit-mode,-32bit-mode,+64bit,+adx,+aes,+allow-light-256-bit,-amx-bf16,-amx-complex,-amx-fp16,-amx-int8,-amx-tile,+avx,-avx10.1-256,-avx10.1-512,+avx2,-avx512bf16,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512f,-avx512fp16,-avx512ifma,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vp2intersect,-avx512vpopcntdq,-avxifma,-avxneconvert,-avxvnni,-avxvnniint16,-avxvnniint8,+bmi,+bmi2,-branch-hint,+branchfusion,-ccmp,-cf,-cldemote,+clflushopt,+clwb,+clzero,+cmov,-cmpccxadd,+crc32,+cx16,+cx8,-egpr,-enqcmd,-ermsb,-evex512,+f16c,-false-deps-getmant,-false-deps-lzcnt-tzcnt,-false-deps-mulc,-false-deps-mullq,-false-deps-perm,-false-deps-popcnt,-false-deps-range,-fast-11bytenop,+fast-15bytenop,-fast-7bytenop,+fast-bextr,-fast-dpwssd,-fast-gather,-fast-hops,+fast-imm16,+fast-lzcnt,+fast-movbe,+fast-scalar-fsqrt,+fast-scalar-shift-masks,-fast-shld-rotate,-fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle,+fast-vector-fsqrt,-fast-vector-shift-masks,-faster-shift-than-shuffle,+fma,-fma4,+fsgsbase,+fsrm,+fxsr,-gfni,-harden-sls-ijmp,-harden-sls-ret,-hreset,-idivl-to-divb,+idivq-to-divl,-inline-asm-use-gpr32,+invpcid,-kl,-lea-sp,-lea-uses-ag,-lvi-cfi,-lvi-load-hardening,-lwp,+lzcnt,+macrofusion,+mmx,+movbe,-movdir64b,-movdiri,+mwaitx,-ndd,-nf,-no-bypass-delay,-no-bypass-delay-blend,-no-bypass-delay-mov,-no-bypass-delay-shuffle,+nopl,-pad-short-functions,+pclmul,-pconfig,+pku,+popcnt,-ppx,-prefer-128-bit,-prefer-256-bit,-prefer-mask-registers,-prefer-movmsk-over-vtest,-prefer-no-gather,-prefer-no-scatter,-prefetchi,+prfchw,-ptwrite,-push2pop2,-raoint,+rdpid,+rdpru,+rdrnd,+rdseed,-retpoline,-retpoline-external-thunk,-retpoline-indirect-branches,-retpoline-indirect-calls,-rtm,+sahf,+sbb-dep-breaking,-serialize,-seses,-sgx,+sha,-sha512,-shstk,-slow-3ops-lea,-slow-incdec,-slow-lea,-slow-pmaddwd,-slow-pmulld,+slow-shld,-slow-two-mem-ops,-slow-unaligned-mem-16,-slow-unaligned-mem-32,-sm3,-sm4,-soft-float,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,-sse-unaligned-mem,+ssse3,-tagged-globals,-tbm,-tsxldtrk,-tuning-fast-imm-vector-shift,-uintr,-use-glm-div-sqrt-costs,-use-slm-arith-costs,-usermsr,+vaes,+vpclmulqdq,+vzeroupper,-waitpkg,+wbnoinvd,-widekl,+x87,-xop,+xsave,+xsavec,+xsaveopt,+xsaves,-zu" }
!llvm.module.flags = !{}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsfFlzozyz8K_x3FCkQICXi7lgMfG-xnacmykBAhSzGQmD_eu_QuA1yTwzzzvnvKe-mqnESK1Wqzd1t2QmkBDsRQh9byhaQzG-wYz6cfp9DQPswHT3zYqd4_c-50OHoz4mnB07qCGpXAO0G4r2HDtWHFAuwNGuoRgN0PYpTUhDUhvAbADzhL0nr8J5ilOPAaVTQ1Kn25Hnq6a2d5S5XqjbfLbVxnqoLRxtpJriXLdVOOvq6viUa3SsttR5btLxXDuqC68zpPNtVz0SbAnzV1Uv2pqmDmMtelHVldpLcnV8UM2tp56G62T8HKumonjJwN3Mu231GEtzzV-P5no20rBqEC3J1SNSj1u1N0RqF24LXVWt4Vw19t7Qn23Hqa-gg_c2GL5u9fmy54_MbtF24JaGga51T11NC5EUKZvQsBTDWItaf-3vHLNYp6_i-3pHdTLu5K9CoLa6amDCuEVe-i2tiA1trIraLAa5vkOeikGu6kgvBp2F2lO7hYQawHSktmCrc8-Gan9oTYte5hjE6E4H0jQAmWZmhtQACtC8qX4SEfJYRxLY41XI954PjnE-k_eq14ymqrEe7hZYUzs9ZzmhkqpOkXWyZdWcq5EXjFVNGfoym7zr9Yp-2rLUV-tV7lpbdSLs-9230ewtmqykiQb1zHnfZnm_qaqOvttoKR74m1XR39ir_fZtoZ7IabM4ZltqeNpmotibfm8j9Z53bdpaqvkKB_YKs5UawAQ7Y6nJE00Y-1HU08x2_mq9rrqmpQqrgTbvO8VK78_t1_4y3Hd7235ra8tDbfC8fF5Ow95UOfQp3e7mzztl1-v1m9FYGWuLEIMw26xiIfCEubEQjsEgmCTvk7doDChx2tJyL3TiQ-doGll0MLuLd9cdmViZJp3xfBMv7BdrW4y99-Ux0lwt1ZbLDG1OQa_S99pnz1Bhj60VtoNucdBW1ltIuqk_TOxQnWubVtwA5vuzt8fRisCtGrewoM47ihNAUZFHqL2PprKhbY15_yWeZtJpvh02gGl0Ve35fZ_t3_JFfz73ZR2uk0Pmo-ft3De36uzFGi39nK09lpHaJrLbW-wXQk-nRFTiHdgFxEKn5NAfjNKue9zuinSPe_15sgwjHeyiBjB9dRUq3gbt4DAWBwYlz-_Ws7B8tzRGFwSyM-gcgafRnrAtkpisGPzF6CWs0RnZ1vKUTmK8et69Zcf-bjOwt4ODFu66ejLeLtbt7Vr3-tOCqHNd3arxePcynrcw0Af7VRFizVhMcD6Ixm2qC8PhyNhnb-Rlv8vj_X4EXzVpukdKku27L3tfdE6zZ7gYAn3e1YtJfz0UUhALO3-yEoQ948eW3t8mwWC0DbZBsFiHg_XL2llNVuJoTdfibL3qibkY6TQZ7TI6Bl2ylIHkTI5g9uKY_cMbTXqWPQ9eoxntbCbO8rQaDo1Qa07EbStyxeh1lTiiMO83HenFe1-OD-5yLR627-2lC83VSk8yNE7c93avSDtZrk6b3bGna9nGnwWMv4UmybvTczh5h0soHFZAs5pzDceD8T7U9_7eGIhjNVS7XeO0Xg08LU4H3txb5mo3A101J37-siee_pJN92N6LJJg1ENitFpoLyZ8c4KmOjQW6rRnG0VmvBlsSaUzn0SvxoJ11spxUUxCoff2dmpL86nRHc9laTaWj_5x9rYlyw5ZvPdVVUwD3B1oWHluBUZ3abh6ogbboTU72Z2lZEux_9YAZnTaq95yj077_agwsDJaSE3woh-GzbRJ1SCd0mZrNLKHXSvd7PV2Z7g5BZTMRmtv0tvOEnFeOMaxlyodDZ3QLAOrkYrW-W7ubvXe1p5pvZVrqJLtjPvR0c2G0UDFWRS3Wn7XOYJd0ziOepEam0yyCZyZRzCbBUWZdqY6MNPX5-m73bMmUhCnqjck09wRRJq-bmTDsKyu-GzM5iYZvG0KStc60oRkGw9XmjFupnS7RcfXxDNRq2saQvSa2fNpR3OavjiY9pZTwWk2C-l9F71ug7Yg79TTwe36o44tE8E05hFjKXGgaRVSdFjtJvZeJd3AUwX96GND6_rjtqruvHyjU7VttAwzkRdePx4dSQjUnUOWfsfvGjKaLle7rmtMAjqWNe-Uv1tZ2I4Pi7D75h-T1SA66uOeZmKhK4_gqyf5md4254NcVTf-9nV7LNa-LmW9eDY_qKu-rQvjqaYSQtSip-7n2rSvWfP5UTZzYy72Vd1GXtQszKHV3Qi-P9WXpqzn-vzZ8wp_KAzny0FPQ5qEjefd-yBR2WBv3uwr2lB7H-DhVvW01bM6OMl9HfYdWYTQlHuLN69Qw6WtycO58ebMwwXx8CTe7qYnpA_ft_3-ZGdo0LBmSysflfYrPGNqdHutsZKoRCXP47FqzzvHWSCbormyV47cAGYQ7_ZT2d63TmuTGpvtdqZ2F1jtTWzT25jkNHo_zMzxXO8fF2Oj183N9i6f4hctHW_MeT_PVVPtvucDTw-twWbhT4Cbz-d9rzCIvjP68zn21sa-2kRW_CosfPwadokR476j9PWROVdHk35_qOqCNaCeqq_hie5yVR2_WvrweV10tspkrs72L4tgtezk2fZtRXreEqzyzXvsJcPmGw4WG7VYK_29udLyrhrp789tM4e7RFPfX56Hw1VX3fnuUjGXat8Qu_5h5cfNkeCKau4B2oOT1XIrw8NqkA26YSseW1VmKnrvi7EVD63DWjnszRBspzDTR-pq1qVbhuKrkTbRLb2VgNx_BS_hPFL1TNP19nC58cTBYGT6b8OtsTt6ONfD5TOkSz2hLwNj0N-vV3g3X061yaSvC0LSWj4D22wuVTdx4fPONrLZ5qBIL0iSpr0BDvqGP9BUtQEUybj96JQ_gtEQ1PqzKVQ_J-xVEDuOCOUIdbiGZHANWcBhEqe0rDsBINRpAFDSkLRbdCvDAcXRZ1PqoYdp1ScqSjzOjTg3jhugXbAKVxbWyKZx2gBtCTSAzmXtivFy6OWYoKnLcEtAq6bHcRxXsXJAdk3lAVUyODsOE4pDVIr3RHDoPKUoQZBxKgsEnyr8x7nsR-caiiY2G4qRtRstTW4AXWoAHdS_4sOv8NPflnGrjJL5FNEsjbhDQvzMtRqgXcoBdK7gGlK3IXVLgUgSMF7lszqAxsAoQHYJL_VUzTBqQ0DyqTj6LTXhKuHH1a_ov0XqxtAt49bi7q2IFFoBO9TA6EiPCSqp4cjBNiKPJqxQP3rBGX7vCdjlKmZxpNcmZ87Y-YBZ_jvAlEsRyQL6uOqZmdp9sshBLo6Qc2e58p8bp-WKwtNTQxYsTJefudKVWmU8k2tX_Oi40dI_8nX1aRw5iJn1oh5Fw-W575GPypOYKBVGNYmp40ykW4KEghmLEzgUEMRValS0Ggcotf6-EuXOHLUgn_HzYP0ri8zZz0q_mfTJhEoFIaJ-7BAmD6FpZtOPCkMFRWlUhpOGLDQACIJD-FS0m0_wUCgieGKO92Q9KSJg4ah9G2qa8k2o0bkvhzpfDj0K_zN2Lsx8ZOQu5un_EA4_HfplRgghSLqoRWTx-oEbsfklN3dDnS-HHs17nwJu3IHkmNo-9zNXu1j8CxtUoa9be_xduH-BqYcoE9tFkGYpWiLaY1GtTlFPdpKdx0hJsvYbK6-Xr33w6Re9q-b8GtNAp9ptDVkoWcMB6qYpE6EBgD5bcZTxyAXQ3hGOZEmVHeP0HDPPpEtTfKKIGx_484oA_6iEB5_-8-IDpfko_jnOfO57f1gLbLv8XA1f7Kg_r4sz6Y-6qOhWgn8kX8ruhvTprIxZiqO6UutHBxhgh4Opl4UoolyZk7kEEoIcjsaXxF0myZZWbmVFr-o6nXsqIZ_t2pZxKS--CAOXiH8uRW_DwyyNncxG1R2ouhw3JPXT8hWSsII8jfRZX_ghXBDPank6oTTmOI5tElGpB5-sI0Ucx8kPyDVY-hwMfg4-98XP0X4H_AWu8K_A_9nsf0f0dxT7D2r9PTX-OyP872nwX5GovRt89G6G93_Viz9a5b-lwF80bHkcfVTxwUpj6NiQUCyCNscdw5CFviIM8zh1uISm5RExxQk7mF1MpRgPdBKSBjmbXx4Uy2d5KHw03iGBkcPdoZ2fP1lO-GS5Ik45rmRTqtm9PivMQ2KHCdpb5ynHGuXM2fGKepWhTAW3GOAy40z0giI-oIhfSnpd7pEYdBzrDkX4nFiK6E_SySiOd4QL8A5xjaZQqUxsNAUuh4QjZYqNXS7JKEd9lCLOyigXZyn78o3LAopDSFFw5BxkY6dKihlhpO6do6SII0IRdDgSc3EUHEuKnNjkmZ8dUEpwHHE4urIBzmxEyEaEwPT4dMt5P6IoRYTiyAuOpei5jyKuz7kBThjtkon_jy4PmkKpXYvJ9X-UTabC39F5JVeJVBosSWMrQCHnYAKTBMGU_GpxI15j06dVzT9kiX9Myr-YIH4l8v-R5PHfrF9-Dr7LE38uQVwitljPvz4fMD8EbvHn4fEmKktfBO6PaUr4tTT1GJl_IrT4idBfpjvpY0b5KulciT2mC_EB8-d5oldGf0w4yDlZmJRJodyxseuiyMGRVyWEA4ZcdXPO7r8dPrbeuacGMElqN4BZngl_lIhPJQY_5RYoQJAgExLK8fX5rmg3fzRlPsBRVnB8aCcZd4oOKJU4nj-g1IoJ4ktCPE453iWU6VHqXmkHAQfKgAOa4oMMF8FK5Bokadw4drIA9aubwQZoXUg1QKvCInGW2uiHiwMUwRDViOAGsY4AtQwOpDCAxzijZ1TEhw1JRXwCWuVBTALso-yK992y1ZTZB48vjTKDSqoI2rzbFupWxEDN8_SmzC_rI_AtK6V-ggvHtXKzaBfFeVQpmQ8zElym1Z9Aqa8D9CR7Mqsj_9MSVfKwU3CjpZVurHAFV_KpGDc3lXezx7GDgod5La3cBuz435TZRKB_Bf2alU_Xu1-ppvclkWqx-ruMVilL-wtRjGMEQ2yPcLRD6Qc1AEU5T2Yk24_3tg1ZON-inLD3w4L2DkVOfYNNURrBgMui0rucH9Bx0uqSF0aU6YLtahhgL-LaF3qfS_SEwoQef4Xw15otUyiOMMUwwCeU_mTxot1kt0L1Fv3tVWvn-NQnziDOQxQFKEQRLXs4suIscgi7wWe1D4uosvDjB4zi6AcAypmIUBcrZbv5tZv9Ty30E8_9sHcUrZwrym0BSM1WS5DkZge02vKZqigKktLpCO0OkNsdoSMI55E2aDYlpQ1EpS12WkpTvk4Sro3Kqc-sPVrzKtEvmfB2q9gNACrrNxS95OrGV8UPvm_XG_R3nOR3zfOpaz5a6t8YRwEKaIFWs9kEotQSWuBqnI7UbIlCW2x1mpLY7lxG2m0ZtIEsS6JUGkj4mXGqPsdXGrxTMvue7SvjEQpT-kRwmATYxcj5EcQetn8ptIicCwOCfmaxOKNJRn-EZX7_FZKA4z_1gM_C6FMUR79E9csw_CH6VqqqY7BwrzLxLiBLGmdmkU3LY6dKKTtscFGcRTmOHC7L2YUtF8UElpHwhH7Y8QGl0EMc2eEkSeOyHKhoVV-Ccg6JfwSxDctsp0ugYqk697hxzL5HuocDRahOTZJw_Sbn5ixTYgCmnxMq6JWqxGZLOpY4vvKnv40PDalbnpfvNH6j1ipXBcRPH43FjMICBLjBl6vXJWAQcC4k1LY_2vhagtZ1eR1VRUUSPtpe0nGbk2tHleoneHiK__AU_sPnf2_9skDXP6peuryNw7RepyM7TDi0_8JQj8XKdXbzr83-N2wm3NusVb2RwK6nrshijax8SqL5Efq1WdtsAeg4XJTlH2nJ9e5tnaekiH7EOqfPhyr9zyeFS2b7My54jk6PULFMJHfJ8z6rgPusIl23xqcMffIN9u9w8lPVS_-B6s-qtQOYov8R1ku93RUKkNIUWxlFpFapVB0YftcryvO3m8IQ8UnMnKIslSWjAUBZBTUAKBGqUztvJ9ll9Fy_3o5fv4SvkXixaWHKh-wyQuclcNNrAK0pW5hWTegUdYN9h182giDO-QB7PuWB0uQrVB6GBW-57N0B1rbjMAlQce66yXUIR7R9blMc1IvCQ4V8KEThSeSrXX7psjc3ajRQDygiuKxY9TCFgXfTz69t27m2nf217d40k1ti2A3htXewQnzfu-HiENy0o-gWMQHMeIRdvl-hcWJH9MLGzVIRsuPSgmfsG3JlE0f0wmPdb1d6qfirGow1K4WR7fM-ez2BDTCAmxEcRyWCbYcJezIV2IGDwpjWxrADN8iIHyf03M-tc6sMtXU7jA9sbpjYdgEdpwantlRbyy4Yu6zFbI68JGXPaG-HzCQoDYnFGgdUXMzsik27BLIDB--ghPAeoiFkwtxCg5MdUZ6Wnw8jYRY8kgizINg_wBKUho8gZp4HYAojD1UwQnlRtI4URXFSs8tgyhVWYbU-IlmoYLcJFYKT5IQ4l64HqY-uo36ckJupOAzP2mT9oBb63A_jg4Vu-sSGAUx5l-xT-hFMfOxSPoRkRy4LEj9w-DSmkF4lPcAUlwGLt9OYkABGiC8DpRvcLnVBSlD6FQp7v-jCDX8L_IQXdIZSH0YP5Krd4oZQrgHEIxYk52HCDFq2CsKU6bnVJvJh6qCIJwHh8Xvl_DeglN3v8X6KSNXCDj4EPI15Bx9q7y9B-xrENj2OAhwhHpKQzwjivSQ9uz6ODomNmW13DDVAkCfJuZURRHjIglVwwLzt4nMziKFT84WjCiGvPejG4iG00_iymUtAWEfqsxuU_uDgtClb104dI8IcYsrCbcQ2LR-xGBDFvHVMICG8gwJ4_ATEWwGKnM8G6lDwCL4zXBQnTBMJdHjixynl3TqF126e2EGYVSh2HLnYq8G7rG5cNmaSMPaTFLko5UXQPuehGnKTmWpI6V18ijxc-ha5HYgPIdnxZQ7mDxSR20lRfLMnrzBiQ0pvgNT2a80mqWv7LO0kNE9xtY-SjPggiRMWl1MYX0Jy6iTYuTTT7NxMowuUIMT0nSKaxKWv3XX46tVUGPDUz6Ld_RiOHJwim9apgCXwz4bLuq4ao_XGIdB365ZlleGPt1IEd7U7EpRWZXbVIRVh4tX-R3y2PYkPq2jOE59QxhopKwcpLqM2ghcAjmyHffVbdW-HkhA6Tu7c9LMgqFXDAGXAuozSPOZDFPJV1KxgWcQuc5DDRqrc-cmAVDHKvtPjSSizR-xS3g1iWBuLnAMMIQhcWtKlJT-JN-0rhlzJQ9D9mufxigRPoechh_eC2IKVNajF8hIlReDQlCmQZmVI4M_Z4C58luMZjqrkwmJREJZhii8DLm_HhJLzCAlCHqaY-nfgNGTRsgG0w6XYO1Q7cs9KlbJfJv8sSSrfL6NIsqs3aW5FMY4OzBw5dhALeg2gFe1WCSrOWbAg8IBumvZN-1JvsB5j7JSxWvZc_d-X1-LX5fXf8vlv-fy3fP5bPv8tn_-Wz3_L57_l89_y-W_5_Ld8Pr-mJLKr75C9yvbkBtAj9TtfYv0_k-7fgPvmfJecjtSB39B3sQVaclMQQPOb_x22ZAkpgo1Ey24DKDZhx5WQIDdbLpKa0P2GvwMByEIHtMS2IADw1GraroUcCwhWU2gpUkMWUAhx8MQ4ilPvGyYkQ99FUZAE5VsALRQQ9keeAIhQzrHRshJXjG_pd_Zqn5V5pCELASaUXMlQTAP216HeUMRJDcXgDAQdTgLVK-SXlwWgbSP2P7Tq1xE_vokexZRDAQ5xBClyODeNQw4SgkIrOH7L0uD7_d-O8jD1M-vJjsP6Jcb6wSdp_M4KWZMJQRrArKU8fAf_LwAA__-MjQic">