From 0cfeeb0a46fc202c6087c43c49346e98b11dda3c Mon Sep 17 00:00:00 2001 From: Smit-create Date: Mon, 6 Feb 2023 12:06:21 +1100 Subject: [PATCH 1/4] LLVM: Support logical binop for strings, int, real --- src/libasr/codegen/asr_to_llvm.cpp | 40 +++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 406dbc83ae..2dee31e863 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -4651,14 +4651,48 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *left_val = tmp; this->visit_expr_wrapper(x.m_right, true); llvm::Value *right_val = tmp; - LCOMPILERS_ASSERT(ASRUtils::is_logical(*x.m_type)) + llvm::Value *zero, *cond; + if (ASRUtils::is_integer(*x.m_type)) { + int a_kind = down_cast(x.m_type)->m_kind; + int init_value_bits = 8*a_kind; + zero = llvm::ConstantInt::get(context, + llvm::APInt(init_value_bits, 0)); + cond = builder->CreateICmpEQ(left_val, zero); + } else if (ASRUtils::is_real(*x.m_type)) { + int a_kind = down_cast(x.m_type)->m_kind; + int init_value_bits = 8*a_kind; + if (init_value_bits == 32) { + zero = llvm::ConstantFP::get(context, + llvm::APFloat((float)0)); + } else { + zero = llvm::ConstantFP::get(context, + llvm::APFloat((double)0)); + } + cond = builder->CreateFCmpUEQ(left_val, zero); + } else if (ASRUtils::is_character(*x.m_type)) { + zero = llvm::Constant::getNullValue(character_type); + cond = lfortran_str_cmp(left_val, zero, "_lpython_str_compare_eq"); + } else if (ASRUtils::is_logical(*x.m_type)) { + zero = llvm::ConstantInt::get(context, + llvm::APInt(1, 0)); + cond = builder->CreateICmpEQ(left_val, zero); + } else { + throw CodeGenError("Only Integer, Real, Strings and Logical types are supported " + "in logical binary operation.", x.base.base.loc); + } switch (x.m_op) { case ASR::logicalbinopType::And: { - tmp = builder->CreateAnd(left_val, right_val); + tmp = right_val; + create_if_else(cond, [=]() { + tmp = left_val; + }, []() {}); break; }; case ASR::logicalbinopType::Or: { - tmp = builder->CreateOr(left_val, right_val); + tmp = left_val; + create_if_else(cond, [=]() { + tmp = right_val; + }, []() {}); break; }; case ASR::logicalbinopType::Xor: { From 316e8a43481804a440e44423985ad609872af5bb Mon Sep 17 00:00:00 2001 From: Smit-create Date: Thu, 9 Feb 2023 20:09:23 +0530 Subject: [PATCH 2/4] Fix assignment --- src/libasr/codegen/asr_to_llvm.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 2dee31e863..e452ccdc9f 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -4652,12 +4652,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_right, true); llvm::Value *right_val = tmp; llvm::Value *zero, *cond; + llvm::AllocaInst *result; if (ASRUtils::is_integer(*x.m_type)) { int a_kind = down_cast(x.m_type)->m_kind; int init_value_bits = 8*a_kind; zero = llvm::ConstantInt::get(context, llvm::APInt(init_value_bits, 0)); cond = builder->CreateICmpEQ(left_val, zero); + result = builder->CreateAlloca(getIntType(a_kind), nullptr); } else if (ASRUtils::is_real(*x.m_type)) { int a_kind = down_cast(x.m_type)->m_kind; int init_value_bits = 8*a_kind; @@ -4668,31 +4670,39 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor zero = llvm::ConstantFP::get(context, llvm::APFloat((double)0)); } + result = builder->CreateAlloca(getFPType(a_kind), nullptr); cond = builder->CreateFCmpUEQ(left_val, zero); } else if (ASRUtils::is_character(*x.m_type)) { zero = llvm::Constant::getNullValue(character_type); cond = lfortran_str_cmp(left_val, zero, "_lpython_str_compare_eq"); + result = builder->CreateAlloca(character_type, nullptr); } else if (ASRUtils::is_logical(*x.m_type)) { zero = llvm::ConstantInt::get(context, llvm::APInt(1, 0)); cond = builder->CreateICmpEQ(left_val, zero); + result = builder->CreateAlloca(getIntType(1), nullptr); } else { throw CodeGenError("Only Integer, Real, Strings and Logical types are supported " "in logical binary operation.", x.base.base.loc); } switch (x.m_op) { case ASR::logicalbinopType::And: { - tmp = right_val; - create_if_else(cond, [=]() { - tmp = left_val; - }, []() {}); + create_if_else(cond, [&, result, left_val]() { + LLVM::CreateStore(*builder, left_val, result); + }, [&, result, right_val]() { + LLVM::CreateStore(*builder, right_val, result); + }); + tmp = LLVM::CreateLoad(*builder, result); break; }; case ASR::logicalbinopType::Or: { - tmp = left_val; - create_if_else(cond, [=]() { - tmp = right_val; - }, []() {}); + create_if_else(cond, [&, result, right_val]() { + LLVM::CreateStore(*builder, right_val, result); + + }, [&, result, left_val]() { + LLVM::CreateStore(*builder, left_val, result); + }); + tmp = LLVM::CreateLoad(*builder, result); break; }; case ASR::logicalbinopType::Xor: { From 474da732557b95753e7bc62b86b4f10dd60340e5 Mon Sep 17 00:00:00 2001 From: Smit-create Date: Thu, 9 Feb 2023 20:22:57 +0530 Subject: [PATCH 3/4] Add tests --- integration_tests/CMakeLists.txt | 1 + integration_tests/logical_binop1.py | 50 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 integration_tests/logical_binop1.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index ca484bae7b..e3e68e9b7d 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -395,6 +395,7 @@ RUN(NAME test_str_to_int LABELS cpython llvm c) RUN(NAME test_platform LABELS cpython llvm c) RUN(NAME test_vars_01 LABELS cpython llvm) RUN(NAME test_version LABELS cpython llvm) +RUN(NAME logical_binop1 LABELS cpython llvm) RUN(NAME vec_01 LABELS cpython llvm c) RUN(NAME test_str_comparison LABELS cpython llvm c) RUN(NAME test_bit_length LABELS cpython llvm c) diff --git a/integration_tests/logical_binop1.py b/integration_tests/logical_binop1.py new file mode 100644 index 0000000000..e6b052f8f9 --- /dev/null +++ b/integration_tests/logical_binop1.py @@ -0,0 +1,50 @@ +from ltypes import i32 + +def test_issue_1487_1(): + a : i32 + b : i32 + x : i32 + y : i32 + or_op1 : i32 + or_op2 : i32 + a = 1 + b = 2 + x = 0 + y = 4 + or_op1 = a or b + or_op2 = x or y + assert or_op1 == 1 + assert or_op2 == 4 + y = 0 + or_op2 = x or y + assert or_op2 == 0 + + +def test_issue_1487_2(): + a : i32 + b : i32 + x : i32 + y : i32 + and_op1 : i32 + and_op2 : i32 + a = 100 + b = 150 + x = 175 + y = 0 + and_op1 = a and b + and_op2 = y and x + assert and_op1 == 150 + assert and_op2 == 0 + x = 0 + and_op2 = y and x + and_op1 = b and a + assert and_op2 == 0 + assert and_op1 == 100 + + +def check(): + test_issue_1487_1() + test_issue_1487_2() + + +check() From ae7562271cb85e0f40cedf3c6a404171db232e01 Mon Sep 17 00:00:00 2001 From: Smit-create Date: Mon, 13 Feb 2023 13:28:42 +0530 Subject: [PATCH 4/4] Fix logical type --- src/libasr/codegen/asr_to_llvm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index e452ccdc9f..bfbaa787a0 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -4680,7 +4680,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor zero = llvm::ConstantInt::get(context, llvm::APInt(1, 0)); cond = builder->CreateICmpEQ(left_val, zero); - result = builder->CreateAlloca(getIntType(1), nullptr); + result = builder->CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); } else { throw CodeGenError("Only Integer, Real, Strings and Logical types are supported " "in logical binary operation.", x.base.base.loc);