Skip to content

[InstCombine] Pass disjoint in or combine #138800

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
May 8, 2025

Conversation

fengfeng09
Copy link
Contributor

@fengfeng09 fengfeng09 commented May 7, 2025

@llvmbot
Copy link
Member

llvmbot commented May 7, 2025

@llvm/pr-subscribers-llvm-transforms

Author: fengfeng (fengfeng09)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+12-1)
  • (added) llvm/test/Transforms/InstCombine/or-or-combine.ll (+48)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 100c144c177fe..d474262ab902a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3894,12 +3894,23 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
   // be simplified by a later pass either, so we try swapping the inner/outer
   // ORs in the hopes that we'll be able to simplify it this way.
   // (X|C) | V --> (X|V) | C
+  // Pass the disjoint flag in two following patters:
+  // 1. or-disjoint (or-disjoint X, C), V -->
+  //    or-disjoint (or-disjoint X, V), C
+  //
+  // 2. or-disjoint (or X, C), V -->
+  //    or (or-disjoint X, V), C
   ConstantInt *CI;
   if (Op0->hasOneUse() && !match(Op1, m_ConstantInt()) &&
       match(Op0, m_Or(m_Value(A), m_ConstantInt(CI)))) {
+    bool IsDisjointOuter = cast<PossiblyDisjointInst>(I).isDisjoint();
+    bool IsDisjointInner = cast<PossiblyDisjointInst>(Op0)->isDisjoint();
     Value *Inner = Builder.CreateOr(A, Op1);
+    cast<PossiblyDisjointInst>(Inner)->setIsDisjoint(IsDisjointOuter);
     Inner->takeName(Op0);
-    return BinaryOperator::CreateOr(Inner, CI);
+    return IsDisjointOuter && IsDisjointInner
+               ? BinaryOperator::CreateDisjointOr(Inner, CI)
+               : BinaryOperator::CreateOr(Inner, CI);
   }
 
   // Change (or (bool?A:B),(bool?C:D)) --> (bool?(or A,C):(or B,D))
diff --git a/llvm/test/Transforms/InstCombine/or-or-combine.ll b/llvm/test/Transforms/InstCombine/or-or-combine.ll
new file mode 100644
index 0000000000000..9dc0dcc29b2f2
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/or-or-combine.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+; (X | C) | Y --> (X | Y) | C
+
+define i32 @test1(i32 %x, i32 %y) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    [[INNER:%.*]] = or disjoint i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OUTER:%.*]] = or disjoint i32 [[INNER]], 5
+; CHECK-NEXT:    ret i32 [[OUTER]]
+;
+  %inner = or disjoint i32 %x, 5
+  %outer = or disjoint i32 %inner, %y
+  ret i32 %outer
+}
+
+define i32 @test2(i32 %x, i32 %y) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    [[INNER:%.*]] = or disjoint i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OUTER:%.*]] = or i32 [[INNER]], 5
+; CHECK-NEXT:    ret i32 [[OUTER]]
+;
+  %inner = or i32 %x, 5
+  %outer = or disjoint i32 %inner, %y
+  ret i32 %outer
+}
+
+define i32 @test3(i32 %x, i32 %y) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[INNER:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OUTER:%.*]] = or i32 [[INNER]], 5
+; CHECK-NEXT:    ret i32 [[OUTER]]
+;
+  %inner = or disjoint i32 %x, 5
+  %outer = or i32 %inner, %y
+  ret i32 %outer
+}
+
+define i32 @test4(i32 %x, i32 %y) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    [[INNER:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OUTER:%.*]] = or i32 [[INNER]], 5
+; CHECK-NEXT:    ret i32 [[OUTER]]
+;
+  %inner = or i32 %x, 5
+  %outer = or i32 %inner, %y
+  ret i32 %outer
+}

@dtcxzyw dtcxzyw changed the title Pass disjoint in or combine [InstCombine] Pass disjoint in or combine May 7, 2025
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

LG

@fengfeng09 fengfeng09 force-pushed the pass-disjoint-in-or-combine branch from 9407645 to a6b000f Compare May 8, 2025 01:42
or-disjoint (or-disjoint X, C), V
-->
or-disjoint (or-disjoint X, V), C

or-disjoint (or X, C), V
-->
or (or-disjoint X, V), C

Proof: https://alive2.llvm.org/ce/z/wtTm5V
https://alive2.llvm.org/ce/z/WC7Ai2

Signed-off-by: feng.feng <[email protected]>
@dtcxzyw dtcxzyw merged commit e7bf750 into llvm:main May 8, 2025
8 of 10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 8, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/19647

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang-Unit :: ./AllClangUnitTests/12/48' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests-Clang-Unit-52672-12-48.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=48 GTEST_SHARD_INDEX=12 /Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests
--

Script:
--
/Users/buildbot/buildbot-root/aarch64-darwin/build/tools/clang/unittests/./AllClangUnitTests --gtest_filter=DirectoryWatcherTest.DeleteWatchedDir
--
/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:259: Failure
Value of: WaitForExpectedStateResult.wait_for(EventualResultTimeout) == std::future_status::ready
  Actual: false
Expected: true
The expected result state wasn't reached before the time-out.

/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:262: Failure
Value of: TestConsumer.result().has_value()
  Actual: false
Expected: true


/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:259
Value of: WaitForExpectedStateResult.wait_for(EventualResultTimeout) == std::future_status::ready
  Actual: false
Expected: true
The expected result state wasn't reached before the time-out.

/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp:262
Value of: TestConsumer.result().has_value()
  Actual: false
Expected: true



********************


petrhosek pushed a commit to petrhosek/llvm-project that referenced this pull request May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants