19#include "llvm/ADT/StringRef.h"
27#define GEN_PASS_DEF_IDIOMRECOGNIZER
28#include "clang/CIR/Dialect/Passes.h.inc"
35bool isNoBuiltin(CallOp call, llvm::StringRef
name) {
36 if (call->hasAttr(cir::CIRDialect::getBuiltinAttrName()))
38 if (call->hasAttr(cir::CIRDialect::getNoBuiltinAttrName()))
40 auto noBuiltins = call->getAttrOfType<mlir::ArrayAttr>(
41 cir::CIRDialect::getNoBuiltinsAttrName());
44 return noBuiltins.empty() ||
45 llvm::any_of(noBuiltins, [
name](mlir::Attribute entry) {
46 auto builtinName = mlir::dyn_cast<mlir::StringAttr>(entry);
47 return builtinName && builtinName.getValue() ==
name;
52template <
typename... TargetOps>
class StdRecognizer {
53 template <
typename TargetOp,
size_t... Indices>
54 static TargetOp buildCall(cir::CIRBaseBuilderTy &builder, CallOp call,
55 std::index_sequence<Indices...>) {
56 return TargetOp::create(builder, call.getLoc(),
57 call->getResult(0).getType(),
58 call.getOperand(Indices)..., call.getCalleeAttr());
61 template <
typename TargetOp>
62 static bool raiseOne(CallOp call, mlir::MLIRContext &context,
63 mlir::SymbolTableCollection &symbolTables) {
65 if (!call.getCallee() || call.getMusttail() ||
66 !TargetOp::signatureMatches(call->getOperandTypes(),
67 call->getResultTypes()))
70 if constexpr (TargetOp::hasKnownFuncKind()) {
74 cir::FuncOp callee = call.resolveCalleeInTable(symbolTables);
75 if (!callee || callee.getFunctionType().isVarArg())
77 auto funcIdentity = mlir::dyn_cast_if_present<cir::FuncIdentityAttr>(
78 callee.getFuncInfoAttr());
79 if (!funcIdentity || funcIdentity.getKind() != TargetOp::getFuncKind())
86 if (*call.getCallee() != TargetOp::getFunctionName() ||
87 isNoBuiltin(call, TargetOp::getFunctionName()))
92 cir::FuncOp callee = call.resolveCalleeInTable(symbolTables);
93 if (callee && callee.getFunctionType().isVarArg())
97 cir::CIRBaseBuilderTy builder(context);
98 builder.setInsertionPointAfter(call.getOperation());
99 constexpr unsigned numArgs = TargetOp::getNumArgs();
101 buildCall<TargetOp>(builder, call, std::make_index_sequence<numArgs>());
104 for (mlir::NamedAttribute attr : call->getAttrs())
105 if (
attr.getName() != call.getCalleeAttrName())
106 op->setAttr(
attr.getName(),
attr.getValue());
107 call.replaceAllUsesWith(op);
114 static bool raise(CallOp call, mlir::MLIRContext &context,
115 mlir::SymbolTableCollection &symbolTables) {
116 return (raiseOne<TargetOps>(call, context, symbolTables) || ...);
121using RecognizedStdOps = StdRecognizer<StdFindOp, StrLenOp>;
123struct IdiomRecognizerPass
124 :
public impl::IdiomRecognizerBase<IdiomRecognizerPass> {
125 IdiomRecognizerPass() =
default;
127 void runOnOperation()
override;
129 void recognizeStandardLibraryCall(CallOp call,
130 mlir::SymbolTableCollection &symbolTables);
134void IdiomRecognizerPass::recognizeStandardLibraryCall(
135 CallOp call, mlir::SymbolTableCollection &symbolTables) {
136 RecognizedStdOps::raise(call, getContext(), symbolTables);
139void IdiomRecognizerPass::runOnOperation() {
142 mlir::SymbolTableCollection symbolTables;
144 getOperation()->walk([&](CallOp callOp) {
146 std::optional<llvm::StringRef> callee = callOp.getCallee();
150 recognizeStandardLibraryCall(callOp, symbolTables);
155 return std::make_unique<IdiomRecognizerPass>();
const internal::VariadicAllOfMatcher< Attr > attr
std::unique_ptr< Pass > createIdiomRecognizerPass()