Skip to content

[InstCombine] Don't mix X << Y / Z << Y with X << Y / X << Z #69302

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 1 commit into from
Oct 17, 2023

Conversation

XChy
Copy link
Member

@XChy XChy commented Oct 17, 2023

Fixes #69291.
This patch improve the logic handling different patterns to avoid mixing these pattern.

@XChy XChy requested review from dtcxzyw and goldsteinn October 17, 2023 09:02
@XChy XChy requested a review from nikic as a code owner October 17, 2023 09:02
@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2023

@llvm/pr-subscribers-llvm-transforms

Author: XChy (XChy)

Changes

Fixes #69291.
This patch adds else for different patterns to avoid mixing these pattern.


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+4-4)
  • (modified) llvm/test/Transforms/InstCombine/div-shift.ll (+14)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 26e0a6700042ef0..81c6c3f88e148e2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -959,8 +959,8 @@ static Instruction *foldIDivShl(BinaryOperator &I,
 
   // With appropriate no-wrap constraints, remove a common factor in the
   // dividend and divisor that is disguised as a left-shift amount.
-  if (match(Op0, m_Shl(m_Value(X), m_Value(Z))) &&
-      match(Op1, m_Shl(m_Value(Y), m_Specific(Z)))) {
+  else if (match(Op0, m_Shl(m_Value(X), m_Value(Z))) &&
+           match(Op1, m_Shl(m_Value(Y), m_Specific(Z)))) {
     auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
     auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
 
@@ -982,8 +982,8 @@ static Instruction *foldIDivShl(BinaryOperator &I,
 
   // If X << Y and X << Z does not overflow, then:
   // (X << Y) / (X << Z) -> (1 << Y) / (1 << Z) -> 1 << Y >> Z
-  if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
-      match(Op1, m_Shl(m_Specific(X), m_Value(Z)))) {
+  else if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
+           match(Op1, m_Shl(m_Specific(X), m_Value(Z)))) {
     auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
     auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
 
diff --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index 635c01d84441d8a..d208837f04594ab 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -1280,3 +1280,17 @@ entry:
   %div = sdiv i32 %lhs, %rhs
   ret i32 %div
 }
+
+@a = external global i32
+define i32 @pr69291() {
+; CHECK-LABEL: @pr69291(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 1
+;
+entry:
+  %conv = load i32, ptr @a, align 1
+  %add = shl nuw nsw i32 %conv, 1
+  %add2 = shl nuw nsw i32 %conv, 1
+  %div = sdiv i32 %add, %add2
+  ret i32 %div
+}

@nikic
Copy link
Contributor

nikic commented Oct 17, 2023

Wow, what a footgun. Please change this code to replace all the Ret = BinaryOperator::CreateUDiv(X, Y); with return Builder.CreateUDiv(X, Y, "", I.isExact()); instead.

@XChy
Copy link
Member Author

XChy commented Oct 17, 2023

I think it may be also necessary to add an IsExact argument for this function? To remind other developers to care about exact flag.

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

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.

Clang crashed: Assertion `materialized_use_empty() && "Uses remain when a value is destroyed!"' failed.
3 participants