| 372 | } |
| 373 | |
| 374 | Status DotOpEmitter::Emit() { |
| 375 | // The dot operation performs a sum of products over dimension 0 of the left |
| 376 | // hand side operand and dimension 1 of the right hand side operand. |
| 377 | // |
| 378 | // Let the shapes of lhs and rhs be defined as below: |
| 379 | // |
| 380 | // lhs = [L{n-1} x L{n-2} x ... L{0}] |
| 381 | // rhs = [R{m-1} x R{m-2} x ... R{0}] |
| 382 | // |
| 383 | // The sum-of-products dimension in the lhs has size L{0} and the dimension in |
| 384 | // the rhs has size R{1}. Necessarily, then: |
| 385 | // |
| 386 | // L{0} == R{1} |
| 387 | // |
| 388 | // The output of the operation has the following shape: |
| 389 | // |
| 390 | // output = [L{n-1} x L{n-2} x ... L{1} x R{m-1} x R{m-2} x ... R{2} x R{0}] |
| 391 | // |
| 392 | // To perform the operation we construct a loop nest with one for-loop for |
| 393 | // each dimension of the output. Inside this loop nest is another for-loop |
| 394 | // which performs the sum-of-products (the reduction loop) before storing |
| 395 | // the result in the output buffer. |
| 396 | |
| 397 | const Shape& lhs_shape = lhs_array_.GetShape(); |
| 398 | const Shape& rhs_shape = rhs_array_.GetShape(); |
| 399 | |
| 400 | if (ShapeUtil::IsScalar(lhs_shape) || ShapeUtil::IsScalar(rhs_shape)) { |
| 401 | // If the operands are scalar, don't emit any loops. |
| 402 | TF_RET_CHECK(ShapeUtil::IsScalar(lhs_shape) && |
| 403 | ShapeUtil::IsScalar(rhs_shape)); |
| 404 | return EmitScalarDot(); |
| 405 | } |
| 406 | |
| 407 | switch (GetDotImplementationStrategy(hlo_module_config_, dot_info_, |
| 408 | target_machine_features_)) { |
| 409 | case DotImplementationStrategy::kNaiveLlvmIr: |
| 410 | EmitNaiveLlvmIrGemm(); |
| 411 | return Status::OK(); |
| 412 | |
| 413 | case DotImplementationStrategy::kTiledLlvmIrGemv: |
| 414 | EmitTiledLlvmIrGemv(); |
| 415 | return Status::OK(); |
| 416 | |
| 417 | case DotImplementationStrategy::kTiledLlvmIrGemm: |
| 418 | EmitTiledLlvmIrGemm(); |
| 419 | return Status::OK(); |
| 420 | |
| 421 | case DotImplementationStrategy::kEigen: |
| 422 | return EmitCallToRuntime(); |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | void DotOpEmitter::EmitNaiveLlvmIrGemm() { |
| 427 | CHECK_EQ(addend_array_, nullptr); |
no test coverage detected