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
12 #define DEBUG_TYPE "lower-vector-intrinsics"
13
14 using namespace llvm;
15
lowerUnaryVectorIntrinsicAsLoop(Module & M,CallInst * CI)16 bool llvm::lowerUnaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
17 Type *ArgTy = CI->getArgOperand(0)->getType();
18 VectorType *VecTy = cast<VectorType>(ArgTy);
19
20 BasicBlock *PreLoopBB = CI->getParent();
21 BasicBlock *PostLoopBB = nullptr;
22 Function *ParentFunc = PreLoopBB->getParent();
23 LLVMContext &Ctx = PreLoopBB->getContext();
24 Type *Int64Ty = IntegerType::get(Ctx, 64);
25
26 PostLoopBB = PreLoopBB->splitBasicBlock(CI);
27 BasicBlock *LoopBB = BasicBlock::Create(Ctx, "", ParentFunc, PostLoopBB);
28 PreLoopBB->getTerminator()->setSuccessor(0, LoopBB);
29
30 // Loop preheader
31 IRBuilder<> PreLoopBuilder(PreLoopBB->getTerminator());
32 Value *LoopEnd =
33 PreLoopBuilder.CreateElementCount(Int64Ty, VecTy->getElementCount());
34
35 // Loop body
36 IRBuilder<> LoopBuilder(LoopBB);
37
38 PHINode *LoopIndex = LoopBuilder.CreatePHI(Int64Ty, 2);
39 LoopIndex->addIncoming(ConstantInt::get(Int64Ty, 0U), PreLoopBB);
40 PHINode *Vec = LoopBuilder.CreatePHI(VecTy, 2);
41 Vec->addIncoming(CI->getArgOperand(0), PreLoopBB);
42
43 Value *Elem = LoopBuilder.CreateExtractElement(Vec, LoopIndex);
44 Function *Exp = Intrinsic::getOrInsertDeclaration(&M, CI->getIntrinsicID(),
45 VecTy->getElementType());
46 Value *Res = LoopBuilder.CreateCall(Exp, Elem);
47 Value *NewVec = LoopBuilder.CreateInsertElement(Vec, Res, LoopIndex);
48 Vec->addIncoming(NewVec, LoopBB);
49
50 Value *One = ConstantInt::get(Int64Ty, 1U);
51 Value *NextLoopIndex = LoopBuilder.CreateAdd(LoopIndex, One);
52 LoopIndex->addIncoming(NextLoopIndex, LoopBB);
53
54 Value *ExitCond =
55 LoopBuilder.CreateICmp(CmpInst::ICMP_EQ, NextLoopIndex, LoopEnd);
56 LoopBuilder.CreateCondBr(ExitCond, PostLoopBB, LoopBB);
57
58 CI->replaceAllUsesWith(NewVec);
59 CI->eraseFromParent();
60 return true;
61 }
62