Commit Graph

110 Commits

Author SHA1 Message Date
Roman Tereshin
673840e684 [GlobalISel][Tablegen] Assign small opcodes to pseudos
Sort pseudo instructions first while emitting enum's for target
instructions info. That puts them close to each other and to generic
G_* opcodes for GlobalISel. This makes it easier to build small jump
tables over opcodes that could be directly embedded into MatchTable's
Tablegen'erated for GlobalISel's InstructionSelect.

Reviewed By: bogner

Differential Revision: https://reviews.llvm.org/D47240

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333135 91177308-0d34-0410-b5e6-96231b3b80d8
2018-05-23 22:10:21 +00:00
Roman Tereshin
c349f81487 [Tablegen] Tidying up InstRegexOp a little, NFC
Differential Review: https://reviews.llvm.org/D47240

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333121 91177308-0d34-0410-b5e6-96231b3b80d8
2018-05-23 20:45:43 +00:00
Nicola Zaghen
0818e789cb Rename DEBUG macro to LLVM_DEBUG.
The DEBUG() macro is very generic so it might clash with other projects.
The renaming was done as follows:
- git grep -l 'DEBUG' | xargs sed -i 's/\bDEBUG\s\?(/LLVM_DEBUG(/g'
- git diff -U0 master | ../clang/tools/clang-format/clang-format-diff.py -i -p1 -style LLVM
- Manual change to APInt
- Manually chage DOCS as regex doesn't match it.

In the transition period the DEBUG() macro is still present and aliased
to the LLVM_DEBUG() one.

Differential Revision: https://reviews.llvm.org/D43624



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332240 91177308-0d34-0410-b5e6-96231b3b80d8
2018-05-14 12:53:11 +00:00
Andrea Di Biagio
bf50bde3b1 [Tablegen] Simplify code in CodeGenSchedule. NFCI
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330935 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-26 12:56:26 +00:00
Clement Courbet
c486bdf550 [MC][TableGen] Add optional libpfm counter names for ProcResUnits.
Summary:
Subtargets can define the libpfm counter names that can be used to
measure cycles and uops issued on ProcResUnits.
This allows making llvm-exegesis available on more targets.
Fixes PR36984.

Reviewers: gchatelet, RKSimon, andreadb, craig.topper

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D45360

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329675 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-10 08:16:37 +00:00
Mandeep Singh Grang
351641203e [TableGen] Change std::sort to llvm::sort in response to r327219
Summary:
r327219 added wrappers to std::sort which randomly shuffle the container before sorting.
This will help in uncovering non-determinism caused due to undefined sorting
order of objects having the same key.

To make use of that infrastructure we need to invoke llvm::sort instead of std::sort.

Note: This patch is one of a series of patches to replace *all* std::sort to llvm::sort.
Refer the comments section in D44363 for a list of all the required patches.

Reviewers: stoklund, kparzysz, dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D45144

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329451 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-06 20:18:05 +00:00
Andrea Di Biagio
8c6c51699f [MC][Tablegen] Allow models to describe the retire control unit for llvm-mca.
This patch adds the ability to describe properties of the hardware retire
control unit.

Tablegen class RetireControlUnit has been added for this purpose (see
TargetSchedule.td).

A RetireControlUnit specifies the size of the reorder buffer, as well as the
maximum number of opcodes that can be retired every cycle.

A zero (or negative) value for the reorder buffer size means: "the size is
unknown". If the size is unknown, then llvm-mca defaults it to the value of
field SchedMachineModel::MicroOpBufferSize.  A zero or negative number of
opcodes retired per cycle means: "there is no restriction on the number of
instructions that can be retired every cycle".

Models can optionally specify an instance of RetireControlUnit. There can only
be up-to one RetireControlUnit definition per scheduling model.

Information related to the RCU (RetireControlUnit) is stored in (two new fields
of) MCExtraProcessorInfo.  llvm-mca loads that information when it initializes
the DispatchUnit / RetireControlUnit (see Dispatch.h/Dispatch.cpp).

This patch fixes PR36661.

Differential Revision: https://reviews.llvm.org/D45259


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329304 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-05 15:41:41 +00:00
Simon Pilgrim
00a96df3a5 [SchedModel] Complete models shouldn't match against itineraries when they don't use them (PR35639)
For schedule models that don't use itineraries, checkCompleteness still checks that an instruction has a matching itinerary instead of skipping and going straight to matching the InstRWs. That doesn't seem to match what happens in TargetSchedule.cpp

This patch causes problems for a number of models that had been incorrectly flagged as complete.

Differential Revision: https://reviews.llvm.org/D43235

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329280 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-05 13:11:36 +00:00
Andrea Di Biagio
ce79db6254 [MC][Tablegen] Allow the definition of processor register files in the scheduling model for llvm-mca
This patch allows the description of register files in processor scheduling
models. This addresses PR36662.

A new tablegen class named 'RegisterFile' has been added to TargetSchedule.td.
Targets can optionally describe register files for their processors using that
class. In particular, class RegisterFile allows to specify:
 - The total number of physical registers.
 - Which target registers are accessible through the register file.
 - The cost of allocating a register at register renaming stage.

Example (from this patch - see file X86/X86ScheduleBtVer2.td)

  def FpuPRF : RegisterFile<72, [VR64, VR128, VR256], [1, 1, 2]>

Here, FpuPRF describes a register file for MMX/XMM/YMM registers. On Jaguar
(btver2), a YMM register definition consumes 2 physical registers, while MMX/XMM
register definitions only cost 1 physical register.

The syntax allows to specify an empty set of register classes.  An empty set of
register classes means: this register file models all the registers specified by
the Target.  For each register class, users can specify an optional register
cost. By default, register costs default to 1.  A value of 0 for the number of
physical registers means: "this register file has an unbounded number of
physical registers".

This patch is structured in two parts.

* Part 1 - MC/Tablegen *

A first part adds the tablegen definition of RegisterFile, and teaches the
SubtargetEmitter how to emit information related to register files.

Information about register files is accessible through an instance of
MCExtraProcessorInfo.
The idea behind this design is to logically partition the processor description
which is only used by external tools (like llvm-mca) from the processor
information used by the llvm machine schedulers.
I think that this design would make easier for targets to get rid of the extra
processor information if they don't want it.

* Part 2 - llvm-mca related *

The second part of this patch is related to changes to llvm-mca.

The main differences are:
 1) class RegisterFile now needs to take into account the "cost of a register"
when allocating physical registers at register renaming stage.
 2) Point 1. triggered a minor refactoring which lef to the removal of the
"maximum 32 register files" restriction.
 3) The BackendStatistics view has been updated so that we can print out extra
details related to each register file implemented by the processor.

The effect of point 3. is also visible in tests register-files-[1..5].s.

Differential Revision: https://reviews.llvm.org/D44980


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@329067 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-03 13:36:24 +00:00
Simon Pilgrim
fb87505f61 [SchedModel] Remove instregex entries that don't match any instructions
This patch throws a fatal error if an instregex entry doesn't actually match any instructions. This is part of the work to reduce the compile time impact of increased instregex usage (PR35955), although the x86 models seem to be relatively clean.

All the cases I encountered have now been fixed in trunk and this will ensure they don't get reintroduced.

Differential Revision: https://reviews.llvm.org/D44687

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328459 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-25 19:20:08 +00:00
Craig Topper
419fa24002 [SchedModel] Remove an unneeded temporary vector.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328442 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 22:58:03 +00:00
Craig Topper
284e1ff26d [SchedModel] Use std::move in a couple places to reduce copying
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328441 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 22:58:02 +00:00
Craig Topper
af807a64a6 [SchedModel] Use std::move to replace a vector instead of vector::swap
We don't really care about the old vector value so we don't care to swap it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328440 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 22:58:00 +00:00
Craig Topper
92016652c4 [SchedModel] Remove std::vectors that were created with 1 element and then passed to an ArrayRef parameter.
ArrayRef can capture a single element. We don't need a vector for that.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328438 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 21:57:35 +00:00
Simon Pilgrim
ded7cc40da [SchedModel] Record::getName() returns StringRef - avoid std::string creation. NFCI.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328437 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 21:22:32 +00:00
Simon Pilgrim
79483b2bf4 [SchedModel] Avoid std::string creation for instregex patterns that don't contain regex metas. NFCI.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328436 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-24 21:04:20 +00:00
Craig Topper
b0f8e696aa [TableGen] Use empty emplace_back to add defaulted constructed objects to vectors to avoid using resize(size()+1). NFC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328184 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-22 06:15:10 +00:00
Craig Topper
d74de62f37 [TableGen] Add a non-default constructor to CodeGenSchedClass and use it via emplace_back to create new SchedClasses instead of using resize(size+1)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328183 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-22 06:15:08 +00:00
Craig Topper
6790638696 [TableGen] Hoist the code for copying InstRWs from an old scheduling class to a new one out of the loop that assigns instructions to the new class. NFCI
We already know all the of instructions we're processing in the instruction loop belong to no class or all to the same class. So we only have to worry about remapping one class. So hoist it all out and remove the SmallPtrSet that tracked which class we'd already remapped.

I had to introduce new instruction loop inside this code to print an error message, but that only occurs on the error path.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328142 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 19:52:13 +00:00
Craig Topper
cbb421beaa [TableGen] Remove unnecessary map lookup and shadowing of a variable. NFCI
We already have an OldSCIdx variable in the outer loop here. And we already did the map lookup in the loop that populated ClassInstrs. And the outer OldSCIdx got it from ClassInstrs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328139 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 19:30:33 +00:00
Craig Topper
e2cd723d4e [TableGen] Use range-based for loops. NFC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328138 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 19:30:31 +00:00
Craig Topper
788fc6f75e [TableGen] Use count_if instead of a manual loop. NFC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328137 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 19:30:30 +00:00
Simon Pilgrim
4a705d1b60 [SchedModel] Use CodeGenSchedClass::getSchedClassIdx helper directly. NFCI.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328128 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 18:09:34 +00:00
Simon Pilgrim
6ee668d4cb [SchedModel] Use CodeGenSchedClass::isKeyEqual instead of duplicating code. NFCI.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328126 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 17:57:21 +00:00
Craig Topper
dbb224560c [TableGen] Remove a defaulted function argument that is never called with another value. NFC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328075 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 05:13:04 +00:00
Craig Topper
6eda329d34 [TableGen] Move a function from llvm namespace and make it a static function. NFC
It's only called from one place and is defined just above that use.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328074 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 05:13:01 +00:00
Craig Topper
b6f73f8f0b [TableGen] Use SmallMapVector to simplify some code that was trying to keep a vector unique
Summary:
This code previously had a SmallVector of std::pairs containing an unsigned and another SmallVector. The outer vector was using the unsigned effectively as a key to decide which SmallVector to add into. So each time something new needed to be added the out vector needed to be scanned. If it wasn't found a new entry needed to be added to be added. This sounds very much like a map, but the next loop iterates over the outer vector to get a deterministic order.

We can simplify this code greatly if use SmallMapVector instead. This uses more stack space since we now have a vector and a map, but the searching and creating new entries all happens behind the scenes. It should also make the search more efficient though usually there are only a few entries so that doesn't matter much.

We could probably get determinism by just using std::map which would iterate over the unsigned key, but that would generate different output from what we get with the current implementation.

Reviewers: RKSimon, dblaikie

Reviewed By: dblaikie

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D44711

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328070 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-21 02:48:34 +00:00
Simon Pilgrim
10d5949495 [SchedModel] Simplify InstRegexOp::apply. NFCI.
As discussed on D44687, there was no need for 2 separate for loops for collecting the Regex and then matching against instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328052 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-20 22:20:28 +00:00
Craig Topper
0cd071c82e [TableGen] Use range based for loop. NFC
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328034 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-20 20:24:16 +00:00
Craig Topper
36fc59c476 [TableGen] Use vector::append instead of looping and calling push_back. NFC
Both vectors contain unsigned so we can just use append to do the copying. Not only is this shorter, but it should be able to predict the final size and only grow the vector once if needed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328033 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-20 20:24:14 +00:00
Craig Topper
24e5cd2399 [TableGen] Use llvm::transform to simplify some loops. NFCI
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328032 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-20 20:24:12 +00:00
Craig Topper
17ab24c8db [TableGen] Pass result of std::unique to vector::erase instead of calculating a size and calling resize.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328031 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-20 20:24:10 +00:00
Craig Topper
27bdb27dad [TableGen] When trying to reuse a scheduler class for instructions from an InstRW, make sure we haven't already seen another InstRW containing this instruction on this CPU.
This is similar to the check later when we remap some of the instructions from one class to a new one. But if we reuse the class we don't get to do that check.

So many CPUs have violations of this check that I had to add a flag to the SchedMachineModel to allow it to be disabled. Hopefully we can get those cleaned up quickly and remove this flag.

A lot of the violations are due to overlapping regular expressions, but that's not the only kind of issue it found.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327808 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-18 19:56:15 +00:00
Craig Topper
6ef6701c93 [TableGen] Remove unnecessary uses of make_range.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327785 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-18 08:38:03 +00:00
Craig Topper
65c850f581 [TableGen] Move some variables into for loop declaration. NFC
They aren't needed after the loop.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327784 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-18 08:38:02 +00:00
Clement Courbet
703a63c82f [CodeGenSchedule][NFC] Always emit ProcResourceUnits.
Summary:
Right now only the ProcResourceUnits that are directly referenced by
instructions are emitted. This change emits all of them, so that
analysis passes can use the information.
This has no functional impact. It typically adds a few entries (e.g. 4
for X86/haswell) to the generated ProcRes table.

Reviewers: gchatelet

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D42903

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324228 91177308-0d34-0410-b5e6-96231b3b80d8
2018-02-05 12:23:51 +00:00
Benjamin Kramer
8001e1bb4e [TableGen] Add a way of getting the number of generic opcodes without including modular CodeGen headers.
This is a bit of a hack, but removes a cycle that broke modular builds
of LLVM. Of course the cycle is still there in form of a dependency
on the .def file.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323383 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-24 22:35:11 +00:00
Benjamin Kramer
ed48d8b95f [TableGen] Optimize the regex search.
llvm::Regex is still the slowest regex engine on earth, running it over
all instructions on X86 takes a while. Extract a prefix and use a binary
search to reduce the search space before we resort to regex matching.

There are a couple of caveats here:
- The generic opcodes are outside of the sorted enum. They're handled in an extra loop.
- If there's a top-level bar we can't use the prefix trick.
- We bail on top-level ?. This could be handled, but it's rare.

This brings the time to generate X86GenInstrInfo.inc from 21s to 4.7s on
my machine.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323277 91177308-0d34-0410-b5e6-96231b3b80d8
2018-01-23 23:05:04 +00:00
Evandro Menezes
8304ff28f1 [TableGen] Improve error reporting
When searching for a resource unit, use the reference location instead of
the definition location in case of an error.

Differential revision: https://reviews.llvm.org/D40263

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318803 91177308-0d34-0410-b5e6-96231b3b80d8
2017-11-21 21:33:52 +00:00
Javed Absar
d138a57d9a [TableGen] Tidy up CodeGenSchedule.cpp
Use range_loop where it simplifies.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315446 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-11 09:33:23 +00:00
Javed Absar
1eab66d0f8 [TableGen] Convert VarDef to range_loop. NFC.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315321 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-10 15:58:45 +00:00
Javed Absar
c453306c9b [TableGen] remove make_range where not necessary
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315209 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-09 16:21:25 +00:00
Javed Absar
52122df05b [TableGen] Simplify, add range_loop in CodeGenSchedule
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315183 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-08 17:23:30 +00:00
Javed Absar
3c69ee5540 [TablgeGen] : Tidy up CodeGenSchedule. NFC.
Reviewed by: @MatzeB
Differential Revision: https://reviews.llvm.org/D38534



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314982 91177308-0d34-0410-b5e6-96231b3b80d8
2017-10-05 13:27:43 +00:00
Javed Absar
0a82c73f50 [MiSched|TableGen] : Tidy up and modernise. NFC.
Replacing with range-based loop and substituting 'using'.

Reviewed by: @MatzeB
Differential Revision: https://reviews.llvm.org/D37748



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313140 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-13 10:31:10 +00:00
Joel Jones
59d9d429cc [TableGen] Improve Debug Output for --debug-only=subtarget-emitter NFCI
Add headers for each section of output, with white space and "+++" to
improve readability.

Differential Revision: https://reviews.llvm.org/D34713


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306492 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-28 00:06:40 +00:00
Craig Topper
2a129871cc [TableGen] Adapt more places to getValueAsString now returning a StringRef instead of a std::string.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304347 91177308-0d34-0410-b5e6-96231b3b80d8
2017-05-31 21:12:46 +00:00
Eugene Zelenko
c02caf5200 Fix some Clang-tidy and Include What You Use warnings; other minor fixes (NFC).
This preparation to remove SetVector.h dependency on SmallSet.h.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288256 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-30 17:48:10 +00:00
Ulrich Weigand
96c7b39744 Fix per-processor model scheduler definition completeness check
The CodeGenSchedModels::checkCompleteness routine in TableGen/
CodeGenSchedule.cpp is supposed to verify for each processor
model that is marked as "complete" that it actually defines a
scheduling class for each instruction.

However, this did not work correctly due to an incorrect
check whether a scheduling class has an itinerary.

Reviewer: atrick
Differential revision: https://reviews.llvm.org/D26156



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285622 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-31 18:59:52 +00:00
Andrew Trick
3c59fd410e Improve tablegen gen-subtarget diagnostics for missing machine models.
-debug-only=subtarget-emitter prints a lot of machine model diagnostics.
This prunes the output so that the "No machine model for XXX on processor YYY"
only appears when there is definitely no machine model for that opcode.
Previously it was printing that error even if the opcode was covered by
a more general scheduling class.

<rdar://problem/15919845> [TableGen][CodeGenSchedule] Debug output does not help spotting the missing scheduling classes

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284452 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-18 04:17:44 +00:00