From 73fc3dca5bbcb670074345ad2133cda22ae9bbd2 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 1 Jul 2024 09:38:14 -0500 Subject: [PATCH 1/7] merge allocations in same basic block up to a size bound --- include/kllvm/codegen/CreateTerm.h | 14 ++++++-- include/kllvm/codegen/Util.h | 2 ++ lib/codegen/CreateTerm.cpp | 55 ++++++++++++++++++++++++------ lib/codegen/Util.cpp | 6 ++++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/include/kllvm/codegen/CreateTerm.h b/include/kllvm/codegen/CreateTerm.h index a9d41aade..deba00bc4 100644 --- a/include/kllvm/codegen/CreateTerm.h +++ b/include/kllvm/codegen/CreateTerm.h @@ -1,6 +1,8 @@ #ifndef CREATE_TERM_H #define CREATE_TERM_H +#include + #include "kllvm/ast/AST.h" #include "kllvm/codegen/DecisionParser.h" @@ -8,6 +10,9 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" +// size up to which calls to the same allocation function will be merged. +#define MAX_BLOCK_MERGE_SIZE 4096 + namespace kllvm { class create_term { @@ -143,12 +148,15 @@ bool is_injection_symbol(kore_pattern *p, kore_symbol *sym); void add_abort(llvm::BasicBlock *block, llvm::Module *module); +template + requires std::same_as + || std::same_as llvm::Value *allocate_term( - llvm::Type *alloc_type, llvm::BasicBlock *block, + llvm::Type *alloc_type, llvm::Value *len, T *insert_point, char const *alloc_fn = "kore_alloc"); llvm::Value *allocate_term( - llvm::Type *alloc_type, llvm::Value *len, llvm::BasicBlock *block, - char const *alloc_fn = "kore_alloc"); + llvm::Type *alloc_type, llvm::BasicBlock *block, + char const *alloc_fn = "kore_alloc", bool mergeable = false); } // namespace kllvm #endif // CREATE_TERM_H diff --git a/include/kllvm/codegen/Util.h b/include/kllvm/codegen/Util.h index 0044826d0..d0a8d815d 100644 --- a/include/kllvm/codegen/Util.h +++ b/include/kllvm/codegen/Util.h @@ -23,6 +23,8 @@ llvm::Function *kore_heap_alloc(std::string const &name, llvm::Module *module); llvm::Instruction *create_malloc( llvm::BasicBlock *block, llvm::Value *alloc_size, llvm::Function *malloc_f); +llvm::Instruction *create_malloc( + llvm::Instruction *inst, llvm::Value *alloc_size, llvm::Function *malloc_f); // getOrInsertFunction on module, aborting on failure template diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 4aef12827..b555efd34 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -168,22 +168,53 @@ llvm::Value *get_block_header( llvm::Type::getInt64Ty(module->getContext()), header_val)); } +template + requires std::same_as + || std::same_as llvm::Value *allocate_term( - llvm::Type *alloc_type, llvm::BasicBlock *block, char const *alloc_fn) { - return allocate_term( - alloc_type, llvm::ConstantExpr::getSizeOf(alloc_type), block, alloc_fn); -} - -llvm::Value *allocate_term( - llvm::Type *alloc_type, llvm::Value *len, llvm::BasicBlock *block, + llvm::Type *alloc_type, llvm::Value *len, T *insert_point, char const *alloc_fn) { auto *malloc = create_malloc( - block, len, kore_heap_alloc(alloc_fn, block->getModule())); + insert_point, len, kore_heap_alloc(alloc_fn, insert_point->getModule())); set_debug_loc(malloc); return malloc; } +llvm::Value *allocate_term( + llvm::Type *alloc_type, llvm::BasicBlock *block, char const *alloc_fn, + bool mergeable) { + llvm::DataLayout layout(block->getModule()); + auto type_size = layout.getTypeAllocSize(alloc_type).getFixedValue(); + auto *ty = llvm::Type::getInt64Ty(block->getContext()); + if (mergeable) { + if (auto *first = block->getFirstNonPHI()) { + if (auto *call = llvm::dyn_cast(first)) { + if (auto *func = call->getCalledFunction()) { + if (func->getName() == alloc_fn) { + if (auto *size + = llvm::dyn_cast(call->getOperand(0))) { + if (size->getLimitedValue() + type_size < MAX_BLOCK_MERGE_SIZE) { + call->setOperand( + 0, llvm::ConstantExpr::getAdd( + size, llvm::ConstantInt::get(ty, type_size))); + return llvm::GetElementPtrInst::Create( + llvm::Type::getInt8Ty(block->getContext()), call, {size}, + "alloc_chunk", block); + } + } + } + } + } + } + return allocate_term( + alloc_type, llvm::ConstantInt::get(ty, type_size), block, alloc_fn); + } else { + return allocate_term( + alloc_type, llvm::ConstantInt::get(ty, type_size), block, alloc_fn); + } +} + value_type term_type( kore_pattern *pattern, llvm::StringMap &substitution, kore_definition *definition) { @@ -686,7 +717,8 @@ llvm::Value *create_term::create_function_call( // we don't use alloca here because the tail call optimization pass for llvm // doesn't handle correctly functions with alloca alloc_sret = allocate_term( - return_type, current_block_, get_collection_alloc_fn(return_cat.cat)); + return_type, current_block_, get_collection_alloc_fn(return_cat.cat), + true); sret_type = return_type; real_args.insert(real_args.begin(), alloc_sret); types.insert(types.begin(), alloc_sret->getType()); @@ -759,7 +791,8 @@ llvm::Value *create_term::not_injection_case( children.push_back(child_value); idx++; } - llvm::Value *block = allocate_term(block_type, current_block_); + llvm::Value *block + = allocate_term(block_type, current_block_, "kore_alloc", true); llvm::Value *block_header_ptr = llvm::GetElementPtrInst::CreateInBounds( block_type, block, {llvm::ConstantInt::get(llvm::Type::getInt64Ty(ctx_), 0), @@ -1162,7 +1195,7 @@ std::string make_apply_rule_function( if (!arg->getType()->isPointerTy()) { auto *ptr = allocate_term( arg->getType(), creator.get_current_block(), - get_collection_alloc_fn(cat.cat)); + get_collection_alloc_fn(cat.cat), true); new llvm::StoreInst(arg, ptr, creator.get_current_block()); arg = ptr; } diff --git a/lib/codegen/Util.cpp b/lib/codegen/Util.cpp index 8f71b980a..c38c6106d 100644 --- a/lib/codegen/Util.cpp +++ b/lib/codegen/Util.cpp @@ -29,6 +29,12 @@ llvm::Instruction *create_malloc( return llvm::CallInst::Create(malloc_f, {alloc_size}, "", block); } +llvm::Instruction *create_malloc( + llvm::Instruction *inst, llvm::Value *alloc_size, + llvm::Function *malloc_f) { + return llvm::CallInst::Create(malloc_f, {alloc_size}, "", inst); +} + llvm::Constant *get_offset_of_member( [[maybe_unused]] llvm::Module *mod, llvm::StructType *struct_ty, int nth_member) { From ed0370a332a960b04e6110457f0463037ca87579 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Thu, 1 Aug 2024 15:04:13 -0500 Subject: [PATCH 2/7] fix bug where allocs are merged that are not safe to merge --- lib/codegen/CreateTerm.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index b555efd34..84344eaad 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -181,6 +181,11 @@ llvm::Value *allocate_term( return malloc; } +static bool is_basic_alloc(std::string alloc_fn) { + return alloc_fn == "kore_alloc" || alloc_fn == "kore_alloc_old" + || alloc_fn == "kore_alloc_always_gc"; +} + llvm::Value *allocate_term( llvm::Type *alloc_type, llvm::BasicBlock *block, char const *alloc_fn, bool mergeable) { @@ -191,7 +196,7 @@ llvm::Value *allocate_term( if (auto *first = block->getFirstNonPHI()) { if (auto *call = llvm::dyn_cast(first)) { if (auto *func = call->getCalledFunction()) { - if (func->getName() == alloc_fn) { + if (func->getName() == alloc_fn && is_basic_alloc(alloc_fn)) { if (auto *size = llvm::dyn_cast(call->getOperand(0))) { if (size->getLimitedValue() + type_size < MAX_BLOCK_MERGE_SIZE) { From 7cc190e180ecae0d43d4c0b01e57f347a6af5d76 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Thu, 1 Aug 2024 15:09:39 -0500 Subject: [PATCH 3/7] fix clang tidy --- include/kllvm/codegen/CreateTerm.h | 2 +- lib/codegen/CreateTerm.cpp | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/kllvm/codegen/CreateTerm.h b/include/kllvm/codegen/CreateTerm.h index deba00bc4..9b78566df 100644 --- a/include/kllvm/codegen/CreateTerm.h +++ b/include/kllvm/codegen/CreateTerm.h @@ -11,7 +11,7 @@ #include "llvm/IR/Value.h" // size up to which calls to the same allocation function will be merged. -#define MAX_BLOCK_MERGE_SIZE 4096 +enum { MAX_BLOCK_MERGE_SIZE = 4096 }; namespace kllvm { diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 84344eaad..927736d68 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -196,17 +196,16 @@ llvm::Value *allocate_term( if (auto *first = block->getFirstNonPHI()) { if (auto *call = llvm::dyn_cast(first)) { if (auto *func = call->getCalledFunction()) { - if (func->getName() == alloc_fn && is_basic_alloc(alloc_fn)) { - if (auto *size - = llvm::dyn_cast(call->getOperand(0))) { - if (size->getLimitedValue() + type_size < MAX_BLOCK_MERGE_SIZE) { - call->setOperand( - 0, llvm::ConstantExpr::getAdd( - size, llvm::ConstantInt::get(ty, type_size))); - return llvm::GetElementPtrInst::Create( - llvm::Type::getInt8Ty(block->getContext()), call, {size}, - "alloc_chunk", block); - } + if (auto *size + = llvm::dyn_cast(call->getOperand(0))) { + if (func->getName() == alloc_fn && is_basic_alloc(alloc_fn) + && size->getLimitedValue() + type_size < MAX_BLOCK_MERGE_SIZE) { + call->setOperand( + 0, llvm::ConstantExpr::getAdd( + size, llvm::ConstantInt::get(ty, type_size))); + return llvm::GetElementPtrInst::Create( + llvm::Type::getInt8Ty(block->getContext()), call, {size}, + "alloc_chunk", block); } } } @@ -214,10 +213,9 @@ llvm::Value *allocate_term( } return allocate_term( alloc_type, llvm::ConstantInt::get(ty, type_size), block, alloc_fn); - } else { - return allocate_term( - alloc_type, llvm::ConstantInt::get(ty, type_size), block, alloc_fn); } + return allocate_term( + alloc_type, llvm::ConstantInt::get(ty, type_size), block, alloc_fn); } value_type term_type( From 3111cfc9efa59de67877b30b19bbf7aa4166faf7 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Thu, 1 Aug 2024 16:35:07 -0500 Subject: [PATCH 4/7] fix clang tidy --- include/kllvm/codegen/CreateTerm.h | 2 +- lib/codegen/CreateTerm.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/kllvm/codegen/CreateTerm.h b/include/kllvm/codegen/CreateTerm.h index 9b78566df..b5f490bda 100644 --- a/include/kllvm/codegen/CreateTerm.h +++ b/include/kllvm/codegen/CreateTerm.h @@ -11,7 +11,7 @@ #include "llvm/IR/Value.h" // size up to which calls to the same allocation function will be merged. -enum { MAX_BLOCK_MERGE_SIZE = 4096 }; +enum { MaxBlockMergeSize = 4096 }; namespace kllvm { diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 927736d68..e4bd024fe 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -199,7 +199,7 @@ llvm::Value *allocate_term( if (auto *size = llvm::dyn_cast(call->getOperand(0))) { if (func->getName() == alloc_fn && is_basic_alloc(alloc_fn) - && size->getLimitedValue() + type_size < MAX_BLOCK_MERGE_SIZE) { + && size->getLimitedValue() + type_size < MaxBlockMergeSize) { call->setOperand( 0, llvm::ConstantExpr::getAdd( size, llvm::ConstantInt::get(ty, type_size))); From f1d5ffc84ef268eaf9fc48fb1c7d3f53b33e73e0 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Fri, 2 Aug 2024 12:07:57 -0500 Subject: [PATCH 5/7] Update CreateTerm.cpp --- lib/codegen/CreateTerm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index e4bd024fe..313bd3062 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -181,7 +181,7 @@ llvm::Value *allocate_term( return malloc; } -static bool is_basic_alloc(std::string alloc_fn) { +static bool is_basic_alloc(std::string const &alloc_fn) { return alloc_fn == "kore_alloc" || alloc_fn == "kore_alloc_old" || alloc_fn == "kore_alloc_always_gc"; } From 202e4d971eda96490a8f2dafb0bd634dc978ef25 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 5 Aug 2024 07:56:04 -0500 Subject: [PATCH 6/7] use constexpr global for global constant --- include/kllvm/codegen/CreateTerm.h | 2 +- lib/codegen/CreateTerm.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/kllvm/codegen/CreateTerm.h b/include/kllvm/codegen/CreateTerm.h index b5f490bda..099a4176c 100644 --- a/include/kllvm/codegen/CreateTerm.h +++ b/include/kllvm/codegen/CreateTerm.h @@ -11,7 +11,7 @@ #include "llvm/IR/Value.h" // size up to which calls to the same allocation function will be merged. -enum { MaxBlockMergeSize = 4096 }; +static constexpr int max_block_merge_size = 4096; namespace kllvm { diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 313bd3062..c1aab7707 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -199,7 +199,7 @@ llvm::Value *allocate_term( if (auto *size = llvm::dyn_cast(call->getOperand(0))) { if (func->getName() == alloc_fn && is_basic_alloc(alloc_fn) - && size->getLimitedValue() + type_size < MaxBlockMergeSize) { + && size->getLimitedValue() + type_size < max_block_merge_size) { call->setOperand( 0, llvm::ConstantExpr::getAdd( size, llvm::ConstantInt::get(ty, type_size))); From d1883827479548fd32cd0a2a2d7814b8a831ba36 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 5 Aug 2024 08:03:42 -0500 Subject: [PATCH 7/7] add debug loc --- lib/codegen/CreateTerm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index c1aab7707..34a8377c1 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -203,9 +203,11 @@ llvm::Value *allocate_term( call->setOperand( 0, llvm::ConstantExpr::getAdd( size, llvm::ConstantInt::get(ty, type_size))); - return llvm::GetElementPtrInst::Create( + auto *ret = llvm::GetElementPtrInst::Create( llvm::Type::getInt8Ty(block->getContext()), call, {size}, "alloc_chunk", block); + set_debug_loc(ret); + return ret; } } }