File: TestEmulateWideInt.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (97 lines) | stat: -rw-r--r-- 3,759 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//===- TestWideIntEmulation.cpp - Test Wide Int Emulation  ------*- c++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass for integration testing of wide integer
// emulation patterns. Applies conversion patterns only to functions whose
// names start with a specified prefix.
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Arith/Transforms/Passes.h"
#include "mlir/Dialect/Arith/Transforms/WideIntEmulationConverter.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"

using namespace mlir;

namespace {
struct TestEmulateWideIntPass
    : public PassWrapper<TestEmulateWideIntPass, OperationPass<func::FuncOp>> {
  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestEmulateWideIntPass)

  TestEmulateWideIntPass() = default;
  TestEmulateWideIntPass(const TestEmulateWideIntPass &pass)
      : PassWrapper(pass) {}

  void getDependentDialects(DialectRegistry &registry) const override {
    registry.insert<arith::ArithDialect, func::FuncDialect, LLVM::LLVMDialect,
                    vector::VectorDialect>();
  }
  StringRef getArgument() const final { return "test-arith-emulate-wide-int"; }
  StringRef getDescription() const final {
    return "Function pass to test Wide Integer Emulation";
  }

  void runOnOperation() override {
    if (!llvm::isPowerOf2_32(widestIntSupported) || widestIntSupported < 2) {
      signalPassFailure();
      return;
    }

    func::FuncOp op = getOperation();
    if (!op.getSymName().startswith(testFunctionPrefix))
      return;

    MLIRContext *ctx = op.getContext();
    arith::WideIntEmulationConverter typeConverter(widestIntSupported);

    // Use `llvm.bitcast` as the bridge so that we can use preserve the
    // function argument and return types of the processed function.
    // TODO: Consider extending `arith.bitcast` to support scalar-to-1D-vector
    // casts (and vice versa) and using it insted of `llvm.bitcast`.
    auto addBitcast = [](OpBuilder &builder, Type type, ValueRange inputs,
                         Location loc) -> std::optional<Value> {
      auto cast = builder.create<LLVM::BitcastOp>(loc, type, inputs);
      return cast->getResult(0);
    };
    typeConverter.addSourceMaterialization(addBitcast);
    typeConverter.addTargetMaterialization(addBitcast);

    ConversionTarget target(*ctx);
    target
        .addDynamicallyLegalDialect<arith::ArithDialect, vector::VectorDialect>(
            [&typeConverter](Operation *op) {
              return typeConverter.isLegal(op);
            });

    RewritePatternSet patterns(ctx);
    arith::populateArithWideIntEmulationPatterns(typeConverter, patterns);
    if (failed(applyPartialConversion(op, target, std::move(patterns))))
      signalPassFailure();
  }

  Option<std::string> testFunctionPrefix{
      *this, "function-prefix",
      llvm::cl::desc("Prefix of functions to run the emulation pass on"),
      llvm::cl::init("emulate_")};
  Option<unsigned> widestIntSupported{
      *this, "widest-int-supported",
      llvm::cl::desc("Maximum integer bit width supported by the target"),
      llvm::cl::init(32)};
};
} // namespace

namespace mlir::test {
void registerTestArithEmulateWideIntPass() {
  PassRegistration<TestEmulateWideIntPass>();
}
} // namespace mlir::test