[llvm-dev] Incorrect mangling of intrinsics

Krzysztof Parzyszek via llvm-dev llvm-dev at lists.llvm.org
Tue Mar 24 10:21:37 PDT 2020

Long story short, when I do "getDeclaration" for llvm.ctlz, I get "llvm.ctlz.i32.i1" instead of "llvm.ctlz.i32", and the module verifier flags this as an error.

When bitcode is read from a file, the auto-remangler takes care of this, but when the intrinsic is created programmatically, it has an incorrect mangling.  Should we also do the remangling in Intrinsic::getDeclaration?

Here's a standalone example that shows the problem:

#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/raw_ostream.h>

int main() {
  llvm::LLVMContext Ctx;
  llvm::Module M("blah", Ctx);
  llvm::Intrinsic::ID Ctlz = llvm::Intrinsic::ctlz;
  llvm::Function* In = llvm::Intrinsic::getDeclaration(&M, Ctlz,
      {llvm::Type::getInt32Ty(Ctx), llvm::Type::getInt1Ty(Ctx)});

  llvm::FunctionCallee FC =
      M.getOrInsertFunction("fred", In->getFunctionType());
  auto *F = llvm::cast<llvm::Function>(FC.getCallee());
  auto *Entry = llvm::BasicBlock::Create(Ctx, "entry", F);
  llvm::IRBuilder<> Builder(Entry);
  auto *V = Builder.CreateCall(In->getFunctionType(), In,
      {&*F->arg_begin(), llvm::ConstantInt::getFalse(Ctx)}, "ctlz");

  llvm::errs() << *In << '\n' << *F << '\n';
  verifyModule(M, &llvm::errs());
  return 0;


$ ./a.out
; Function Attrs: nounwind readnone speculatable willreturn
declare i32 @llvm.ctlz.i32.i1(i32, i1 immarg) #0

define i32 @fred(i32 %0, i1 %1) {
  %ctlz = call i32 @llvm.ctlz.i32.i1(i32 %0, i1 false)
  ret i32 %ctlz

Intrinsic name not mangled correctly for type arguments! Should be: llvm.ctlz.i32
i32 (i32, i1)* @llvm.ctlz.i32.i1

Krzysztof Parzyszek  kparzysz at quicinc.com   AI tools development

More information about the llvm-dev mailing list