17 #include "ExprConfig.h"
19 #ifdef SEEXPR_ENABLE_LLVM
27 using namespace SeExpr2;
34 Function *llvm_getFunction(
LLVM_BUILDER Builder) {
return Builder.GetInsertBlock()->getParent(); }
36 Module *llvm_getModule(
LLVM_BUILDER Builder) {
return llvm_getFunction(Builder)->getParent(); }
39 std::string llvmTypeString(llvm::Type* type){
41 llvm::raw_string_ostream rawStream(myString);
42 type->print(rawStream);
43 return rawStream.str();
47 if (seFuncType == ExprFuncStandard::FUNCN || seFuncType == ExprFuncStandard::FUNCNV ||
48 seFuncType == ExprFuncStandard::FUNCNVV)
54 if (seFuncType == ExprFuncStandard::FUNC1VV || seFuncType == ExprFuncStandard::FUNC2VV ||
55 seFuncType == ExprFuncStandard::FUNCNVV)
61 if (seFuncType <= ExprFuncStandard::FUNC6 || seFuncType == ExprFuncStandard::FUNCN)
return true;
66 assert(sft != ExprFuncStandard::NONE);
68 Type *intType = TypeBuilder<int, false>::get(llvmContext);
69 Type *doubleType = TypeBuilder<double, false>::get(llvmContext);
70 Type *doublePtrType = TypeBuilder<double *, false>::get(llvmContext);
71 Type *voidType = TypeBuilder<void, false>::get(llvmContext);
74 if (sft <= ExprFuncStandard::FUNC6) {
75 std::vector<Type *> paramTypes;
77 case ExprFuncStandard::FUNC6:
78 paramTypes.push_back(doubleType);
79 case ExprFuncStandard::FUNC5:
80 paramTypes.push_back(doubleType);
81 case ExprFuncStandard::FUNC4:
82 paramTypes.push_back(doubleType);
83 case ExprFuncStandard::FUNC3:
84 paramTypes.push_back(doubleType);
85 case ExprFuncStandard::FUNC2:
86 paramTypes.push_back(doubleType);
87 case ExprFuncStandard::FUNC1:
88 paramTypes.push_back(doubleType);
89 case ExprFuncStandard::FUNC0:
91 FT = FunctionType::get(doubleType, paramTypes,
false);
93 }
else if (sft == ExprFuncStandard::FUNC1V) {
94 Type *paramTypes[1] = {doublePtrType};
95 FT = FunctionType::get(doubleType, paramTypes,
false);
96 }
else if (sft == ExprFuncStandard::FUNC2V) {
97 Type *paramTypes[2] = {doublePtrType, doublePtrType};
98 FT = FunctionType::get(doubleType, paramTypes,
false);
99 }
else if (sft == ExprFuncStandard::FUNC1VV) {
100 Type *paramTypes[2] = {doublePtrType, doublePtrType};
101 FT = FunctionType::get(voidType, paramTypes,
false);
102 }
else if (sft == ExprFuncStandard::FUNC2VV) {
103 Type *paramTypes[3] = {doublePtrType, doublePtrType, doublePtrType};
104 FT = FunctionType::get(voidType, paramTypes,
false);
105 }
else if (sft == ExprFuncStandard::FUNCN) {
106 Type *paramTypes[2] = {intType, doublePtrType};
107 FT = FunctionType::get(doubleType, paramTypes,
false);
108 }
else if (sft == ExprFuncStandard::FUNCNV) {
109 Type *paramTypes[2] = {intType, doublePtrType};
110 FT = FunctionType::get(doubleType, paramTypes,
false);
111 }
else if (sft == ExprFuncStandard::FUNCNVV) {
112 Type *paramTypes[3] = {doublePtrType, intType, doublePtrType};
113 FT = FunctionType::get(voidType, paramTypes,
false);
120 Type *createLLVMTyForSeExprType(LLVMContext &llvmContext,
ExprType seType) {
122 int dim = seType.
dim();
123 return dim == 1 ? Type::getDoubleTy(llvmContext) : VectorType::get(Type::getDoubleTy(llvmContext), dim);
127 return Type::getInt8PtrTy(llvmContext);
129 assert(!
"unknown SeExpr type encountered");
135 LLVMContext &llvmContext = Builder.getContext();
136 VectorType *doubleVecTy = VectorType::get(Type::getDoubleTy(llvmContext), dim);
137 LLVM_VALUE vecVal = UndefValue::get(doubleVecTy);
138 for (
unsigned i = 0; i < dim; i++)
139 vecVal = Builder.CreateInsertElement(vecVal, val, ConstantInt::get(Type::getInt32Ty(llvmContext), i));
145 if (!val.size())
return 0;
147 LLVMContext &llvmContext = Builder.getContext();
148 unsigned dim = val.size();
149 VectorType *elemType = VectorType::get(val[0]->getType(), dim);
150 LLVM_VALUE vecVal = UndefValue::get(elemType);
151 for (
unsigned i = 0; i < dim; i++)
152 vecVal = Builder.CreateInsertElement(vecVal, val[i], ConstantInt::get(Type::getInt32Ty(llvmContext), i), name);
157 Type *destTy = destPtr->getType()->getPointerElementType();
158 assert(destTy->isDoubleTy() || destTy->isArrayTy());
159 std::vector<LLVM_VALUE> vals;
161 for (
unsigned i = 0; i < vecLen; ++i) {
162 LLVM_VALUE ptr = destTy->isDoubleTy() ? Builder.CreateConstGEP1_32(destPtr, i)
163 : Builder.CreateConstGEP2_32(
nullptr, destPtr, 0, i);
164 vals.push_back(Builder.CreateLoad(ptr));
167 return createVecVal(Builder, vals);
171 Type *VTy = V->getType();
172 if (VTy->isDoubleTy())
return V;
174 assert(VTy->isVectorTy());
175 LLVMContext &llvmContext = Builder.getContext();
176 LLVM_VALUE zero = ConstantInt::get(Type::getInt32Ty(llvmContext), 0);
177 return Builder.CreateExtractElement(V, zero);
181 Type *srcTy = val->getType();
182 if (srcTy == destTy)
return val;
184 if (destTy->isDoubleTy())
return val;
186 return createVecVal(Builder, val, destTy->getVectorNumElements());
189 AllocaInst *createAllocaInst(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize = 1,
const std::string &varName =
"") {
191 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
192 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
194 Builder.SetInsertPoint(&entryBB->front());
196 Builder.SetInsertPoint(entryBB);
199 LLVMContext &llvmContext = Builder.getContext();
200 LLVM_VALUE arraySizeVal = ConstantInt::get(Type::getInt32Ty(llvmContext), arraySize);
201 AllocaInst *varPtr = Builder.CreateAlloca(ty, arraySizeVal, varName);
203 Builder.restoreIP(oldIP);
207 AllocaInst *createArray(
LLVM_BUILDER Builder, Type *ty,
unsigned arraySize,
const std::string &varName =
"") {
209 BasicBlock *entryBB = &llvm_getFunction(Builder)->getEntryBlock();
210 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
212 Builder.SetInsertPoint(&entryBB->front());
214 Builder.SetInsertPoint(entryBB);
217 ArrayType *arrayTy = ArrayType::get(ty, arraySize);
218 AllocaInst *varPtr = Builder.CreateAlloca(arrayTy, 0, varName);
220 Builder.restoreIP(oldIP);
224 std::pair<LLVM_VALUE, LLVM_VALUE> promoteBinaryOperandsToAppropriateVector(
LLVM_BUILDER Builder,
227 Type *op1Ty = op1->getType();
228 Type *op2Ty = op2->getType();
229 if (op1Ty == op2Ty)
return std::make_pair(op1, op2);
233 if (op1Ty->isVectorTy()) std::swap(toPromote, target);
235 assert(target->getType()->isVectorTy());
237 unsigned dim = target->getType()->getVectorNumElements();
238 LLVM_VALUE vecVal = createVecVal(Builder, toPromote, dim);
240 if (op1Ty->isVectorTy())
245 return std::make_pair(op1, op2);
249 Type *valTy = val->getType();
250 if (refType.
isFP() && refType.
dim() > 1 && !valTy->isVectorTy()) {
251 return createVecVal(Builder, val, refType.
dim());
258 LLVMContext &llvmContext = Builder.getContext();
259 AllocaInst *doublePtr =
260 createAllocaInst(Builder, Type::getDoubleTy(llvmContext), vecVal->getType()->getVectorNumElements());
261 for (
unsigned i = 0; i < 3; ++i) {
262 LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), i);
263 LLVM_VALUE val = Builder.CreateExtractElement(vecVal, idx);
264 LLVM_VALUE ptr = Builder.CreateConstGEP1_32(doublePtr, i);
265 Builder.CreateStore(val, ptr);
271 std::vector<LLVM_VALUE> args;
276 std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
LLVM_BUILDER Builder, FunctionType *llvmFuncType) {
277 std::vector<LLVM_VALUE> ret;
278 for (
unsigned i = 0; i < args.size(); ++i)
279 ret.push_back(promoteToTy(args[i], llvmFuncType->getParamType(i), Builder));
283 std::vector<LLVM_VALUE> promoteArgs(std::vector<LLVM_VALUE> args,
286 if (isTakeOnlyDoubleArg(seFuncType))
return args;
288 LLVMContext &llvmContext = Builder.getContext();
289 VectorType *destTy = VectorType::get(Type::getDoubleTy(llvmContext), 3);
290 std::vector<LLVM_VALUE> ret;
291 for (
unsigned i = 0; i < args.size(); ++i) ret.push_back(promoteToTy(args[i], destTy, Builder));
295 std::vector<LLVM_VALUE> replaceVecArgWithDoublePointer(
LLVM_BUILDER Builder, std::vector<LLVM_VALUE> args) {
296 for (
unsigned i = 0; i < args.size(); ++i)
297 if (args[i]->getType()->isVectorTy()) args[i] = storeVectorToDoublePtr(Builder, args[i]);
301 std::vector<LLVM_VALUE> convertArgsToPointerAndLength(
LLVM_BUILDER Builder,
302 std::vector<LLVM_VALUE> actualArgs,
304 assert(isVarArg(seFuncType));
306 LLVMContext &llvmContext = Builder.getContext();
307 unsigned numArgs = actualArgs.size();
310 for (
unsigned i = 0; i < numArgs; ++i)
311 assert(actualArgs[i]->getType()->isDoubleTy() || actualArgs[i]->getType() == Type::getDoublePtrTy(llvmContext));
313 std::vector<LLVM_VALUE> args;
315 args.push_back(ConstantInt::get(Type::getInt32Ty(llvmContext), numArgs));
317 if (seFuncType == ExprFuncStandard::FUNCN) {
318 AllocaInst *doublePtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), numArgs);
319 for (
unsigned i = 0; i < numArgs; ++i) {
320 LLVM_VALUE ptr = Builder.CreateConstGEP1_32(doublePtr, i);
321 Builder.CreateStore(actualArgs[i], ptr);
323 args.push_back(doublePtr);
327 AllocaInst *arrayPtr = createArray(Builder, ArrayType::get(Type::getDoubleTy(llvmContext), 3), numArgs);
328 for (
unsigned i = 0; i < numArgs; ++i) {
330 LLVM_VALUE subArrayPtr = Builder.CreateConstGEP2_32(
nullptr, arrayPtr, 0, i);
331 for (
unsigned j = 0; j < 3; ++j) {
332 LLVM_VALUE destAddr = Builder.CreateConstGEP2_32(
nullptr, subArrayPtr, 0, j);
333 LLVM_VALUE srcAddr = Builder.CreateConstGEP1_32(toInsert, j);
334 Builder.CreateStore(Builder.CreateLoad(srcAddr), destAddr);
337 args.push_back(Builder.CreateBitCast(arrayPtr, Type::getDoublePtrTy(llvmContext)));
343 std::vector<LLVM_VALUE> args,
345 LLVMContext &llvmContext = Builder.getContext();
347 args = promoteArgs(args, Builder, seFuncType);
348 args = replaceVecArgWithDoublePointer(Builder, args);
350 if (isVarArg(seFuncType)) args = convertArgsToPointerAndLength(Builder, args, seFuncType);
352 if (isReturnVector(seFuncType) ==
false)
return Builder.CreateCall(addrVal, args);
356 AllocaInst *retPtr = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), 3);
357 args.insert(args.begin(), retPtr);
358 Builder.CreateCall(addrVal, replaceVecArgWithDoublePointer(Builder, args));
359 return createVecValFromAlloca(Builder, retPtr, 3);
364 LLVMContext &llvmContext = Builder.getContext();
365 std::vector<LLVM_VALUE> args;
370 assert(formatStrNode);
371 std::string formatStr(formatStrNode->
str());
372 std::string::size_type pos = std::string::npos;
373 while ((pos = formatStr.find(
"%v")) != std::string::npos) formatStr.replace(pos, 2, std::string(
"[%f,%f,%f]"));
374 formatStr.append(
"\n");
375 args.push_back(Builder.CreateGlobalStringPtr(formatStr));
380 if (arg->getType()->isVectorTy()) {
381 AllocaInst *vecArray = storeVectorToDoublePtr(Builder, arg);
382 for (
unsigned i = 0; i < arg->getType()->getVectorNumElements(); ++i) {
383 LLVM_VALUE elemPtr = Builder.CreateConstGEP1_32(vecArray, i);
384 args.push_back(Builder.CreateLoad(elemPtr));
390 Builder.CreateCall(callee, args);
391 return ConstantFP::get(Type::getDoubleTy(llvmContext), 0.0);
396 LLVMContext &llvmContext = Builder.getContext();
399 std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder, funcNode);
402 unsigned sizeOfRet = (unsigned)funcNode->
type().
dim();
403 createAllocaInst(Builder, Type::getDoubleTy(llvmContext), sizeOfRet);
406 unsigned sizeOfFpArgs = 1 + sizeOfRet;
407 unsigned sizeOfStrArgs = 2;
408 for (
int i = 0; i < nargs; ++i) {
410 if (argType.
isFP()) {
415 assert(
false &&
"invalid type encountered");
420 AllocaInst *opDataArg = createAllocaInst(Builder, Type::getInt32Ty(llvmContext), (
unsigned)nargs+4,
"opDataArgPtr");
421 AllocaInst *fpArg = createAllocaInst(Builder, Type::getDoubleTy(llvmContext), sizeOfFpArgs,
"fpArgPtr");
422 AllocaInst *strArg = createAllocaInst(Builder, Type::getInt8PtrTy(llvmContext), sizeOfStrArgs,
"strArgPtr");
424 Builder.CreateStore(ConstantFP::get(Type::getDoubleTy(llvmContext), nargs),fpArg);
425 LLVM_VALUE opDataPtr0 = Builder.CreateConstGEP1_32(opDataArg, 0);
426 Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(llvmContext),0),opDataPtr0);
427 LLVM_VALUE opDataPtr1 = Builder.CreateConstGEP1_32(opDataArg, 1);
428 Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(llvmContext),1),opDataPtr1);
429 LLVM_VALUE opDataPtr2 = Builder.CreateConstGEP1_32(opDataArg, 2);
430 Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(llvmContext),1),opDataPtr2);
431 LLVM_VALUE opDataPtr3 = Builder.CreateConstGEP1_32(opDataArg, 3);
432 Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(llvmContext),0),opDataPtr3);
436 unsigned fpIdx = 1 + sizeOfRet;
437 unsigned strIdx = 1 + 1;
438 for (
int argIndex = 0; argIndex < nargs; ++argIndex) {
439 int opIndex = argIndex + 4;
442 unsigned operand=fpIdx;
443 LLVM_VALUE operandVal = ConstantInt::get(Type::getInt32Ty(llvmContext), operand);
444 LLVM_VALUE opDataPtr = Builder.CreateConstGEP1_32(opDataArg, opIndex);
445 Builder.CreateStore(operandVal, opDataPtr);
447 for(
int comp=0;comp<argType.
dim();comp++){
448 LLVM_VALUE compIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), comp);
449 LLVM_VALUE val = Builder.CreateExtractElement(args[argIndex], compIndex);
450 LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx+comp);
451 Builder.CreateStore(val, fpArgPtr);
453 fpIdx+=argType.
dim();
456 int promote=funcNode->
promote(argIndex);
459 for(
int comp=0;comp<promote;comp++){
460 LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx+comp);
461 Builder.CreateStore(val, fpArgPtr);
465 LLVM_VALUE fpArgPtr = Builder.CreateConstGEP1_32(fpArg, fpIdx);
466 Builder.CreateStore(args[argIndex], fpArgPtr);
471 unsigned operand=strIdx;
472 LLVM_VALUE operandVal = ConstantInt::get(Type::getInt32Ty(llvmContext), operand);
473 LLVM_VALUE opDataPtr = Builder.CreateConstGEP1_32(opDataArg, opIndex);
474 Builder.CreateStore(operandVal, opDataPtr);
475 LLVM_VALUE strArgPtr = Builder.CreateConstGEP1_32(strArg, strIdx);
476 Builder.CreateStore(args[argIndex], strArgPtr);
484 ConstantPointerNull *nullPtrVal = ConstantPointerNull::get(Type::getInt8PtrTy(llvmContext));
485 Module *M = llvm_getModule(Builder);
487 GlobalVariable *dataGV =
488 new GlobalVariable(*M, Type::getInt8PtrTy(llvmContext),
false, GlobalValue::InternalLinkage, nullPtrVal);
490 std::vector<LLVM_VALUE> params;
491 params.push_back(opDataArg);
492 params.push_back(fpArg);
493 params.push_back(strArg);
494 params.push_back(dataGV);
495 ConstantInt *ptrToExprNode = ConstantInt::get(Type::getInt64Ty(llvmContext), (uint64_t)funcNode);
496 params.push_back(ptrToExprNode);
498 Function* callee = llvm_getModule(Builder)->getFunction(
"SeExpr2LLVMEvalCustomFunction");
499 Builder.CreateCall(callee, params);
502 int resultOffset = 1;
503 if (sizeOfRet == 1) {
504 LLVM_VALUE ptr = Builder.CreateConstGEP1_32(fpArg, resultOffset);
505 return Builder.CreateLoad(ptr);
506 }
else if (sizeOfRet > 1) {
507 std::vector<LLVM_VALUE> resultArray;
508 for (
unsigned int comp = 0; comp < sizeOfRet; comp++) {
509 LLVM_VALUE ptr = Builder.CreateConstGEP1_32(fpArg, resultOffset+comp);
510 resultArray.push_back(Builder.CreateLoad(ptr));
512 return createVecVal(Builder, resultArray);
526 Type *srcTy = val->getType();
527 if (srcTy->isVectorTy() || dim <= 1)
return val;
529 assert(srcTy->isDoubleTy());
530 return createVecVal(Builder, val, dim);
534 for (
int i = 0; i < numChildren(); i++) child(i)->codegen(Builder);
540 for (
int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
547 for (
int i = 0; i < numChildren(); i++) lastVal = child(i)->codegen(Builder);
553 return ConstantFP::get(Builder.getContext(), APFloat(_val));
559 std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, c1, c2);
565 return Builder.CreateFAdd(op1, op2);
567 return Builder.CreateFSub(op1, op2);
569 return Builder.CreateFMul(op1, op2);
571 return Builder.CreateFDiv(op1, op2);
576 Function* floorFun = Intrinsic::getDeclaration(llvm_getModule(Builder), Intrinsic::floor, op1->getType());
577 LLVM_VALUE normal = Builder.CreateFSub(a, Builder.CreateFMul(Builder.CreateCall(floorFun, {aOverB}), b));
578 Constant* zero = ConstantFP::get(op1->getType(), 0.0);
579 return Builder.CreateSelect(Builder.CreateFCmpOEQ(zero, op1),
zero, normal);
585 std::vector<Type *> arg_type;
586 arg_type.push_back(op1->getType());
587 Function *fun = Intrinsic::getDeclaration(llvm_getModule(Builder),
Intrinsic::pow, arg_type);
588 std::vector<LLVM_VALUE> ops = {op1, op2};
589 return Builder.CreateCall(fun, ops);
593 assert(
false &&
"unexpected op");
603 const std::string &varName = name();
604 LLVM_VALUE varPtr=_localVar->codegen(Builder,varName,val);
606 Builder.CreateStore(val,varPtr);
612 _varPtr = createAllocaInst(Builder, refValue->getType(), 1, varName);
617 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
618 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
623 boolVal = Builder.CreateFCmpONE(op1, op2);
626 boolVal = Builder.CreateFCmpOEQ(op1, op2);
629 assert(
false &&
"Unkown CompareEq op.");
632 return Builder.CreateUIToFP(boolVal, op1->getType());
636 if (_op ==
'&' || _op ==
'|') {
638 LLVMContext &llvmContext = Builder.getContext();
640 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
641 Type *opTy = op1->getType();
642 Constant *zero = ConstantFP::get(opTy, 0.0);
644 LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
646 Function *F = llvm_getFunction(Builder);
647 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
648 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
649 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
650 Builder.CreateCondBr(op1IsOne, thenBlock, elseBlock);
653 Type *intTy = Type::getInt1Ty(llvmContext);
654 Type *doubleTy = Type::getDoubleTy(llvmContext);
655 llvm::PHINode *phiNode =
nullptr;
658 Builder.SetInsertPoint(thenBlock);
660 op2IsOne = Builder.CreateFCmpUNE(op2, zero);
661 Builder.CreateBr(phiBlock);
662 thenBlock = Builder.GetInsertBlock();
664 Builder.SetInsertPoint(elseBlock);
665 Builder.CreateBr(phiBlock);
666 Builder.SetInsertPoint(phiBlock);
668 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
669 phiNode->addIncoming(op2IsOne, thenBlock);
670 phiNode->addIncoming(op1IsOne, elseBlock);
671 }
else if (_op ==
'|') {
673 Builder.SetInsertPoint(thenBlock);
674 Builder.CreateBr(phiBlock);
676 Builder.SetInsertPoint(elseBlock);
678 op2IsOne = Builder.CreateFCmpUNE(op2, zero);
679 Builder.CreateBr(phiBlock);
680 elseBlock = Builder.GetInsertBlock();
682 Builder.SetInsertPoint(phiBlock);
683 phiNode = Builder.CreatePHI(intTy, 2,
"iftmp");
684 phiNode->addIncoming(op1IsOne, thenBlock);
685 phiNode->addIncoming(op2IsOne, elseBlock);
687 throw std::runtime_error(
"Logical inconsistency.");
689 LLVM_VALUE out = Builder.CreateUIToFP(phiNode, doubleTy);
692 LLVM_VALUE op1 = getFirstElement(child(0)->codegen(Builder), Builder);
693 LLVM_VALUE op2 = getFirstElement(child(1)->codegen(Builder), Builder);
695 Type *opTy = op1->getType();
696 Constant *zero = ConstantFP::get(opTy, 0.0);
701 LLVM_VALUE op1IsOne = Builder.CreateFCmpUNE(op1, zero);
702 LLVM_VALUE op2IsOne = Builder.CreateFCmpUNE(op2, zero);
703 boolVal = Builder.CreateOr(op1IsOne, op2IsOne);
711 boolVal = Builder.CreateFCmpOGE(op1, op2);
714 boolVal = Builder.CreateFCmpOLE(op1, op2);
717 boolVal = Builder.CreateFCmpOGT(op1, op2);
720 boolVal = Builder.CreateFCmpOLT(op1, op2);
723 assert(
false &&
"Unkown Compare op.");
726 return Builder.CreateUIToFP(boolVal, opTy);
732 #if 0 // old non-short circuit
733 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
734 LLVM_VALUE cond = Builder.CreateFCmpUNE(condVal,
735 ConstantFP::get(condVal->getType(), 0.0));
736 LLVM_VALUE trueVal = child(1)->codegen(Builder);
737 LLVM_VALUE falseVal = child(2)->codegen(Builder);
738 std::pair<LLVM_VALUE, LLVM_VALUE> pv = promoteBinaryOperandsToAppropriateVector(Builder, trueVal, falseVal);
739 return Builder.CreateSelect(cond, pv.first, pv.second);
740 #else // new short circuit version
741 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
742 LLVM_VALUE condAsBool = Builder.CreateFCmpUNE(condVal, ConstantFP::get(condVal->getType(), 0.0));
743 LLVMContext &llvmContext = Builder.getContext();
744 Function *F = llvm_getFunction(Builder);
745 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
746 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
747 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
748 Builder.CreateCondBr(condAsBool, thenBlock, elseBlock);
750 Builder.SetInsertPoint(thenBlock);
751 LLVM_VALUE trueVal = promoteOperand(Builder, _type, child(1)->codegen(Builder));
752 Builder.CreateBr(phiBlock);
753 thenBlock = Builder.GetInsertBlock();
755 Builder.SetInsertPoint(elseBlock);
756 LLVM_VALUE falseVal = promoteOperand(Builder, _type, child(2)->codegen(Builder));
757 Builder.CreateBr(phiBlock);
758 elseBlock = Builder.GetInsertBlock();
760 Builder.SetInsertPoint(phiBlock);
761 llvm::PHINode *phiNode = Builder.CreatePHI(trueVal->getType(), 2,
"iftmp");
762 phiNode->addIncoming(trueVal, thenBlock);
763 phiNode->addIncoming(falseVal, elseBlock);
770 LLVMContext &llvmContext = Builder.getContext();
771 Module *M = llvm_getModule(Builder);
772 std::string calleeName(name());
775 Function *callee = M->getFunction(calleeName);
776 if (calleeName ==
"printf") {
778 FunctionType *FT = FunctionType::get(Type::getVoidTy(llvmContext), Type::getInt8PtrTy(llvmContext),
true);
779 callee = Function::Create(FT, GlobalValue::ExternalLinkage,
"printf", llvm_getModule(Builder));
781 return callPrintf(
this, Builder, callee);
783 std::vector<LLVM_VALUE> args =
784 promoteArgs(codegenFuncCallArgs(Builder,
this), Builder, callee->getFunctionType());
785 return Builder.CreateCall(callee, args);
791 if (!standfunc)
return callCustomFunction(
this, Builder);
796 FunctionType *llvmFuncType = getSeExprFuncStandardLLVMType(seFuncType, llvmContext);
798 ConstantInt *funcAddr = ConstantInt::get(Type::getInt64Ty(llvmContext), (uint64_t)fp);
799 LLVM_VALUE addrVal = Builder.CreateIntToPtr(funcAddr, PointerType::getUnqual(llvmFuncType));
802 std::vector<LLVM_VALUE> args = codegenFuncCallArgs(Builder,
this);
803 std::vector<int> argumentIsVectorAndNeedsDistribution(args.size(), 0);
804 Type *maxVectorArgType =
nullptr;
805 if (seFuncType == ExprFuncStandard::FUNCN) {
806 for (
unsigned i = 0; i < args.size(); ++i)
807 if (args[i]->getType()->isVectorTy()) {
808 maxVectorArgType = args[i]->getType();
809 argumentIsVectorAndNeedsDistribution[i] = 1;
811 }
else if (seFuncType == ExprFuncStandard::FUNCNV || seFuncType == ExprFuncStandard::FUNCNVV) {
814 unsigned shift = isReturnVector(seFuncType) ? 1 : 0;
815 for (
unsigned i = 0; i < args.size(); ++i) {
816 Type *paramType = llvmFuncType->getParamType(i + shift);
817 Type *argType = args[i]->getType();
818 if (argType->isVectorTy() && paramType->isDoubleTy()) {
819 maxVectorArgType = args[i]->getType();
820 argumentIsVectorAndNeedsDistribution[i] = 1;
825 if (!maxVectorArgType)
826 return executeStandardFunction(Builder, seFuncType, args, addrVal);
828 assert(maxVectorArgType->isVectorTy());
830 std::vector<LLVM_VALUE> ret;
831 for (
unsigned vecComponent = 0; vecComponent < maxVectorArgType->getVectorNumElements(); ++vecComponent) {
832 LLVM_VALUE idx = ConstantInt::get(Type::getInt32Ty(llvmContext), vecComponent);
833 std::vector<LLVM_VALUE> realArgs;
836 for (
unsigned argIndex = 0; argIndex < args.size(); ++argIndex) {
838 if (argumentIsVectorAndNeedsDistribution[argIndex]) {
839 if (args[argIndex]->getType()->isPointerTy())
840 realArg = Builder.CreateLoad(Builder.CreateConstGEP2_32(
nullptr, args[argIndex], 0, vecComponent));
842 realArg = Builder.CreateExtractElement(args[argIndex], idx);
844 realArgs.push_back(realArg);
846 ret.push_back(executeStandardFunction(Builder, seFuncType, realArgs, addrVal));
848 return createVecVal(Builder, ret);
852 LLVM_VALUE condVal = getFirstElement(child(0)->codegen(Builder), Builder);
853 Type *condTy = condVal->getType();
855 LLVMContext &llvmContext = Builder.getContext();
857 Constant *zero = ConstantFP::get(condTy, 0.0);
858 LLVM_VALUE intCond = Builder.CreateFCmpUNE(condVal, zero);
860 Function *F = llvm_getFunction(Builder);
861 BasicBlock *thenBlock = BasicBlock::Create(llvmContext,
"then", F);
862 BasicBlock *elseBlock = BasicBlock::Create(llvmContext,
"else", F);
863 BasicBlock *phiBlock = BasicBlock::Create(llvmContext,
"phi", F);
864 Builder.CreateCondBr(intCond, thenBlock, elseBlock);
866 Builder.SetInsertPoint(thenBlock);
867 child(1)->codegen(Builder);
868 thenBlock = Builder.GetInsertBlock();
870 Builder.SetInsertPoint(elseBlock);
871 child(2)->codegen(Builder);
872 elseBlock = Builder.GetInsertBlock();
878 Builder.SetInsertPoint(phiBlock);
879 const auto& merges=_varEnv->merge(_varEnvMergeIndex);
880 std::vector<LLVM_VALUE> phis;phis.reserve(merges.size());
881 for(
auto&
it:merges){
883 if(finalVar->
valid()){
885 Builder.SetInsertPoint(thenBlock);
887 Builder.SetInsertPoint(elseBlock);
890 Type* finalType=thenValue->getType();
891 Builder.SetInsertPoint(phiBlock);
892 PHINode* phi=Builder.CreatePHI(finalType,2,
it.first);
893 phi->addIncoming(thenValue, thenBlock);
894 phi->addIncoming(elseValue, elseBlock);
900 for(
auto&
it:_varEnv->merge(_varEnvMergeIndex)){
901 const std::string& name=
it.first;
903 if(finalVar->
valid()){
905 Builder.CreateStore(phis[idx++],_finalVarPtr);
909 Builder.SetInsertPoint(thenBlock);
910 Builder.CreateBr(phiBlock);
911 Builder.SetInsertPoint(elseBlock);
912 Builder.CreateBr(phiBlock);
914 Builder.SetInsertPoint(phiBlock);
920 IRBuilder<>::InsertPoint oldIP = Builder.saveIP();
921 LLVMContext &llvmContext = Builder.getContext();
924 Function *F = cast<Function>(child(0)->codegen(Builder));
927 BasicBlock *BB = BasicBlock::Create(llvmContext,
"entry", F);
928 Builder.SetInsertPoint(BB);
929 Function::arg_iterator AI = F->arg_begin();
930 for (
int i = 0, e = F->arg_size(); i != e; ++i, ++AI) {
931 AllocaInst *Alloca = createAllocaInst(Builder, AI->getType(), 1, AI->getName());
932 Alloca->takeName(&*AI);
933 Builder.CreateStore(&*AI, Alloca);
937 for (
int i = 1; i < numChildren(); i++) result = child(i)->codegen(Builder);
939 Builder.CreateRet(result);
940 Builder.restoreIP(oldIP);
945 LLVMContext &llvmContext = Builder.getContext();
948 std::vector<Type *> ParamTys;
949 for (
int i = 0; i < numChildren(); ++i) ParamTys.push_back(createLLVMTyForSeExprType(llvmContext, argType(i)));
951 Type *retTy = createLLVMTyForSeExprType(llvmContext, returnType());
953 FunctionType *FT = FunctionType::get(retTy, ParamTys,
false);
954 Function *F = Function::Create(FT, GlobalValue::InternalLinkage, name(), llvm_getModule(Builder));
957 auto AI = F->arg_begin();
958 for (
int i = 0, e = numChildren(); i != e; ++i, ++AI) {
961 AI->setName(childNode->
name());
973 if (op1->getType()->isDoubleTy())
return op1;
975 LLVMContext &llvmContext = Builder.getContext();
976 LLVM_VALUE idx = Builder.CreateFPToUI(op2, Type::getInt32Ty(llvmContext));
977 return Builder.CreateExtractElement(op1, idx);
982 Type *op1Ty = op1->getType();
983 Constant *negateZero = ConstantFP::getZeroValueForNegation(op1Ty);
984 Constant *zero = ConstantFP::get(op1Ty, 0.0);
985 Constant *one = ConstantFP::get(op1Ty, 1.0);
989 return Builder.CreateFSub(negateZero, op1);
991 LLVM_VALUE neg = Builder.CreateFSub(negateZero, op1);
992 return Builder.CreateFAdd(neg, one);
995 LLVM_VALUE eqZero = Builder.CreateFCmpOEQ(zero, op1);
996 return Builder.CreateSelect(eqZero, one, zero);
1000 assert(
false &&
"not implemented.");
1005 struct VarCodeGeneration {
1007 LLVMContext &llvmContext = Builder.getContext();
1008 Type *voidPtrType = Type::getInt8PtrTy(llvmContext);
1009 Type *doubleTy = Type::getDoubleTy(llvmContext);
1010 ConstantInt *varAddr = ConstantInt::get(Type::getInt64Ty(llvmContext), (uint64_t)varRef);
1011 LLVM_VALUE addrVal = Builder.CreateIntToPtr(varAddr, voidPtrType);
1012 Function *evalVarFunc = llvm_getModule(Builder)->getFunction(
"SeExpr2LLVMEvalVarRef");
1014 int dim = varRef->
type().
dim();
1015 AllocaInst *varAlloca = createAllocaInst(Builder, doubleTy, dim);
1017 Builder.CreateCall(evalVarFunc, params);
1021 ret = Builder.CreateLoad(varAlloca);
1024 assert(dim == 3 &&
"future work.");
1025 ret = createVecValFromAlloca(Builder, varAlloca, dim);
1028 AllocaInst *thisvar = createAllocaInst(Builder, ret->getType(), 1, varName);
1029 Builder.CreateStore(ret, thisvar);
1034 LLVMContext &llvmContext = Builder.getContext();
1036 int variableOffset = varRef->
offset();
1037 int variableStride = varRef->
stride();
1038 Function *
function = llvm_getFunction(Builder);
1039 auto argIterator =
function->arg_begin();
1041 llvm::Argument *variableBlock = &*(argIterator++);
1042 llvm::Argument *indirectIndex = &*(argIterator++);
1044 int dim = varRef->
type().
dim();
1046 Type *ptrToPtrTy = variableBlock->getType();
1047 Value *variableBlockAsPtrPtr = Builder.CreatePointerCast(variableBlock, ptrToPtrTy);
1048 Value *variableOffsetIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), variableOffset);
1049 Value *variableBlockIndirectPtrPtr = Builder.CreateInBoundsGEP(variableBlockAsPtrPtr, variableOffsetIndex);
1050 Value *baseMemory = Builder.CreateLoad(variableBlockIndirectPtrPtr);
1051 Value *variableStrideValue = ConstantInt::get(Type::getInt32Ty(llvmContext), variableStride);
1054 Value *variablePointer =
1055 varRef->
type().
isLifetimeUniform() ? baseMemory : Builder.CreateInBoundsGEP(baseMemory, indirectIndex);
1056 return Builder.CreateLoad(variablePointer);
1058 std::vector<Value *> loadedValues(3);
1059 for (
int component = 0; component < dim; component++) {
1060 Value *componentIndex = ConstantInt::get(Type::getInt32Ty(llvmContext), component);
1062 Value *variablePointer =
1064 ? Builder.CreateInBoundsGEP(Type::getDoubleTy(llvmContext), baseMemory, componentIndex)
1065 : Builder.CreateInBoundsGEP(
1066 Type::getDoubleTy(llvmContext),
1068 Builder.CreateAdd(Builder.CreateMul(indirectIndex, variableStrideValue), componentIndex));
1069 loadedValues[component] = Builder.CreateLoad(variablePointer, varName);
1071 return createVecVal(Builder, loadedValues, varName);
1081 std::string varName(
"external_");
1082 varName.append(name());
1086 return VarCodeGeneration::codegen(varBlockRef, varName, Builder);
1088 return VarCodeGeneration::codegen(_var, varName, Builder);
1089 }
else if (_localVar) {
1094 assert(varPtr &&
"can not found symbol?");
1095 return Builder.CreateLoad(varPtr);
1104 std::vector<LLVM_VALUE> elems;
1105 ConstantInt *zero = ConstantInt::get(Type::getInt32Ty(Builder.getContext()), 0);
1106 for (
int i = 0; i < numChildren(); i++) {
1108 elems.push_back(val->getType()->isVectorTy() ? Builder.CreateExtractElement(val, zero) : val);
1110 return createVecVal(Builder, elems);
const ExprType & type() const
The type of the node.
const char * name() const
bool isFP() const
Direct is predicate checks.
Node that references a variable.
ExprType type() const
returns type of the variable
When fbmScale is zero(the default)
void * getFuncPointer() const
Node that stores a string.
virtual LLVM_VALUE codegen(LLVM_BUILDER) LLVM_BODY
double max(double x, double y)
Node that calls a function.
bool isLifetimeUniform() const
< br > pow($a, 0.5)+$b< br >< br ></div > External variables can also be overridden by local assignment. 
virtual LLVM_VALUE codegen(LLVM_BUILDER, const std::string &name, LLVM_VALUE referenceType) LLVM_BODY
LLVM value that has been allocated.
int numChildren() const
Number of children.
void SeExpr2LLVMEvalVarRef(SeExpr2::ExprVarRef *seVR, double *result)
virtual LLVM_VALUE varPtr()
LLVM value that has been pre-done.
Internally implemented var ref used by SeExpr.
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this...
const ExprNode * child(size_t i) const
Get 0 indexed child.
virtual ExprType type() const
returns (current) type
virtual void eval(double *result)=0
returns this variable's value by setting result
FuncType getFuncType() const
you may not use this file except in compliance with the License and the following modification to it
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
abstract class for implementing variable references