1 //===- LowerVectorIntrinsics.cpp ------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Utils/LowerVectorIntrinsics.h" 10 #include "llvm/IR/IRBuilder.h" 11 #include "llvm/IR/IntrinsicInst.h" 12 #include "llvm/Support/Debug.h" 13 14 #define DEBUG_TYPE "lower-vector-intrinsics" 15 16 using namespace llvm; 17 18 bool llvm::lowerUnaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) { 19 Type *ArgTy = CI->getArgOperand(0)->getType(); 20 VectorType *VecTy = cast<VectorType>(ArgTy); 21 22 BasicBlock *PreLoopBB = CI->getParent(); 23 BasicBlock *PostLoopBB = nullptr; 24 Function *ParentFunc = PreLoopBB->getParent(); 25 LLVMContext &Ctx = PreLoopBB->getContext(); 26 27 PostLoopBB = PreLoopBB->splitBasicBlock(CI); 28 BasicBlock *LoopBB = BasicBlock::Create(Ctx, "", ParentFunc, PostLoopBB); 29 PreLoopBB->getTerminator()->setSuccessor(0, LoopBB); 30 31 // Loop preheader 32 IRBuilder<> PreLoopBuilder(PreLoopBB->getTerminator()); 33 Value *LoopEnd = nullptr; 34 if (auto *ScalableVecTy = dyn_cast<ScalableVectorType>(VecTy)) { 35 Value *VScale = PreLoopBuilder.CreateVScale( 36 ConstantInt::get(PreLoopBuilder.getInt64Ty(), 1)); 37 Value *N = ConstantInt::get(PreLoopBuilder.getInt64Ty(), 38 ScalableVecTy->getMinNumElements()); 39 LoopEnd = PreLoopBuilder.CreateMul(VScale, N); 40 } else { 41 FixedVectorType *FixedVecTy = cast<FixedVectorType>(VecTy); 42 LoopEnd = ConstantInt::get(PreLoopBuilder.getInt64Ty(), 43 FixedVecTy->getNumElements()); 44 } 45 46 // Loop body 47 IRBuilder<> LoopBuilder(LoopBB); 48 Type *Int64Ty = LoopBuilder.getInt64Ty(); 49 50 PHINode *LoopIndex = LoopBuilder.CreatePHI(Int64Ty, 2); 51 LoopIndex->addIncoming(ConstantInt::get(Int64Ty, 0U), PreLoopBB); 52 PHINode *Vec = LoopBuilder.CreatePHI(VecTy, 2); 53 Vec->addIncoming(CI->getArgOperand(0), PreLoopBB); 54 55 Value *Elem = LoopBuilder.CreateExtractElement(Vec, LoopIndex); 56 Function *Exp = Intrinsic::getOrInsertDeclaration(&M, CI->getIntrinsicID(), 57 VecTy->getElementType()); 58 Value *Res = LoopBuilder.CreateCall(Exp, Elem); 59 Value *NewVec = LoopBuilder.CreateInsertElement(Vec, Res, LoopIndex); 60 Vec->addIncoming(NewVec, LoopBB); 61 62 Value *One = ConstantInt::get(Int64Ty, 1U); 63 Value *NextLoopIndex = LoopBuilder.CreateAdd(LoopIndex, One); 64 LoopIndex->addIncoming(NextLoopIndex, LoopBB); 65 66 Value *ExitCond = 67 LoopBuilder.CreateICmp(CmpInst::ICMP_EQ, NextLoopIndex, LoopEnd); 68 LoopBuilder.CreateCondBr(ExitCond, PostLoopBB, LoopBB); 69 70 CI->replaceAllUsesWith(NewVec); 71 CI->eraseFromParent(); 72 return true; 73 } 74