<commit_before>#include "Arith256.h"

#include <iostream>
#include <iomanip>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "Type.h"
#include "Endianness.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

Arith256::Arith256(llvm::IRBuilder<>& _builder) :
	CompilerHelper(_builder)
{}

void Arith256::debug(llvm::Value* _value, char _c)
{
	if (!m_debug)
	{
		llvm::Type* argTypes[] = {Type::Word, m_builder.getInt8Ty()};
		m_debug = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "debug", getModule());
	}
	createCall(m_debug, {m_builder.CreateZExtOrTrunc(_value, Type::Word), m_builder.getInt8(_c)});
}

llvm::Function* Arith256::getMulFunc(llvm::Module& _module)
{
	static const auto funcName = "evm.mul.i256";
	if (auto func = _module.getFunction(funcName))
		return func;

	llvm::Type* argTypes[] = {Type::Word, Type::Word};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto y = x->getNextNode();
	y->setName("y");

	auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
	auto builder = llvm::IRBuilder<>{bb};
	auto i64 = Type::Size;
	auto i128 = builder.getIntNTy(128);
	auto i256 = Type::Word;
	auto c64 = Constant::get(64);
	auto c128 = Constant::get(128);
	auto c192 = Constant::get(192);

	auto x_lo = builder.CreateTrunc(x, i64, "x.lo");
	auto y_lo = builder.CreateTrunc(y, i64, "y.lo");
	auto x_mi = builder.CreateTrunc(builder.CreateLShr(x, c64), i64);
	auto y_mi = builder.CreateTrunc(builder.CreateLShr(y, c64), i64);
	auto x_hi = builder.CreateTrunc(builder.CreateLShr(x, c128), i128);
	auto y_hi = builder.CreateTrunc(builder.CreateLShr(y, c128), i128);

	auto t1 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_lo, i128));
	auto t2 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_mi, i128));
	auto t3 = builder.CreateMul(builder.CreateZExt(x_lo, i128), y_hi);
	auto t4 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_lo, i128));
	auto t5 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_mi, i128));
	auto t6 = builder.CreateMul(builder.CreateZExt(x_mi, i128), y_hi);
	auto t7 = builder.CreateMul(x_hi, builder.CreateZExt(y_lo, i128));
	auto t8 = builder.CreateMul(x_hi, builder.CreateZExt(y_mi, i128));

	auto p = builder.CreateZExt(t1, i256);
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i256), c64));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i256), c64));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t5, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t6, i256), c192));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t7, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t8, i256), c192));
	builder.CreateRet(p);
	return func;
}

llvm::Function* Arith256::getMul512Func(llvm::Module& _module)
{
	static const auto funcName = "evm.mul.i512";
	if (auto func = _module.getFunction(funcName))
		return func;

	auto i512Ty = llvm::IntegerType::get(_module.getContext(), 512);
	auto func = llvm::Function::Create(llvm::FunctionType::get(i512Ty, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto y = x->getNextNode();
	y->setName("y");

	auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
	auto builder = llvm::IRBuilder<>{bb};

	auto i128 = builder.getIntNTy(128);
	auto i256 = Type::Word;
	auto x_lo = builder.CreateZExt(builder.CreateTrunc(x, i128, "x.lo"), i256);
	auto y_lo = builder.CreateZExt(builder.CreateTrunc(y, i128, "y.lo"), i256);
	auto x_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(x, Constant::get(128)), i128, "x.hi"), i256);
	auto y_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(y, Constant::get(128)), i128, "y.hi"), i256);

	auto mul256Func = getMulFunc(_module);
	auto t1 = builder.CreateCall(mul256Func, {x_lo, y_lo});
	auto t2 = builder.CreateCall(mul256Func, {x_lo, y_hi});
	auto t3 = builder.CreateCall(mul256Func, {x_hi, y_lo});
	auto t4 = builder.CreateCall(mul256Func, {x_hi, y_hi});

	auto p = builder.CreateZExt(t1, i512Ty);
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i512Ty), builder.getIntN(512, 128)));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i512Ty), builder.getIntN(512, 128)));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i512Ty), builder.getIntN(512, 256)));
	builder.CreateRet(p);

	return func;
}

namespace
{
llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName)
{
	// Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research
	// The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder

	auto retType = llvm::VectorType::get(_type, 2);
	auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {_type, _type}, false), llvm::Function::PrivateLinkage, _funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto zero = llvm::ConstantInt::get(_type, 0);
	auto one = llvm::ConstantInt::get(_type, 1);

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto yArg = x->getNextNode();
	yArg->setName("y");

	auto entryBB = llvm::BasicBlock::Create(_module.getContext(), "Entry", func);
	auto mainBB = llvm::BasicBlock::Create(_module.getContext(), "Main", func);
	auto loopBB = llvm::BasicBlock::Create(_module.getContext(), "Loop", func);
	auto continueBB = llvm::BasicBlock::Create(_module.getContext(), "Continue", func);
	auto returnBB = llvm::BasicBlock::Create(_module.getContext(), "Return", func);

	auto builder = llvm::IRBuilder<>{entryBB};
	auto yNonZero = builder.CreateICmpNE(yArg, zero);
	auto yLEx = builder.CreateICmpULE(yArg, x);
	auto r0 = builder.CreateSelect(yNonZero, x, zero, "r0");
	builder.CreateCondBr(builder.CreateAnd(yLEx, yNonZero), mainBB, returnBB);

	builder.SetInsertPoint(mainBB);<commit_msg>Remove div by 0 check in udivrem implementation.<commit_after>#include "Arith256.h"

#include <iostream>
#include <iomanip>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "Type.h"
#include "Endianness.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

Arith256::Arith256(llvm::IRBuilder<>& _builder) :
	CompilerHelper(_builder)
{}

void Arith256::debug(llvm::Value* _value, char _c)
{
	if (!m_debug)
	{
		llvm::Type* argTypes[] = {Type::Word, m_builder.getInt8Ty()};
		m_debug = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "debug", getModule());
	}
	createCall(m_debug, {m_builder.CreateZExtOrTrunc(_value, Type::Word), m_builder.getInt8(_c)});
}

llvm::Function* Arith256::getMulFunc(llvm::Module& _module)
{
	static const auto funcName = "evm.mul.i256";
	if (auto func = _module.getFunction(funcName))
		return func;

	llvm::Type* argTypes[] = {Type::Word, Type::Word};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto y = x->getNextNode();
	y->setName("y");

	auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
	auto builder = llvm::IRBuilder<>{bb};
	auto i64 = Type::Size;
	auto i128 = builder.getIntNTy(128);
	auto i256 = Type::Word;
	auto c64 = Constant::get(64);
	auto c128 = Constant::get(128);
	auto c192 = Constant::get(192);

	auto x_lo = builder.CreateTrunc(x, i64, "x.lo");
	auto y_lo = builder.CreateTrunc(y, i64, "y.lo");
	auto x_mi = builder.CreateTrunc(builder.CreateLShr(x, c64), i64);
	auto y_mi = builder.CreateTrunc(builder.CreateLShr(y, c64), i64);
	auto x_hi = builder.CreateTrunc(builder.CreateLShr(x, c128), i128);
	auto y_hi = builder.CreateTrunc(builder.CreateLShr(y, c128), i128);

	auto t1 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_lo, i128));
	auto t2 = builder.CreateMul(builder.CreateZExt(x_lo, i128), builder.CreateZExt(y_mi, i128));
	auto t3 = builder.CreateMul(builder.CreateZExt(x_lo, i128), y_hi);
	auto t4 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_lo, i128));
	auto t5 = builder.CreateMul(builder.CreateZExt(x_mi, i128), builder.CreateZExt(y_mi, i128));
	auto t6 = builder.CreateMul(builder.CreateZExt(x_mi, i128), y_hi);
	auto t7 = builder.CreateMul(x_hi, builder.CreateZExt(y_lo, i128));
	auto t8 = builder.CreateMul(x_hi, builder.CreateZExt(y_mi, i128));

	auto p = builder.CreateZExt(t1, i256);
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i256), c64));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i256), c64));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t5, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t6, i256), c192));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t7, i256), c128));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t8, i256), c192));
	builder.CreateRet(p);
	return func;
}

llvm::Function* Arith256::getMul512Func(llvm::Module& _module)
{
	static const auto funcName = "evm.mul.i512";
	if (auto func = _module.getFunction(funcName))
		return func;

	auto i512Ty = llvm::IntegerType::get(_module.getContext(), 512);
	auto func = llvm::Function::Create(llvm::FunctionType::get(i512Ty, {Type::Word, Type::Word}, false), llvm::Function::PrivateLinkage, funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto y = x->getNextNode();
	y->setName("y");

	auto bb = llvm::BasicBlock::Create(_module.getContext(), {}, func);
	auto builder = llvm::IRBuilder<>{bb};

	auto i128 = builder.getIntNTy(128);
	auto i256 = Type::Word;
	auto x_lo = builder.CreateZExt(builder.CreateTrunc(x, i128, "x.lo"), i256);
	auto y_lo = builder.CreateZExt(builder.CreateTrunc(y, i128, "y.lo"), i256);
	auto x_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(x, Constant::get(128)), i128, "x.hi"), i256);
	auto y_hi = builder.CreateZExt(builder.CreateTrunc(builder.CreateLShr(y, Constant::get(128)), i128, "y.hi"), i256);

	auto mul256Func = getMulFunc(_module);
	auto t1 = builder.CreateCall(mul256Func, {x_lo, y_lo});
	auto t2 = builder.CreateCall(mul256Func, {x_lo, y_hi});
	auto t3 = builder.CreateCall(mul256Func, {x_hi, y_lo});
	auto t4 = builder.CreateCall(mul256Func, {x_hi, y_hi});

	auto p = builder.CreateZExt(t1, i512Ty);
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t2, i512Ty), builder.getIntN(512, 128)));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t3, i512Ty), builder.getIntN(512, 128)));
	p = builder.CreateAdd(p, builder.CreateShl(builder.CreateZExt(t4, i512Ty), builder.getIntN(512, 256)));
	builder.CreateRet(p);

	return func;
}

namespace
{
llvm::Function* createUDivRemFunc(llvm::Type* _type, llvm::Module& _module, char const* _funcName)
{
	// Based of "Improved shift divisor algorithm" from "Software Integer Division" by Microsoft Research
	// The following algorithm also handles divisor of value 0 returning 0 for both quotient and reminder

	auto retType = llvm::VectorType::get(_type, 2);
	auto func = llvm::Function::Create(llvm::FunctionType::get(retType, {_type, _type}, false), llvm::Function::PrivateLinkage, _funcName, &_module);
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory();

	auto zero = llvm::ConstantInt::get(_type, 0);
	auto one = llvm::ConstantInt::get(_type, 1);

	auto x = &func->getArgumentList().front();
	x->setName("x");
	auto yArg = x->getNextNode();
	yArg->setName("y");

	auto entryBB = llvm::BasicBlock::Create(_module.getContext(), "Entry", func);
	auto mainBB = llvm::BasicBlock::Create(_module.getContext(), "Main", func);
	auto loopBB = llvm::BasicBlock::Create(_module.getContext(), "Loop", func);
	auto continueBB = llvm::BasicBlock::Create(_module.getContext(), "Continue", func);
	auto returnBB = llvm::BasicBlock::Create(_module.getContext(), "Return", func);

	auto builder = llvm::IRBuilder<>{entryBB};
	auto yLEx = builder.CreateICmpULE(yArg, x);
	auto r0 = x;
	builder.CreateCondBr(yLEx, mainBB, returnBB);

	builder.SetInsertPoint(mainBB);
{'fraction_non_alphanumeric': 0.16901730578638408, 'fraction_numerical': 0.04315011054356942, 'mean_word_length': 6.752955082742317, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2605492', 'n_tokens_mistral': 5174, 'n_tokens_neox': 4844, 'n_words': 934}