================
@@ -50,26 +51,133 @@ struct LibOptPass : public impl::LibOptBase<LibOptPass> {
   // Raw libopt option string forwarded by the frontend. This will later 
control
   // which optimizations the pass enables.
   std::string optimizationOptions;
-
-  /// Tracks current module.
-  ModuleOp theModule;
 };
 } // namespace
 
 mlir::LogicalResult LibOptPass::initializeOptions(
     llvm::StringRef options,
-    llvm::function_ref<mlir::LogicalResult(const llvm::Twine &)> errorHandler) 
{
-  (void)errorHandler;
+    llvm::function_ref<mlir::LogicalResult(const llvm::Twine &)>) {
   optimizationOptions = options.str();
   // TODO(cir): Parse options to select the active transformations for the
   // pass.
   return mlir::success();
 }
 
+static void rewriteStdFindToMemchr(StdFindOp findOp,
+                                   mlir::SymbolTableCollection &symbolTables) {
+  auto iterTy = mlir::dyn_cast<cir::PointerType>(findOp.getResult().getType());
+  if (!iterTy || iterTy.getAddrSpace())
+    return;
+  auto elemTy = mlir::dyn_cast<cir::IntType>(iterTy.getPointee());
+  if (!elemTy || elemTy.getWidth() != 8)
+    return;
+
+  auto patternPtrTy =
+      mlir::dyn_cast<cir::PointerType>(findOp.getPattern().getType());
+  if (!patternPtrTy || patternPtrTy.getPointee() != elemTy)
+    return;
+
+  // LibOpt runs before LoweringPrepare, so a global initializer is still a
+  // cir.global here. Anything else is not a shape CIRGen produces.
+  auto enclosing = findOp->getParentOfType<cir::FuncOp>();
+  auto enclosingGlobal = findOp->getParentOfType<cir::GlobalOp>();
+  if (!enclosing && !enclosingGlobal)
+    return;
+
+  // No builtin state rides on the raised call and on the enclosing function.
+  // A global initializer has no function to carry the list.
+  if (isNoBuiltin(findOp, "memchr") ||
+      (enclosing && noBuiltinListDisables(enclosing, "memchr")))
+    return;
+
+  // An enum or atomic element also lowers to a byte wide integer.
+  auto callee = symbolTables.lookupNearestSymbolFrom<cir::FuncOp>(
+      findOp, findOp.getOriginalFnAttr());
+  auto funcIdentity = mlir::dyn_cast_if_present<cir::FuncIdentityAttr>(
+      callee ? callee.getFuncInfoAttr() : mlir::Attribute());
+  if (!funcIdentity || funcIdentity.getKind() != cir::KnownFuncKind::StdFind ||
+      !funcIdentity.getNarrowCharParams()) {
+    return;
+  }
+
+  auto moduleOp = findOp->getParentOfType<mlir::ModuleOp>();
+  if (!moduleOp)
+    return;
+
+  auto tripleAttr = moduleOp->getAttrOfType<mlir::StringAttr>(
+      cir::CIRDialect::getTripleAttrName());
+  if (!tripleAttr)
+    return;
+
+  llvm::Triple triple(tripleAttr.getValue().str());
+
+  // cir.libc.memchr currently requires a 64 bit length. Use the AST size_t
+  // width recorded by CIRGen instead of inferring it from target properties.
+  auto sizeWidthAttr = moduleOp->getAttrOfType<mlir::IntegerAttr>(
+      cir::CIRDialect::getSizeTypeWidthAttrName());
+  bool sizeTypeMismatch = !sizeWidthAttr ||
+                          !sizeWidthAttr.getType().isSignlessInteger(32) ||
+                          sizeWidthAttr.getInt() != 64;
+
+  // The current memchr lowering supplies no target ABI extension attributes, 
so
+  // restrict the rewrite to targets known not to need them.
+  // TODO(cir): use target-aware ABI and libcall availability information.
+  bool abiSafeTarget =
+      triple.getArch() == llvm::Triple::x86_64 || triple.isAArch64();
+
+  // AArch64 GNUILP32 AST types disagree with LLVM's data layout.
+  bool unsupportedABI =
+      triple.isAArch64() && triple.getEnvironment() == llvm::Triple::GNUILP32;
+
+  if (sizeTypeMismatch || !abiSafeTarget || unsupportedABI)
+    return;
+
+  // Lowering resolves memchr in the module symbol table. An existing symbol 
may
+  // collide with the introduced libcall or carry incompatible semantics.
+  if (symbolTables.lookupSymbolIn(
----------------
SharmaRithik wrote:

I did confirm this and a single ordinary memchr call blocks the rewrite so you 
are right that the guard is too broad. The cases that motivated it used false 
noreturn or returns_nonnull promises. My current plan is to follow the normal 
libcall policy by checking availability and a compatible function prototype 
while keeping the no builtin handling. I would appreciate any suggestions if 
another approach fits CIR better.

https://github.com/llvm/llvm-project/pull/212355
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to