Skip to content

Commit ba6a97b

Browse files
committed
LLVMCodeBuilder: Implement round operator
1 parent 5e1e3b6 commit ba6a97b

File tree

5 files changed

+74
-0
lines changed

5 files changed

+74
-0
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class ICodeBuilder
3838
virtual void createNot() = 0;
3939

4040
virtual void createMod() = 0;
41+
virtual void createRound() = 0;
4142

4243
virtual void beginIfStatement() = 0;
4344
virtual void beginElseBranch() = 0;

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,23 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
194194
break;
195195
}
196196

197+
case Step::Type::Round: {
198+
assert(step.args.size() == 1);
199+
const auto &arg = step.args[0];
200+
// x >= 0.0 ? round(x) : (x >= -0.5 ? -0.0 : floor(x + 0.5))
201+
llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0));
202+
llvm::Constant *negativeZero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.0));
203+
llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy());
204+
llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::floor, m_builder.getDoubleTy());
205+
llvm::Value *num = removeNaN(castValue(arg.second, arg.first));
206+
llvm::Value *notNegative = m_builder.CreateFCmpOGE(num, zero); // num >= 0.0
207+
llvm::Value *roundNum = m_builder.CreateCall(roundFunc, num); // round(num)
208+
llvm::Value *negativeCond = m_builder.CreateFCmpOGE(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.5))); // num >= -0.5
209+
llvm::Value *negativeRound = m_builder.CreateCall(floorFunc, m_builder.CreateFAdd(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.5)))); // floor(x + 0.5)
210+
step.functionReturnReg->value = m_builder.CreateSelect(notNegative, roundNum, m_builder.CreateSelect(negativeCond, negativeZero, negativeRound));
211+
break;
212+
}
213+
197214
case Step::Type::Yield:
198215
if (!m_warp) {
199216
freeHeap();
@@ -567,6 +584,11 @@ void LLVMCodeBuilder::createMod()
567584
createOp(Step::Type::Mod, Compiler::StaticType::Number, Compiler::StaticType::Number, 2);
568585
}
569586

587+
void LLVMCodeBuilder::createRound()
588+
{
589+
createOp(Step::Type::Round, Compiler::StaticType::Number, Compiler::StaticType::Number, 1);
590+
}
591+
570592
void LLVMCodeBuilder::beginIfStatement()
571593
{
572594
Step step(Step::Type::BeginIf);

src/dev/engine/internal/llvmcodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class LLVMCodeBuilder : public ICodeBuilder
4040
void createNot() override;
4141

4242
void createMod() override;
43+
void createRound() override;
4344

4445
void beginIfStatement() override;
4546
void beginElseBranch() override;
@@ -84,6 +85,7 @@ class LLVMCodeBuilder : public ICodeBuilder
8485
Or,
8586
Not,
8687
Mod,
88+
Round,
8789
Yield,
8890
BeginIf,
8991
BeginElse,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,54 @@ TEST_F(LLVMCodeBuilderTest, Mod)
10851085
addOpTest("NaN", -5);
10861086
}
10871087

1088+
TEST_F(LLVMCodeBuilderTest, Round)
1089+
{
1090+
std::string expected;
1091+
1092+
auto addOpTest = [this, &expected](Value v1, double expectedResult) {
1093+
createBuilder(true);
1094+
1095+
m_builder->addConstValue(v1);
1096+
m_builder->createRound();
1097+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1098+
1099+
m_builder->addConstValue(v1);
1100+
m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number });
1101+
m_builder->createRound();
1102+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1103+
1104+
std::stringstream stream;
1105+
stream << expectedResult;
1106+
std::string str = stream.str() + '\n';
1107+
std::string expected = str + str;
1108+
1109+
auto code = m_builder->finalize();
1110+
auto ctx = code->createExecutionContext(&m_target);
1111+
1112+
testing::internal::CaptureStdout();
1113+
code->run(ctx.get());
1114+
const std::string quotes1 = v1.isString() ? "\"" : "";
1115+
ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1;
1116+
};
1117+
1118+
static const double inf = std::numeric_limits<double>::infinity();
1119+
static const double nan = std::numeric_limits<double>::quiet_NaN();
1120+
1121+
addOpTest(4.0, 4.0);
1122+
addOpTest(3.2, 3.0);
1123+
addOpTest(3.5, 4.0);
1124+
addOpTest(3.6, 4.0);
1125+
addOpTest(-2.4, -2.0);
1126+
addOpTest(-2.5, -2.0);
1127+
addOpTest(-2.6, -3.0);
1128+
addOpTest(-0.4, -0.0);
1129+
addOpTest(-0.5, -0.0);
1130+
addOpTest(-0.51, -1.0);
1131+
addOpTest(inf, inf);
1132+
addOpTest(-inf, -inf);
1133+
addOpTest(nan, 0);
1134+
}
1135+
10881136
TEST_F(LLVMCodeBuilderTest, Yield)
10891137
{
10901138
auto build = [this]() {

test/mocks/codebuildermock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CodeBuilderMock : public ICodeBuilder
2828
MOCK_METHOD(void, createNot, (), (override));
2929

3030
MOCK_METHOD(void, createMod, (), (override));
31+
MOCK_METHOD(void, createRound, (), (override));
3132

3233
MOCK_METHOD(void, beginIfStatement, (), (override));
3334
MOCK_METHOD(void, beginElseBranch, (), (override));

0 commit comments

Comments
 (0)