Skip to content

Commit f992ae4

Browse files
committed
Slightly improve the getenv("bar") linking problem
There's been a variation of the following in the code since 2005: if (unoptimizable_true) return; use_this_symbol_to_force_linking(); // unreachable but never removed Way back in 00d5508 it was the win32 call `GetCurrentProcess` but switched to `getenv("bar")` fairly soon after in 63e504f. While that pulled in fewer dependencies and made the code portable, it's a bit of a weird construct. The environment variable used for the `getenv` call is "bar", which is particularly weird to see fly past when you run `ltrace` on a binary linked against LLVM. In this patch I don't try to replace this construct wholesale - it's still required for architectural reasons I'm not able to tackle right now, but I did try and make it slightly less weird and opaque: - It gives the construct a name - The environment variable hints where this comes from and that its value is ignored Combined, this should be a bit of improvement for the next person who wonders what LLVM is up to when they trace their process or see smatterings of `getenv("bar")` dotted around the source.
1 parent 283fd3f commit f992ae4

File tree

8 files changed

+58
-42
lines changed

8 files changed

+58
-42
lines changed

llvm/include/llvm/CodeGen/LinkAllAsmWriterComponents.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,17 @@
1515
#define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H
1616

1717
#include "llvm/IR/BuiltinGCs.h"
18-
#include <cstdlib>
18+
#include "llvm/Support/AlwaysTrue.h"
1919

2020
namespace {
2121
struct ForceAsmWriterLinking {
2222
ForceAsmWriterLinking() {
2323
// We must reference the plug-ins in such a way that compilers will not
2424
// delete it all as dead code, even with whole program optimization,
25-
// yet is effectively a NO-OP. As the compiler isn't smart enough
26-
// to know that getenv() never returns -1, this will do the job.
27-
// This is so that globals in the translation units where these functions
28-
// are defined are forced to be initialized, populating various
29-
// registries.
30-
if (std::getenv("bar") != (char*) -1)
25+
// yet is effectively a NO-OP. This is so that globals in the translation
26+
// units where these functions are defined are forced to be initialized,
27+
// populating various registries.
28+
if (llvm::getNonFoldableAlwaysTrue())
3129
return;
3230

3331
llvm::linkOcamlGCPrinter();

llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,18 @@
1616

1717
#include "llvm/CodeGen/Passes.h"
1818
#include "llvm/CodeGen/SchedulerRegistry.h"
19+
#include "llvm/Support/AlwaysTrue.h"
1920
#include "llvm/Target/TargetMachine.h"
20-
#include <cstdlib>
2121

2222
namespace {
2323
struct ForceCodegenLinking {
2424
ForceCodegenLinking() {
2525
// We must reference the passes in such a way that compilers will not
2626
// delete it all as dead code, even with whole program optimization,
27-
// yet is effectively a NO-OP. As the compiler isn't smart enough
28-
// to know that getenv() never returns -1, this will do the job.
29-
// This is so that globals in the translation units where these functions
30-
// are defined are forced to be initialized, populating various
31-
// registries.
32-
if (std::getenv("bar") != (char*) -1)
27+
// yet is effectively a NO-OP. This is so that globals in the translation
28+
// units where these functions are defined are forced to be initialized,
29+
// populating various registries.
30+
if (llvm::getNonFoldableAlwaysTrue())
3331
return;
3432

3533
(void) llvm::createFastRegisterAllocator();

llvm/include/llvm/ExecutionEngine/MCJIT.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,20 @@
1515
#define LLVM_EXECUTIONENGINE_MCJIT_H
1616

1717
#include "llvm/ExecutionEngine/ExecutionEngine.h"
18+
#include "llvm/Support/AlwaysTrue.h"
1819
#include "llvm/Support/Compiler.h"
19-
#include <cstdlib>
2020

2121
extern "C" LLVM_ABI void LLVMLinkInMCJIT();
2222

2323
namespace {
2424
struct ForceMCJITLinking {
2525
ForceMCJITLinking() {
2626
// We must reference MCJIT in such a way that compilers will not
27-
// delete it all as dead code, even with whole program optimization,
28-
// yet is effectively a NO-OP. As the compiler isn't smart enough
29-
// to know that getenv() never returns -1, this will do the job.
30-
// This is so that globals in the translation units where these functions
31-
// are defined are forced to be initialized, populating various
32-
// registries.
33-
if (std::getenv("bar") != (char*) -1)
27+
// delete it all as dead code, even with whole program optimization, yet
28+
// is effectively a NO-OP. This is so that globals in the translation
29+
// units where these functions are defined are forced to be initialized,
30+
// populating various registries.
31+
if (llvm::getNonFoldableAlwaysTrue())
3432
return;
3533

3634
LLVMLinkInMCJIT();

llvm/include/llvm/LinkAllIR.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/IR/LLVMContext.h"
2222
#include "llvm/IR/Module.h"
2323
#include "llvm/IR/Verifier.h"
24+
#include "llvm/Support/AlwaysTrue.h"
2425
#include "llvm/Support/DynamicLibrary.h"
2526
#include "llvm/Support/MathExtras.h"
2627
#include "llvm/Support/Memory.h"
@@ -29,19 +30,16 @@
2930
#include "llvm/Support/Process.h"
3031
#include "llvm/Support/Program.h"
3132
#include "llvm/Support/Signals.h"
32-
#include <cstdlib>
3333

3434
namespace {
3535
struct ForceVMCoreLinking {
3636
ForceVMCoreLinking() {
3737
// We must reference VMCore in such a way that compilers will not
38-
// delete it all as dead code, even with whole program optimization,
39-
// yet is effectively a NO-OP. As the compiler isn't smart enough
40-
// to know that getenv() never returns -1, this will do the job.
38+
// delete it all as dead code, even with whole program optimization.
4139
// This is so that globals in the translation units where these functions
4240
// are defined are forced to be initialized, populating various
4341
// registries.
44-
if (std::getenv("bar") != (char*) -1)
42+
if (llvm::getNonFoldableAlwaysTrue())
4543
return;
4644
llvm::LLVMContext Context;
4745
(void)new llvm::Module("", Context);

llvm/include/llvm/LinkAllPasses.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "llvm/CodeGen/Passes.h"
3535
#include "llvm/IR/Function.h"
3636
#include "llvm/IR/IRPrintingPasses.h"
37+
#include "llvm/Support/AlwaysTrue.h"
3738
#include "llvm/Support/Valgrind.h"
3839
#include "llvm/Transforms/IPO.h"
3940
#include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -54,14 +55,12 @@ class Triple;
5455
namespace {
5556
struct ForcePassLinking {
5657
ForcePassLinking() {
57-
// We must reference the passes in such a way that compilers will not
58-
// delete it all as dead code, even with whole program optimization,
59-
// yet is effectively a NO-OP. As the compiler isn't smart enough
60-
// to know that getenv() never returns -1, this will do the job.
61-
// This is so that globals in the translation units where these functions
62-
// are defined are forced to be initialized, populating various
63-
// registries.
64-
if (std::getenv("bar") != (char *)-1)
58+
// We must reference the passes in such a way that compilers will not delete
59+
// it all as dead code, even with whole program optimization, yet is
60+
// effectively a NO-OP. This is so that globals in the translation units
61+
// where these functions are defined are forced to be initialized,
62+
// populating various registries.
63+
if (llvm::getNonFoldableAlwaysTrue())
6564
return;
6665

6766
(void)llvm::createAtomicExpandLegacyPass();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===--- AlwaysTrue.h - Helper for oqaque truthy values --*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_SUPPORT_ALWAYS_TRUE_H
10+
#define LLVM_SUPPORT_ALWAYS_TRUE_H
11+
12+
#include <cstdlib>
13+
14+
namespace llvm {
15+
inline bool getNonFoldableAlwaysTrue() {
16+
// Some parts of the codebase require a "constant true value" used as a
17+
// predicate. These cases require that even with LTO and static linking,
18+
// it's not possible for the compiler to fold the value. As compilers
19+
// aren't smart enough to know that getenv() never returns -1, this will do
20+
// the job.
21+
return std::getenv("LLVM_IGNORED_ENV_VAR") != (char *)-1;
22+
}
23+
} // end namespace llvm
24+
25+
#endif // LLVM_SUPPORT_ALWAYS_TRUE_H

llvm/tools/bugpoint/bugpoint.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/LinkAllIR.h"
2323
#include "llvm/LinkAllPasses.h"
2424
#include "llvm/Passes/PassPlugin.h"
25+
#include "llvm/Support/AlwaysTrue.h"
2526
#include "llvm/Support/CommandLine.h"
2627
#include "llvm/Support/InitLLVM.h"
2728
#include "llvm/Support/PluginLoader.h"
@@ -111,7 +112,7 @@ int main(int argc, char **argv) {
111112
initializeInstCombine(Registry);
112113
initializeTarget(Registry);
113114

114-
if (std::getenv("bar") == (char*) -1) {
115+
if (!llvm::getNonFoldableAlwaysTrue()) {
115116
InitializeAllTargets();
116117
InitializeAllTargetMCs();
117118
InitializeAllAsmPrinters();

polly/include/polly/LinkAllPasses.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "polly/Support/DumpFunctionPass.h"
1919
#include "polly/Support/DumpModulePass.h"
2020
#include "llvm/ADT/StringRef.h"
21-
#include <cstdlib>
21+
#include "llvm/Support/AlwaysTrue.h"
2222

2323
namespace llvm {
2424
class Pass;
@@ -72,11 +72,10 @@ extern char &CodePreparationID;
7272
namespace {
7373
struct PollyForcePassLinking {
7474
PollyForcePassLinking() {
75-
// We must reference the passes in such a way that compilers will not
76-
// delete it all as dead code, even with whole program optimization,
77-
// yet is effectively a NO-OP. As the compiler isn't smart enough
78-
// to know that getenv() never returns -1, this will do the job.
79-
if (std::getenv("bar") != (char *)-1)
75+
// We must reference the passes in such a way that compilers will not delete
76+
// it all as dead code, even with whole program optimization, yet is
77+
// effectively a NO-OP.
78+
if (llvm::getNonFoldableAlwaysTrue())
8079
return;
8180

8281
polly::createCodePreparationPass();

0 commit comments

Comments
 (0)