LLVM also provides the API to emit an instruction, which inserts a scalar into a vector type. Note that this vector is different from an array. A vector type is a simple derived type that represents a vector of elements. Vector types are used when multiple primitive data are operated in parallel using single instruction multiple data (SIMD). A vector type requires a size (number of elements) and an underlying primitive data type. For example, we have a vector Vec
that has four integers of i32
type <4 x i32>
. Now, we want to insert the values 10, 20, 30, and 40 at 0, 1, 2, and 3 indexes of the vector.
The insertelement
instruction takes three arguments. The first argument is a value of vector type. The second operand is a scalar value whose type must equal the element type of the first operand. The third operand is an index indicating the position at which to insert the value. The resultant value is a vector of the same type.
The insertelement
instruction looks like the following:
%vec0 = insertelement <4 x double> Vec, %val0, %idx
This can be further understood by keeping the following in mind:
Vec
is of vector type < 4 x i32 >
val0
is the value to be insertedidx
is the index at which the value is to be inserted in the vectorConsider the following code:
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include <vector> using namespace llvm; static LLVMContext &Context = getGlobalContext(); static Module *ModuleOb = new Module("my compiler", Context); static std::vector<std::string> FunArgs; Function *createFunc(IRBuilder<> &Builder, std::string Name) { Type *u32Ty = Type::getInt32Ty(Context); Type *vecTy = VectorType::get(u32Ty, 4); FunctionType *funcType = FunctionType::get(Builder.getInt32Ty(), vecTy, false); Function *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, ModuleOb); return fooFunc; } void setFuncArgs(Function *fooFunc, std::vector<std::string> FunArgs) { unsigned Idx = 0; Function::arg_iterator AI, AE; for (AI = fooFunc->arg_begin(), AE = fooFunc->arg_end(); AI != AE; ++AI, ++Idx) AI->setName(FunArgs[Idx]); } BasicBlock *createBB(Function *fooFunc, std::string Name) { return BasicBlock::Create(Context, Name, fooFunc); } Value *getInsertElement(IRBuilder<> &Builder, Value *Vec, Value *Val, Value *Index) { return Builder.CreateInsertElement(Vec, Val, Index); } int main(int argc, char *argv[]) { FunArgs.push_back("a"); static IRBuilder<> Builder(Context); Function *fooFunc = createFunc(Builder, "foo"); setFuncArgs(fooFunc, FunArgs); BasicBlock *entry = createBB(fooFunc, "entry"); Builder.SetInsertPoint(entry); Value *Vec = fooFunc->arg_begin(); for (unsigned int i = 0; i < 4; i++) Value *V = getInsertElement(Builder, Vec, Builder.getInt32((i + 1) * 10), Builder.getInt32(i)); Builder.CreateRet(Builder.getInt32(0)); verifyFunction(*fooFunc); ModuleOb->dump(); return 0; }
$ clang++ toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -fno-rtti -o toy $ ./toy
The resulting output is as follows:
; ModuleID = 'my compiler' define i32 @foo(<4 x i32> %a) { entry: %0 = insertelement <4 x i32> %a, i32 10, i32 0 %1 = insertelement <4 x i32> %a, i32 20, i32 1 %2 = insertelement <4 x i32> %a, i32 30, i32 2 %3 = insertelement <4 x i32> %a, i32 40, i32 3 ret i32 0 }
3.147.60.63