Commit Graph

2681 Commits

Author SHA1 Message Date
Matthias Springer
6588073724 [mlir][func] Fix incorrect API usage in FuncOpConversion (#113977)
This commit fixes a case of incorrect dialect conversion API usage
during `FuncOpConversion`. `replaceAllUsesExcept` (same as
`replaceAllUsesWith`) is currently not supported in a dialect
conversion. `replaceUsesOfBlockArgument` should be used instead. It
sometimes works anyway (like in this case), but that's just because of
the way we insert materializations.

This commit is in preparation of merging the 1:1 and 1:N dialect
conversion drivers. (At that point, the current use of
`replaceAllUsesExcept` will no longer work.)
2024-10-29 13:19:43 +09:00
Thomas Preud'homme
7db4cacfd7 [MLIR] Add missing MLIRLLVMDialect dep to MLIRLinalgToStandard (#113561)
This fixes the following failure when doing a clean build (in particular
no .ninja* lying around) of lib/libMLIRLinalgToStandard.a only:
```
In file included from llvm/include/llvm/IR/Module.h:22,
                 from mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h:37,
                 from mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp:13:
llvm/include/llvm/IR/Attributes.h:90:14: fatal error: llvm/IR/Attributes.inc: No such file or directory
```
2024-10-28 22:53:39 +01:00
Thomas Preud'homme
82cb22e735 [MLIR] Add missing MLIRLLVMDialect dep to MLIRMathToLibm (#113563)
This fixes the following failure when doing a clean build (in particular
no .ninja* lying around) of lib/libMLIRMathToLibm.a only:
```
In file included from llvm/include/llvm/IR/Module.h:22,
                 from mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h:37,
                 from mlir/lib/Conversion/MathToLibm/MathToLibm.cpp:13
llvm/include/llvm/IR/Attributes.h:90:14: fatal error: llvm/IR/Attributes.inc: No such file or directory
```
2024-10-28 22:50:23 +01:00
Longsheng Mou
7ad63c0e44 [mlir][MathToFuncs] MathToFuncs only support integer type (#113693)
This PR fixes a bug in `MathToFuncs` where it incorrectly converts index
type for `math.ctlz` and `math.ipowi`, leading to a crash. Fixes
#108150.
2024-10-28 09:54:51 +08:00
Longsheng Mou
5aa741d7ca [mlir][SPIRVToLLVM] Erase empty spirv.mlir.loop in LoopPattern (#113527)
This PR erases `spirv.mlir.loop` with an empty region in `LoopPattern`,
resolving a crash. Fixes #113404.
2024-10-26 11:22:57 +08:00
Longsheng Mou
8f9fc6ce47 [mlir][GPU] Add FunctionOpInterface check for OpToFuncCallLowering (#113449)
This PR adds a `FunctionOpInterface` check in `OpToFuncCallLowering` to
resolve a crash when ops not in function. Fixes #113334.
2024-10-26 11:22:08 +08:00
Thomas Preud'homme
bbc0e631d2 [MLIR] Remove unneeded LLVMDialect.h include in ControlFlowToSCF.cpp (#113560)
This fixes the following failure when doing a clean build (in particular
no .ninja* lying around) of lib/libMLIRControlFlowToSCF.a only:
```
In file included from llvm/include/llvm/IR/Module.h:22,
                 from mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h:37,
                 from mlir/lib/Conversion/ControlFlowToSCF/ControlFlowToSCF.cpp:19
llvm/include/llvm/IR/Attributes.h:90:14: fatal error: llvm/IR/Attributes.inc: No such file or directory
```
2024-10-25 15:41:39 +01:00
Sayan Saha
b91ce7bc0e [Tosa] : Fix integer overflow for computing intmax+1 in tosa.cast to linalg. (#112455)
This PR fixes an issue related to integer overflow when computing
`(intmax+1)` for `i64` during `tosa-to-linalg` pass for `tosa.cast`.

Found this issue while debugging a numerical mismatch for `deeplabv3`
model from `torchvision` represented in `tosa` dialect using the
`TorchToTosa` pipeline in `torch-mlir` repository. `torch.aten.to.dtype`
is converted to `tosa.cast` that casts `f32` to `i64` type. Technically
by the specification, `tosa.cast` doesn't handle casting `f32` to `i64`.
So it's possible to add a verifier to error out for such tosa ops
instead of producing incorrect code. However, I chose to fix the
overflow issue to still be able to represent the `deeplabv3` model with
`tosa` ops in the above-mentioned pipeline. Open to suggestions if
adding the verifier is more appropriate instead.
2024-10-25 10:51:09 +01:00
Longsheng Mou
927559d27d [mlir][vector] Fix a crash in VectorToGPU (#113454)
This PR fixes a crash in `VectorToGPU` when the operand of `extOp` is a
function argument, which cannot be retrieved using `getDefiningOp`.
Fixes #107967.
2024-10-24 20:28:42 +08:00
Matthias Springer
f18c3e4e73 [mlir][Transforms] Dialect Conversion: Simplify materialization fn result type (#113031)
This commit simplifies the result type of materialization functions.

Previously: `std::optional<Value>`
Now: `Value`

The previous implementation allowed 3 possible return values:
- Non-null value: The materialization function produced a valid
materialization.
- `std::nullopt`: The materialization function failed, but another
materialization can be attempted.
- `Value()`: The materialization failed and so should the dialect
conversion. (Previously: Dialect conversion can roll back.)

This commit removes the last variant. It is not particularly useful
because the dialect conversion will fail anyway if all other
materialization functions produced `std::nullopt`.

Furthermore, in contrast to type conversions, at least one
materialization callback is expected to succeed. In case of a failing
type conversion, the current dialect conversion can roll back and try a
different pattern. This also used to be the case for materializations,
but that functionality was removed with #107109: failed materializations
can no longer trigger a rollback. (They can just make the entire dialect
conversion fail without rollback.) With this in mind, it is even less
useful to have an additional error state for materialization functions.

This commit is in preparation of merging the 1:1 and 1:N type
converters. Target materializations will have to return multiple values
instead of a single one. With this commit, we can keep the API simple:
`SmallVector<Value>` instead of `std::optional<SmallVector<Value>>`.

Note for LLVM integration: All 1:1 materializations should return
`Value` instead of `std::optional<Value>`. Instead of `std::nullopt`
return `Value()`.
2024-10-23 07:29:17 -07:00
Dmitriy Smirnov
27158edaa4 [MLIR][SPIRV] Update cast from IntN to Bool (#113329)
This PR updates the cast to bool from IntN to treat any non-zero value
as TRUE. This makes the cast more resilient to non-generic (i.e. "non
1") TRUE values.

Signed-off-by: Dmitriy Smirnov <dmitriy.smirnov@arm.com>
2024-10-23 09:47:33 +01:00
Longsheng Mou
519eef3bdc [mlir][tosa] Add a verifier for tosa.mul (#113320)
This PR adds a verifier check for tosa.mul, requiring that the shift be
0 for float types.
Fixes #112716.
2024-10-22 22:34:04 +01:00
Finlay
1775b98de7 [mlir][spirv] Add spirv-to-llvm conversion for OpControlBarrier (#111864)
The conversion is based on the expected llvm function from the
LLVM/SPIRV translation tool.
2024-10-19 11:55:04 +01:00
Frank Schlimbach
d5746d73ce eliminating g++ warnings (#105520)
Eliminating g++ warnings. Mostly declaring "[[maybe_unused]]", adding
return statements where missing and fixing casts.

@rengolin

---------

Co-authored-by: Benjamin Maxwell <macdue@dueutil.tech>
Co-authored-by: Renato Golin <rengolin@systemcall.eu>
2024-10-18 21:20:47 +01:00
Jay Foad
922992a22f Fix typo "instrinsic" (#112899) 2024-10-18 15:58:33 +01:00
Sergio Afonso
0a17bdfc36 [MLIR][OpenMP] Remove terminators from loop wrappers (#112229)
This patch simplifies the representation of OpenMP loop wrapper
operations by introducing the `NoTerminator` trait and updating
accordingly the verifier for the `LoopWrapperInterface`.

Since loop wrappers are already limited to having exactly one region
containing exactly one block, and this block can only hold a single
`omp.loop_nest` or loop wrapper and an `omp.terminator` that does not
return any values, it makes sense to simplify the representation of loop
wrappers by removing the terminator.

There is an extensive list of Lit tests that needed updating to remove
the `omp.terminator`s adding some noise to this patch, but actual
changes are limited to the definition of the `omp.wsloop`, `omp.simd`,
`omp.distribute` and `omp.taskloop` loop wrapper ops, Flang lowering for
those, `LoopWrapperInterface::verifyImpl()`, SCF to OpenMP conversion
and OpenMP dialect documentation.
2024-10-15 11:28:39 +01:00
Durgadoss R
a8b5115441 [MLIR][NVGPU] Fix the cga_cluster.mlir test (#112191)
This patch fixes the sm90 cluster test by:
* Fixing a typo in LowerGpuOpsToNVVMOps where one of the ClusterDim Op
   conversion pattern should actually be for the
   ClusterDimBlocks Op. This addresses the compilation error for this test.
* The grid-size should be (4,4,1) instead of (2,2,1). This passes the
   scf-if check against the threshold of 3 below and actually
   generates the required prints from the GPU.

Signed-off-by: Durgadoss R <durgadossr@nvidia.com>
2024-10-14 19:44:13 +05:30
Nikita Popov
e692af8596 [MLIR] Update APInt construction to correctly set isSigned/implicitTrunc (#110466)
This fixes all the places in MLIR that hit the new assertion added in
#106524, in preparation for enabling it by default. That is, cases where
the value passed to the APInt constructor is not an N-bit
signed/unsigned integer, where N is the bit width and signedness is
determined by the isSigned flag.

The fixes either set the correct value for isSigned, or set the
implicitTrunc flag to retain the old behavior. I've left TODOs for the
latter case in some places, where I think that it may be worthwhile to
stop doing implicit truncation in the future.

Note that the assertion is currently still disabled by default, so this
patch is mostly NFC.

This is just the MLIR changes split off from
https://github.com/llvm/llvm-project/pull/80309.
2024-10-14 15:01:05 +02:00
Fabian Mora
58d97034c9 [mlir][OpenMP] Implement the ConvertToLLVMPatternInterface (#101997)
This patch implements the `ConvertToLLVMPatternInterface` for the OpenMP
dialect, allowing `convert-to-llvm` to act on the OpenMP dialect.
2024-10-11 15:07:08 -04:00
Simon Camphausen
777142937a [mlir][EmitC] Fail on memrefs with 0 dims in type conversion (#111965)
This let's the type conversion fail instead of generating invalid array
types.
2024-10-11 11:45:25 +02:00
TatWai Chong
cc9e7cb99b [mlir][tosa] Change the type of profile option to ListOption (#111214)
In tosa valiation pass, change the type of profile option to ListOption.
Now TOSA profiles is turned from hierarchical to composable. Each
profile is an independent set, i.e. an target can implement multiple
profiles.

Set the profile option to none by default, and limit to profiles if
requested.
The profiles can be specified via command line, e.g.
$ mlir-opt ... --tosa-validate="profile=bi,mi" which tells the valiation
pass that BI and MI are enabled.

Change-Id: I1fb8d0c1b27eccd768349b6eb4234093313efb57
2024-10-10 09:54:34 -07:00
Petr Kurapov
f8b7a65395 [MLIR][GPU-LLVM] Add in-pass signature update for opencl kernels (#105664)
Default to Global address space for memrefs that do not have an explicit address space set in the IR.

---------

Co-authored-by: Victor Perez <victor.perez@intel.com>
Co-authored-by: Jakub Kuderski <kubakuderski@gmail.com>
Co-authored-by: Victor Perez <victor.perez@codeplay.com>
2024-10-10 14:04:52 +02:00
Adam Siemieniuk
ec450b1900 [mlir][xegpu] Allow out-of-bounds writes (#110811)
Relaxes vector.transfer_write lowering to allow out-of-bound writes.

This aligns lowering with the current hardware specification which does
not update bytes in out-of-bound locations during block stores.
2024-10-09 18:59:14 +02:00
Kazu Hirata
01a0e85ab7 [Conversion] Avoid repeated hash lookups (NFC) (#111637) 2024-10-09 06:46:07 -07:00
Dmitriy Smirnov
b9314a8219 [mlir][spirv] Update math.powf lowering (#111388)
The PR updates math.powf lowering to produce NaN result for a negative
base with a fractional exponent which matches the actual behaviour of
the C/C++ implementation.
2024-10-09 09:04:31 +01:00
Benoit Jacob
d8a656ffaf [MLIR] AMDGPUToROCDL: Use a bitcast op to reintepret a vector of i8 as single integer. (#111400)
Found by inspecting AMDGPU assembly - so the arithmetic ops created
there were definitely making their way into the target ISA. A
`LLVM::BitcastOp` seems equivalent, and evaporates as expected in the
target asm.

Along the way, I thought that this helper function `mfmaConcatIfNeeded`
could be renamed to `convertMFMAVectorOperand` to better convey its
contract; so I don't need to think about whether a bitcast is a
legitimate "concat" :-)

---------

Signed-off-by: Benoit Jacob <jacob.benoit.1@gmail.com>
2024-10-07 14:14:18 -04:00
BARRET
1666d13078 [CMake]: Remove unnecessary dependencies on LLVM/MLIR (#111255)
Previous https://github.com/llvm/llvm-project/pull/110362 (reverted)
caused breakage. Here is the PR with fix.

My build cmdline:

```
cmake ../llvm \
    -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_INSTALL_PREFIX=install \
    -DCMAKE_C_COMPILER=gcc-9 \
    -DCMAKE_CXX_COMPILER=g++-9 \
    -DCMAKE_CUDA_COMPILER=$(which nvcc) \
    -DLLVM_ENABLE_LLD=OFF \
    -DLLVM_ENABLE_ASSERTIONS=ON \
    -DLLVM_BUILD_EXAMPLES=ON \
    -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
    -DLLVM_CCACHE_BUILD=ON \
    -DMLIR_ENABLE_BINDINGS_PYTHON=ON \
    -DBUILD_SHARED_LIBS=ON \
    -DLLVM_ENABLE_PROJECTS='llvm;mlir'
```
2024-10-07 15:52:43 +02:00
Matthias Springer
98723e6566 [mlir][SPIRV] Fix build (2) (#111265) 2024-10-05 22:01:57 +02:00
Matthias Springer
206fad0e21 [mlir][NFC] Mark type converter in populate... functions as const (#111250)
This commit marks the type converter in `populate...` functions as
`const`. This is useful for debugging.

Patterns already take a `const` type converter. However, some
`populate...` functions do not only add new patterns, but also add
additional type conversion rules. That makes it difficult to find the
place where a type conversion was added in the code base. With this
change, all `populate...` functions that only populate pattern now have
a `const` type converter. Programmers can then conclude from the
function signature that these functions do not register any new type
conversion rules.

Also some minor cleanups around the 1:N dialect conversion
infrastructure, which did not always pass the type converter as a
`const` object internally.
2024-10-05 21:32:40 +02:00
Matthias Springer
6937dbbe51 [mlir][memref] Fix alloca lowering with 0 dimensions (#111119)
The `memref.alloca` lowering computed the allocation size incorrectly
when there were 0 dimensions.

Previously:
```
memref.alloca() : memref<10x0x2xf32>
--> llvm.alloca 20xf32
```

Now:
```
memref.alloca() : memref<10x0x2xf32>
--> llvm.alloca 0xf32
```

From the `llvm.alloca` documentation:
```
Allocating zero bytes is legal, but the returned pointer may not be unique.
```
2024-10-04 17:32:31 +02:00
Sergey Kozub
3f9cabae00 [MLIR] Add f8E8M0FNU type (#111028)
This PR adds `f8E8M0FNU` type to MLIR.

`f8E8M0FNU` type is proposed in [OpenCompute MX
Specification](https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf).
It defines a 8-bit floating point number with bit layout S0E8M0. Unlike
IEEE-754 types, there are no infinity, denormals, zeros or negative
values.

```c
f8E8M0FNU
- Exponent bias: 127
- Maximum stored exponent value: 254 (binary 1111'1110)
- Maximum unbiased exponent value: 254 - 127 = 127
- Minimum stored exponent value: 0 (binary 0000'0000)
- Minimum unbiased exponent value: 0 − 127 = -127
- Doesn't have zero
- Doesn't have infinity
- NaN is encoded as binary 1111'1111

Additional details:
- Zeros cannot be represented
- Negative values cannot be represented
- Mantissa is always 1
```

Related PRs:
- [PR-107127](https://github.com/llvm/llvm-project/pull/107127)
[APFloat] Add APFloat support for E8M0 type
- [PR-105573](https://github.com/llvm/llvm-project/pull/105573) [MLIR]
Add f6E3M2FN type - was used as a template for this PR
- [PR-107999](https://github.com/llvm/llvm-project/pull/107999) [MLIR]
Add f6E2M3FN type
- [PR-108877](https://github.com/llvm/llvm-project/pull/108877) [MLIR]
Add f4E2M1FN type
2024-10-04 09:23:12 +02:00
Adam Siemieniuk
6c25604df2 [mlir][xegpu] Convert Vector load and store to XeGPU (#110826)
Adds patterns to lower vector.load|store to XeGPU operations.
2024-10-03 08:59:39 +02:00
Jack Frankland
8a57d82120 [mlir] Add Scalar Broadcast TOSA Depthwise Conv (#110806)
Support broadcasting of depthwise conv2d bias in tosa->linalg named
lowering in the case that bias is a rank-1 tensor with exactly 1
element. In this case TOSA specifies the value should first be broadcast
across the bias dimension and then across the result tensor.

Add `lit` tests for depthwise conv2d with scalar bias and for conv3d
which was already supported but missing coverage.

Signed-off-by: Jack Frankland <jack.frankland@arm.com>
2024-10-03 06:40:15 +01:00
Matthias Springer
2da417e7f6 [mlir][GPU] gpu.printf: Do not emit duplicate format strings (#110504)
Even if the same format string is used multiple times, emit just one
`LLVM:GlobalOp`.
2024-10-01 09:12:08 +02:00
Mehdi Amini
8b47711e84 Revert "CMake: Remove unnecessary dependencies on LLVM/MLIR" (#110594)
Reverts llvm/llvm-project#110362

Multiple bots are broken.
2024-10-01 00:44:21 +02:00
BARRET
4980f2177e CMake: Remove unnecessary dependencies on LLVM/MLIR (#110362)
There are some spurious libraries which can be removed.

I'm trying to bundle MLIR/LLVM library dependencies for our own
libraries. We're utilizing cmake function to recursively collect
MLIR/LLVM related dependencies. However, we identified certain library
dependencies as redundant and safe for removal.
2024-09-30 23:57:13 +02:00
Dimple Prajapati
f8ba021e64 [mlir][spirv] Add gpu printf op lowering to spirv.CL.printf op (#78510)
This change contains following:
	- adds lowering of printf op to spirv.CL.printf op in GPUToSPIRV pass.
	- Fixes Constant decoration parsing for spirv GlobalVariable.
	- minor modification to spirv.CL.printf op assembly format.

---------

Co-authored-by: Jakub Kuderski <kubakuderski@gmail.com>
2024-09-30 15:39:13 -04:00
Matthias Springer
49df12c01e [mlir][NFC] Minor cleanup around ModuleOp usage (#110498)
Use `moduleOp.getBody()` instead of `moduleOp.getBodyRegion().front()`.
2024-09-30 21:20:48 +02:00
Jerry-Ge
c6876b4e21 Update input names from input to input1 for Table, Reverse, Slice (#109807)
- For input naming consistency, updated the inputs to input1 for Table,
Reverse and Slice operator

Signed-off-by: Jerry Ge <jerry.ge@arm.com>
2024-09-26 13:33:05 -07:00
Kazu Hirata
b52885bc23 [mlir] Use std::optional::value_or (NFC) (#109893) 2024-09-26 09:53:43 -07:00
Finlay
af7aa223d2 [MLIR][GPU] Lower subgroup query ops in gpu-to-llvm-spv (#108839)
These ops are:
* gpu.subgroup_id
* gpu.lane_id
* gpu.num_subgroups
* gpu.subgroup_size

---------

Signed-off-by: Finlay Marno <finlay.marno@codeplay.com>
2024-09-26 14:52:12 +01:00
Sirui Mu
fde3c16ac9 [mlir][LLVM] Add operand bundle support (#108933)
This PR adds LLVM [operand
bundle](https://llvm.org/docs/LangRef.html#operand-bundles) support to
MLIR LLVM dialect. It affects these 3 operations related to making
function calls: `llvm.call`, `llvm.invoke`, and `llvm.call_intrinsic`.

This PR adds two new parameters to each of the 3 operations. The first
parameter is a variadic operand `op_bundle_operands` that contains the
SSA values for operand bundles. The second parameter is a property
`op_bundle_tags` which holds an array of strings that represent the tags
of each operand bundle.
2024-09-26 07:59:37 +02:00
Mehdi Amini
8ea0dbab2e [mlir] Remove spurious CMake dependencies for convert-vector-to-llvm (NFC)
These don't seem used by this pass.
2024-09-25 03:48:46 -07:00
Chao Chen
8b5e841487 [MLIR][XeGPU] Updates XeGPU TensorDescAttr and Refine Gather/Scatter definition (#109675)
Bring back #109144 with fixes to VectorToXeGPU
2024-09-24 10:14:13 -05:00
Sergey Kozub
2c58063435 [MLIR] Add f4E2M1FN type (#108877)
This PR adds `f4E2M1FN` type to mlir.

`f4E2M1FN` type is proposed in [OpenCompute MX
Specification](https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf).
It defines a 4-bit floating point number with bit layout S1E2M1. Unlike
IEEE-754 types, there are no infinity or NaN values.

```c
f4E2M1FN
- Exponent bias: 1
- Maximum stored exponent value: 3 (binary 11)
- Maximum unbiased exponent value: 3 - 1 = 2
- Minimum stored exponent value: 1 (binary 01)
- Minimum unbiased exponent value: 1 − 1 = 0
- Has Positive and Negative zero
- Doesn't have infinity
- Doesn't have NaNs

Additional details:
- Zeros (+/-): S.00.0
- Max normal number: S.11.1 = ±2^(2) x (1 + 0.5) = ±6.0
- Min normal number: S.01.0 = ±2^(0) = ±1.0
- Min subnormal number: S.00.1 = ±2^(0) x 0.5 = ±0.5
```

Related PRs:
- [PR-95392](https://github.com/llvm/llvm-project/pull/95392) [APFloat]
Add APFloat support for FP4 data type
- [PR-105573](https://github.com/llvm/llvm-project/pull/105573) [MLIR]
Add f6E3M2FN type - was used as a template for this PR
- [PR-107999](https://github.com/llvm/llvm-project/pull/107999) [MLIR]
Add f6E2M3FN type
2024-09-24 08:22:48 +02:00
Daniel Hernandez-Juarez
1c47fa9b62 [mlir][AMDGPU] Add support for AMD f16 math library calls (#108809)
In this PR we add support for AMD f16 math library calls
(`__ocml_*_f16`)

CC: @krzysz00 @manupak
2024-09-23 12:52:00 -05:00
Youngsuk Kim
123e8c735d [mlir] Don't call llvm::raw_string_ostream::flush() (NFC)
Don't call raw_string_ostream::flush(), which is essentially a no-op.
As specified in the docs, raw_string_ostream is always unbuffered.
( 65b13610a5 for further reference )
2024-09-22 15:37:34 -05:00
Daniel Hernandez-Juarez
b014265d99 [mlir][AMDGPU] New gfx12 barrier instructions and update lowering LDSBarrierOp (#109273)
New gfx12 barrier instructions: s.barrier.signal, s.barrier.wait and
s.wait.dscnt. And update lowering LDSBarrierOp accordingly.

CC: @krzysz00 @manupak @giuseros
2024-09-20 17:41:36 -05:00
Adam Siemieniuk
02d34d800b [mlir][vector][xegpu] Vector to XeGPU conversion pass (#107419)
Add pass for Vector to XeGPU dialect conversion and initial conversion
patterns for vector.transfer_read|write operations.
2024-09-19 15:16:23 -05:00
Benjamin Kramer
ac11945386 [mlir][GPU] block_id has the grid size as its range 2024-09-17 18:38:04 +02:00