Commit Graph

1983 Commits

Author SHA1 Message Date
Dale Johannesen 34aa41c475 Make temporaries explicit to avoid premature
destruction of compiler-created ones.

llvm-svn: 42383
2007-09-26 23:20:33 +00:00
Gordon Henriksen c23b66c58b Added C and Ocaml bindings for functions, basic blocks, and
instruction creation. No support yet for instruction introspection.

Also eliminated allocas from the Ocaml bindings for portability,
and avoided unnecessary casts.

llvm-svn: 42367
2007-09-26 20:56:12 +00:00
Dale Johannesen 17663f40b9 Remove no-longer-used variable.
llvm-svn: 42329
2007-09-25 23:32:20 +00:00
Dale Johannesen e7439eff5a Make APFloat->int conversions deterministic even in
cases with undefined behavior.

llvm-svn: 42328
2007-09-25 23:07:07 +00:00
Duncan Sands 734b861299 Add missing end-of-file newlines.
llvm-svn: 42294
2007-09-25 07:10:01 +00:00
Dale Johannesen 5026f4ba93 float->int conversion rounds toward 0. Duh.
Fixes PR1698.

llvm-svn: 42273
2007-09-24 21:06:09 +00:00
Owen Anderson 4f7c390939 Merge significant portions of the DomTree and PostDomTree implementations.
The two remaining unmerged parts are DFSPass, and the Calculate().

llvm-svn: 42255
2007-09-24 02:29:29 +00:00
Dale Johannesen acbb26f125 Just use APFloat for const / const. Fixes
-1. / -0.

llvm-svn: 42254
2007-09-24 00:32:45 +00:00
Owen Anderson da853a400f Move DFSPass back down into DominatorTree. I need to figure out what the difference is between it
and the PostDomTree version first.

llvm-svn: 42250
2007-09-23 22:16:38 +00:00
Owen Anderson 7888658c5f Fix header.
llvm-svn: 42249
2007-09-23 21:32:55 +00:00
Owen Anderson 84c357fc26 Factor the dominator tree calculation details out into DominatorCalculation.h. This
change is not useful in and of itself, but it lays the groundwork for combining
the dominator and postdominator implementations.

Also, factor a few methods that are common to DominatorTree and PostDominatorTree
into DominatorTreeBase.  Again, this will make merging the two calculation methods
simpler in the future.

llvm-svn: 42248
2007-09-23 21:31:44 +00:00
Dale Johannesen cc7c475705 Fix dumb regression in constant folding (Regression/C/casts)
llvm-svn: 42165
2007-09-20 16:50:21 +00:00
Chris Lattner d79f3d51b1 reject things like "declare internal @foo"
llvm-svn: 42140
2007-09-19 17:14:45 +00:00
Dale Johannesen f4bad97ea0 Fix some long double issues.
llvm-svn: 42133
2007-09-19 14:22:58 +00:00
Duncan Sands a38e527523 Partial fix for PR1678: correct some parts of constant
fold that were missed in the fix for PR1646.  Probably
this null/not-null logic should be factorized somewhere.

llvm-svn: 42131
2007-09-19 10:16:17 +00:00
Gordon Henriksen dc88c06732 Tests of the ocaml (and thus C) bindings for constants.
llvm-svn: 42101
2007-09-18 18:07:51 +00:00
Gordon Henriksen be6bd16418 Incorporating review feedback for GC verifier patch.
llvm-svn: 42087
2007-09-18 10:14:30 +00:00
Gordon Henriksen 76a0374b25 C bindings for libLLVMCore.a and libLLVMBitWriter.a.
- The naming prefix is LLVM.
- All types are represented using opaque references.
- Functions are not named LLVM{Type}{Method}; the names became
  unreadable goop. Instead, they are named LLVM{ImperativeSentence}.
- Where an attribute only appears once in the class hierarchy (e.g.,
  linkage only applies to values; parameter types only apply to
  function types), the class is omitted from identifiers for
  brevity. Tastes like methods.
- Strings are C strings or string/length tuples on a case-by-case
  basis.
- APIs which give the caller ownership of an object are not mapped
  (removeFromParent, certain constructor overloads). This keeps
  keep memory management as simple as possible.

For each library with bindings:

  llvm-c/<LIB>.h       - Declares the bindings.
  lib/<LIB>/<LIB>.cpp  - Implements the bindings.

So just link with the library of your choice and use the C header
instead of the C++ one.

llvm-svn: 42077
2007-09-18 03:18:57 +00:00
Bill Wendling 5752f692ed Add support for appending a suffix to the end of a mangled name.
llvm-svn: 42071
2007-09-17 22:39:32 +00:00
Gordon Henriksen a2f3e13cf4 Fix for PR1633: Verifier doesn't fully verify GC intrinsics
LLVM now enforces the following prototypes for the write barriers:

<ty>* @llvm.gcread(<ty2>*, <ty>**)
void @llvm.gcwrite(<ty>*, <ty2>*, <ty>**)

And for @llvm.gcroot, the first stack slot is verified to be an alloca or a 
bitcast of an alloca.

Fixes test/CodeGen/Generic/GC/lower_gcroot.ll, which violated these.

llvm-svn: 42051
2007-09-17 20:30:04 +00:00
Chris Lattner 0625bd6472 Merge DenseMapKeyInfo & DenseMapValueInfo into DenseMapInfo
Add a new DenseMapInfo::isEqual method to allow clients to redefine
the equality predicate used when probing the hash table.

llvm-svn: 42042
2007-09-17 18:34:04 +00:00
Dale Johannesen 98d3a08d8f Remove the assumption that FP's are either float or
double from some of the many places in the optimizers
it appears, and do something reasonable with x86
long double.
Make APInt::dump() public, remove newline, use it to
dump ConstantSDNode's.
Allow APFloats in FoldingSet.
Expand X86 backend handling of long doubles (conversions
to/from int, mostly).

llvm-svn: 41967
2007-09-14 22:26:36 +00:00
Dale Johannesen 028084efe5 Revise previous patch per review comments.
Next round of x87 long double stuff.
Getting close now, basically works.

llvm-svn: 41875
2007-09-12 03:30:33 +00:00
Dale Johannesen 245dceb06d Add APInt interfaces to APFloat (allows directly
access to bits).  Use them in place of float and
double interfaces where appropriate.
First bits of x86 long double constants handling 
(untested, probably does not work).

llvm-svn: 41858
2007-09-11 18:32:33 +00:00
Duncan Sands d781335d39 Two ParamAttrsVectors which differ by a permutation
of their elements do not yield the same ParamAttrsList,
though they should.  On the other hand, everyone seems
to pass such vectors with elements ordered by increasing
index, so rather than sorting the elements simply assert
that the elements are ordered in this way.

llvm-svn: 41845
2007-09-11 14:40:04 +00:00
Chris Lattner 52fe869374 Fix a buggy constant folding transformation when handling aliases.
llvm-svn: 41818
2007-09-10 23:42:42 +00:00
Owen Anderson e2f23a3abf Add lengthof and endof templates that hide a lot of sizeof computations.
Patch by Sterling Stein!

llvm-svn: 41758
2007-09-07 04:06:50 +00:00
Dale Johannesen bed9dc423c Next round of APFloat changes.
Use APFloat in UpgradeParser and AsmParser.
Change all references to ConstantFP to use the
APFloat interface rather than double.  Remove
the ConstantFP double interfaces.
Use APFloat functions for constant folding arithmetic
and comparisons.
(There are still way too many places APFloat is
just a wrapper around host float/double, but we're
getting there.)

llvm-svn: 41747
2007-09-06 18:13:44 +00:00
David Greene c656cbb8c2 Update GEP constructors to use an iterator interface to fix
GLIBCXX_DEBUG issues.

llvm-svn: 41697
2007-09-04 15:46:09 +00:00
Dale Johannesen d246b2ca5c Change LegalFPImmediates to use APFloat.
Add APFloat interfaces to ConstantFP, SelectionDAG.
Fix integer bit in double->APFloat conversion.
Convert LegalizeDAG to use APFloat interface in
ConstantFPSDNode uses.

llvm-svn: 41587
2007-08-30 00:23:21 +00:00
David Greene 703623d571 Update InvokeInst to work like CallInst
llvm-svn: 41506
2007-08-27 19:04:21 +00:00
Dale Johannesen bdea32d812 Poison APFloat::operator==. Replace existing uses with bitwiseIsEqual.
This means backing out the preceding change to Constants.cpp, alas.

llvm-svn: 41378
2007-08-24 22:09:56 +00:00
Chris Lattner 0b490b0d38 sink clone() down the class hierarchy from CmpInst into ICmpInst/FCmpInst.
This eliminates a conditional on that path, and ensures ICmpInst/FCmpInst
both have an out-of-line virtual method to home the class.

llvm-svn: 41371
2007-08-24 20:48:18 +00:00
Dale Johannesen 918c33c67a Revised per review feedback from previous patch.
llvm-svn: 41353
2007-08-24 05:08:11 +00:00
Dale Johannesen a719a60609 Change internal representation of ConstantFP to use APFloat.
Interface to rest of the compiler unchanged, as yet.

llvm-svn: 41348
2007-08-24 00:56:33 +00:00
Chris Lattner 913849b5df Fix potentially N^2 behavior handling arrays with many of the
same value which get RAUW'd.  This speeds up reading the .bc
file in PR1616 from 852s to 0.19s on my G5 with a debug build.

llvm-svn: 41209
2007-08-21 00:55:23 +00:00
Chris Lattner 8e5b2c27a3 simplify code, improve a comment.
llvm-svn: 41205
2007-08-21 00:21:07 +00:00
Dan Gohman f63668e655 Add Type::isIntOrIntVector, like Type::isFPOrFPVector.
llvm-svn: 41190
2007-08-20 19:25:59 +00:00
Dan Gohman 3a0714836e When Intrinsic::getName is constructing names for overloaded intrinsics,
use the ValueType name instead of the llvm type name, to match what the
verifier expects. For integers these are the same, but for floating-point
values the intrinsics use f32/f64 instead of float/double.

llvm-svn: 41189
2007-08-20 19:23:34 +00:00
Chris Lattner 10f03a644a simplify code and print visibility for declarations.
llvm-svn: 41173
2007-08-19 22:15:26 +00:00
Chris Lattner e2de908a28 Compute the argument list as lazily as possible. This ensures that clients
that don't use it don't have to pay the memory cost for the arguments.  This
allows us to avoid creating Argument nodes for many prototypes and for clients
who lazily deserialize code from a bytecode file.

llvm-svn: 41166
2007-08-18 06:14:52 +00:00
Chris Lattner 45ffa21cb3 use a nicer accessor.
llvm-svn: 41165
2007-08-18 06:13:19 +00:00
Dan Gohman 88ac781644 Fix the verification for overloaded intrinsic types. Check that they are
what they're supposed to be before using them.

llvm-svn: 41130
2007-08-16 22:06:45 +00:00
Dan Gohman febf946ea7 Add MVT::fAny for overloading intrinsics on floating-point types.
llvm-svn: 41128
2007-08-16 21:57:19 +00:00
Devang Patel 367260c0df Assert sooner. Fix wordings.
llvm-svn: 41075
2007-08-14 16:53:52 +00:00
Devang Patel c0fa0c52b3 Add methods to erase basic block entry.
llvm-svn: 41052
2007-08-13 22:10:29 +00:00
Chris Lattner aadc778782 Constant fold: getelementptr (i8* inttoptr (i64 1 to i8*), i32 -1)
Into: inttoptr (i64 0 to i8*)  -> null

This occurs in the example in PR1602.  With this fixed, we now compile
the example in PR1602 into fully "devirtualized" code:

define void @_Z1g1S(%struct.S* noalias  %s) {
entry:        %tmp131415 = getelementptr %struct.S* %s, i32 0, i32 0          ; <i32 (...)***> [#uses=1]        %tmp16 = load i32 (...)*** %tmp131415, align 4          ; <i32 (...)**> [#uses=1]
        %tmp26277 = load i32 (...)** %tmp16             ; <i32 (...)*> [#uses=1]
        %tmp2829 = bitcast i32 (...)* %tmp26277 to void (%struct.S*)*           ; <void (%struct.S*)*> [#uses=1]
        tail call void %tmp2829( %struct.S* %s )
        ret void
}

This still has the vtable dispatch (as required) but does not have any pointer
to method cruft left.

llvm-svn: 41046
2007-08-13 17:09:08 +00:00
Devang Patel d305c404be Do not overuse std::string. Pass around char * directly.
llvm-svn: 41001
2007-08-10 18:29:32 +00:00
Chris Lattner 5109a88ac3 add Value::getNameStart/getNameLen() accessors.
llvm-svn: 40989
2007-08-10 15:34:35 +00:00
Chris Lattner de2aa65877 minor simplifications.
llvm-svn: 40981
2007-08-10 06:22:25 +00:00
Chris Lattner dd6304f6b1 avoid copying strings.
llvm-svn: 40980
2007-08-10 06:17:04 +00:00
Dale Johannesen bdad80977b Patch 10 for long double. Doing constants right needs expanding ConstantFP
to handle values bigger than double.  If we assume host==target and host
long double works correctly, this is not too bad, but we don't want to
have that limitation longterm.  I could implement accepting double
constants as long double or something like that, which would lead to
incorrect codegen with no errors; the more I think about that the worse
it seems.  Rather than do such a hack that would be backed out later,
I'm settling for giving reasonable error messages, for now.

llvm-svn: 40974
2007-08-09 22:51:36 +00:00
Chris Lattner 415750e132 Speed up updateDFSNumbers with two observations:
1. domtree is a tree, not a graph.  There is no need to avoid revisiting nodes with a set.
2. the worklist can contain the child iterator pointers so we don't get N^2 rescanning of children.

This speeds up updateDFSNumbers significantly, making it basically free.  On the testcase in PR1432,
this speeds up loopsimplify by another 3x, dropping it from the 12th most expensive pass to the to
the 30th. :)  It used to be #1.

llvm-svn: 40923
2007-08-08 06:24:20 +00:00
Chris Lattner c63d4c2e4e reimplement dfs number computation to be significantly faster. This speeds up
natural loop canonicalization (which does many cfg xforms) by 4.3x, for 
example.  This also fixes a bug in postdom dfnumber computation.

llvm-svn: 40920
2007-08-08 05:51:24 +00:00
Chris Lattner 67f1c3335c 1. Random tidiness cleanups
2. Make domtree printing print dfin/dfout #'s
3. Fix the Transforms/LoopSimplify/2004-04-13-LoopSimplifyUpdateDomFrontier.ll failure from last night (in DominanceFrontier::splitBlock).

w.r.t. #3, my patches last night happened to expose the bug, but this 
has been broken since Owen's r35839 patch to LoopSimplify.  The code
was subsequently moved over from LoopSimplify into Dominators, carrying
the latent bug.  Fun stuff.

llvm-svn: 40858
2007-08-06 06:19:47 +00:00
Reid Spencer 446282ae3d Fix minor doxygen nits.
llvm-svn: 40854
2007-08-05 20:06:04 +00:00
Reid Spencer 05d55b396c Fix a doxygen directive.
llvm-svn: 40849
2007-08-05 19:27:01 +00:00
Chris Lattner d2eb0c9653 Fix an iterator invalidation bug I induced.
llvm-svn: 40830
2007-08-05 00:24:30 +00:00
Chris Lattner 0e8f85f87e Switch some std::sets to SmallPtrSet. This speeds up
domtree by 10% and postdomtree by 17%

llvm-svn: 40829
2007-08-05 00:15:57 +00:00
Chris Lattner 5f5585c432 Switch DomTreeNode::assignDFSNumber from using a std::set to using
a smallptrset.  This speeds up domtree by about 15% and postdomtree by 20%.

llvm-svn: 40828
2007-08-05 00:10:08 +00:00
Chris Lattner 77e05fe20d Switch the internal "Info" map from an std::map to a DenseMap. This
speeds up idom by about 45% and postidom by about 33%.

Some extra precautions must be taken not to invalidate densemap iterators.

llvm-svn: 40827
2007-08-05 00:02:00 +00:00
Chris Lattner bd0fe01daf switch the DomTreeNodes and IDoms maps in idom/postidom to a
DenseMap instead of an std::map.  This speeds up postdomtree
by about 25% and domtree by about 23%.  It also speeds up clients,
for example, domfrontier by 11%, mem2reg by 4% and ADCE by 6%.

llvm-svn: 40826
2007-08-04 23:48:07 +00:00
Chandler Carruth 7132e00de7 This is the patch to provide clean intrinsic function overloading support in LLVM. It cleans up the intrinsic definitions and generally smooths the process for more complicated intrinsic writing. It will be used by the upcoming atomic intrinsics as well as vector and float intrinsics in the future.
This also changes the syntax for llvm.bswap, llvm.part.set, llvm.part.select, and llvm.ct* intrinsics. They are automatically upgraded by both the LLVM ASM reader and the bitcode reader. The test cases have been updated, with special tests added to ensure the automatic upgrading is supported.

llvm-svn: 40807
2007-08-04 01:51:18 +00:00
Dale Johannesen 65c8a9ee9a long double patch 3 of N. Add to MVT.
llvm-svn: 40793
2007-08-03 20:51:37 +00:00
Dale Johannesen ff4c3be741 Long double, part 1 of N. Support in IR.
llvm-svn: 40774
2007-08-03 01:03:46 +00:00
Devang Patel a882328e61 Update dominator info for the middle blocks created while spliting
exit edge to preserve LCSSA.

Fix dominance frontier update during loop unswitch. This fixes PR 1589, again

llvm-svn: 40737
2007-08-02 15:25:57 +00:00
Devang Patel 34890b2f27 Undo previous check-in.
llvm-svn: 40698
2007-08-01 23:24:50 +00:00
Devang Patel 561b0c29a3 Update dominator info for the middle blocks created while spliting
exit edge to preserve LCSSA.

Fix dominance frontier update during loop unswitch. This fixes PR 1589.

llvm-svn: 40695
2007-08-01 22:23:50 +00:00
David Greene 17a5dfe6f7 New CallInst interface to address GLIBCXX_DEBUG errors caused by
indexing an empty std::vector.

Updates to all clients.

llvm-svn: 40660
2007-08-01 03:43:44 +00:00
Reid Spencer b6508349a7 After a discussion with Anton, it turns out that the InReg attribute is not
permitted on function results. So, revert the last patch to make it illegal.

llvm-svn: 40632
2007-07-31 14:39:10 +00:00
Reid Spencer 160e4faedc The InReg parameter attribute is valid on function results. The llvm-gcc-4.0
front end converts regparm attribute on the gcc function into InReg attribute 
on the llvm function. This fixes test/CFrontend/2002-07-30-SubrefSetAssertion.c

llvm-svn: 40618
2007-07-31 06:33:37 +00:00
Dan Gohman e6656eb4ad Fix pastos in comments for doFinalization functions.
llvm-svn: 40588
2007-07-30 14:51:13 +00:00
Devang Patel 004937bbd9 Add facility to dump pass manager structure
to make it easier to understand failure.

llvm-svn: 40567
2007-07-27 20:06:09 +00:00
Devang Patel 381a2a26e9 Fix edge cases in handling basic block split.
llvm-svn: 40564
2007-07-27 19:13:43 +00:00
Duncan Sands 5d49bcdce0 It seems logical that InReg should be incompatible
with StructReturn and ByVal, so make it so.

llvm-svn: 40554
2007-07-27 16:45:18 +00:00
Duncan Sands 07c9066238 As the number of parameter attributes increases,
Verifier::visitFunction is suffering a combinatorial
explosion due to the number of mutually incompatible
attributes.  This patch tidies the whole thing up
using attribute masks.  While there I fixed some
small bugs: (1) the ByVal attribute tests cast a
type to a pointer type, which can fail.  Yes, the
fact it is of a pointer type is checked before,
but a failing check does not cause the program
to exit, it continues on outputting further errors;
(2) Nothing was checking that an sret attribute is
on the first parameter; (3) nothing was checking that
a function for which isStructReturn() is true has a
parameter with the sret attribute and vice-versa (I
don't think it is possible for this to go wrong, but
it seems right to check it).

llvm-svn: 40553
2007-07-27 15:09:54 +00:00
Duncan Sands 644f917358 Support for trampolines, except for X86 codegen which is
still under discussion.

llvm-svn: 40549
2007-07-27 12:58:54 +00:00
Dan Gohman 6e853bc73f Move the GET_SIDE_EFFECT_INFO logic from isInstructionTriviallyDead
to Instruction::mayWriteToMemory, fixing a FIXME, and helping
various places that call mayWriteToMemory directly.

llvm-svn: 40533
2007-07-26 16:06:08 +00:00
Dan Gohman f2af2bb6aa DummyInst's member functions don't need to be virtual.
llvm-svn: 40530
2007-07-26 15:25:08 +00:00
Christopher Lamb cd97a21064 Add support for 3 element 32-bit vector ValueTypes.
llvm-svn: 40506
2007-07-26 01:46:52 +00:00
Reid Spencer a2e618712d Make output match actual condition tested. Thanks, Duncan.
llvm-svn: 40464
2007-07-24 14:35:44 +00:00
Reid Spencer 0f8fd66a62 1. Make sure we print the Function Value for parameter attribute errors
2. Fold an if statement into the Assert1 macro call.

llvm-svn: 40455
2007-07-23 23:46:43 +00:00
Reid Spencer 6c2b393f0c Add better verification of attributes on function types. It is not permitted
to use sret or inreg on the function. It is equally illegal to use noreturn
or nounwind on a parameter; they only go with the function. This patch
enforces these rules.

llvm-svn: 40453
2007-07-23 23:09:55 +00:00
Chris Lattner 363485da82 zext(undef) = 0 and sext(undef) = 0, not undef.
This hopefully fixes a miscompilation of TargetData.cpp when self hosting.

llvm-svn: 40125
2007-07-20 22:09:02 +00:00
Devang Patel 8adae86688 Use SmallVector instead of std::vector.
llvm-svn: 40109
2007-07-20 18:04:54 +00:00
Reid Spencer 314e1cb7ee For PR1553:
Change the keywords for the zext and sext parameter attributes to be 
zeroext and signext so they don't conflict with the keywords for the
instructions of the same name. This gets around the ambiguity.

llvm-svn: 40069
2007-07-19 23:13:04 +00:00
Devang Patel a273d1cd3a Verify loop info.
llvm-svn: 40062
2007-07-19 18:02:32 +00:00
Devang Patel ef43253e2e Set up ground work to verify preserved analysis info.
llvm-svn: 40039
2007-07-19 05:36:09 +00:00
Dan Gohman 68659280fa Add constructor overloads for LoadInst and StoreInst that insert at the
end of a BasicBlock and have an alignment parameter.

llvm-svn: 40016
2007-07-18 20:51:11 +00:00
Rafael Espindola 6389ef9854 detect invalid combination of sret and byval
llvm-svn: 39971
2007-07-17 13:34:23 +00:00
Dan Gohman 06c60b6032 Fix comments about vectors to use the current wording.
llvm-svn: 39921
2007-07-16 14:29:03 +00:00
Rafael Espindola 9521a564fb check for correct usage of the byval attribute
llvm-svn: 38506
2007-07-10 19:28:12 +00:00
Devang Patel 94d0fbe1a6 Fix memory leak.
llvm-svn: 38469
2007-07-09 20:52:39 +00:00
Rafael Espindola b567e3ffb0 Add the byval attribute
llvm-svn: 37940
2007-07-06 10:57:03 +00:00
Chris Lattner fb0b269032 This enum is dead
llvm-svn: 37920
2007-07-05 17:28:01 +00:00
Gabor Greif e16561cd5d Here is the bulk of the sanitizing.
Almost all occurrences of "bytecode" in the sources have been eliminated.

llvm-svn: 37913
2007-07-05 17:07:56 +00:00
Devang Patel c445982764 Remove ETForest.
llvm-svn: 37765
2007-06-27 20:53:52 +00:00
Dan Gohman 3b62d7265d Rename ("shrinkify") MVT::isExtendedValueType to MVT::isExtendedVT.
llvm-svn: 37758
2007-06-27 16:08:04 +00:00
Dan Gohman 3176887a73 Use utostr from StringExtras.h instead of ostringstream from <sstream>.
llvm-svn: 37731
2007-06-26 15:14:48 +00:00
Dan Gohman a866514528 Generalize MVT::ValueType and associated functions to be able to represent
extended vector types. Remove the special SDNode opcodes used for pre-legalize
vector operations, and the special MVT::Vector type used with them. Adjust
lowering and legalize to work with the normal SDNode kinds instead, and to
use the normal MVT functions to work with vector types instead of using the
two special operands that the pre-legalize nodes held.

This allows pre-legalize and post-legalize DAGs, and the code that operates
on them, to be more consistent. Pre-legalize vector operators can be handled
more consistently with scalar operators. And, -view-dag-combine1-dags and
-view-legalize-dags now look prettier for vector code.

llvm-svn: 37719
2007-06-25 16:23:39 +00:00