[llvm] [AsmParser] Implicitly declare intrinsics (PR #78251)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 16 05:30:07 PST 2024


================
@@ -246,6 +246,34 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
                  "use of undefined comdat '$" +
                      ForwardRefComdats.begin()->first + "'");
 
+  // Automatically create declarations for intrinsics. Intrinsics can only be
+  // called directly, so the call function type directly determines the
+  // declaration function type.
+  for (const auto &[Name, Info] : make_early_inc_range(ForwardRefVals)) {
+    if (!StringRef(Name).starts_with("llvm."))
+      continue;
+
+    // Don't do anything if the intrinsic is called with different function
+    // types. This would result in a verifier error anyway.
+    auto GetCommonFunctionType = [](Value *V) -> FunctionType * {
+      FunctionType *FTy = nullptr;
+      for (User *U : V->users()) {
+        auto *CB = dyn_cast<CallBase>(U);
+        if (!CB || (FTy && FTy != CB->getFunctionType()))
+          return nullptr;
+        FTy = CB->getFunctionType();
+      }
+      return FTy;
+    };
+    if (FunctionType *FTy = GetCommonFunctionType(Info.first)) {
+      Function *Fn =
+          Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
----------------
dtcxzyw wrote:

I'd like to see a test that shows the result of `II->getIntrinsicID()` is correct.
```
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
define i32 @test_canonicalize_fshr_to_fshl(i32 %x) {
  %ret = call i32 @llvm.fshr(i32 %x, i32 %x, i32 16)
  ret i32 %ret
}
```
Expected output:
```
define i32 @test_canonicalize_fshr_to_fshl(i32 %x) {
  %ret = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 16)
  ret i32 %ret
}

declare i32 @llvm.fshr.i32(i32, i32, i32)
declare i32 @llvm.fshl.i32(i32, i32, i32)
```

It should be handled by `llvm::UpgradeCallsToIntrinsic`.


https://github.com/llvm/llvm-project/pull/78251


More information about the llvm-commits mailing list