[llvm] [SLSR] Skip candidate-basis differences when `SCEVUnknown`s differ (NFCI) (PR #217451)
Justin Fargnoli via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 19:00:49 PDT 2026
https://github.com/justinfargnoli updated https://github.com/llvm/llvm-project/pull/217451
>From ccc21e9996ac43a5e227f6543a2162106cb7355e Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Wed, 19 Aug 2026 20:44:52 +0000
Subject: [PATCH 1/3] [SLSR] Add pre-commit test for mismatched SCEVUnknowns
(NFC)
---
.../NVPTX/scev-unknown-filtering.ll | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
new file mode 100644
index 0000000000000..42c855f7ff584
--- /dev/null
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; REQUIRES: asserts
+; RUN: opt -passes=slsr -stats -S < %s 2> %t.stats | FileCheck %s
+; RUN: FileCheck %s --check-prefix=STATS < %t.stats
+
+; TODO: Avoid computing the candidate-basis difference between %candidate and
+; %other.basis after finding a reusable variable delta. Their different
+; symbolic leaves mean their difference cannot be constant.
+;
+; STATS: 4 slsr - Number of candidate-basis SCEV differences computed by SLSR
+
+target triple = "nvptx64-nvidia-cuda"
+
+define ptr @different_unknowns(ptr %root, i64 %idx, i64 %other) {
+; CHECK-LABEL: define ptr @different_unknowns(
+; CHECK-SAME: ptr [[ROOT:%.*]], i64 [[IDX:%.*]], i64 [[OTHER:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[IDX_MINUS_4:%.*]] = sub i64 [[IDX]], 4
+; CHECK-NEXT: [[CONST_DELTA_BASIS:%.*]] = getelementptr i8, ptr [[ROOT]], i64 [[IDX_MINUS_4]]
+; CHECK-NEXT: [[OTHER_BASIS:%.*]] = getelementptr i8, ptr [[ROOT]], i64 [[OTHER]]
+; CHECK-NEXT: [[VAR_DELTA_BASIS:%.*]] = getelementptr i8, ptr [[ROOT]], i64 0
+; CHECK-NEXT: [[CANDIDATE:%.*]] = getelementptr i8, ptr [[CONST_DELTA_BASIS]], i64 4
+; CHECK-NEXT: ret ptr [[CANDIDATE]]
+;
+entry:
+ %idx.minus.4 = sub i64 %idx, 4
+ %const.delta.basis = getelementptr i8, ptr %root, i64 %idx.minus.4
+ %other.basis = getelementptr i8, ptr %root, i64 %other
+ %var.delta.basis = getelementptr i8, ptr %root, i64 0
+ %candidate = getelementptr i8, ptr %root, i64 %idx
+ ret ptr %candidate
+}
>From ad0884ccb9c38925a8a1c740f907690006405788 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Wed, 19 Aug 2026 20:44:52 +0000
Subject: [PATCH 2/3] [SLSR] Skip candidate differences with mismatched
SCEVUnknowns
---
llvm/include/llvm/Analysis/ScalarEvolution.h | 8 ++++++
llvm/lib/Analysis/ScalarEvolution.cpp | 27 +++++++++++++++++++
.../Scalar/StraightLineStrengthReduce.cpp | 12 +++++++++
.../NVPTX/scev-candidate-differences.ll | 2 +-
.../NVPTX/scev-unknown-filtering.ll | 10 ++++---
.../Analysis/ScalarEvolutionTest.cpp | 23 ++++++++++++++++
6 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 4f59bc99cb697..2d12fdeb198c8 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -704,6 +704,10 @@ class ScalarEvolution {
/// scAddRecExpr. The result will be cached in HasRecMap.
LLVM_ABI bool containsAddRecurrence(const SCEV *S);
+ /// Return whether \p A and \p B contain the same set of SCEVUnknowns.
+ /// Results are cached in SCEVUnknownsCache.
+ LLVM_ABI bool hasSameSCEVUnknowns(const SCEV *A, const SCEV *B);
+
/// Is operation \p BinOp between \p LHS and \p RHS provably does not have
/// a signed/unsigned overflow (\p Signed)? If \p CtxI is specified, the
/// no-overflow fact should be true in the context of this instruction.
@@ -1707,6 +1711,10 @@ class ScalarEvolution {
/// This is a cache to record whether a SCEV contains any scAddRecExpr.
HasRecMapType HasRecMap;
+ using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
+
+ DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
+
/// The type for ExprValueMap.
using ValueSetVector = SmallSetVector<Value *, 4>;
using ExprValueMapType = DenseMap<const SCEV *, ValueSetVector>;
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index f6ad701ce819e..884923e5dbf5a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4532,6 +4532,30 @@ bool ScalarEvolution::containsAddRecurrence(const SCEV *S) {
return FoundAddRec;
}
+bool ScalarEvolution::hasSameSCEVUnknowns(const SCEV *A, const SCEV *B) {
+ auto CacheUnknowns = [&](const SCEV *Root) {
+ auto [It, Inserted] = SCEVUnknownsCache.try_emplace(Root);
+ if (!Inserted)
+ return;
+
+ struct Collector {
+ SCEVUnknownSet &Unknowns;
+
+ bool follow(const SCEV *S) {
+ if (auto *Unknown = dyn_cast<SCEVUnknown>(S))
+ Unknowns.insert(Unknown);
+ return true;
+ }
+ bool isDone() const { return false; }
+ } C{It->second};
+ visitAll(Root, C);
+ };
+ CacheUnknowns(A);
+ CacheUnknowns(B);
+
+ return SCEVUnknownsCache.find(A)->second == SCEVUnknownsCache.find(B)->second;
+}
+
/// Return the ValueOffsetPair set for \p S. \p S can be represented
/// by the value and offset from any ValueOffsetPair in the set.
ArrayRef<Value *> ScalarEvolution::getSCEVValues(const SCEV *S) {
@@ -8635,6 +8659,7 @@ void ScalarEvolution::forgetAllLoops() {
SignedRanges.clear();
ExprValueMap.clear();
HasRecMap.clear();
+ SCEVUnknownsCache.clear();
ConstantMultipleCache.clear();
PredicatedSCEVRewrites.clear();
FoldCache.clear();
@@ -14082,6 +14107,7 @@ ScalarEvolution::~ScalarEvolution() {
ExprValueMap.clear();
ValueExprMap.clear();
HasRecMap.clear();
+ SCEVUnknownsCache.clear();
BackedgeTakenCounts.clear();
PredicatedBackedgeTakenCounts.clear();
@@ -14629,6 +14655,7 @@ void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
UnsignedRanges.erase(S);
SignedRanges.erase(S);
HasRecMap.erase(S);
+ SCEVUnknownsCache.erase(S);
ConstantMultipleCache.erase(S);
if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) {
diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index b1f1f6efc59b1..ea3bebf2ffd5c 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -731,6 +731,18 @@ bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
if (!isSimilar(C, *Basis, K))
return false;
+ // Once a reusable delta is found, only a constant delta can improve it.
+ // Different symbolic leaves cannot cancel to a constant, so such a basis
+ // cannot improve C. Skip it and continue searching older candidates.
+ if (C.Delta && K != Candidate::IndexDelta) {
+ const SCEV *CandidateSCEV =
+ K == Candidate::BaseDelta ? C.Base : C.StrideSCEV;
+ const SCEV *BasisSCEV =
+ K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
+ if (!SE->hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
+ return false;
+ }
+
assert(DT->dominates(Basis->Ins, C.Ins));
Value *Delta = getDelta(C, *Basis, K);
if (!Delta)
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
index ddd1bf4748f5d..ba015e72c4e51 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -1,7 +1,7 @@
; REQUIRES: asserts
; RUN: opt -passes=slsr -stats -disable-output < %s 2>&1 | FileCheck %s
-; CHECK: 8 slsr - Number of candidate-basis SCEV differences computed by SLSR
+; CHECK: 6 slsr - Number of candidate-basis SCEV differences computed by SLSR
target triple = "nvptx64-nvidia-cuda"
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
index 42c855f7ff584..f52d88f2f761d 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
@@ -3,11 +3,13 @@
; RUN: opt -passes=slsr -stats -S < %s 2> %t.stats | FileCheck %s
; RUN: FileCheck %s --check-prefix=STATS < %t.stats
-; TODO: Avoid computing the candidate-basis difference between %candidate and
-; %other.basis after finding a reusable variable delta. Their different
-; symbolic leaves mean their difference cannot be constant.
+; For %candidate, %var.delta.basis first provides the variable delta %idx.
+; %other.basis cannot provide a constant delta because it has different
+; SCEVUnknown leaves. Skip it, then continue to %const.delta.basis and use its
+; constant delta. Without the leaf check, SLSR computes four candidate-basis
+; differences instead of three.
;
-; STATS: 4 slsr - Number of candidate-basis SCEV differences computed by SLSR
+; STATS: 3 slsr - Number of candidate-basis SCEV differences computed by SLSR
target triple = "nvptx64-nvidia-cuda"
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index a94952c3d0c44..decbc158a0e0b 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -125,6 +125,29 @@ TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) {
EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V0);
}
+TEST_F(ScalarEvolutionsTest, SameSCEVUnknowns) {
+ Type *Ty = Type::getInt64Ty(Context);
+ FunctionType *FTy =
+ FunctionType::get(Type::getVoidTy(Context), {Ty, Ty}, false);
+ Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", M);
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+ ReturnInst::Create(Context, nullptr, BB);
+
+ ScalarEvolution SE = buildSE(*F);
+
+ const SCEV *S0 = SE.getSCEV(F->getArg(0));
+ const SCEV *S1 = SE.getSCEV(F->getArg(1));
+ const SCEV *One = SE.getOne(Ty);
+ const SCEV *Two = SE.getConstant(Ty, 2);
+ const SCEV *S0PlusOne = SE.getAddExpr(S0, One);
+ const SCEV *S0PlusTwo = SE.getAddExpr(S0, Two);
+ const SCEV *S0PlusS1 = SE.getAddExpr(S0, S1);
+
+ EXPECT_TRUE(SE.hasSameSCEVUnknowns(S0PlusOne, S0PlusTwo));
+ EXPECT_FALSE(SE.hasSameSCEVUnknowns(S0PlusOne, S0PlusS1));
+ EXPECT_TRUE(SE.hasSameSCEVUnknowns(One, Two));
+}
+
TEST_F(ScalarEvolutionsTest, SimplifiedPHI) {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
std::vector<Type *>(), false);
>From af768633f5ee9f06aa7bd8de07241e92737e985d Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Wed, 26 Aug 2026 02:00:23 +0000
Subject: [PATCH 3/3] Address review feedback
---
llvm/include/llvm/Analysis/ScalarEvolution.h | 8 -----
llvm/lib/Analysis/ScalarEvolution.cpp | 27 ---------------
.../Scalar/StraightLineStrengthReduce.cpp | 33 ++++++++++++++++++-
.../Analysis/ScalarEvolutionTest.cpp | 23 -------------
4 files changed, 32 insertions(+), 59 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 2d12fdeb198c8..4f59bc99cb697 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -704,10 +704,6 @@ class ScalarEvolution {
/// scAddRecExpr. The result will be cached in HasRecMap.
LLVM_ABI bool containsAddRecurrence(const SCEV *S);
- /// Return whether \p A and \p B contain the same set of SCEVUnknowns.
- /// Results are cached in SCEVUnknownsCache.
- LLVM_ABI bool hasSameSCEVUnknowns(const SCEV *A, const SCEV *B);
-
/// Is operation \p BinOp between \p LHS and \p RHS provably does not have
/// a signed/unsigned overflow (\p Signed)? If \p CtxI is specified, the
/// no-overflow fact should be true in the context of this instruction.
@@ -1711,10 +1707,6 @@ class ScalarEvolution {
/// This is a cache to record whether a SCEV contains any scAddRecExpr.
HasRecMapType HasRecMap;
- using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
-
- DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
-
/// The type for ExprValueMap.
using ValueSetVector = SmallSetVector<Value *, 4>;
using ExprValueMapType = DenseMap<const SCEV *, ValueSetVector>;
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 884923e5dbf5a..f6ad701ce819e 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4532,30 +4532,6 @@ bool ScalarEvolution::containsAddRecurrence(const SCEV *S) {
return FoundAddRec;
}
-bool ScalarEvolution::hasSameSCEVUnknowns(const SCEV *A, const SCEV *B) {
- auto CacheUnknowns = [&](const SCEV *Root) {
- auto [It, Inserted] = SCEVUnknownsCache.try_emplace(Root);
- if (!Inserted)
- return;
-
- struct Collector {
- SCEVUnknownSet &Unknowns;
-
- bool follow(const SCEV *S) {
- if (auto *Unknown = dyn_cast<SCEVUnknown>(S))
- Unknowns.insert(Unknown);
- return true;
- }
- bool isDone() const { return false; }
- } C{It->second};
- visitAll(Root, C);
- };
- CacheUnknowns(A);
- CacheUnknowns(B);
-
- return SCEVUnknownsCache.find(A)->second == SCEVUnknownsCache.find(B)->second;
-}
-
/// Return the ValueOffsetPair set for \p S. \p S can be represented
/// by the value and offset from any ValueOffsetPair in the set.
ArrayRef<Value *> ScalarEvolution::getSCEVValues(const SCEV *S) {
@@ -8659,7 +8635,6 @@ void ScalarEvolution::forgetAllLoops() {
SignedRanges.clear();
ExprValueMap.clear();
HasRecMap.clear();
- SCEVUnknownsCache.clear();
ConstantMultipleCache.clear();
PredicatedSCEVRewrites.clear();
FoldCache.clear();
@@ -14107,7 +14082,6 @@ ScalarEvolution::~ScalarEvolution() {
ExprValueMap.clear();
ValueExprMap.clear();
HasRecMap.clear();
- SCEVUnknownsCache.clear();
BackedgeTakenCounts.clear();
PredicatedBackedgeTakenCounts.clear();
@@ -14655,7 +14629,6 @@ void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
UnsignedRanges.erase(S);
SignedRanges.erase(S);
HasRecMap.erase(S);
- SCEVUnknownsCache.erase(S);
ConstantMultipleCache.erase(S);
if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) {
diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index ea3bebf2ffd5c..5c0c5882dba9f 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -72,6 +72,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ScalarEvolution.h"
@@ -420,6 +421,9 @@ class StraightLineStrengthReduce {
// instructions are sorted in depth-first order.
DenseMap<const SCEV *, SmallSetVector<Instruction *, 2>> SCEVToInsts;
+ using SCEVUnknownSet = SmallPtrSet<const SCEVUnknown *, 4>;
+ DenseMap<const SCEV *, SCEVUnknownSet> SCEVUnknownsCache;
+
// Record the dependency between instructions. If C.Basis == B, we would have
// {B.Ins -> {C.Ins, ...}}.
MapVector<Instruction *, std::vector<Instruction *>> DependencyGraph;
@@ -510,6 +514,8 @@ class StraightLineStrengthReduce {
bool candidatePredicate(Candidate *Basis, Candidate &C, Candidate::DKind K);
+ bool hasSameSCEVUnknowns(const SCEV *A, const SCEV *B);
+
bool searchFrom(const CandidateDictTy::BBToCandsTy &BBToCands, Candidate &C,
Candidate::DKind K);
@@ -721,6 +727,31 @@ bool StraightLineStrengthReduce::isSimilar(Candidate &C, Candidate &Basis,
Basis.CandidateKind == C.CandidateKind;
}
+bool StraightLineStrengthReduce::hasSameSCEVUnknowns(const SCEV *A,
+ const SCEV *B) {
+ auto CacheUnknowns = [&](const SCEV *Root) {
+ auto [It, Inserted] = SCEVUnknownsCache.try_emplace(Root);
+ if (!Inserted)
+ return;
+
+ struct Collector {
+ SCEVUnknownSet &Unknowns;
+
+ bool follow(const SCEV *S) {
+ if (auto *Unknown = dyn_cast<SCEVUnknown>(S))
+ Unknowns.insert(Unknown);
+ return true;
+ }
+ bool isDone() const { return false; }
+ } C{It->second};
+ visitAll(Root, C);
+ };
+ CacheUnknowns(A);
+ CacheUnknowns(B);
+
+ return SCEVUnknownsCache.find(A)->second == SCEVUnknownsCache.find(B)->second;
+}
+
// Try to find a Delta that C can reuse Basis to rewrite.
// Set C.Delta, C.Basis, and C.DeltaKind if found.
// Return true if found a constant delta.
@@ -739,7 +770,7 @@ bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
K == Candidate::BaseDelta ? C.Base : C.StrideSCEV;
const SCEV *BasisSCEV =
K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
- if (!SE->hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
+ if (!hasSameSCEVUnknowns(CandidateSCEV, BasisSCEV))
return false;
}
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index decbc158a0e0b..a94952c3d0c44 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -125,29 +125,6 @@ TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) {
EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V0);
}
-TEST_F(ScalarEvolutionsTest, SameSCEVUnknowns) {
- Type *Ty = Type::getInt64Ty(Context);
- FunctionType *FTy =
- FunctionType::get(Type::getVoidTy(Context), {Ty, Ty}, false);
- Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", M);
- BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
- ReturnInst::Create(Context, nullptr, BB);
-
- ScalarEvolution SE = buildSE(*F);
-
- const SCEV *S0 = SE.getSCEV(F->getArg(0));
- const SCEV *S1 = SE.getSCEV(F->getArg(1));
- const SCEV *One = SE.getOne(Ty);
- const SCEV *Two = SE.getConstant(Ty, 2);
- const SCEV *S0PlusOne = SE.getAddExpr(S0, One);
- const SCEV *S0PlusTwo = SE.getAddExpr(S0, Two);
- const SCEV *S0PlusS1 = SE.getAddExpr(S0, S1);
-
- EXPECT_TRUE(SE.hasSameSCEVUnknowns(S0PlusOne, S0PlusTwo));
- EXPECT_FALSE(SE.hasSameSCEVUnknowns(S0PlusOne, S0PlusS1));
- EXPECT_TRUE(SE.hasSameSCEVUnknowns(One, Two));
-}
-
TEST_F(ScalarEvolutionsTest, SimplifiedPHI) {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
std::vector<Type *>(), false);
More information about the llvm-commits
mailing list