xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
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