Skip to content

Commit 32bcc9f

Browse files
authored
[SandboxVec] Add option -sbvec-allow-file for bisection debugging (#129127)
This new option lets you specify an allow-list of source files and disables vectorization if the IR is not in the list. This can be used for debugging miscompiles.
1 parent db4dd33 commit 32bcc9f

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
3737
// within FPM may register/unregister callbacks, so they need access to
3838
// Context.
3939
sandboxir::FunctionPassManager FPM;
40+
/// \Returns true if we should attempt to vectorize \p SrcFilePath based on
41+
/// `AllowFiles` option.
42+
bool allowFile(const std::string &SrcFilePath);
4043

4144
bool runImpl(Function &F);
4245

llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
1010
#include "llvm/Analysis/TargetTransformInfo.h"
11+
#include "llvm/IR/Module.h"
1112
#include "llvm/SandboxIR/Constant.h"
1213
#include "llvm/Support/CommandLine.h"
1314
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
15+
#include <regex>
1416

1517
using namespace llvm;
1618

@@ -29,6 +31,22 @@ static cl::opt<std::string> UserDefinedPassPipeline(
2931
cl::desc("Comma-separated list of vectorizer passes. If not set "
3032
"we run the predefined pipeline."));
3133

34+
// This option is useful for bisection debugging.
35+
// For example you may use it to figure out which filename is the one causing a
36+
// miscompile. You can specify a regex for the filename like: "/[a-m][^/]*"
37+
// which will enable any file name starting with 'a' to 'm' and disable the
38+
// rest. If the miscompile goes away, then we try "/[n-z][^/]*" for the other
39+
// half of the range, from 'n' to 'z'. If we can reproduce the miscompile then
40+
// we can keep looking in [n-r] and [s-z] and so on, in a binary-search fashion.
41+
//
42+
// Please note that we are using [^/]* and not .* to make sure that we are
43+
// matching the actual filename and not some other directory in the path.
44+
cl::opt<std::string> AllowFiles(
45+
"sbvec-allow-files", cl::init(".*"), cl::Hidden,
46+
cl::desc("Run the vectorizer only on file paths that match any in the "
47+
"list of comma-separated regex's."));
48+
static constexpr const char AllowFilesDelim = ',';
49+
3250
SandboxVectorizerPass::SandboxVectorizerPass() : FPM("fpm") {
3351
if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
3452
// TODO: Add passes to the default pipeline. It currently contains:
@@ -66,6 +84,23 @@ PreservedAnalyses SandboxVectorizerPass::run(Function &F,
6684
return PA;
6785
}
6886

87+
bool SandboxVectorizerPass::allowFile(const std::string &SrcFilePath) {
88+
// Iterate over all files in AllowFiles separated by `AllowFilesDelim`.
89+
size_t DelimPos = 0;
90+
do {
91+
size_t LastPos = DelimPos != 0 ? DelimPos + 1 : DelimPos;
92+
DelimPos = AllowFiles.find(AllowFilesDelim, LastPos);
93+
auto FileNameToMatch = AllowFiles.substr(LastPos, DelimPos - LastPos);
94+
if (FileNameToMatch.empty())
95+
return false;
96+
// Note: This only runs when debugging so its OK not to reuse the regex.
97+
std::regex FileNameRegex(std::string(".*") + FileNameToMatch);
98+
if (std::regex_match(SrcFilePath, FileNameRegex))
99+
return true;
100+
} while (DelimPos != std::string::npos);
101+
return false;
102+
}
103+
69104
bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
70105
if (Ctx == nullptr)
71106
Ctx = std::make_unique<sandboxir::Context>(LLVMF.getContext());
@@ -75,6 +110,13 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
75110
return false;
76111
}
77112

113+
// This is used for debugging.
114+
if (LLVM_UNLIKELY(AllowFiles != ".*")) {
115+
const auto &SrcFilePath = LLVMF.getParent()->getSourceFileName();
116+
if (!allowFile(SrcFilePath))
117+
return false;
118+
}
119+
78120
// If the target claims to have no vector registers early return.
79121
if (!TTI->getNumberOfRegisters(TTI->getRegisterClassForType(true))) {
80122
LLVM_DEBUG(dbgs() << "SBVec: Target has no vector registers, return.\n");
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="some_other_file" %s -S | FileCheck %s --check-prefix=ALLOW_OTHER
2+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="allow_files.ll" %s -S | FileCheck %s --check-prefix=ALLOW_THIS
3+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="al.*_files.ll" %s -S | FileCheck %s --check-prefix=ALLOW_REGEX
4+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="some_file,.*_files.ll,some_other_file" %s -S | FileCheck %s --check-prefix=ALLOW_REGEX_CSV
5+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="allow" %s -S | FileCheck %s --check-prefix=ALLOW_BAD_REGEX
6+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="some_file,some_other_file1,some_other_file2" %s -S | FileCheck %s --check-prefix=ALLOW_OTHER_CSV
7+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" -sbvec-allow-files="" %s -S | FileCheck %s --check-prefix=ALLOW_EMPTY
8+
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" %s -S | FileCheck %s --check-prefix=DEFAULT
9+
10+
; Checks the command-line option `-sbvec-allow-files`.
11+
define void @widen(ptr %ptr) {
12+
; ALLOW_OTHER: store float {{%.*}}, ptr {{%.*}}, align 4
13+
; ALLOW_OTHER: store float {{%.*}}, ptr {{%.*}}, align 4
14+
;
15+
; ALLOW_THIS: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
16+
;
17+
; ALLOW_REGEX: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
18+
;
19+
; ALLOW_REGEX_CSV: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
20+
;
21+
; ALLOW_BAD_REGEX: store float {{%.*}}, ptr {{%.*}}, align 4
22+
; ALLOW_BAD_REGEX: store float {{%.*}}, ptr {{%.*}}, align 4
23+
;
24+
; ALLOW_OTHER_CSV: store float {{%.*}}, ptr {{%.*}}, align 4
25+
; ALLOW_OTHER_CSV: store float {{%.*}}, ptr {{%.*}}, align 4
26+
;
27+
; ALLOW_EMPTY: store float {{%.*}}, ptr {{%.*}}, align 4
28+
; ALLOW_EMPTY: store float {{%.*}}, ptr {{%.*}}, align 4
29+
;
30+
; DEFAULT: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
31+
;
32+
%ptr0 = getelementptr float, ptr %ptr, i32 0
33+
%ptr1 = getelementptr float, ptr %ptr, i32 1
34+
%ld0 = load float, ptr %ptr0
35+
%ld1 = load float, ptr %ptr1
36+
store float %ld0, ptr %ptr0
37+
store float %ld1, ptr %ptr1
38+
ret void
39+
}

0 commit comments

Comments
 (0)