Skip to content

[LVI] Skip self loops in solveBlockValueNonLocal #127763

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 23, 2025

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Feb 19, 2025

We cannot infer more information from backedges in solveBlockValueNonLocal. However, since DT is unavailable in LVI, there is not a precise way to check whether a BB edge is a backedge. This patch only skips self loops to unblock the range analysis.

The motivating case is extracted from #127663.

Compile-time impact is high: https://llvm-compile-time-tracker.com/compare.php?from=84ddda58c870681dd12ed765e9d59d5e00567f94&to=af032f1351358f2f5b5d9f4e87c5601c23b9bd37&stat=instructions:u

Copy link

⚠️ undef deprecator found issues in your code. ⚠️

You can test this locally with the following command:
git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 22d65d898961e96f0a8340e090ffa34558279eab af032f1351358f2f5b5d9f4e87c5601c23b9bd37 llvm/test/Transforms/CorrelatedValuePropagation/loop.ll llvm/lib/Analysis/LazyValueInfo.cpp llvm/test/Transforms/JumpThreading/ddt-crash.ll

The following files introduce new uses of undef:

  • llvm/test/Transforms/JumpThreading/ddt-crash.ll

Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields undef. You should use poison values for placeholders instead.

In tests, avoid using undef and having tests that trigger undefined behavior. If you need an operand with some unimportant value, you can add a new argument to the function and use that instead.

For example, this is considered a bad practice:

define void @fn() {
  ...
  br i1 undef, ...
}

Please use the following instead:

define void @fn(i1 %cond) {
  ...
  br i1 %cond, ...
}

Please refer to the Undefined Behavior Manual for more information.

@nikic
Copy link
Contributor

nikic commented Feb 19, 2025

Compile-time impact is high: https://llvm-compile-time-tracker.com/compare.php?from=84ddda58c870681dd12ed765e9d59d5e00567f94&to=af032f1351358f2f5b5d9f4e87c5601c23b9bd37&stat=instructions:u

I think this may look worse than it actually is, due to second order impact. E.g. the bigger regressions are on mafft, which also has 0.1-0.26% code size increase. There is no significant impact on the clang build.

It would be good to confirm comptime with llvm-opt-benchmark as well, but I don't think this is a blocker.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dtcxzyw dtcxzyw marked this pull request as ready for review February 19, 2025 12:58
@llvmbot llvmbot added llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Feb 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2025

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: Yingwei Zheng (dtcxzyw)

Changes

We cannot infer more information from backedges in solveBlockValueNonLocal. However, since DT is unavailable in LVI, there is not a precise way to check whether a BB edge is a backedge. This patch only skips self loops to unblock the range analysis.

The motivating case is extracted from #127663.

Compile-time impact is high: https://llvm-compile-time-tracker.com/compare.php?from=84ddda58c870681dd12ed765e9d59d5e00567f94&to=af032f1351358f2f5b5d9f4e87c5601c23b9bd37&stat=instructions:u


Full diff: https://github.com/llvm/llvm-project/pull/127763.diff

3 Files Affected:

  • (modified) llvm/lib/Analysis/LazyValueInfo.cpp (+3)
  • (added) llvm/test/Transforms/CorrelatedValuePropagation/loop.ll (+39)
  • (modified) llvm/test/Transforms/JumpThreading/ddt-crash.ll (+7-11)
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 5cd179df436de..581358a645780 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -694,6 +694,9 @@ LazyValueInfoImpl::solveBlockValueNonLocal(Value *Val, BasicBlock *BB) {
   // canonicalizing to make this true rather than relying on this happy
   // accident.
   for (BasicBlock *Pred : predecessors(BB)) {
+    // Skip self loops.
+    if (Pred == BB)
+      continue;
     std::optional<ValueLatticeElement> EdgeResult = getEdgeValue(Val, Pred, BB);
     if (!EdgeResult)
       // Explore that input, then return here
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/loop.ll b/llvm/test/Transforms/CorrelatedValuePropagation/loop.ll
new file mode 100644
index 0000000000000..41e5be78ace8a
--- /dev/null
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/loop.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=correlated-propagation -S %s | FileCheck %s
+
+define i64 @test_self_loop(i64 %x, i1 %cond) {
+; CHECK-LABEL: define range(i64 0, 576460752303423488) i64 @test_self_loop(
+; CHECK-SAME: i64 [[X:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[COND1:%.*]] = icmp ugt i64 [[X]], 576460752303423487
+; CHECK-NEXT:    br i1 [[COND1]], label %[[COMMON_RET:.*]], label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 [[COND]], label %[[INDIRECT:.*]], label %[[LOOP]]
+; CHECK:       [[INDIRECT]]:
+; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    br i1 [[COND2]], label %[[COMMON_RET]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[COMMON_RET]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[X]], %[[EXIT]] ], [ 0, %[[INDIRECT]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  %cond1 = icmp ugt i64 %x, 576460752303423487
+  br i1 %cond1, label %common.ret, label %loop
+
+loop:
+  br i1 %cond, label %indirect, label %loop
+
+indirect:
+  %cond2 = icmp eq i64 %x, 0
+  br i1 %cond2, label %common.ret, label %exit
+
+exit:
+  %smax = tail call i64 @llvm.smax.i64(i64 %x, i64 1)
+  br label %common.ret
+
+common.ret:
+  %res = phi i64 [ %smax, %exit ], [ 0, %indirect ], [ 0, %entry ]
+  ret i64 %res
+}
diff --git a/llvm/test/Transforms/JumpThreading/ddt-crash.ll b/llvm/test/Transforms/JumpThreading/ddt-crash.ll
index b0bba1a2dd0c4..94ab4791f1664 100644
--- a/llvm/test/Transforms/JumpThreading/ddt-crash.ll
+++ b/llvm/test/Transforms/JumpThreading/ddt-crash.ll
@@ -131,20 +131,16 @@ define void @spam(ptr %arg, i1 %arg2) {
 ; CHECK:       bb31:
 ; CHECK-NEXT:    [[TMP32:%.*]] = phi i8 [ [[TMP32]], [[BB31]] ], [ [[TMP32_PR]], [[BB30]] ]
 ; CHECK-NEXT:    [[TMP33:%.*]] = icmp eq i8 [[TMP32]], 0
-; CHECK-NEXT:    br i1 [[TMP33]], label [[BB31]], label [[BB37]]
+; CHECK-NEXT:    br i1 [[TMP33]], label [[BB31]], label [[BB41_THREAD]]
 ; CHECK:       bb37:
-; CHECK-NEXT:    [[TMP36:%.*]] = phi i1 [ false, [[BB23]] ], [ true, [[BB31]] ]
+; CHECK-NEXT:    [[TMP36:%.*]] = phi i1 [ false, [[BB23]] ]
 ; CHECK-NEXT:    [[TMP38:%.*]] = icmp eq ptr [[TMP15]], null
-; CHECK-NEXT:    br i1 [[TMP38]], label [[BB39:%.*]], label [[BB41:%.*]]
-; CHECK:       bb39:
-; CHECK-NEXT:    [[TMP364:%.*]] = phi i1 [ [[TMP36]], [[BB37]] ]
-; CHECK-NEXT:    [[TMP40:%.*]] = load ptr, ptr @global, align 8
-; CHECK-NEXT:    br i1 [[TMP364]], label [[BB41_THREAD]], label [[BB41_THREAD]]
+; CHECK-NEXT:    br i1 [[TMP38]], label [[BB41:%.*]], label [[BB41_THREAD]]
 ; CHECK:       bb41:
-; CHECK-NEXT:    [[TMP363:%.*]] = phi i1 [ [[TMP36]], [[BB37]] ]
-; CHECK-NEXT:    br i1 [[TMP363]], label [[BB41_THREAD]], label [[BB41_THREAD]]
-; CHECK:       bb41.thread:
-; CHECK-NEXT:    [[TMP0:%.*]] = phi ptr [ undef, [[BB41]] ], [ undef, [[BB39]] ], [ undef, [[BB39]] ], [ undef, [[BB41]] ], [ undef, [[BB27]] ], [ undef, [[BB25]] ]
+; CHECK-NEXT:    [[TMP40:%.*]] = load ptr, ptr @global, align 8
+; CHECK-NEXT:    br label [[BB41_THREAD]]
+; CHECK:       bb41.thread11:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi ptr [ undef, [[BB41]] ], [ undef, [[BB25]] ], [ undef, [[BB31]] ], [ undef, [[BB27]] ], [ undef, [[BB37]] ]
 ; CHECK-NEXT:    ret void
 ;
 bb:

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Feb 23, 2025

Seems like the comptime overhead is due to more optimizations performed in CVP.

Improvements:
  correlated-value-propagation.NumSRems 1242 -> 1957 +57.57%
  correlated-value-propagation.NumReturns 203 -> 237 +16.75%
  correlated-value-propagation.NumAShrsConverted 4035 -> 4424 +9.64%
  correlated-value-propagation.NumSICmps 48127 -> 51578 +7.17%
  correlated-value-propagation.NumSMinMax 4646 -> 4871 +4.84%
  correlated-value-propagation.NumSIToFP 1557 -> 1631 +4.75%
  instcombine.NegatorNumNegationsFoundInCache 4056 -> 4245 +4.66%
  correlated-value-propagation.NumSubNUW 27953 -> 29215 +4.51%
  correlated-value-propagation.NumSDivs 17512 -> 18290 +4.44%
  correlated-value-propagation.NumMinMax 10215 -> 10647 +4.23%

@dtcxzyw dtcxzyw merged commit 2071ea2 into llvm:main Feb 23, 2025
12 of 13 checks passed
@dtcxzyw dtcxzyw deleted the perf/lvi-self-loop branch February 23, 2025 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants