From dfb5e83b6821c274fe199072b16e27e360adc21e Mon Sep 17 00:00:00 2001 From: Giuliano Belinassi Date: Mon, 19 Aug 2024 21:51:31 -0300 Subject: [PATCH] Remove redundant decls Pass through the closure set looking for Decls we can erase. For example: ``` struct ll; struct ll; int get(struct ll *); struct ll; ``` We just need the first `struct ll;` Signed-off-by: Giuliano Belinassi --- libcextract/FunctionDepsFinder.cpp | 24 ++++++++++++++++++++++-- libcextract/LLVMMisc.cpp | 15 +++++++++++++++ libcextract/LLVMMisc.hh | 3 +++ testsuite/small/redundant-1.c | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 testsuite/small/redundant-1.c diff --git a/libcextract/FunctionDepsFinder.cpp b/libcextract/FunctionDepsFinder.cpp index dfe76bf..5f64a63 100644 --- a/libcextract/FunctionDepsFinder.cpp +++ b/libcextract/FunctionDepsFinder.cpp @@ -57,8 +57,10 @@ void FunctionDependencyFinder::Remove_Redundant_Decls(void) { ClosureSet &closure = Visitor.Get_Closure(); std::unordered_set &closure_set = closure.Get_Set(); + bool inc; - for (auto it = closure_set.begin(); it != closure_set.end(); ++it) { + for (auto it = closure_set.begin(); it != closure_set.end(); inc ? ++it : it) { + inc = true; /* Handle the case where a enum or struct is declared as: typedef enum Hand { @@ -198,9 +200,27 @@ void FunctionDependencyFinder::Remove_Redundant_Decls(void) } } } + + /* Try to remove any decls in the main file which are + redundant, which means that have equivalent previous decl. */ + Decl *decl = *it; + + if (AST->isInMainFileID(decl->getBeginLoc()) && + AST->isInMainFileID(decl->getEndLoc())) { + + for (Decl *prev = decl->getPreviousDecl(); + prev != nullptr; + prev = prev->getPreviousDecl()) { + if (closure.Is_Decl_Marked(prev) && Is_Decl_Equivalent_To(decl, prev)) { + ++it; + inc = false; + closure.Remove_Decl(decl); + break; + } + } + } } - // FIXME: use interval tree ASTUnit::top_level_iterator it; Decl *prev = nullptr; for (it = AST->top_level_begin(); it != AST->top_level_end(); ++it) { diff --git a/libcextract/LLVMMisc.cpp b/libcextract/LLVMMisc.cpp index 398ba69..86a52f4 100644 --- a/libcextract/LLVMMisc.cpp +++ b/libcextract/LLVMMisc.cpp @@ -281,3 +281,18 @@ DeclContextLookupResult Get_Decl_From_Symtab(ASTUnit *ast, const StringRef &name return Get_Decl_From_Symtab(ast, info->getValue()); } + +/** Check if two Decls are equivalent. */ +bool Is_Decl_Equivalent_To(Decl *a, Decl *b) +{ + std::string a_str; + std::string b_str; + + llvm::raw_string_ostream a_stream(a_str); + llvm::raw_string_ostream b_stream(b_str); + + a->print(a_stream); + b->print(b_stream); + + return a_str == b_str; +} diff --git a/libcextract/LLVMMisc.hh b/libcextract/LLVMMisc.hh index cf83602..11bfe60 100644 --- a/libcextract/LLVMMisc.hh +++ b/libcextract/LLVMMisc.hh @@ -100,3 +100,6 @@ DeclContextLookupResult Get_Decl_From_Symtab(ASTUnit *ast, const IdentifierInfo /** Lookup in the symbol table for a declaration with given name passed by name. */ DeclContextLookupResult Get_Decl_From_Symtab(ASTUnit *ast, const StringRef &name); + +/** Check if two Decls are equivalent. */ +bool Is_Decl_Equivalent_To(Decl *a, Decl *b); diff --git a/testsuite/small/redundant-1.c b/testsuite/small/redundant-1.c new file mode 100644 index 0000000..df59deb --- /dev/null +++ b/testsuite/small/redundant-1.c @@ -0,0 +1,16 @@ +/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_NO_EXTERNALIZATION" }*/ + +struct ll; + +struct ll; + +int get(struct ll *); + +struct ll; + +int f(struct ll *l) +{ + return get(l); +} + +/* { dg-final { scan-tree-dump-not "struct ll;\n+int get\(struct ll \*\);" } } */