Skip to content

Commit 60ae176

Browse files
committed
LLVMCodeBuilder: Implement sin operator
1 parent 34d5c42 commit 60ae176

File tree

5 files changed

+72
-0
lines changed

5 files changed

+72
-0
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ICodeBuilder
4343
virtual void createFloor() = 0;
4444
virtual void createCeil() = 0;
4545
virtual void createSqrt() = 0;
46+
virtual void createSin() = 0;
4647

4748
virtual void beginIfStatement() = 0;
4849
virtual void beginElseBranch() = 0;

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,24 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
250250
break;
251251
}
252252

253+
case Step::Type::Sin: {
254+
assert(step.args.size() == 1);
255+
const auto &arg = step.args[0];
256+
// round(sin(x * pi / 180.0) * 1e10) / 1e10 + 0.0
257+
// +0.0 to avoid -0.0
258+
llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0));
259+
llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0)));
260+
llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0));
261+
llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10));
262+
llvm::Function *sinFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::sin, m_builder.getDoubleTy());
263+
llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy());
264+
llvm::Value *num = removeNaN(castValue(arg.second, arg.first));
265+
llvm::Value *sinResult = m_builder.CreateCall(sinFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // sin(x * pi / 180)
266+
llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(sinResult, factor)); // round(sin(x * 180) * 1e10)
267+
step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateFDiv(rounded, factor), zero);
268+
break;
269+
}
270+
253271
case Step::Type::Yield:
254272
if (!m_warp) {
255273
freeHeap();
@@ -648,6 +666,11 @@ void LLVMCodeBuilder::createSqrt()
648666
createOp(Step::Type::Sqrt, Compiler::StaticType::Number, Compiler::StaticType::Number, 1);
649667
}
650668

669+
void LLVMCodeBuilder::createSin()
670+
{
671+
createOp(Step::Type::Sin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1);
672+
}
673+
651674
void LLVMCodeBuilder::beginIfStatement()
652675
{
653676
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
@@ -45,6 +45,7 @@ class LLVMCodeBuilder : public ICodeBuilder
4545
void createFloor() override;
4646
void createCeil() override;
4747
void createSqrt() override;
48+
void createSin() override;
4849

4950
void beginIfStatement() override;
5051
void beginElseBranch() override;
@@ -94,6 +95,7 @@ class LLVMCodeBuilder : public ICodeBuilder
9495
Floor,
9596
Ceil,
9697
Sqrt,
98+
Sin,
9799
Yield,
98100
BeginIf,
99101
BeginElse,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,51 @@ TEST_F(LLVMCodeBuilderTest, Sqrt)
13221322
addOpTest(nan, 0);
13231323
}
13241324

1325+
TEST_F(LLVMCodeBuilderTest, Sin)
1326+
{
1327+
std::string expected;
1328+
1329+
auto addOpTest = [this, &expected](Value v1, double expectedResult) {
1330+
createBuilder(true);
1331+
1332+
m_builder->addConstValue(v1);
1333+
m_builder->createSin();
1334+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1335+
1336+
m_builder->addConstValue(v1);
1337+
m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number });
1338+
m_builder->createSin();
1339+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1340+
1341+
std::stringstream stream;
1342+
stream << expectedResult;
1343+
std::string str = stream.str() + '\n';
1344+
std::string expected = str + str;
1345+
1346+
auto code = m_builder->finalize();
1347+
auto ctx = code->createExecutionContext(&m_target);
1348+
1349+
testing::internal::CaptureStdout();
1350+
code->run(ctx.get());
1351+
const std::string quotes1 = v1.isString() ? "\"" : "";
1352+
ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1;
1353+
};
1354+
1355+
static const double inf = std::numeric_limits<double>::infinity();
1356+
static const double nan = std::numeric_limits<double>::quiet_NaN();
1357+
1358+
addOpTest(30.0, 0.5);
1359+
addOpTest(90.0, 1.0);
1360+
addOpTest(570.0, -0.5);
1361+
addOpTest(-30.0, -0.5);
1362+
addOpTest(-90.0, -1.0);
1363+
addOpTest(0.0, 0.0);
1364+
addOpTest(-0.0, 0.0);
1365+
addOpTest(inf, -nan); // negative NaN shouldn't be a problem
1366+
addOpTest(-inf, -nan);
1367+
addOpTest(nan, 0);
1368+
}
1369+
13251370
TEST_F(LLVMCodeBuilderTest, Yield)
13261371
{
13271372
auto build = [this]() {

test/mocks/codebuildermock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class CodeBuilderMock : public ICodeBuilder
3333
MOCK_METHOD(void, createFloor, (), (override));
3434
MOCK_METHOD(void, createCeil, (), (override));
3535
MOCK_METHOD(void, createSqrt, (), (override));
36+
MOCK_METHOD(void, createSin, (), (override));
3637

3738
MOCK_METHOD(void, beginIfStatement, (), (override));
3839
MOCK_METHOD(void, beginElseBranch, (), (override));

0 commit comments

Comments
 (0)