diff --git a/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index c22f9d49f374b..c70413d72ebfd 100644 --- a/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -15,19 +15,17 @@ #define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H #include "llvm/IR/BuiltinGCs.h" -#include +#include "llvm/Support/AlwaysTrue.h" namespace { struct ForceAsmWriterLinking { ForceAsmWriterLinking() { // We must reference the plug-ins in such a way that compilers will not // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char*) -1) + // yet is effectively a NO-OP. This is so that globals in the translation + // units where these functions are defined are forced to be initialized, + // populating various registries. + if (llvm::getNonFoldableAlwaysTrue()) return; llvm::linkOcamlGCPrinter(); diff --git a/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h b/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h index 6f56682dce5fa..f0a01d2baf0e0 100644 --- a/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -16,20 +16,18 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/Support/AlwaysTrue.h" #include "llvm/Target/TargetMachine.h" -#include namespace { struct ForceCodegenLinking { ForceCodegenLinking() { // We must reference the passes in such a way that compilers will not // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char*) -1) + // yet is effectively a NO-OP. This is so that globals in the translation + // units where these functions are defined are forced to be initialized, + // populating various registries. + if (llvm::getNonFoldableAlwaysTrue()) return; (void) llvm::createFastRegisterAllocator(); diff --git a/llvm/include/llvm/ExecutionEngine/MCJIT.h b/llvm/include/llvm/ExecutionEngine/MCJIT.h index c836c06813fc6..1e035c0008fbd 100644 --- a/llvm/include/llvm/ExecutionEngine/MCJIT.h +++ b/llvm/include/llvm/ExecutionEngine/MCJIT.h @@ -15,8 +15,8 @@ #define LLVM_EXECUTIONENGINE_MCJIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/AlwaysTrue.h" #include "llvm/Support/Compiler.h" -#include extern "C" LLVM_ABI void LLVMLinkInMCJIT(); @@ -24,13 +24,11 @@ namespace { struct ForceMCJITLinking { ForceMCJITLinking() { // We must reference MCJIT in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char*) -1) + // delete it all as dead code, even with whole program optimization, yet + // is effectively a NO-OP. This is so that globals in the translation + // units where these functions are defined are forced to be initialized, + // populating various registries. + if (llvm::getNonFoldableAlwaysTrue()) return; LLVMLinkInMCJIT(); diff --git a/llvm/include/llvm/LinkAllIR.h b/llvm/include/llvm/LinkAllIR.h index ceed784d557de..894a8dd5bd926 100644 --- a/llvm/include/llvm/LinkAllIR.h +++ b/llvm/include/llvm/LinkAllIR.h @@ -21,6 +21,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" +#include "llvm/Support/AlwaysTrue.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Memory.h" @@ -29,19 +30,16 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" -#include namespace { struct ForceVMCoreLinking { ForceVMCoreLinking() { // We must reference VMCore in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. + // delete it all as dead code, even with whole program optimization. // This is so that globals in the translation units where these functions // are defined are forced to be initialized, populating various // registries. - if (std::getenv("bar") != (char*) -1) + if (llvm::getNonFoldableAlwaysTrue()) return; llvm::LLVMContext Context; (void)new llvm::Module("", Context); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index bae7f0da7022c..f82a43967e67a 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -34,6 +34,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" +#include "llvm/Support/AlwaysTrue.h" #include "llvm/Support/Valgrind.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" @@ -54,14 +55,12 @@ class Triple; namespace { struct ForcePassLinking { ForcePassLinking() { - // We must reference the passes in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - // This is so that globals in the translation units where these functions - // are defined are forced to be initialized, populating various - // registries. - if (std::getenv("bar") != (char *)-1) + // We must reference the passes in such a way that compilers will not delete + // it all as dead code, even with whole program optimization, yet is + // effectively a NO-OP. This is so that globals in the translation units + // where these functions are defined are forced to be initialized, + // populating various registries. + if (llvm::getNonFoldableAlwaysTrue()) return; (void)llvm::createAtomicExpandLegacyPass(); diff --git a/llvm/include/llvm/Support/AlwaysTrue.h b/llvm/include/llvm/Support/AlwaysTrue.h new file mode 100644 index 0000000000000..b6968568c11a0 --- /dev/null +++ b/llvm/include/llvm/Support/AlwaysTrue.h @@ -0,0 +1,25 @@ +//===--- AlwaysTrue.h - Helper for oqaque truthy values --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALWAYS_TRUE_H +#define LLVM_SUPPORT_ALWAYS_TRUE_H + +#include + +namespace llvm { +inline bool getNonFoldableAlwaysTrue() { + // Some parts of the codebase require a "constant true value" used as a + // predicate. These cases require that even with LTO and static linking, + // it's not possible for the compiler to fold the value. As compilers + // aren't smart enough to know that getenv() never returns -1, this will do + // the job. + return std::getenv("LLVM_IGNORED_ENV_VAR") != (char *)-1; +} +} // end namespace llvm + +#endif // LLVM_SUPPORT_ALWAYS_TRUE_H diff --git a/llvm/tools/bugpoint/bugpoint.cpp b/llvm/tools/bugpoint/bugpoint.cpp index e49efdfe7c8e0..87581e80a2496 100644 --- a/llvm/tools/bugpoint/bugpoint.cpp +++ b/llvm/tools/bugpoint/bugpoint.cpp @@ -22,6 +22,7 @@ #include "llvm/LinkAllIR.h" #include "llvm/LinkAllPasses.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Support/AlwaysTrue.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/PluginLoader.h" @@ -111,7 +112,7 @@ int main(int argc, char **argv) { initializeInstCombine(Registry); initializeTarget(Registry); - if (std::getenv("bar") == (char*) -1) { + if (!llvm::getNonFoldableAlwaysTrue()) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); diff --git a/polly/include/polly/LinkAllPasses.h b/polly/include/polly/LinkAllPasses.h index a2f8f33299918..d2e10d1a7acc6 100644 --- a/polly/include/polly/LinkAllPasses.h +++ b/polly/include/polly/LinkAllPasses.h @@ -18,7 +18,7 @@ #include "polly/Support/DumpFunctionPass.h" #include "polly/Support/DumpModulePass.h" #include "llvm/ADT/StringRef.h" -#include +#include "llvm/Support/AlwaysTrue.h" namespace llvm { class Pass; @@ -72,11 +72,10 @@ extern char &CodePreparationID; namespace { struct PollyForcePassLinking { PollyForcePassLinking() { - // We must reference the passes in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - if (std::getenv("bar") != (char *)-1) + // We must reference the passes in such a way that compilers will not delete + // it all as dead code, even with whole program optimization, yet is + // effectively a NO-OP. + if (llvm::getNonFoldableAlwaysTrue()) return; polly::createCodePreparationPass();