[llvm] [OptBisect] Add opt-bisect-skip option for skipping passes during bisection (PR #152393)
Yonah Goldberg via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 3 11:20:17 PDT 2025
https://github.com/YonahGoldberg updated https://github.com/llvm/llvm-project/pull/152393
>From 329098d16054afc1975327e75ebf02fb0ebe37a5 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 6 Aug 2025 21:28:33 +0000
Subject: [PATCH 1/9] opt bisect skip
---
llvm/include/llvm/IR/OptBisect.h | 8 +++++++-
llvm/lib/IR/OptBisect.cpp | 10 ++++++++--
llvm/test/Other/opt-bisect-skip.ll | 15 +++++++++++++++
3 files changed, 30 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/Other/opt-bisect-skip.ll
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index d813ae933d65e..7b244c833f767 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -14,6 +14,7 @@
#ifndef LLVM_IR_OPTBISECT_H
#define LLVM_IR_OPTBISECT_H
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
@@ -67,7 +68,11 @@ class LLVM_ABI OptBisect : public OptPassGate {
StringRef IRDescription) const override;
/// isEnabled() should return true before calling shouldRunPass().
- bool isEnabled() const override { return BisectLimit != Disabled; }
+ bool isEnabled() const override { return BisectLimit != Disabled || !BisectSkipNumbers.empty(); }
+
+ void addSkip(int SkipNumber) {
+ BisectSkipNumbers.insert(SkipNumber);
+ }
/// Set the new optimization limit and reset the counter. Passing
/// OptBisect::Disabled disables the limiting.
@@ -81,6 +86,7 @@ class LLVM_ABI OptBisect : public OptPassGate {
private:
int BisectLimit = Disabled;
mutable int LastBisectNum = 0;
+ SmallSet<int, 4> BisectSkipNumbers;
};
/// This class implements a mechanism to disable passes and individual
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 29ca268408265..59639f3b1981d 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -37,6 +37,13 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
}),
cl::desc("Maximum optimization to perform"));
+static cl::opt<int> OptBisectSkip("opt-bisect-skip", cl::Hidden,
+ cl::init(OptBisect::Disabled), cl::Optional,
+ cl::cb<void, int>([](int PassNum) {
+ getOptBisector().addSkip(PassNum);
+ }),
+ cl::desc("Skip pass at the given index in the optimization pipeline"));
+
static cl::opt<bool> OptBisectVerbose(
"opt-bisect-verbose",
cl::desc("Show verbose output when opt-bisect-limit is set"), cl::Hidden,
@@ -66,8 +73,7 @@ bool OptBisect::shouldRunPass(StringRef PassName,
assert(isEnabled());
int CurBisectNum = ++LastBisectNum;
- bool ShouldRun = (BisectLimit == -1 || CurBisectNum <= BisectLimit);
- if (OptBisectVerbose)
+ bool ShouldRun = (BisectLimit == -1 || BisectLimit == Disabled || CurBisectNum <= BisectLimit) && !BisectSkipNumbers.contains(CurBisectNum); if (OptBisectVerbose)
printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
return ShouldRun;
}
diff --git a/llvm/test/Other/opt-bisect-skip.ll b/llvm/test/Other/opt-bisect-skip.ll
new file mode 100644
index 0000000000000..da94ad6230527
--- /dev/null
+++ b/llvm/test/Other/opt-bisect-skip.ll
@@ -0,0 +1,15 @@
+; Test that verifies functionality for -opt-bisect-skip
+
+; RUN: opt -O1 -opt-bisect-skip=3 -opt-bisect-skip=7 %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLE-PASS
+; CHECK-DISABLE-PASS: BISECT: running pass (1) annotation2metadata on [module]
+; CHECK-DISABLE-PASS: BISECT: running pass (2) forceattrs on [module]
+; CHECK-DISABLE-PASS: BISECT: NOT running pass (3) inferattrs on [module]
+; CHECK-DISABLE-PASS: BISECT: running pass (4) lower-expect on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (5) simplifycfg on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (6) sroa on foo
+; CHECK-DISABLE-PASS: BISECT: NOT running pass (7) early-cse on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (8) openmp-opt on [module]
+
+define void @foo() {
+ ret void
+}
\ No newline at end of file
>From 723514de5f46c562591fdf634442866498673969 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 6 Aug 2025 21:28:51 +0000
Subject: [PATCH 2/9] format
---
llvm/include/llvm/IR/OptBisect.h | 8 ++++----
llvm/lib/IR/OptBisect.cpp | 15 ++++++++-------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 7b244c833f767..ee787e0580032 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -68,12 +68,12 @@ class LLVM_ABI OptBisect : public OptPassGate {
StringRef IRDescription) const override;
/// isEnabled() should return true before calling shouldRunPass().
- bool isEnabled() const override { return BisectLimit != Disabled || !BisectSkipNumbers.empty(); }
-
- void addSkip(int SkipNumber) {
- BisectSkipNumbers.insert(SkipNumber);
+ bool isEnabled() const override {
+ return BisectLimit != Disabled || !BisectSkipNumbers.empty();
}
+ void addSkip(int SkipNumber) { BisectSkipNumbers.insert(SkipNumber); }
+
/// Set the new optimization limit and reset the counter. Passing
/// OptBisect::Disabled disables the limiting.
void setLimit(int Limit) {
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 59639f3b1981d..defb8a98f9716 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -37,12 +37,10 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
}),
cl::desc("Maximum optimization to perform"));
-static cl::opt<int> OptBisectSkip("opt-bisect-skip", cl::Hidden,
- cl::init(OptBisect::Disabled), cl::Optional,
- cl::cb<void, int>([](int PassNum) {
- getOptBisector().addSkip(PassNum);
- }),
- cl::desc("Skip pass at the given index in the optimization pipeline"));
+static cl::opt<int> OptBisectSkip(
+ "opt-bisect-skip", cl::Hidden, cl::init(OptBisect::Disabled), cl::Optional,
+ cl::cb<void, int>([](int PassNum) { getOptBisector().addSkip(PassNum); }),
+ cl::desc("Skip pass at the given index in the optimization pipeline"));
static cl::opt<bool> OptBisectVerbose(
"opt-bisect-verbose",
@@ -73,7 +71,10 @@ bool OptBisect::shouldRunPass(StringRef PassName,
assert(isEnabled());
int CurBisectNum = ++LastBisectNum;
- bool ShouldRun = (BisectLimit == -1 || BisectLimit == Disabled || CurBisectNum <= BisectLimit) && !BisectSkipNumbers.contains(CurBisectNum); if (OptBisectVerbose)
+ bool ShouldRun = (BisectLimit == -1 || BisectLimit == Disabled ||
+ CurBisectNum <= BisectLimit) &&
+ !BisectSkipNumbers.contains(CurBisectNum);
+ if (OptBisectVerbose)
printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
return ShouldRun;
}
>From 431c13be5ad020febf1fc2e51dd3af5f8384127f Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 6 Aug 2025 21:36:51 +0000
Subject: [PATCH 3/9] comment
---
llvm/include/llvm/IR/OptBisect.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index ee787e0580032..9dcc0077552d4 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -72,6 +72,8 @@ class LLVM_ABI OptBisect : public OptPassGate {
return BisectLimit != Disabled || !BisectSkipNumbers.empty();
}
+ /// Add pass at index SkipNumber to the list of passes to skip
+ /// during bisection.
void addSkip(int SkipNumber) { BisectSkipNumbers.insert(SkipNumber); }
/// Set the new optimization limit and reset the counter. Passing
>From ec6842e2c65af9260284850d17dde4b7c3cf3bf8 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 6 Aug 2025 21:46:32 +0000
Subject: [PATCH 4/9] newline
---
llvm/test/Other/opt-bisect-skip.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Other/opt-bisect-skip.ll b/llvm/test/Other/opt-bisect-skip.ll
index da94ad6230527..0f26e5f46f742 100644
--- a/llvm/test/Other/opt-bisect-skip.ll
+++ b/llvm/test/Other/opt-bisect-skip.ll
@@ -12,4 +12,4 @@
define void @foo() {
ret void
-}
\ No newline at end of file
+}
>From 6b3ed997ddea73cdfdd3a2dc7ad8e225d27363fd Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 20 Aug 2025 21:58:07 +0000
Subject: [PATCH 5/9] renaming
---
llvm/include/llvm/IR/OptBisect.h | 4 ++--
llvm/lib/IR/OptBisect.cpp | 8 ++++----
llvm/test/Other/opt-bisect-skip.ll | 15 ---------------
3 files changed, 6 insertions(+), 21 deletions(-)
delete mode 100644 llvm/test/Other/opt-bisect-skip.ll
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 9dcc0077552d4..bc2294a870389 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -72,9 +72,9 @@ class LLVM_ABI OptBisect : public OptPassGate {
return BisectLimit != Disabled || !BisectSkipNumbers.empty();
}
- /// Add pass at index SkipNumber to the list of passes to skip
+ /// Add pass at index Index to the list of passes to skip
/// during bisection.
- void addSkip(int SkipNumber) { BisectSkipNumbers.insert(SkipNumber); }
+ void disablePassAtIndex(int Index) { BisectSkipNumbers.insert(Index); }
/// Set the new optimization limit and reset the counter. Passing
/// OptBisect::Disabled disables the limiting.
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index defb8a98f9716..8850e8f0c32a6 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -37,10 +37,10 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
}),
cl::desc("Maximum optimization to perform"));
-static cl::opt<int> OptBisectSkip(
- "opt-bisect-skip", cl::Hidden, cl::init(OptBisect::Disabled), cl::Optional,
- cl::cb<void, int>([](int PassNum) { getOptBisector().addSkip(PassNum); }),
- cl::desc("Skip pass at the given index in the optimization pipeline"));
+static cl::list<int> OptDisableIndices(
+ "opt-disable-indices", cl::Hidden, cl::CommaSeparated, cl::Optional,
+ cl::cb<void, int>([](int Index) { getOptBisector().disablePassAtIndex(Index); }),
+ cl::desc("Disable passes at the given indices in the optimization pipeline (comma-separated list)"));
static cl::opt<bool> OptBisectVerbose(
"opt-bisect-verbose",
diff --git a/llvm/test/Other/opt-bisect-skip.ll b/llvm/test/Other/opt-bisect-skip.ll
deleted file mode 100644
index 0f26e5f46f742..0000000000000
--- a/llvm/test/Other/opt-bisect-skip.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; Test that verifies functionality for -opt-bisect-skip
-
-; RUN: opt -O1 -opt-bisect-skip=3 -opt-bisect-skip=7 %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLE-PASS
-; CHECK-DISABLE-PASS: BISECT: running pass (1) annotation2metadata on [module]
-; CHECK-DISABLE-PASS: BISECT: running pass (2) forceattrs on [module]
-; CHECK-DISABLE-PASS: BISECT: NOT running pass (3) inferattrs on [module]
-; CHECK-DISABLE-PASS: BISECT: running pass (4) lower-expect on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (5) simplifycfg on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (6) sroa on foo
-; CHECK-DISABLE-PASS: BISECT: NOT running pass (7) early-cse on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (8) openmp-opt on [module]
-
-define void @foo() {
- ret void
-}
>From 895a1bbba27fac2187bbdd7f251fff800d3883aa Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 20 Aug 2025 22:03:17 +0000
Subject: [PATCH 6/9] format
---
llvm/lib/IR/OptBisect.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 8850e8f0c32a6..e5d64a02455ac 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -37,10 +37,13 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
}),
cl::desc("Maximum optimization to perform"));
-static cl::list<int> OptDisableIndices(
- "opt-disable-indices", cl::Hidden, cl::CommaSeparated, cl::Optional,
- cl::cb<void, int>([](int Index) { getOptBisector().disablePassAtIndex(Index); }),
- cl::desc("Disable passes at the given indices in the optimization pipeline (comma-separated list)"));
+static cl::list<int>
+ OptDisableIndices("opt-disable-indices", cl::Hidden, cl::CommaSeparated,
+ cl::Optional, cl::cb<void, int>([](int Index) {
+ getOptBisector().disablePassAtIndex(Index);
+ }),
+ cl::desc("Disable passes at the given indices in the "
+ "optimization pipeline (comma-separated list)"));
static cl::opt<bool> OptBisectVerbose(
"opt-bisect-verbose",
>From 4b382092d7b7dd2ccf9b02e476a69477bf80d869 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 3 Sep 2025 04:33:27 +0000
Subject: [PATCH 7/9] range support
---
llvm/include/llvm/IR/OptBisect.h | 40 +--
llvm/include/llvm/Support/DebugCounter.h | 17 +-
llvm/include/llvm/Support/Range.h | 80 ++++++
llvm/lib/IR/OptBisect.cpp | 52 ++--
llvm/lib/Support/CMakeLists.txt | 1 +
llvm/lib/Support/DebugCounter.cpp | 79 +-----
llvm/lib/Support/Range.cpp | 140 +++++++++++
llvm/test/Other/debugcounter-multi-ranges.ll | 38 +++
llvm/test/Other/opt-bisect-ranges.ll | 35 +++
llvm/test/Other/opt-disable-indices.ll | 15 ++
.../reduce-chunk-list/reduce-chunk-list.cpp | 47 ++--
llvm/unittests/Support/CMakeLists.txt | 1 +
llvm/unittests/Support/RangeTest.cpp | 233 ++++++++++++++++++
13 files changed, 629 insertions(+), 149 deletions(-)
create mode 100644 llvm/include/llvm/Support/Range.h
create mode 100644 llvm/lib/Support/Range.cpp
create mode 100644 llvm/test/Other/debugcounter-multi-ranges.ll
create mode 100644 llvm/test/Other/opt-bisect-ranges.ll
create mode 100644 llvm/test/Other/opt-disable-indices.ll
create mode 100644 llvm/unittests/Support/RangeTest.cpp
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index bc2294a870389..901fb5625aefd 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -14,11 +14,12 @@
#ifndef LLVM_IR_OPTBISECT_H
#define LLVM_IR_OPTBISECT_H
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
-#include <limits>
+#include "llvm/Support/Range.h"
namespace llvm {
@@ -41,7 +42,7 @@ class OptPassGate {
/// This class implements a mechanism to disable passes and individual
/// optimizations at compile time based on a command line option
-/// (-opt-bisect-limit) in order to perform a bisecting search for
+/// (-opt-bisect) in order to perform a bisecting search for
/// optimization-related problems.
class LLVM_ABI OptBisect : public OptPassGate {
public:
@@ -54,12 +55,12 @@ class LLVM_ABI OptBisect : public OptPassGate {
virtual ~OptBisect() = default;
- /// Checks the bisect limit to determine if the specified pass should run.
+ /// Checks the bisect ranges to determine if the specified pass should run.
///
/// The method prints the name of the pass, its assigned bisect number, and
/// whether or not the pass will be executed. It returns true if the pass
- /// should run, i.e. if the bisect limit is set to -1 or has not yet been
- /// exceeded.
+ /// should run, i.e. if no ranges are specified or the current pass number
+ /// falls within one of the specified ranges.
///
/// Most passes should not call this routine directly. Instead, it is called
/// through helper routines provided by the base classes of the pass. For
@@ -68,27 +69,28 @@ class LLVM_ABI OptBisect : public OptPassGate {
StringRef IRDescription) const override;
/// isEnabled() should return true before calling shouldRunPass().
- bool isEnabled() const override {
- return BisectLimit != Disabled || !BisectSkipNumbers.empty();
- }
+ bool isEnabled() const override { return !BisectRanges.empty(); }
- /// Add pass at index Index to the list of passes to skip
- /// during bisection.
- void disablePassAtIndex(int Index) { BisectSkipNumbers.insert(Index); }
+ /// Parse range specification and set the ranges for bisection.
+ /// Range format: "1-10,20-30,45" (runs passes 1-10, 20-30, and 45)
+ /// Returns true on parsing error.
+ bool parseRanges(StringRef RangeStr);
- /// Set the new optimization limit and reset the counter. Passing
- /// OptBisect::Disabled disables the limiting.
- void setLimit(int Limit) {
- BisectLimit = Limit;
+ /// Set ranges programmatically (for testing or other uses).
+ void setRanges(ArrayRef<Range> Ranges) {
+ BisectRanges.assign(Ranges.begin(), Ranges.end());
LastBisectNum = 0;
}
- static constexpr int Disabled = std::numeric_limits<int>::max();
+ /// Clear all ranges, effectively disabling bisection.
+ void clearRanges() {
+ BisectRanges.clear();
+ LastBisectNum = 0;
+ }
private:
- int BisectLimit = Disabled;
mutable int LastBisectNum = 0;
- SmallSet<int, 4> BisectSkipNumbers;
+ RangeUtils::RangeList BisectRanges;
};
/// This class implements a mechanism to disable passes and individual
diff --git a/llvm/include/llvm/Support/DebugCounter.h b/llvm/include/llvm/Support/DebugCounter.h
index 89349d1ebffee..d6f46ce2346d8 100644
--- a/llvm/include/llvm/Support/DebugCounter.h
+++ b/llvm/include/llvm/Support/DebugCounter.h
@@ -48,6 +48,7 @@
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Range.h"
#include <string>
namespace llvm {
@@ -56,18 +57,10 @@ class raw_ostream;
class DebugCounter {
public:
- struct Chunk {
- int64_t Begin;
- int64_t End;
- LLVM_ABI void print(llvm::raw_ostream &OS);
- bool contains(int64_t Idx) const { return Idx >= Begin && Idx <= End; }
- };
-
- LLVM_ABI static void printChunks(raw_ostream &OS, ArrayRef<Chunk>);
+ // For backward compatibility, alias Range as Chunk
+ using Chunk = Range;
- /// Return true on parsing error and print the error message on the
- /// llvm::errs()
- LLVM_ABI static bool parseChunks(StringRef Str, SmallVector<Chunk> &Res);
+ LLVM_ABI static void printChunks(raw_ostream &OS, ArrayRef<Range> Ranges);
/// Returns a reference to the singleton instance.
LLVM_ABI static DebugCounter &instance();
@@ -176,7 +169,7 @@ class DebugCounter {
uint64_t CurrChunkIdx = 0;
bool IsSet = false;
std::string Desc;
- SmallVector<Chunk> Chunks;
+ SmallVector<Range> Chunks;
};
DenseMap<unsigned, CounterInfo> Counters;
diff --git a/llvm/include/llvm/Support/Range.h b/llvm/include/llvm/Support/Range.h
new file mode 100644
index 0000000000000..c05cced7c7912
--- /dev/null
+++ b/llvm/include/llvm/Support/Range.h
@@ -0,0 +1,80 @@
+//===- llvm/Support/Range.h - Range parsing utility -----------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides utilities for parsing range specifications like "1-10,20-30,45"
+// which are commonly used in debugging and bisection tools.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RANGE_H
+#define LLVM_SUPPORT_RANGE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+
+namespace llvm {
+class raw_ostream;
+} // end namespace llvm
+
+namespace llvm {
+
+/// Represents a range of integers [Begin, End] (inclusive on both ends)
+struct Range {
+ int64_t Begin;
+ int64_t End;
+
+ Range(int64_t Begin, int64_t End) : Begin(Begin), End(End) {}
+ Range(int64_t Single) : Begin(Single), End(Single) {}
+
+ /// Check if the given value is within this range (inclusive)
+ bool contains(int64_t Value) const { return Value >= Begin && Value <= End; }
+
+ /// Check if this range overlaps with another range
+ bool overlaps(const Range &Other) const {
+ return Begin <= Other.End && End >= Other.Begin;
+ }
+
+ /// Get the size of this range
+ int64_t size() const { return End - Begin + 1; }
+
+ bool operator==(const Range &Other) const {
+ return Begin == Other.Begin && End == Other.End;
+ }
+};
+
+/// Utility class for parsing and managing range specifications
+class RangeUtils {
+public:
+ using RangeList = SmallVector<Range, 8>;
+
+ /// Parse a range specification string like "1-10,20-30,45" or "1-10:20-30:45"
+ /// Returns true on error, false on success
+ /// \param RangeStr The string to parse
+ /// \param Ranges Output list of parsed ranges
+ /// \param Separator The separator character to use (',' or ':')
+ static bool parseRanges(StringRef RangeStr, RangeList &Ranges, char Separator = ',');
+
+ /// Check if a value is contained in any of the ranges
+ static bool contains(const RangeList &Ranges, int64_t Value);
+
+ /// Convert ranges back to string representation for debugging
+ static std::string rangesToString(const RangeList &Ranges, char Separator = ',');
+
+ /// Print ranges to output stream (DebugCounter-compatible)
+ static void printRanges(raw_ostream &OS, ArrayRef<Range> Ranges);
+
+ /// Merge adjacent/consecutive ranges into single ranges
+ /// Example: [1-3, 4-6, 8-10] -> [1-6, 8-10]
+ static RangeList mergeAdjacentRanges(ArrayRef<Range> Ranges);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_RANGE_H
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index e5d64a02455ac..ad0dd8930ecc1 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -13,10 +13,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/OptBisect.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Range.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
+#include <cstdlib>
using namespace llvm;
@@ -31,19 +34,34 @@ static OptDisable &getOptDisabler() {
}
static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
- cl::init(OptBisect::Disabled), cl::Optional,
+ cl::init(-1), cl::Optional,
cl::cb<void, int>([](int Limit) {
- getOptBisector().setLimit(Limit);
+ if (Limit == -1) {
+ // -1 means run all passes, which is equivalent to no ranges
+ getOptBisector().clearRanges();
+ } else if (Limit > 0) {
+ // Convert limit to range 1-Limit
+ std::string RangeStr = "1-" + llvm::utostr(Limit);
+ if (getOptBisector().parseRanges(RangeStr)) {
+ errs() << "Error: Invalid limit for -opt-bisect-limit: "
+ << Limit << "\n";
+ exit(1);
+ }
+ }
}),
- cl::desc("Maximum optimization to perform"));
-
-static cl::list<int>
- OptDisableIndices("opt-disable-indices", cl::Hidden, cl::CommaSeparated,
- cl::Optional, cl::cb<void, int>([](int Index) {
- getOptBisector().disablePassAtIndex(Index);
- }),
- cl::desc("Disable passes at the given indices in the "
- "optimization pipeline (comma-separated list)"));
+ cl::desc("Maximum optimization to perform (equivalent to -opt-bisect=1-N)"));
+
+static cl::opt<std::string> OptBisectRanges(
+ "opt-bisect", cl::Hidden, cl::Optional,
+ cl::cb<void, const std::string &>([](const std::string &RangeStr) {
+ if (getOptBisector().parseRanges(RangeStr)) {
+ errs() << "Error: Invalid range specification for -opt-bisect: "
+ << RangeStr << "\n";
+ exit(1);
+ }
+ }),
+ cl::desc("Run optimization passes only for the specified ranges. "
+ "Format: '1-10,20-30,45' (runs passes 1-10, 20-30, and 45)"));
static cl::opt<bool> OptBisectVerbose(
"opt-bisect-verbose",
@@ -69,14 +87,20 @@ static void printPassMessage(StringRef Name, int PassNum, StringRef TargetDesc,
<< " on " << TargetDesc << '\n';
}
+bool OptBisect::parseRanges(StringRef RangeStr) {
+ LastBisectNum = 0;
+ return RangeUtils::parseRanges(RangeStr, BisectRanges);
+}
+
bool OptBisect::shouldRunPass(StringRef PassName,
StringRef IRDescription) const {
assert(isEnabled());
int CurBisectNum = ++LastBisectNum;
- bool ShouldRun = (BisectLimit == -1 || BisectLimit == Disabled ||
- CurBisectNum <= BisectLimit) &&
- !BisectSkipNumbers.contains(CurBisectNum);
+
+ // Check if current pass number falls within any of the specified ranges
+ bool ShouldRun = RangeUtils::contains(BisectRanges, CurBisectNum);
+
if (OptBisectVerbose)
printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
return ShouldRun;
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 10b6101d73277..f6c64579cec5c 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -231,6 +231,7 @@ add_llvm_component_library(LLVMSupport
PluginLoader.cpp
PrettyStackTrace.cpp
RandomNumberGenerator.cpp
+ Range.cpp
Regex.cpp
RewriteBuffer.cpp
RewriteRope.cpp
diff --git a/llvm/lib/Support/DebugCounter.cpp b/llvm/lib/Support/DebugCounter.cpp
index 6b65720440f30..ce01400893724 100644
--- a/llvm/lib/Support/DebugCounter.cpp
+++ b/llvm/lib/Support/DebugCounter.cpp
@@ -9,77 +9,8 @@ using namespace llvm;
namespace llvm {
-void DebugCounter::Chunk::print(llvm::raw_ostream &OS) {
- if (Begin == End)
- OS << Begin;
- else
- OS << Begin << "-" << End;
-}
-
-void DebugCounter::printChunks(raw_ostream &OS, ArrayRef<Chunk> Chunks) {
- if (Chunks.empty()) {
- OS << "empty";
- } else {
- bool IsFirst = true;
- for (auto E : Chunks) {
- if (!IsFirst)
- OS << ':';
- else
- IsFirst = false;
- E.print(OS);
- }
- }
-}
-
-bool DebugCounter::parseChunks(StringRef Str, SmallVector<Chunk> &Chunks) {
- StringRef Remaining = Str;
-
- auto ConsumeInt = [&]() -> int64_t {
- StringRef Number =
- Remaining.take_until([](char c) { return c < '0' || c > '9'; });
- int64_t Res;
- if (Number.getAsInteger(10, Res)) {
- errs() << "Failed to parse int at : " << Remaining << "\n";
- return -1;
- }
- Remaining = Remaining.drop_front(Number.size());
- return Res;
- };
-
- while (1) {
- int64_t Num = ConsumeInt();
- if (Num == -1)
- return true;
- if (!Chunks.empty() && Num <= Chunks[Chunks.size() - 1].End) {
- errs() << "Expected Chunks to be in increasing order " << Num
- << " <= " << Chunks[Chunks.size() - 1].End << "\n";
- return true;
- }
- if (Remaining.starts_with("-")) {
- Remaining = Remaining.drop_front();
- int64_t Num2 = ConsumeInt();
- if (Num2 == -1)
- return true;
- if (Num >= Num2) {
- errs() << "Expected " << Num << " < " << Num2 << " in " << Num << "-"
- << Num2 << "\n";
- return true;
- }
-
- Chunks.push_back({Num, Num2});
- } else {
- Chunks.push_back({Num, Num});
- }
- if (Remaining.starts_with(":")) {
- Remaining = Remaining.drop_front();
- continue;
- }
- if (Remaining.empty())
- break;
- errs() << "Failed to parse at : " << Remaining;
- return true;
- }
- return false;
+void DebugCounter::printChunks(raw_ostream &OS, ArrayRef<Range> Ranges) {
+ RangeUtils::printRanges(OS, Ranges);
}
} // namespace llvm
@@ -185,11 +116,13 @@ void DebugCounter::push_back(const std::string &Val) {
return;
}
StringRef CounterName = CounterPair.first;
- SmallVector<Chunk> Chunks;
+ RangeUtils::RangeList TempRanges;
+ SmallVector<Range> Chunks;
- if (parseChunks(CounterPair.second, Chunks)) {
+ if (RangeUtils::parseRanges(CounterPair.second, TempRanges, ':')) {
return;
}
+ Chunks.assign(TempRanges.begin(), TempRanges.end());
unsigned CounterID = getCounterId(std::string(CounterName));
if (!CounterID) {
diff --git a/llvm/lib/Support/Range.cpp b/llvm/lib/Support/Range.cpp
new file mode 100644
index 0000000000000..4b1952ab8e202
--- /dev/null
+++ b/llvm/lib/Support/Range.cpp
@@ -0,0 +1,140 @@
+//===- llvm/Support/Range.cpp - Range parsing utility ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Range.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+#include <sstream>
+
+using namespace llvm;
+
+bool RangeUtils::parseRanges(StringRef Str, RangeList &Ranges, char Separator) {
+ Ranges.clear();
+
+ if (Str.empty())
+ return false;
+
+ // Split by the specified separator
+ SmallVector<StringRef, 8> Parts;
+ Str.split(Parts, Separator, -1, false);
+
+ // Regex to match either single number or range "num1-num2"
+ Regex RangeRegex("^([0-9]+)(-([0-9]+))?$");
+
+ for (StringRef Part : Parts) {
+ Part = Part.trim();
+ if (Part.empty())
+ continue;
+
+ SmallVector<StringRef, 4> Matches;
+ if (!RangeRegex.match(Part, &Matches)) {
+ errs() << "Invalid range format: '" << Part << "'\n";
+ return true;
+ }
+
+ int64_t Begin, End;
+ if (Matches[1].getAsInteger(10, Begin)) {
+ errs() << "Failed to parse number: '" << Matches[1] << "'\n";
+ return true;
+ }
+
+ if (!Matches[3].empty()) {
+ // Range format "begin-end"
+ if (Matches[3].getAsInteger(10, End)) {
+ errs() << "Failed to parse number: '" << Matches[3] << "'\n";
+ return true;
+ }
+ if (Begin >= End) {
+ errs() << "Invalid range: " << Begin << " >= " << End << "\n";
+ return true;
+ }
+ } else {
+ // Single number
+ End = Begin;
+ }
+
+ // Check ordering constraint (ranges must be in increasing order)
+ if (!Ranges.empty() && Begin <= Ranges.back().End) {
+ errs() << "Expected ranges to be in increasing order: " << Begin
+ << " <= " << Ranges.back().End << "\n";
+ return true;
+ }
+
+ Ranges.push_back(Range(Begin, End));
+ }
+
+ return false;
+}
+
+bool RangeUtils::contains(const RangeList &Ranges, int64_t Value) {
+ for (const Range &R : Ranges) {
+ if (R.contains(Value))
+ return true;
+ }
+ return false;
+}
+
+
+
+std::string RangeUtils::rangesToString(const RangeList &Ranges, char Separator) {
+ std::ostringstream OS;
+ for (size_t I = 0; I < Ranges.size(); ++I) {
+ if (I > 0)
+ OS << Separator;
+ const Range &R = Ranges[I];
+ if (R.Begin == R.End) {
+ OS << R.Begin;
+ } else {
+ OS << R.Begin << "-" << R.End;
+ }
+ }
+ return OS.str();
+}
+
+void RangeUtils::printRanges(raw_ostream &OS, ArrayRef<Range> Ranges) {
+ if (Ranges.empty()) {
+ OS << "empty";
+ } else {
+ bool IsFirst = true;
+ for (const Range &R : Ranges) {
+ if (!IsFirst)
+ OS << ':';
+ else
+ IsFirst = false;
+
+ if (R.Begin == R.End)
+ OS << R.Begin;
+ else
+ OS << R.Begin << "-" << R.End;
+ }
+ }
+}
+
+RangeUtils::RangeList RangeUtils::mergeAdjacentRanges(ArrayRef<Range> Ranges) {
+ if (Ranges.empty())
+ return {};
+
+ RangeList Result;
+ Result.push_back(Ranges[0]);
+
+ for (size_t I = 1; I < Ranges.size(); ++I) {
+ const Range &Current = Ranges[I];
+ Range &Last = Result.back();
+
+ // Check if current range is adjacent to the last merged range
+ if (Current.Begin == Last.End + 1) {
+ // Merge by extending the end of the last range
+ Last.End = Current.End;
+ } else {
+ // Not adjacent, add as separate range
+ Result.push_back(Current);
+ }
+ }
+
+ return Result;
+}
diff --git a/llvm/test/Other/debugcounter-multi-ranges.ll b/llvm/test/Other/debugcounter-multi-ranges.ll
new file mode 100644
index 0000000000000..30cdbc6e40c0b
--- /dev/null
+++ b/llvm/test/Other/debugcounter-multi-ranges.ll
@@ -0,0 +1,38 @@
+; REQUIRES: asserts
+; Test debug counter with multiple ranges using colon separators
+; (DebugCounter uses colon separators to avoid conflicts with cl::CommaSeparated)
+
+; RUN: opt -passes=dce -S -debug-counter=dce-transform=1:3:5 < %s | FileCheck %s --check-prefix=CHECK-COLON
+; RUN: opt -passes=dce -S -debug-counter=dce-transform=1-2:4:6-7 < %s | FileCheck %s --check-prefix=CHECK-MIXED-COLON
+
+; Test that with debug counters on, we can selectively apply transformations
+; using different range syntaxes. All variants should produce the same result.
+
+; Original function has 8 dead instructions that DCE can eliminate
+define void @test() {
+ %dead1 = add i32 1, 2
+ %dead2 = add i32 3, 4
+ %dead3 = add i32 5, 6
+ %dead4 = add i32 7, 8
+ %dead5 = add i32 9, 10
+ %dead6 = add i32 11, 12
+ %dead7 = add i32 13, 14
+ %dead8 = add i32 15, 16
+ ret void
+}
+
+; Test colon separator: apply transformations 1, 3, 5 (eliminate dead2, dead4, dead6)
+; CHECK-COLON-LABEL: @test
+; CHECK-COLON-NEXT: %dead1 = add i32 1, 2
+; CHECK-COLON-NEXT: %dead3 = add i32 5, 6
+; CHECK-COLON-NEXT: %dead5 = add i32 9, 10
+; CHECK-COLON-NEXT: %dead7 = add i32 13, 14
+; CHECK-COLON-NEXT: %dead8 = add i32 15, 16
+; CHECK-COLON-NEXT: ret void
+
+; Test mixed ranges with colon: apply transformations 1-2, 4, 6-7 (eliminate dead2, dead3, dead5, dead7, dead8)
+; CHECK-MIXED-COLON-LABEL: @test
+; CHECK-MIXED-COLON-NEXT: %dead1 = add i32 1, 2
+; CHECK-MIXED-COLON-NEXT: %dead4 = add i32 7, 8
+; CHECK-MIXED-COLON-NEXT: %dead6 = add i32 11, 12
+; CHECK-MIXED-COLON-NEXT: ret void
diff --git a/llvm/test/Other/opt-bisect-ranges.ll b/llvm/test/Other/opt-bisect-ranges.ll
new file mode 100644
index 0000000000000..145cf169ca370
--- /dev/null
+++ b/llvm/test/Other/opt-bisect-ranges.ll
@@ -0,0 +1,35 @@
+; Test that verifies functionality for -opt-bisect with range specifications
+
+; Test basic range functionality: run passes 1-3 and 7-8
+; RUN: opt -O1 -opt-bisect=1-3,7-8 %s 2>&1 | FileCheck %s --check-prefix=CHECK-RANGES
+; CHECK-RANGES: BISECT: running pass (1) annotation2metadata on [module]
+; CHECK-RANGES: BISECT: running pass (2) forceattrs on [module]
+; CHECK-RANGES: BISECT: running pass (3) inferattrs on [module]
+; CHECK-RANGES: BISECT: NOT running pass (4) lower-expect on foo
+; CHECK-RANGES: BISECT: NOT running pass (5) simplifycfg on foo
+; CHECK-RANGES: BISECT: NOT running pass (6) sroa on foo
+; CHECK-RANGES: BISECT: running pass (7) early-cse on foo
+; CHECK-RANGES: BISECT: running pass (8) openmp-opt on [module]
+
+; Test single pass selection: run only pass 5
+; RUN: opt -O1 -opt-bisect=5 %s 2>&1 | FileCheck %s --check-prefix=CHECK-SINGLE
+; CHECK-SINGLE: BISECT: NOT running pass (1) annotation2metadata on [module]
+; CHECK-SINGLE: BISECT: NOT running pass (2) forceattrs on [module]
+; CHECK-SINGLE: BISECT: NOT running pass (3) inferattrs on [module]
+; CHECK-SINGLE: BISECT: NOT running pass (4) lower-expect on foo
+; CHECK-SINGLE: BISECT: running pass (5) simplifycfg on foo
+; CHECK-SINGLE: BISECT: NOT running pass (6) sroa on foo
+
+; Test backward compatibility: -opt-bisect-limit=3 should be equivalent to -opt-bisect=1-3
+; RUN: opt -O1 -opt-bisect-limit=3 %s 2>&1 | FileCheck %s --check-prefix=CHECK-LIMIT
+; CHECK-LIMIT: BISECT: running pass (1) annotation2metadata on [module]
+; CHECK-LIMIT: BISECT: running pass (2) forceattrs on [module]
+; CHECK-LIMIT: BISECT: running pass (3) inferattrs on [module]
+; CHECK-LIMIT: BISECT: NOT running pass (4) lower-expect on foo
+; CHECK-LIMIT: BISECT: NOT running pass (5) simplifycfg on foo
+
+define void @foo() {
+ ret void
+}
+
+
diff --git a/llvm/test/Other/opt-disable-indices.ll b/llvm/test/Other/opt-disable-indices.ll
new file mode 100644
index 0000000000000..52c2b5b1c4ffa
--- /dev/null
+++ b/llvm/test/Other/opt-disable-indices.ll
@@ -0,0 +1,15 @@
+; Test that verifies functionality for -opt-disable-indices
+
+; RUN: opt -O1 -opt-disable-indices=3,7 %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLE-PASS
+; CHECK-DISABLE-PASS: BISECT: running pass (1) annotation2metadata on [module]
+; CHECK-DISABLE-PASS: BISECT: running pass (2) forceattrs on [module]
+; CHECK-DISABLE-PASS: BISECT: NOT running pass (3) inferattrs on [module]
+; CHECK-DISABLE-PASS: BISECT: running pass (4) lower-expect on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (5) simplifycfg on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (6) sroa on foo
+; CHECK-DISABLE-PASS: BISECT: NOT running pass (7) early-cse on foo
+; CHECK-DISABLE-PASS: BISECT: running pass (8) openmp-opt on [module]
+
+define void @foo() {
+ ret void
+}
diff --git a/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp b/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
index dc99859b516db..687367b351a6c 100644
--- a/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
+++ b/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
@@ -11,10 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/Range.h"
using namespace llvm;
@@ -24,29 +23,15 @@ static cl::opt<std::string> StartChunks(cl::Positional, cl::Required);
static cl::opt<bool> Pessimist("pessimist", cl::init(false));
-using Chunk = DebugCounter::Chunk;
-
namespace {
-SmallVector<Chunk> simplifyChunksList(ArrayRef<Chunk> Chunks) {
- SmallVector<Chunk> Res;
- Res.push_back(Chunks.front());
- for (unsigned Idx = 1; Idx < Chunks.size(); Idx++) {
- if (Chunks[Idx].Begin == Res.back().End + 1)
- Res.back().End = Chunks[Idx].End;
- else
- Res.push_back(Chunks[Idx]);
- }
- return Res;
-}
-
-bool isStillInteresting(ArrayRef<Chunk> Chunks) {
- SmallVector<Chunk> SimpleChunks = simplifyChunksList(Chunks);
+bool isStillInteresting(ArrayRef<Range> Chunks) {
+ RangeUtils::RangeList SimpleChunks = RangeUtils::mergeAdjacentRanges(Chunks);
std::string ChunkStr;
{
raw_string_ostream OS(ChunkStr);
- DebugCounter::printChunks(OS, SimpleChunks);
+ RangeUtils::printRanges(OS, SimpleChunks);
}
errs() << "Checking with: " << ChunkStr << "\n";
@@ -73,18 +58,18 @@ bool isStillInteresting(ArrayRef<Chunk> Chunks) {
return Res;
}
-bool increaseGranularity(SmallVector<Chunk> &Chunks) {
+bool increaseGranularity(RangeUtils::RangeList &Chunks) {
errs() << "Increasing granularity\n";
- SmallVector<Chunk> NewChunks;
+ RangeUtils::RangeList NewChunks;
bool SplitOne = false;
for (auto &C : Chunks) {
if (C.Begin == C.End) {
NewChunks.push_back(C);
} else {
- int Half = (C.Begin + C.End) / 2;
- NewChunks.push_back({C.Begin, Half});
- NewChunks.push_back({Half + 1, C.End});
+ int64_t Half = (C.Begin + C.End) / 2;
+ NewChunks.push_back(Range(C.Begin, Half));
+ NewChunks.push_back(Range(Half + 1, C.End));
SplitOne = true;
}
}
@@ -99,10 +84,9 @@ bool increaseGranularity(SmallVector<Chunk> &Chunks) {
int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
- SmallVector<Chunk> CurrChunks;
- if (DebugCounter::parseChunks(StartChunks, CurrChunks)) {
+ RangeUtils::RangeList CurrChunks;
+ if (RangeUtils::parseRanges(StartChunks, CurrChunks, ','))
return 1;
- }
auto Program = sys::findProgramByName(ReproductionCmd);
if (!Program) {
@@ -126,9 +110,10 @@ int main(int argc, char **argv) {
if (CurrChunks.size() == 1)
break;
- Chunk Testing = CurrChunks[Idx];
- errs() << "Trying to remove : ";
- Testing.print(errs());
+ Range Testing = CurrChunks[Idx];
+ errs() << "Trying to remove : " << Testing.Begin;
+ if (Testing.Begin != Testing.End)
+ errs() << "-" << Testing.End;
errs() << "\n";
CurrChunks.erase(CurrChunks.begin() + Idx);
@@ -142,6 +127,6 @@ int main(int argc, char **argv) {
}
errs() << "Minimal Chunks = ";
- DebugCounter::printChunks(llvm::errs(), simplifyChunksList(CurrChunks));
+ RangeUtils::printRanges(llvm::errs(), RangeUtils::mergeAdjacentRanges(CurrChunks));
errs() << "\n";
}
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 868c40b13b9b2..e1821b0172960 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -74,6 +74,7 @@ add_llvm_unittest(SupportTests
ProcessTest.cpp
ProgramTest.cpp
ProgramStackTest.cpp
+ RangeTest.cpp
RecyclerTest.cpp
RegexTest.cpp
ReverseIterationTest.cpp
diff --git a/llvm/unittests/Support/RangeTest.cpp b/llvm/unittests/Support/RangeTest.cpp
new file mode 100644
index 0000000000000..d4a91327bd992
--- /dev/null
+++ b/llvm/unittests/Support/RangeTest.cpp
@@ -0,0 +1,233 @@
+//===- llvm/unittests/Support/RangeTest.cpp - Range tests ----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Range.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(RangeTest, BasicRange) {
+ Range R(5, 10);
+ EXPECT_EQ(R.Begin, 5);
+ EXPECT_EQ(R.End, 10);
+ EXPECT_TRUE(R.contains(5));
+ EXPECT_TRUE(R.contains(7));
+ EXPECT_TRUE(R.contains(10));
+ EXPECT_FALSE(R.contains(4));
+ EXPECT_FALSE(R.contains(11));
+}
+
+TEST(RangeTest, SingleValueRange) {
+ Range R(42);
+ EXPECT_EQ(R.Begin, 42);
+ EXPECT_EQ(R.End, 42);
+ EXPECT_TRUE(R.contains(42));
+ EXPECT_FALSE(R.contains(41));
+ EXPECT_FALSE(R.contains(43));
+}
+
+TEST(RangeTest, RangeOverlaps) {
+ Range R1(1, 5);
+ Range R2(3, 8);
+ Range R3(6, 10);
+ Range R4(11, 15);
+
+ EXPECT_TRUE(R1.overlaps(R2));
+ EXPECT_TRUE(R2.overlaps(R1));
+ EXPECT_TRUE(R2.overlaps(R3));
+ EXPECT_FALSE(R1.overlaps(R3));
+ EXPECT_FALSE(R1.overlaps(R4));
+ EXPECT_FALSE(R3.overlaps(R4));
+}
+
+TEST(RangeUtilsTest, ParseSingleNumber) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("42", Ranges));
+ EXPECT_EQ(Ranges.size(), 1U);
+ EXPECT_EQ(Ranges[0].Begin, 42);
+ EXPECT_EQ(Ranges[0].End, 42);
+}
+
+TEST(RangeUtilsTest, ParseSingleRange) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("10-20", Ranges));
+ EXPECT_EQ(Ranges.size(), 1U);
+ EXPECT_EQ(Ranges[0].Begin, 10);
+ EXPECT_EQ(Ranges[0].End, 20);
+}
+
+TEST(RangeUtilsTest, ParseMultipleRanges) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_EQ(Ranges.size(), 3U);
+
+ // Ranges are in input order (DebugCounter style)
+ EXPECT_EQ(Ranges[0].Begin, 1);
+ EXPECT_EQ(Ranges[0].End, 5);
+ EXPECT_EQ(Ranges[1].Begin, 10);
+ EXPECT_EQ(Ranges[1].End, 10);
+ EXPECT_EQ(Ranges[2].Begin, 15);
+ EXPECT_EQ(Ranges[2].End, 20);
+}
+
+TEST(RangeUtilsTest, ParseColonSeparated) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5:10:15-20", Ranges));
+ EXPECT_EQ(Ranges.size(), 3U);
+ EXPECT_EQ(Ranges[0].Begin, 1);
+ EXPECT_EQ(Ranges[0].End, 5);
+ EXPECT_EQ(Ranges[1].Begin, 10);
+ EXPECT_EQ(Ranges[1].End, 10);
+ EXPECT_EQ(Ranges[2].Begin, 15);
+ EXPECT_EQ(Ranges[2].End, 20);
+}
+
+TEST(RangeUtilsTest, ParseEmptyString) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("", Ranges));
+ EXPECT_TRUE(Ranges.empty());
+}
+
+TEST(RangeUtilsTest, ParseInvalidRanges) {
+ RangeUtils::RangeList Ranges;
+
+ // Invalid number
+ EXPECT_TRUE(RangeUtils::parseRanges("abc", Ranges));
+
+ // Invalid range (begin > end)
+ EXPECT_TRUE(RangeUtils::parseRanges("10-5", Ranges));
+
+ // Out of order ranges (DebugCounter constraint)
+ EXPECT_TRUE(RangeUtils::parseRanges("10,5", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5,3-7", Ranges)); // Overlapping
+}
+
+TEST(RangeUtilsTest, Contains) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 1));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 3));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 5));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 10));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 15));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 18));
+ EXPECT_TRUE(RangeUtils::contains(Ranges, 20));
+
+ EXPECT_FALSE(RangeUtils::contains(Ranges, 6));
+ EXPECT_FALSE(RangeUtils::contains(Ranges, 9));
+ EXPECT_FALSE(RangeUtils::contains(Ranges, 11));
+ EXPECT_FALSE(RangeUtils::contains(Ranges, 14));
+ EXPECT_FALSE(RangeUtils::contains(Ranges, 21));
+}
+
+TEST(RangeUtilsTest, RangesToString) {
+ RangeUtils::RangeList Ranges;
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+
+ std::string Result = RangeUtils::rangesToString(Ranges);
+ EXPECT_EQ(Result, "1-5,10,15-20");
+}
+
+TEST(RangeUtilsTest, SeparatorParameter) {
+ RangeUtils::RangeList ColonRanges, CommaRanges;
+
+ // Test explicit separator parameters
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5:10:15-20", ColonRanges, ':'));
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", CommaRanges, ','));
+
+ EXPECT_EQ(ColonRanges.size(), CommaRanges.size());
+ for (size_t I = 0; I < ColonRanges.size(); ++I) {
+ EXPECT_EQ(ColonRanges[I].Begin, CommaRanges[I].Begin);
+ EXPECT_EQ(ColonRanges[I].End, CommaRanges[I].End);
+ }
+
+ // Test that both work with contains()
+ EXPECT_TRUE(RangeUtils::contains(ColonRanges, 3));
+ EXPECT_TRUE(RangeUtils::contains(CommaRanges, 3));
+ EXPECT_TRUE(RangeUtils::contains(ColonRanges, 10));
+ EXPECT_TRUE(RangeUtils::contains(CommaRanges, 10));
+ EXPECT_TRUE(RangeUtils::contains(ColonRanges, 18));
+ EXPECT_TRUE(RangeUtils::contains(CommaRanges, 18));
+
+ EXPECT_FALSE(RangeUtils::contains(ColonRanges, 8));
+ EXPECT_FALSE(RangeUtils::contains(CommaRanges, 8));
+}
+
+TEST(RangeUtilsTest, DefaultCommaSeparator) {
+ RangeUtils::RangeList Ranges;
+
+ // Test that comma is the default separator
+ EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_EQ(Ranges.size(), 3U);
+ EXPECT_EQ(Ranges[0].Begin, 1);
+ EXPECT_EQ(Ranges[0].End, 5);
+ EXPECT_EQ(Ranges[1].Begin, 10);
+ EXPECT_EQ(Ranges[1].End, 10);
+ EXPECT_EQ(Ranges[2].Begin, 15);
+ EXPECT_EQ(Ranges[2].End, 20);
+}
+
+TEST(RangeTest, MergeAdjacentRanges) {
+ RangeUtils::RangeList Input, Expected, Result;
+
+ // Empty input
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_TRUE(Result.empty());
+
+ // Single range - no change
+ Input.push_back(Range(5, 10));
+ Expected.push_back(Range(5, 10));
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_EQ(Expected, Result);
+
+ // Adjacent ranges should merge
+ Input.clear();
+ Expected.clear();
+ Input.push_back(Range(1, 3));
+ Input.push_back(Range(4, 6));
+ Input.push_back(Range(7, 9));
+ Expected.push_back(Range(1, 9));
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_EQ(Expected, Result);
+
+ // Non-adjacent ranges should not merge
+ Input.clear();
+ Expected.clear();
+ Input.push_back(Range(1, 3));
+ Input.push_back(Range(5, 7)); // Gap between 3 and 5
+ Input.push_back(Range(10, 12)); // Gap between 7 and 10
+ Expected.push_back(Range(1, 3));
+ Expected.push_back(Range(5, 7));
+ Expected.push_back(Range(10, 12));
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_EQ(Expected, Result);
+
+ // Mixed adjacent and non-adjacent
+ Input.clear();
+ Expected.clear();
+ Input.push_back(Range(1, 3));
+ Input.push_back(Range(4, 6)); // Adjacent to first
+ Input.push_back(Range(8, 10)); // Gap
+ Input.push_back(Range(11, 13)); // Adjacent to third
+ Input.push_back(Range(14, 16)); // Adjacent to fourth
+ Expected.push_back(Range(1, 6)); // Merged 1-3 and 4-6
+ Expected.push_back(Range(8, 16)); // Merged 8-10, 11-13, 14-16
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_EQ(Expected, Result);
+
+ // Single numbers that are adjacent
+ Input.clear();
+ Expected.clear();
+ Input.push_back(Range(5));
+ Input.push_back(Range(6));
+ Input.push_back(Range(7));
+ Expected.push_back(Range(5, 7));
+ Result = RangeUtils::mergeAdjacentRanges(Input);
+ EXPECT_EQ(Expected, Result);
+}
>From d3f5add03c73de80b56a4bc8262d5b8a6273f000 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 3 Sep 2025 04:53:04 +0000
Subject: [PATCH 8/9] small changes
---
llvm/include/llvm/IR/OptBisect.h | 2 +-
llvm/include/llvm/Support/Range.h | 2 +-
llvm/lib/IR/OptBisect.cpp | 5 ++--
llvm/lib/Support/DebugCounter.cpp | 2 +-
llvm/lib/Support/Range.cpp | 14 +++++------
.../reduce-chunk-list/reduce-chunk-list.cpp | 2 +-
llvm/unittests/Support/RangeTest.cpp | 24 +++++++++----------
7 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 901fb5625aefd..680f4469402af 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -73,7 +73,7 @@ class LLVM_ABI OptBisect : public OptPassGate {
/// Parse range specification and set the ranges for bisection.
/// Range format: "1-10,20-30,45" (runs passes 1-10, 20-30, and 45)
- /// Returns true on parsing error.
+ /// Returns false on parsing error.
bool parseRanges(StringRef RangeStr);
/// Set ranges programmatically (for testing or other uses).
diff --git a/llvm/include/llvm/Support/Range.h b/llvm/include/llvm/Support/Range.h
index c05cced7c7912..56a92ffb1437a 100644
--- a/llvm/include/llvm/Support/Range.h
+++ b/llvm/include/llvm/Support/Range.h
@@ -55,7 +55,7 @@ class RangeUtils {
using RangeList = SmallVector<Range, 8>;
/// Parse a range specification string like "1-10,20-30,45" or "1-10:20-30:45"
- /// Returns true on error, false on success
+ /// Returns false on error, true on success
/// \param RangeStr The string to parse
/// \param Ranges Output list of parsed ranges
/// \param Separator The separator character to use (',' or ':')
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index ad0dd8930ecc1..3e29d8955900d 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -42,7 +42,7 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
} else if (Limit > 0) {
// Convert limit to range 1-Limit
std::string RangeStr = "1-" + llvm::utostr(Limit);
- if (getOptBisector().parseRanges(RangeStr)) {
+ if (!getOptBisector().parseRanges(RangeStr)) {
errs() << "Error: Invalid limit for -opt-bisect-limit: "
<< Limit << "\n";
exit(1);
@@ -54,7 +54,7 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
static cl::opt<std::string> OptBisectRanges(
"opt-bisect", cl::Hidden, cl::Optional,
cl::cb<void, const std::string &>([](const std::string &RangeStr) {
- if (getOptBisector().parseRanges(RangeStr)) {
+ if (!getOptBisector().parseRanges(RangeStr)) {
errs() << "Error: Invalid range specification for -opt-bisect: "
<< RangeStr << "\n";
exit(1);
@@ -88,7 +88,6 @@ static void printPassMessage(StringRef Name, int PassNum, StringRef TargetDesc,
}
bool OptBisect::parseRanges(StringRef RangeStr) {
- LastBisectNum = 0;
return RangeUtils::parseRanges(RangeStr, BisectRanges);
}
diff --git a/llvm/lib/Support/DebugCounter.cpp b/llvm/lib/Support/DebugCounter.cpp
index ce01400893724..fed7b0154c3de 100644
--- a/llvm/lib/Support/DebugCounter.cpp
+++ b/llvm/lib/Support/DebugCounter.cpp
@@ -119,7 +119,7 @@ void DebugCounter::push_back(const std::string &Val) {
RangeUtils::RangeList TempRanges;
SmallVector<Range> Chunks;
- if (RangeUtils::parseRanges(CounterPair.second, TempRanges, ':')) {
+ if (!RangeUtils::parseRanges(CounterPair.second, TempRanges, ':')) {
return;
}
Chunks.assign(TempRanges.begin(), TempRanges.end());
diff --git a/llvm/lib/Support/Range.cpp b/llvm/lib/Support/Range.cpp
index 4b1952ab8e202..0948d00f11ed4 100644
--- a/llvm/lib/Support/Range.cpp
+++ b/llvm/lib/Support/Range.cpp
@@ -17,7 +17,7 @@ bool RangeUtils::parseRanges(StringRef Str, RangeList &Ranges, char Separator) {
Ranges.clear();
if (Str.empty())
- return false;
+ return true;
// Split by the specified separator
SmallVector<StringRef, 8> Parts;
@@ -34,24 +34,24 @@ bool RangeUtils::parseRanges(StringRef Str, RangeList &Ranges, char Separator) {
SmallVector<StringRef, 4> Matches;
if (!RangeRegex.match(Part, &Matches)) {
errs() << "Invalid range format: '" << Part << "'\n";
- return true;
+ return false;
}
int64_t Begin, End;
if (Matches[1].getAsInteger(10, Begin)) {
errs() << "Failed to parse number: '" << Matches[1] << "'\n";
- return true;
+ return false;
}
if (!Matches[3].empty()) {
// Range format "begin-end"
if (Matches[3].getAsInteger(10, End)) {
errs() << "Failed to parse number: '" << Matches[3] << "'\n";
- return true;
+ return false;
}
if (Begin >= End) {
errs() << "Invalid range: " << Begin << " >= " << End << "\n";
- return true;
+ return false;
}
} else {
// Single number
@@ -62,13 +62,13 @@ bool RangeUtils::parseRanges(StringRef Str, RangeList &Ranges, char Separator) {
if (!Ranges.empty() && Begin <= Ranges.back().End) {
errs() << "Expected ranges to be in increasing order: " << Begin
<< " <= " << Ranges.back().End << "\n";
- return true;
+ return false;
}
Ranges.push_back(Range(Begin, End));
}
- return false;
+ return true;
}
bool RangeUtils::contains(const RangeList &Ranges, int64_t Value) {
diff --git a/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp b/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
index 687367b351a6c..29cc32e05f7ee 100644
--- a/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
+++ b/llvm/tools/reduce-chunk-list/reduce-chunk-list.cpp
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
RangeUtils::RangeList CurrChunks;
- if (RangeUtils::parseRanges(StartChunks, CurrChunks, ','))
+ if (!RangeUtils::parseRanges(StartChunks, CurrChunks, ','))
return 1;
auto Program = sys::findProgramByName(ReproductionCmd);
diff --git a/llvm/unittests/Support/RangeTest.cpp b/llvm/unittests/Support/RangeTest.cpp
index d4a91327bd992..5719e107b8ce8 100644
--- a/llvm/unittests/Support/RangeTest.cpp
+++ b/llvm/unittests/Support/RangeTest.cpp
@@ -47,7 +47,7 @@ TEST(RangeTest, RangeOverlaps) {
TEST(RangeUtilsTest, ParseSingleNumber) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("42", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("42", Ranges));
EXPECT_EQ(Ranges.size(), 1U);
EXPECT_EQ(Ranges[0].Begin, 42);
EXPECT_EQ(Ranges[0].End, 42);
@@ -55,7 +55,7 @@ TEST(RangeUtilsTest, ParseSingleNumber) {
TEST(RangeUtilsTest, ParseSingleRange) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("10-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("10-20", Ranges));
EXPECT_EQ(Ranges.size(), 1U);
EXPECT_EQ(Ranges[0].Begin, 10);
EXPECT_EQ(Ranges[0].End, 20);
@@ -63,7 +63,7 @@ TEST(RangeUtilsTest, ParseSingleRange) {
TEST(RangeUtilsTest, ParseMultipleRanges) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
EXPECT_EQ(Ranges.size(), 3U);
// Ranges are in input order (DebugCounter style)
@@ -77,7 +77,7 @@ TEST(RangeUtilsTest, ParseMultipleRanges) {
TEST(RangeUtilsTest, ParseColonSeparated) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("1-5:10:15-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5:10:15-20", Ranges));
EXPECT_EQ(Ranges.size(), 3U);
EXPECT_EQ(Ranges[0].Begin, 1);
EXPECT_EQ(Ranges[0].End, 5);
@@ -89,7 +89,7 @@ TEST(RangeUtilsTest, ParseColonSeparated) {
TEST(RangeUtilsTest, ParseEmptyString) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("", Ranges));
EXPECT_TRUE(Ranges.empty());
}
@@ -97,19 +97,19 @@ TEST(RangeUtilsTest, ParseInvalidRanges) {
RangeUtils::RangeList Ranges;
// Invalid number
- EXPECT_TRUE(RangeUtils::parseRanges("abc", Ranges));
+ EXPECT_FALSE(RangeUtils::parseRanges("abc", Ranges));
// Invalid range (begin > end)
- EXPECT_TRUE(RangeUtils::parseRanges("10-5", Ranges));
+ EXPECT_FALSE(RangeUtils::parseRanges("10-5", Ranges));
// Out of order ranges (DebugCounter constraint)
- EXPECT_TRUE(RangeUtils::parseRanges("10,5", Ranges));
+ EXPECT_FALSE(RangeUtils::parseRanges("10,5", Ranges));
EXPECT_TRUE(RangeUtils::parseRanges("1-5,3-7", Ranges)); // Overlapping
}
TEST(RangeUtilsTest, Contains) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
EXPECT_TRUE(RangeUtils::contains(Ranges, 1));
EXPECT_TRUE(RangeUtils::contains(Ranges, 3));
@@ -128,7 +128,7 @@ TEST(RangeUtilsTest, Contains) {
TEST(RangeUtilsTest, RangesToString) {
RangeUtils::RangeList Ranges;
- EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
std::string Result = RangeUtils::rangesToString(Ranges);
EXPECT_EQ(Result, "1-5,10,15-20");
@@ -138,7 +138,7 @@ TEST(RangeUtilsTest, SeparatorParameter) {
RangeUtils::RangeList ColonRanges, CommaRanges;
// Test explicit separator parameters
- EXPECT_FALSE(RangeUtils::parseRanges("1-5:10:15-20", ColonRanges, ':'));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5:10:15-20", ColonRanges, ':'));
EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", CommaRanges, ','));
EXPECT_EQ(ColonRanges.size(), CommaRanges.size());
@@ -163,7 +163,7 @@ TEST(RangeUtilsTest, DefaultCommaSeparator) {
RangeUtils::RangeList Ranges;
// Test that comma is the default separator
- EXPECT_FALSE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
+ EXPECT_TRUE(RangeUtils::parseRanges("1-5,10,15-20", Ranges));
EXPECT_EQ(Ranges.size(), 3U);
EXPECT_EQ(Ranges[0].Begin, 1);
EXPECT_EQ(Ranges[0].End, 5);
>From 6f20867970219fea1b496ede854b0c6b3577f07b Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Wed, 3 Sep 2025 18:19:58 +0000
Subject: [PATCH 9/9] remove opt-disable-indices
---
llvm/test/Other/opt-disable-indices.ll | 15 ---------------
1 file changed, 15 deletions(-)
delete mode 100644 llvm/test/Other/opt-disable-indices.ll
diff --git a/llvm/test/Other/opt-disable-indices.ll b/llvm/test/Other/opt-disable-indices.ll
deleted file mode 100644
index 52c2b5b1c4ffa..0000000000000
--- a/llvm/test/Other/opt-disable-indices.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; Test that verifies functionality for -opt-disable-indices
-
-; RUN: opt -O1 -opt-disable-indices=3,7 %s 2>&1 | FileCheck %s --check-prefix=CHECK-DISABLE-PASS
-; CHECK-DISABLE-PASS: BISECT: running pass (1) annotation2metadata on [module]
-; CHECK-DISABLE-PASS: BISECT: running pass (2) forceattrs on [module]
-; CHECK-DISABLE-PASS: BISECT: NOT running pass (3) inferattrs on [module]
-; CHECK-DISABLE-PASS: BISECT: running pass (4) lower-expect on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (5) simplifycfg on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (6) sroa on foo
-; CHECK-DISABLE-PASS: BISECT: NOT running pass (7) early-cse on foo
-; CHECK-DISABLE-PASS: BISECT: running pass (8) openmp-opt on [module]
-
-define void @foo() {
- ret void
-}
More information about the llvm-commits
mailing list