Skip to content

Commit e46d70d

Browse files
committed
Resolve llvm#101. Add an early pass called KillUB the removes all UB-enabling flags from LLVM IR. 0.8% regression on PizBench9017, which I think is worth it. I bet the regression is from disabling strict aliasing.
1 parent 61713b4 commit e46d70d

File tree

9 files changed

+136
-16
lines changed

9 files changed

+136
-16
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
7373
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
7474
#include "llvm/Transforms/Instrumentation/KCFI.h"
75+
#include "llvm/Transforms/Instrumentation/KillUB.h"
7576
#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"
7677
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
7778
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
@@ -134,6 +135,8 @@ namespace clang {
134135
extern llvm::cl::opt<bool> ClSanitizeGuardChecks;
135136
}
136137

138+
static cl::opt<bool> FilCKillUB(
139+
"filc-killub", cl::desc("Run the KillUB pass"), cl::Hidden, cl::init(true));
137140
static cl::opt<bool> FilCOptimize(
138141
"filc-optimize", cl::desc("Run Fil-C optimization pipeline"), cl::Hidden, cl::init(true));
139142
static cl::opt<bool> FilCInline(
@@ -1040,6 +1043,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
10401043

10411044
PB.registerPipelineStartEPCallback(
10421045
[](ModulePassManager &MPM, OptimizationLevel Level) {
1046+
if (FilCKillUB)
1047+
MPM.addPass(KillUBPass());
10431048
if (Level != OptimizationLevel::O0 && FilCOptimize) {
10441049
FunctionPassManager EarlyFPM;
10451050
EarlyFPM.addPass(LowerExpectIntrinsicPass());

filc/tests/nullub/manifest

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
return:
2+
success
3+
output-includes:
4+
- "p is null"
5+
output-excludes:
6+
- "p is not null"

filc/tests/nullub/nullub.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdio.h>
2+
#include <stdfil.h>
3+
4+
int main() {
5+
void *p = zandptr((void *)1, ~1ULL);
6+
if (p)
7+
puts("p is not null");
8+
else
9+
puts("p is null");
10+
return 0;
11+
}

filc/tests/strictaliasing/manifest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
return:
2+
success
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <stdfil.h>
2+
3+
static __attribute__((noinline)) int foo(int* p, float* q)
4+
{
5+
int x = *p;
6+
*q = 0;
7+
return x + *p;
8+
}
9+
10+
int main()
11+
{
12+
int x = 42;
13+
ZASSERT(foo(&x, (float*)&x) == 42);
14+
return 0;
15+
}
16+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_KILLUB_H
2+
#define LLVM_TRANSFORMS_INSTRUMENTATION_KILLUB_H
3+
4+
#include "llvm/IR/PassManager.h"
5+
6+
namespace llvm {
7+
8+
class Module;
9+
10+
class KillUBPass : public PassInfoMixin<KillUBPass> {
11+
public:
12+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
13+
static bool isRequired() { return true; }
14+
};
15+
16+
} // namespace llvm
17+
18+
#endif /* LLVM_TRANSFORMS_INSTRUMENTATION_KILLUB_H */
19+

llvm/lib/Transforms/Instrumentation/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_llvm_component_library(LLVMInstrumentation
1414
InstrOrderFile.cpp
1515
InstrProfiling.cpp
1616
KCFI.cpp
17+
KillUB.cpp
1718
LowerAllowCheckPass.cpp
1819
PGOCtxProfFlattening.cpp
1920
PGOCtxProfLowering.cpp

llvm/lib/Transforms/Instrumentation/FilPizlonator.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file is a part of Fil-C.
10-
//
11-
// See here for an overview:
12-
// https://github.com/pizlonator/llvm-project-deluge/blob/deluge/Manifesto.md
13-
//
14-
// This document explains the semantics we're trying to achieve:
15-
// https://github.com/pizlonator/llvm-project-deluge/blob/deluge/gimso_semantics.md
16-
//
17-
// Here is a non-exhaustive set of examples of issues this catches:
18-
// https://github.com/pizlonator/llvm-project-deluge/blob/deluge/invisicaps_by_example.md
19-
//
20-
// And and explanation of the disassembly:
21-
// https://github.com/pizlonator/llvm-project-deluge/blob/deluge/test43.md
22-
//
23-
// This pass strongly relies on the Fil-C runtime and FUGC garbage collector.
24-
// Those components are in the llvm-project/libpas directory.
9+
// This file is a part of Fil-C. https://fil-c.org/
2510
//
2611
//===----------------------------------------------------------------------===//
2712

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===- KillUB.cpp - remove all UB flags -----------------------------------===//
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+
// This file is a part of Fil-C. https://fil-c.org/
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/Transforms/Instrumentation/KillUB.h"
14+
15+
#include <llvm/IR/AttributeMask.h>
16+
#include <llvm/IR/InlineAsm.h>
17+
#include <llvm/IR/Module.h>
18+
#include <llvm/IR/Operator.h>
19+
20+
using namespace llvm;
21+
22+
PreservedAnalyses KillUBPass::run(Module &M, ModuleAnalysisManager&) {
23+
// This is just the beginning! There are probably more UB killings that have to happen.
24+
25+
AttributeMask AM;
26+
AM.addAttribute(Attribute::AllocSize);
27+
AM.addAttribute(Attribute::NoUndef);
28+
AM.addAttribute(Attribute::Convergent);
29+
AM.addAttribute(Attribute::Dereferenceable);
30+
AM.addAttribute(Attribute::DereferenceableOrNull);
31+
AM.addAttribute(Attribute::Memory);
32+
AM.addAttribute(Attribute::NoAlias);
33+
AM.addAttribute(Attribute::NoCallback);
34+
AM.addAttribute(Attribute::NoCapture);
35+
AM.addAttribute(Attribute::Captures);
36+
AM.addAttribute(Attribute::NoDivergenceSource);
37+
AM.addAttribute(Attribute::NoExt);
38+
AM.addAttribute(Attribute::NoFree);
39+
AM.addAttribute(Attribute::DeadOnUnwind);
40+
AM.addAttribute(Attribute::NonNull);
41+
AM.addAttribute(Attribute::NoRecurse);
42+
AM.addAttribute(Attribute::NoRedZone);
43+
AM.addAttribute(Attribute::NoReturn);
44+
AM.addAttribute(Attribute::NoSync);
45+
AM.addAttribute(Attribute::Range);
46+
AM.addAttribute(Attribute::ReadNone);
47+
AM.addAttribute(Attribute::ReadOnly);
48+
AM.addAttribute(Attribute::Returned);
49+
AM.addAttribute(Attribute::Returned);
50+
AM.addAttribute(Attribute::WillReturn);
51+
AM.addAttribute(Attribute::Writable);
52+
AM.addAttribute(Attribute::WriteOnly);
53+
AM.addAttribute(Attribute::MustProgress);
54+
55+
for (Function& F : M) {
56+
if (F.isIntrinsic()) {
57+
assert(F.isDeclaration());
58+
continue;
59+
}
60+
F.removeFnAttrs(AM);
61+
F.removeRetAttrs(AM);
62+
for (size_t Idx = F.arg_size(); Idx--;)
63+
F.removeParamAttrs(Idx, AM);
64+
for (BasicBlock& BB : F) {
65+
for (Instruction& I : BB) {
66+
I.dropUnknownNonDebugMetadata();
67+
I.dropPoisonGeneratingAnnotations();
68+
I.dropUBImplyingAttrsAndUnknownMetadata();
69+
}
70+
}
71+
}
72+
73+
return PreservedAnalyses::none();
74+
}
75+

0 commit comments

Comments
 (0)