[llvm] [SLSR] Skip candidate differences with mismatched SCEVUnknowns (PR #217144)

Justin Fargnoli via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 17:58:43 PDT 2026


https://github.com/justinfargnoli updated https://github.com/llvm/llvm-project/pull/217144

>From e48a2f0bde5bd131144d99860fa6faaa00769ae5 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 21:36:17 +0000
Subject: [PATCH 1/6] [SLSR] Count SCEV candidate differences

---
 .../Scalar/StraightLineStrengthReduce.cpp     |  5 +++++
 .../NVPTX/scev-candidate-differences.ll       | 22 +++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll

diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index 8826127dd7ae3..072575fe6d8ee 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -73,6 +73,7 @@
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ScalarEvolution.h"
 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
@@ -120,6 +121,9 @@ static cl::opt<bool>
     EnablePoisonReuseGuard("enable-poison-reuse-guard", cl::init(true),
                            cl::desc("Enable poison-reuse guard"));
 
+STATISTIC(NumSCEVCandidateDifferences,
+          "Number of SCEV candidate differences computed by SLSR");
+
 namespace {
 
 class StraightLineStrengthReduceLegacyPass : public FunctionPass {
@@ -691,6 +695,7 @@ Value *StraightLineStrengthReduce::getDelta(const Candidate &C,
     const SCEV *BasisPart =
         (K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
     const SCEV *CandPart = (K == Candidate::BaseDelta) ? C.Base : C.StrideSCEV;
+    ++NumSCEVCandidateDifferences;
     const SCEV *Diff = SE->getMinusSCEV(CandPart, BasisPart);
     return getNearestValueOfSCEV(Diff, C.Ins);
   }
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
new file mode 100644
index 0000000000000..08f1d5c473494
--- /dev/null
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -0,0 +1,22 @@
+; REQUIRES: asserts
+; RUN: opt -mtriple=nvptx64-nvidia-cuda -mcpu=sm_100 -passes=slsr -stats \
+; RUN:   -disable-output < %s 2>&1 | FileCheck %s
+
+; CHECK: 2 slsr - Number of SCEV candidate differences computed by SLSR
+
+declare i64 @source(i32)
+declare void @use(ptr)
+
+define void @base_delta(ptr %root, i64 %common) {
+  %offset.0 = call i64 @source(i32 0)
+  %base.0 = getelementptr i8, ptr %root, i64 %offset.0
+  %candidate.0 = getelementptr i8, ptr %base.0, i64 %common
+  call void @use(ptr %candidate.0)
+
+  %delta.1 = call i64 @source(i32 1)
+  %offset.1 = add i64 %offset.0, %delta.1
+  %base.1 = getelementptr i8, ptr %root, i64 %offset.1
+  %candidate.1 = getelementptr i8, ptr %base.1, i64 %common
+  call void @use(ptr %candidate.1)
+  ret void
+}

>From bb6adbedaa7f4bff34aa8475103b8f67b011203b Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 21:57:57 +0000
Subject: [PATCH 2/6] [SLSR] Count path compression SCEV differences

---
 .../Transforms/Scalar/StraightLineStrengthReduce.cpp  |  1 +
 .../NVPTX/scev-candidate-differences.ll               | 11 ++++++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index 072575fe6d8ee..be6ca3619784b 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -911,6 +911,7 @@ auto StraightLineStrengthReduce::compressPath(Candidate &C,
                                 cast<GetElementPtrInst>(NextRoot->Ins), DL))
       break;
 
+    ++NumSCEVCandidateDifferences;
     if (auto DeltaVal =
             dyn_cast<SCEVConstant>(SE->getMinusSCEV(CandPart, BasisPart))) {
       Root = NextRoot;
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
index 08f1d5c473494..cbaa09a40e2d1 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -2,7 +2,10 @@
 ; RUN: opt -mtriple=nvptx64-nvidia-cuda -mcpu=sm_100 -passes=slsr -stats \
 ; RUN:   -disable-output < %s 2>&1 | FileCheck %s
 
-; CHECK: 2 slsr - Number of SCEV candidate differences computed by SLSR
+; The third candidate uses the second as its basis, then compressPath examines
+; the deeper basis. Count both basis selection and path compression.
+;
+; CHECK: 8 slsr - Number of SCEV candidate differences computed by SLSR
 
 declare i64 @source(i32)
 declare void @use(ptr)
@@ -18,5 +21,11 @@ define void @base_delta(ptr %root, i64 %common) {
   %base.1 = getelementptr i8, ptr %root, i64 %offset.1
   %candidate.1 = getelementptr i8, ptr %base.1, i64 %common
   call void @use(ptr %candidate.1)
+
+  %delta.2 = call i64 @source(i32 2)
+  %offset.2 = add i64 %offset.1, %delta.2
+  %base.2 = getelementptr i8, ptr %root, i64 %offset.2
+  %candidate.2 = getelementptr i8, ptr %base.2, i64 %common
+  call void @use(ptr %candidate.2)
   ret void
 }

>From 655887eb07e5fb03d357d3fd19a23ccefd725b72 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 22:04:43 +0000
Subject: [PATCH 3/6] [SLSR] Clarify candidate-basis statistic terminology

---
 llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp | 8 ++++----
 .../NVPTX/scev-candidate-differences.ll                   | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index be6ca3619784b..b1f1f6efc59b1 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -121,8 +121,8 @@ static cl::opt<bool>
     EnablePoisonReuseGuard("enable-poison-reuse-guard", cl::init(true),
                            cl::desc("Enable poison-reuse guard"));
 
-STATISTIC(NumSCEVCandidateDifferences,
-          "Number of SCEV candidate differences computed by SLSR");
+STATISTIC(NumSCEVCandidateBasisDifferences,
+          "Number of candidate-basis SCEV differences computed by SLSR");
 
 namespace {
 
@@ -695,7 +695,7 @@ Value *StraightLineStrengthReduce::getDelta(const Candidate &C,
     const SCEV *BasisPart =
         (K == Candidate::BaseDelta) ? Basis.Base : Basis.StrideSCEV;
     const SCEV *CandPart = (K == Candidate::BaseDelta) ? C.Base : C.StrideSCEV;
-    ++NumSCEVCandidateDifferences;
+    ++NumSCEVCandidateBasisDifferences;
     const SCEV *Diff = SE->getMinusSCEV(CandPart, BasisPart);
     return getNearestValueOfSCEV(Diff, C.Ins);
   }
@@ -911,7 +911,7 @@ auto StraightLineStrengthReduce::compressPath(Candidate &C,
                                 cast<GetElementPtrInst>(NextRoot->Ins), DL))
       break;
 
-    ++NumSCEVCandidateDifferences;
+    ++NumSCEVCandidateBasisDifferences;
     if (auto DeltaVal =
             dyn_cast<SCEVConstant>(SE->getMinusSCEV(CandPart, BasisPart))) {
       Root = NextRoot;
diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
index cbaa09a40e2d1..8f22f38668763 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -5,7 +5,7 @@
 ; The third candidate uses the second as its basis, then compressPath examines
 ; the deeper basis. Count both basis selection and path compression.
 ;
-; CHECK: 8 slsr - Number of SCEV candidate differences computed by SLSR
+; CHECK: 8 slsr - Number of candidate-basis SCEV differences computed by SLSR
 
 declare i64 @source(i32)
 declare void @use(ptr)

>From 1111b00bca1e0c8a287aea0604f888ac6d9c0948 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 22:09:07 +0000
Subject: [PATCH 4/6] [SLSR] Encode NVPTX target in statistic test

---
 .../NVPTX/scev-candidate-differences.ll                      | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
index 8f22f38668763..abccd07f3e129 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -1,12 +1,13 @@
 ; REQUIRES: asserts
-; RUN: opt -mtriple=nvptx64-nvidia-cuda -mcpu=sm_100 -passes=slsr -stats \
-; RUN:   -disable-output < %s 2>&1 | FileCheck %s
+; RUN: opt -passes=slsr -stats -disable-output < %s 2>&1 | FileCheck %s
 
 ; The third candidate uses the second as its basis, then compressPath examines
 ; the deeper basis. Count both basis selection and path compression.
 ;
 ; CHECK: 8 slsr - Number of candidate-basis SCEV differences computed by SLSR
 
+target triple = "nvptx64-nvidia-cuda"
+
 declare i64 @source(i32)
 declare void @use(ptr)
 

>From fd90844bb294f1ee20975db97f35a014eac1722a Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 22:11:01 +0000
Subject: [PATCH 5/6] [SLSR] Remove redundant statistic test comment

---
 .../NVPTX/scev-candidate-differences.ll                        | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
index abccd07f3e129..ddd1bf4748f5d 100644
--- a/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-candidate-differences.ll
@@ -1,9 +1,6 @@
 ; REQUIRES: asserts
 ; RUN: opt -passes=slsr -stats -disable-output < %s 2>&1 | FileCheck %s
 
-; The third candidate uses the second as its basis, then compressPath examines
-; the deeper basis. Count both basis selection and path compression.
-;
 ; CHECK: 8 slsr - Number of candidate-basis SCEV differences computed by SLSR
 
 target triple = "nvptx64-nvidia-cuda"

>From 04df4fb7207d43e598beebaf65a4c3f63e55bca0 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 18 Aug 2026 21:38:33 +0000
Subject: [PATCH 6/6] [SLSR] Skip candidate differences with mismatched
 SCEVUnknowns

---
 llvm/include/llvm/Analysis/ScalarEvolution.h  |  8 +++++
 llvm/lib/Analysis/ScalarEvolution.cpp         | 27 +++++++++++++++
 .../Scalar/StraightLineStrengthReduce.cpp     | 11 ++++++
 .../NVPTX/scev-unknown-filtering.ll           | 34 +++++++++++++++++++
 .../Analysis/ScalarEvolutionTest.cpp          | 23 +++++++++++++
 5 files changed, 103 insertions(+)
 create mode 100644 llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 0d7f9ae298e2a..580feb5f11912 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -701,6 +701,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.
@@ -1690,6 +1694,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 27a1a20bcdf79..3e7d5a8301d26 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4623,6 +4623,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) {
@@ -8726,6 +8750,7 @@ void ScalarEvolution::forgetAllLoops() {
   SignedRanges.clear();
   ExprValueMap.clear();
   HasRecMap.clear();
+  SCEVUnknownsCache.clear();
   ConstantMultipleCache.clear();
   PredicatedSCEVRewrites.clear();
   FoldCache.clear();
@@ -14150,6 +14175,7 @@ ScalarEvolution::~ScalarEvolution() {
   ExprValueMap.clear();
   ValueExprMap.clear();
   HasRecMap.clear();
+  SCEVUnknownsCache.clear();
   BackedgeTakenCounts.clear();
   PredicatedBackedgeTakenCounts.clear();
 
@@ -14697,6 +14723,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..40a4d7780ba3a 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -731,6 +731,17 @@ 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 *CandPart = K == Candidate::BaseDelta ? C.Base : C.StrideSCEV;
+    const SCEV *BasisPart =
+        K == Candidate::BaseDelta ? Basis->Base : Basis->StrideSCEV;
+    if (!SE->hasSameSCEVUnknowns(CandPart, BasisPart))
+      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-unknown-filtering.ll b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
new file mode 100644
index 0000000000000..f52d88f2f761d
--- /dev/null
+++ b/llvm/test/Transforms/StraightLineStrengthReduce/NVPTX/scev-unknown-filtering.ll
@@ -0,0 +1,34 @@
+; 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
+
+; 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: 3 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
+}
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 621c4897a39d7..83ce3e70e3535 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -124,6 +124,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);



More information about the llvm-commits mailing list