Skip to content

Commit a2c9eeb

Browse files
committed
LLVMCodeBuilder: Implement greater than comparison
1 parent cdbba2e commit a2c9eeb

File tree

4 files changed

+226
-5
lines changed

4 files changed

+226
-5
lines changed

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,14 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
136136
break;
137137
}
138138

139+
case Step::Type::CmpGT: {
140+
assert(step.args.size() == 2);
141+
const auto &arg1 = step.args[0].second;
142+
const auto &arg2 = step.args[1].second;
143+
step.functionReturnReg->value = createComparison(arg1, arg2, Comparison::GT);
144+
break;
145+
}
146+
139147
case Step::Type::Yield:
140148
if (!m_warp) {
141149
freeHeap();
@@ -479,6 +487,11 @@ void LLVMCodeBuilder::createCmpEQ()
479487
createOp(Step::Type::CmpEQ, Compiler::StaticType::Bool, 2);
480488
}
481489

490+
void LLVMCodeBuilder::createCmpGT()
491+
{
492+
createOp(Step::Type::CmpGT, Compiler::StaticType::Bool, 2);
493+
}
494+
482495
void LLVMCodeBuilder::beginIfStatement()
483496
{
484497
Step step(Step::Type::BeginIf);
@@ -955,11 +968,17 @@ llvm::Value *LLVMCodeBuilder::createComparison(std::shared_ptr<Register> arg1, s
955968
type2 = Compiler::StaticType::Number;
956969

957970
// Optimize number and bool comparison
958-
if (type1 == Compiler::StaticType::Number && type2 == Compiler::StaticType::Bool)
971+
int optNumberBool = 0;
972+
973+
if (type1 == Compiler::StaticType::Number && type2 == Compiler::StaticType::Bool) {
959974
type2 = Compiler::StaticType::Number;
975+
optNumberBool = 2; // operand 2 was bool
976+
}
960977

961-
if (type1 == Compiler::StaticType::Bool && type2 == Compiler::StaticType::Number)
978+
if (type1 == Compiler::StaticType::Bool && type2 == Compiler::StaticType::Number) {
962979
type1 = Compiler::StaticType::Number;
980+
optNumberBool = 1; // operand 1 was bool
981+
}
963982

964983
if (type1 != type2 || type1 == Compiler::StaticType::Unknown || type2 == Compiler::StaticType::Unknown) {
965984
// If the types are different or at least one of them
@@ -997,8 +1016,25 @@ llvm::Value *LLVMCodeBuilder::createComparison(std::shared_ptr<Register> arg1, s
9971016
return m_builder.CreateSelect(nan, m_builder.getInt1(true), cmp);
9981017
}
9991018

1000-
case Comparison::GT:
1001-
return m_builder.CreateFCmpOGT(value1, value2);
1019+
case Comparison::GT: {
1020+
llvm::Value *bothNan = m_builder.CreateAnd(isNaN(value1), isNaN(value2)); // NaN == NaN
1021+
llvm::Value *cmp = m_builder.CreateFCmpOGT(value1, value2);
1022+
llvm::Value *nan;
1023+
llvm::Value *nanCmp;
1024+
1025+
if (optNumberBool == 1) {
1026+
nan = isNaN(value2);
1027+
nanCmp = castValue(arg1, Compiler::StaticType::Bool);
1028+
} else if (optNumberBool == 2) {
1029+
nan = isNaN(value1);
1030+
nanCmp = m_builder.CreateNot(castValue(arg2, Compiler::StaticType::Bool));
1031+
} else {
1032+
nan = isNaN(value1);
1033+
nanCmp = m_builder.CreateFCmpUGT(value1, value2);
1034+
}
1035+
1036+
return m_builder.CreateAnd(m_builder.CreateNot(bothNan), m_builder.CreateSelect(nan, nanCmp, cmp));
1037+
}
10021038

10031039
case Comparison::LT:
10041040
return m_builder.CreateFCmpOLT(value1, value2);
@@ -1016,7 +1052,8 @@ llvm::Value *LLVMCodeBuilder::createComparison(std::shared_ptr<Register> arg1, s
10161052
return m_builder.CreateICmpEQ(value1, value2);
10171053

10181054
case Comparison::GT:
1019-
return m_builder.CreateICmpSGT(value1, value2);
1055+
// value1 && !value2
1056+
return m_builder.CreateAnd(value1, m_builder.CreateNot(value2));
10201057

10211058
case Comparison::LT:
10221059
return m_builder.CreateICmpSLT(value1, value2);

src/dev/engine/internal/llvmcodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class LLVMCodeBuilder : public ICodeBuilder
3232
void createDiv() override;
3333

3434
void createCmpEQ() override;
35+
void createCmpGT() override;
3536
void beginIfStatement() override;
3637
void beginElseBranch() override;
3738
void endIf() override;
@@ -69,6 +70,7 @@ class LLVMCodeBuilder : public ICodeBuilder
6970
Mul,
7071
Div,
7172
CmpEQ,
73+
CmpGT,
7274
Yield,
7375
BeginIf,
7476
BeginElse,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,187 @@ TEST_F(LLVMCodeBuilderTest, EqualComparison)
595595
addOpTest(nan, "0");
596596
}
597597

598+
TEST_F(LLVMCodeBuilderTest, GreaterThanComparison)
599+
{
600+
auto addOpTest = [this](Value v1, Value v2) {
601+
createBuilder(true);
602+
603+
m_builder->addConstValue(v1);
604+
m_builder->addConstValue(v2);
605+
m_builder->createCmpGT();
606+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String });
607+
608+
m_builder->addConstValue(v1);
609+
callConstFuncForType(v1.type());
610+
m_builder->addConstValue(v2);
611+
callConstFuncForType(v2.type());
612+
m_builder->createCmpGT();
613+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String });
614+
615+
std::string str = Value(v1 > v2).toString() + '\n';
616+
std::string expected = str + str;
617+
618+
auto code = m_builder->finalize();
619+
auto ctx = code->createExecutionContext(&m_target);
620+
621+
testing::internal::CaptureStdout();
622+
code->run(ctx.get());
623+
const std::string quotes1 = v1.isString() ? "\"" : "";
624+
const std::string quotes2 = v2.isString() ? "\"" : "";
625+
ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2;
626+
};
627+
628+
addOpTest(10, 10);
629+
addOpTest(10, 8);
630+
addOpTest(8, 10);
631+
632+
addOpTest(-4.25, -4.25);
633+
addOpTest(-4.25, 5.312);
634+
addOpTest(5.312, -4.25);
635+
636+
addOpTest(true, true);
637+
addOpTest(true, false);
638+
addOpTest(false, true);
639+
640+
addOpTest(1, true);
641+
addOpTest(1, false);
642+
643+
addOpTest("abC def", "abC def");
644+
addOpTest("abC def", "abc dEf");
645+
addOpTest("abC def", "ghi Jkl");
646+
addOpTest("ghi Jkl", "abC def");
647+
addOpTest("abC def", "hello world");
648+
649+
addOpTest(" ", "");
650+
addOpTest(" ", "0");
651+
addOpTest(" ", 0);
652+
addOpTest(0, " ");
653+
addOpTest("", "0");
654+
addOpTest("", 0);
655+
addOpTest(0, "");
656+
addOpTest("0", 0);
657+
addOpTest(0, "0");
658+
659+
addOpTest(5.25, "5.25");
660+
addOpTest("5.25", 5.25);
661+
addOpTest(5.25, " 5.25");
662+
addOpTest(" 5.25", 5.25);
663+
addOpTest(5.25, "5.25 ");
664+
addOpTest("5.25 ", 5.25);
665+
addOpTest(5.25, " 5.25 ");
666+
addOpTest(" 5.25 ", 5.25);
667+
addOpTest(5.25, "5.26");
668+
addOpTest("5.26", 5.25);
669+
addOpTest("5.25", "5.26");
670+
addOpTest(5, "5 ");
671+
addOpTest("5 ", 5);
672+
addOpTest(0, "1");
673+
addOpTest("1", 0);
674+
addOpTest(0, "test");
675+
addOpTest("test", 0);
676+
677+
static const double inf = std::numeric_limits<double>::infinity();
678+
static const double nan = std::numeric_limits<double>::quiet_NaN();
679+
680+
addOpTest(inf, inf);
681+
addOpTest(-inf, -inf);
682+
addOpTest(nan, nan);
683+
addOpTest(inf, -inf);
684+
addOpTest(-inf, inf);
685+
addOpTest(inf, nan);
686+
addOpTest(nan, inf);
687+
addOpTest(-inf, nan);
688+
addOpTest(nan, -inf);
689+
690+
addOpTest(5, inf);
691+
addOpTest(inf, 5);
692+
addOpTest(5, -inf);
693+
addOpTest(-inf, 5);
694+
addOpTest(5, nan);
695+
addOpTest(nan, 5);
696+
addOpTest(0, nan);
697+
addOpTest(nan, 0);
698+
699+
addOpTest(true, "true");
700+
addOpTest("true", true);
701+
addOpTest(false, "false");
702+
addOpTest("false", false);
703+
addOpTest(false, "true");
704+
addOpTest("true", false);
705+
addOpTest(true, "false");
706+
addOpTest("false", true);
707+
addOpTest(true, "TRUE");
708+
addOpTest("TRUE", true);
709+
addOpTest(false, "FALSE");
710+
addOpTest("FALSE", false);
711+
712+
addOpTest(true, "00001");
713+
addOpTest("00001", true);
714+
addOpTest(true, "00000");
715+
addOpTest("00000", true);
716+
addOpTest(false, "00000");
717+
addOpTest("00000", false);
718+
719+
addOpTest("true", 1);
720+
addOpTest(1, "true");
721+
addOpTest("true", 0);
722+
addOpTest(0, "true");
723+
addOpTest("false", 0);
724+
addOpTest(0, "false");
725+
addOpTest("false", 1);
726+
addOpTest(1, "false");
727+
728+
addOpTest("true", "TRUE");
729+
addOpTest("true", "FALSE");
730+
addOpTest("false", "FALSE");
731+
addOpTest("false", "TRUE");
732+
733+
addOpTest(true, inf);
734+
addOpTest(inf, true);
735+
addOpTest(true, -inf);
736+
addOpTest(-inf, true);
737+
addOpTest(true, nan);
738+
addOpTest(nan, true);
739+
addOpTest(false, inf);
740+
addOpTest(inf, false);
741+
addOpTest(false, -inf);
742+
addOpTest(-inf, false);
743+
addOpTest(false, nan);
744+
addOpTest(nan, false);
745+
746+
addOpTest("Infinity", inf);
747+
addOpTest("Infinity", -inf);
748+
addOpTest("Infinity", nan);
749+
addOpTest("infinity", inf);
750+
addOpTest("infinity", -inf);
751+
addOpTest("infinity", nan);
752+
addOpTest("-Infinity", inf);
753+
addOpTest("-Infinity", -inf);
754+
addOpTest("-Infinity", nan);
755+
addOpTest("-infinity", inf);
756+
addOpTest("-infinity", -inf);
757+
addOpTest("-infinity", nan);
758+
addOpTest("NaN", inf);
759+
addOpTest("NaN", -inf);
760+
addOpTest("NaN", nan);
761+
addOpTest("nan", inf);
762+
addOpTest("nan", -inf);
763+
addOpTest("nan", nan);
764+
765+
addOpTest(inf, "abc");
766+
addOpTest(inf, " ");
767+
addOpTest(inf, "");
768+
addOpTest(inf, "0");
769+
addOpTest(-inf, "abc");
770+
addOpTest(-inf, " ");
771+
addOpTest(-inf, "");
772+
addOpTest(-inf, "0");
773+
addOpTest(nan, "abc");
774+
addOpTest(nan, " ");
775+
addOpTest(nan, "");
776+
addOpTest(nan, "0");
777+
}
778+
598779
TEST_F(LLVMCodeBuilderTest, Yield)
599780
{
600781
auto build = [this]() {

test/mocks/codebuildermock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class CodeBuilderMock : public ICodeBuilder
2020
MOCK_METHOD(void, createDiv, (), (override));
2121

2222
MOCK_METHOD(void, createCmpEQ, (), (override));
23+
MOCK_METHOD(void, createCmpGT, (), (override));
2324
MOCK_METHOD(void, beginIfStatement, (), (override));
2425
MOCK_METHOD(void, beginElseBranch, (), (override));
2526
MOCK_METHOD(void, endIf, (), (override));

0 commit comments

Comments
 (0)