Skip to content

[SandboxVec] Add option -sbvec-allow-file for bisection debugging #129127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
// within FPM may register/unregister callbacks, so they need access to
// Context.
sandboxir::FunctionPassManager FPM;
/// \Returns true if we should attempt to vectorize \p SrcFilePath based on
/// `AllowFiles` option.
bool allowFile(const std::string &SrcFilePath);

bool runImpl(Function &F);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/SandboxIR/Constant.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
#include <regex>

using namespace llvm;

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

// This option is useful for bisection debugging.
// For example you may use it to figure out which filename is the one causing a
// miscompile. You can specify a regex for the filename like: "/[a-m][^/]*"
// which will enable any file name starting with 'a' to 'm' and disable the
// rest. If the miscompile goes away, then we try "/[n-z][^/]*" for the other
// half of the range, from 'n' to 'z'. If we can reproduce the miscompile then
// we can keep looking in [n-r] and [s-z] and so on, in a binary-search fashion.
//
// Please note that we are using [^/]* and not .* to make sure that we are
// matching the actual filename and not some other directory in the path.
cl::opt<std::string> AllowFiles(
"sbvec-allow-files", cl::init(".*"), cl::Hidden,
cl::desc("Run the vectorizer only on file paths that match any in the "
"list of comma-separated regex's."));
static constexpr const char AllowFilesDelim = ',';

SandboxVectorizerPass::SandboxVectorizerPass() : FPM("fpm") {
if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
// TODO: Add passes to the default pipeline. It currently contains:
Expand Down Expand Up @@ -66,6 +84,23 @@ PreservedAnalyses SandboxVectorizerPass::run(Function &F,
return PA;
}

bool SandboxVectorizerPass::allowFile(const std::string &SrcFilePath) {
// Iterate over all files in AllowFiles separated by `AllowFilesDelim`.
size_t DelimPos = 0;
do {
size_t LastPos = DelimPos != 0 ? DelimPos + 1 : DelimPos;
DelimPos = AllowFiles.find(AllowFilesDelim, LastPos);
auto FileNameToMatch = AllowFiles.substr(LastPos, DelimPos - LastPos);
if (FileNameToMatch.empty())
return false;
// Note: This only runs when debugging so its OK not to reuse the regex.
std::regex FileNameRegex(std::string(".*") + FileNameToMatch);
if (std::regex_match(SrcFilePath, FileNameRegex))
return true;
} while (DelimPos != std::string::npos);
return false;
}

bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
if (Ctx == nullptr)
Ctx = std::make_unique<sandboxir::Context>(LLVMF.getContext());
Expand All @@ -75,6 +110,13 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
return false;
}

// This is used for debugging.
if (LLVM_UNLIKELY(AllowFiles != ".*")) {
const auto &SrcFilePath = LLVMF.getParent()->getSourceFileName();
if (!allowFile(SrcFilePath))
return false;
}

// If the target claims to have no vector registers early return.
if (!TTI->getNumberOfRegisters(TTI->getRegisterClassForType(true))) {
LLVM_DEBUG(dbgs() << "SBVec: Target has no vector registers, return.\n");
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/Transforms/SandboxVectorizer/allow_files.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; 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
; 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
; 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
; 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
; 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
; 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
; 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
; 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

; Checks the command-line option `-sbvec-allow-files`.
define void @widen(ptr %ptr) {
; ALLOW_OTHER: store float {{%.*}}, ptr {{%.*}}, align 4
; ALLOW_OTHER: store float {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_THIS: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_REGEX: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_REGEX_CSV: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_BAD_REGEX: store float {{%.*}}, ptr {{%.*}}, align 4
; ALLOW_BAD_REGEX: store float {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_OTHER_CSV: store float {{%.*}}, ptr {{%.*}}, align 4
; ALLOW_OTHER_CSV: store float {{%.*}}, ptr {{%.*}}, align 4
;
; ALLOW_EMPTY: store float {{%.*}}, ptr {{%.*}}, align 4
; ALLOW_EMPTY: store float {{%.*}}, ptr {{%.*}}, align 4
;
; DEFAULT: store <2 x float> {{%.*}}, ptr {{%.*}}, align 4
;
%ptr0 = getelementptr float, ptr %ptr, i32 0
%ptr1 = getelementptr float, ptr %ptr, i32 1
%ld0 = load float, ptr %ptr0
%ld1 = load float, ptr %ptr1
store float %ld0, ptr %ptr0
store float %ld1, ptr %ptr1
ret void
}