diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -222,6 +222,12 @@ /// This method returns true on error. bool matchIntrinsicVarArg(bool isVarArg, ArrayRef &Infos); + /// Gets the type arguments of an intrinsic call by matching type contraints + /// specified by the .td file. + /// + /// Returns None if the given function is not a valid intrinsic call. + Optional> getIntrinsicSignature(Function *F); + // Checks if the intrinsic name matches with its signature and if not // returns the declaration with the same signature and remangled name. llvm::Optional remangleIntrinsicFunction(Function *F); diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1427,31 +1427,41 @@ return true; } -Optional Intrinsic::remangleIntrinsicFunction(Function *F) { +Optional> Intrinsic::getIntrinsicSignature(Function *F) { Intrinsic::ID ID = F->getIntrinsicID(); if (!ID) return None; - FunctionType *FTy = F->getFunctionType(); - // Accumulate an array of overloaded types for the given intrinsic + SmallVector Table; + getIntrinsicInfoTableEntries(ID, Table); + ArrayRef TableRef = Table; SmallVector ArgTys; - { - SmallVector Table; - getIntrinsicInfoTableEntries(ID, Table); - ArrayRef TableRef = Table; - - if (Intrinsic::matchIntrinsicSignature(FTy, TableRef, ArgTys)) - return None; - if (Intrinsic::matchIntrinsicVarArg(FTy->isVarArg(), TableRef)) - return None; + + if (Intrinsic::matchIntrinsicSignature(F->getFunctionType(), TableRef, + ArgTys) != + Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) { + return None; } + if (Intrinsic::matchIntrinsicVarArg(F->getFunctionType()->isVarArg(), + TableRef)) + return None; + + return std::move(ArgTys); +} + +Optional Intrinsic::remangleIntrinsicFunction(Function *F) { + Optional> ArgTys = getIntrinsicSignature(F); + if (!ArgTys) + return None; + Intrinsic::ID ID = F->getIntrinsicID(); StringRef Name = F->getName(); - if (Name == Intrinsic::getName(ID, ArgTys)) + if (Name == Intrinsic::getName(ID, *ArgTys)) return None; - auto NewDecl = Intrinsic::getDeclaration(F->getParent(), ID, ArgTys); + auto NewDecl = Intrinsic::getDeclaration(F->getParent(), ID, *ArgTys); NewDecl->setCallingConv(F->getCallingConv()); + FunctionType *FTy = F->getFunctionType(); assert(NewDecl->getFunctionType() == FTy && "Shouldn't change the signature"); return NewDecl; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -1130,25 +1130,21 @@ return nullptr; } - // Determine the overload types of the original intrinsic. - auto IID = II->getIntrinsicID(); - SmallVector Table; - getIntrinsicInfoTableEntries(IID, Table); - ArrayRef TableRef = Table; - // Validate function argument and return types, extracting overloaded types // along the way. - FunctionType *FTy = II->getCalledFunction()->getFunctionType(); - SmallVector OverloadTys; - Intrinsic::matchIntrinsicSignature(FTy, TableRef, OverloadTys); + Optional> OverloadTys = + Intrinsic::getIntrinsicSignature(II->getCalledFunction()); + if (!OverloadTys) + return nullptr; Module *M = II->getParent()->getParent()->getParent(); Type *EltTy = IIVTy->getElementType(); Type *NewTy = (NewNumElts == 1) ? EltTy : FixedVectorType::get(EltTy, NewNumElts); - OverloadTys[0] = NewTy; - Function *NewIntrin = Intrinsic::getDeclaration(M, IID, OverloadTys); + (*OverloadTys)[0] = NewTy; + Function *NewIntrin = + Intrinsic::getDeclaration(M, II->getIntrinsicID(), *OverloadTys); CallInst *NewCall = Builder.CreateCall(NewIntrin, Args); NewCall->takeName(II);