diff --git a/tools/clang/include/clang/Basic/BuiltinsX86.def b/tools/clang/include/clang/Basic/BuiltinsX86.def index cfa38fb..5de5792 100644 --- a/tools/clang/include/clang/Basic/BuiltinsX86.def +++ b/tools/clang/include/clang/Basic/BuiltinsX86.def @@ -746,4 +746,6 @@ BUILTIN(__builtin_ia32_xend, "v", "") BUILTIN(__builtin_ia32_xabort, "vIc", "") BUILTIN(__builtin_ia32_xtest, "i", "") +BUILTIN(__factorial, "UiUi", "n") + #undef BUILTIN diff --git a/tools/clang/lib/CodeGen/CGBuiltin.cpp b/tools/clang/lib/CodeGen/CGBuiltin.cpp index 7ad4492..1660f18 100644 --- a/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ b/tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -3256,6 +3256,44 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *F = CGM.getIntrinsic(Intrinsic::x86_avx2_vbroadcasti128); return Builder.CreateCall(F, Builder.CreateBitCast(VecTmp, Int8PtrTy)); } + case X86::BI__factorial: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + llvm::Type* a_t = ArgValue->getType(); + BasicBlock* preloop = Builder.GetInsertBlock(); + Function* curFun = preloop->getParent(); + BasicBlock* loop = BasicBlock::Create(getGlobalContext(), "fact_loop", curFun); + BasicBlock* after = BasicBlock::Create(getGlobalContext(), "finished", curFun); + + // Temporarily move the insert point to the top of the function to ensure + // that the alloca is in the entry block. + IRBuilder<> TmpB(&curFun->getEntryBlock(), curFun->getEntryBlock().begin()); + Value* tmp = TmpB.CreateAlloca(a_t, 0, "tmp"); + Value* arg = TmpB.CreateAlloca(a_t, 0, "arg"); + // back to the plot. + unsigned bs = a_t->getIntegerBitWidth(); + ConstantInt* one = Builder.getInt(APInt(bs, 1)); + Value *in_test = Builder.CreateICmpULE(ArgValue, one, "nothing.to.do"); + Value *init = Builder.CreateSelect(in_test, one, ArgValue, "init.res"); + Builder.CreateStore(init, arg); + Builder.CreateStore(ArgValue, tmp); + Builder.CreateCondBr(in_test, after, loop); + + // factorial loop. + Builder.SetInsertPoint(loop); + Value *dec = Builder.CreateLoad(tmp, "tmp.load"); + Value *dm1 = Builder.CreateSub(dec, one, "tmp.dec"); + Builder.CreateStore(dm1, tmp); + Value *fact = Builder.CreateLoad(arg, "fact.load"); + Value *prod = Builder.CreateMul(fact, dm1, "fact.prod"); + Builder.CreateStore(prod, arg); + Value *out_test = Builder.CreateICmpULE(dm1, one, "done"); + Builder.CreateCondBr(out_test, after, loop); + + // out. + Builder.SetInsertPoint(after); + Value *res = Builder.CreateLoad(arg, "result"); + return res; + } } }