diff --git a/llvm/test/tools/llvm-reduce/remove-dll.ll b/llvm/test/tools/llvm-reduce/remove-dll.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-dll.ll @@ -0,0 +1,10 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=global-values --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefix=CHECK-FINAL %s --input-file=%t + +; CHECK-INTERESTINGNESS: @g = external {{.*}}global i32 +; CHECK-FINAL: @g = external global i32 +; CHECK-INTERESTINGNESS: @h = external {{.*}}global i32 +; CHECK-FINAL: @h = external global i32 + +@g = external dllimport global i32 +@h = external dllexport global i32 diff --git a/llvm/test/tools/llvm-reduce/remove-thread-local.ll b/llvm/test/tools/llvm-reduce/remove-thread-local.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-thread-local.ll @@ -0,0 +1,7 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=global-values --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefix=CHECK-FINAL %s --input-file=%t + +; CHECK-INTERESTINGNESS: @g = {{.*}}global i32 +; CHECK-FINAL: @g = global i32 + +@g = thread_local(initialexec) global i32 0 diff --git a/llvm/test/tools/llvm-reduce/remove-unnamed-addr.ll b/llvm/test/tools/llvm-reduce/remove-unnamed-addr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-unnamed-addr.ll @@ -0,0 +1,7 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=global-values --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefix=CHECK-FINAL %s --input-file=%t + +; CHECK-INTERESTINGNESS: @g = {{.*}}global i32 +; CHECK-FINAL: @g = global i32 + +@g = unnamed_addr global i32 0 diff --git a/llvm/test/tools/llvm-reduce/remove-visibility.ll b/llvm/test/tools/llvm-reduce/remove-visibility.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-visibility.ll @@ -0,0 +1,7 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=global-values --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck --check-prefix=CHECK-FINAL %s --input-file=%t + +; CHECK-INTERESTINGNESS: @g = {{.*}}global i32 +; CHECK-FINAL: @g = global i32 + +@g = hidden global i32 0 diff --git a/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp b/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp --- a/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp @@ -12,40 +12,73 @@ //===----------------------------------------------------------------------===// #include "ReduceGlobalValues.h" -#include "llvm/IR/Constants.h" #include "llvm/IR/GlobalValue.h" using namespace llvm; -static bool isValidDSOLocalReductionGV(GlobalValue &GV) { +static bool shouldReduceDSOLocal(GlobalValue &GV) { return GV.isDSOLocal() && !GV.isImplicitDSOLocal(); } -/// Sets dso_local to false for all global values. -static void extractGVsFromModule(Oracle &O, Module &Program) { - // remove dso_local from global values - for (auto &GV : Program.global_values()) - if (isValidDSOLocalReductionGV(GV) && !O.shouldKeep()) { +static bool shouldReduceVisibility(GlobalValue &GV) { + return GV.getVisibility() != GlobalValue::VisibilityTypes::DefaultVisibility; +} + +static bool shouldReduceUnnamedAddress(GlobalValue &GV) { + return GV.getUnnamedAddr() != GlobalValue::UnnamedAddr::None; +} + +static bool shouldReduceDLLStorageClass(GlobalValue &GV) { + return GV.getDLLStorageClass() != + GlobalValue::DLLStorageClassTypes::DefaultStorageClass; +} + +static bool shouldReduceThreadLocal(GlobalValue &GV) { + return GV.isThreadLocal(); +} + +static void reduceGVs(Oracle &O, Module &Program) { + for (auto &GV : Program.global_values()) { + if (shouldReduceDSOLocal(GV) && !O.shouldKeep()) GV.setDSOLocal(false); + if (shouldReduceVisibility(GV) && !O.shouldKeep()) { + bool IsImplicitDSOLocal = GV.isImplicitDSOLocal(); + GV.setVisibility(GlobalValue::VisibilityTypes::DefaultVisibility); + if (IsImplicitDSOLocal) + GV.setDSOLocal(false); } + if (shouldReduceUnnamedAddress(GV) && !O.shouldKeep()) + GV.setUnnamedAddr(GlobalValue::UnnamedAddr::None); + if (shouldReduceDLLStorageClass(GV) && !O.shouldKeep()) + GV.setDLLStorageClass( + GlobalValue::DLLStorageClassTypes::DefaultStorageClass); + if (shouldReduceThreadLocal(GV) && !O.shouldKeep()) + GV.setThreadLocal(false); + } } -/// Counts the amount of global values with dso_local and displays their -/// respective name & index static int countGVs(Module &Program) { - // TODO: Silence index with --quiet flag - outs() << "----------------------------\n"; - outs() << "GlobalValue Index Reference:\n"; - int GVCount = 0; - for (auto &GV : Program.global_values()) - if (isValidDSOLocalReductionGV(GV)) - outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n"; - outs() << "----------------------------\n"; - return GVCount; + int DSOLocalCount = count_if(Program.global_values(), [](GlobalValue &GV) { + return shouldReduceDSOLocal(GV); + }); + int VisibilityCount = count_if(Program.global_values(), [](GlobalValue &GV) { + return shouldReduceVisibility(GV); + }); + int UnnamedAddrCount = count_if(Program.global_values(), [](GlobalValue &GV) { + return shouldReduceUnnamedAddress(GV); + }); + int DLLStorageClassCount = + count_if(Program.global_values(), + [](GlobalValue &GV) { return shouldReduceDLLStorageClass(GV); }); + int ThreadLocalCount = count_if(Program.global_values(), [](GlobalValue &GV) { + return shouldReduceThreadLocal(GV); + }); + return DSOLocalCount + VisibilityCount + UnnamedAddrCount + + DLLStorageClassCount + ThreadLocalCount; } void llvm::reduceGlobalValuesDeltaPass(TestRunner &Test) { outs() << "*** Reducing GlobalValues...\n"; int GVCount = countGVs(Test.getProgram()); - runDeltaPass(Test, GVCount, extractGVsFromModule); + runDeltaPass(Test, GVCount, reduceGVs); }