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