Skip to content

[SimplifyCFG] Mark div/rem as not-cheap to sink if we are replacing const denominator #109007

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

Conversation

goldsteinn
Copy link
Contributor

@goldsteinn goldsteinn commented Sep 17, 2024

  • [SimplifyCFG] Add test for sinking div/rem with const remainder; NFC
  • [SimplifyCFG] Mark div/rem as not-cheap to sink if we are replacing const denominator

Divide by a constant (usually done by multiply) is MUCH cheaper than divide by a variable.

@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

Changes
  • [SimplifyCFG] Add test for sinking div/rem with const remainder; NFC
  • [SimplifyCFG] Mark div/rem as not-cheap to sink if we are replacing const denominator

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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+10)
  • (modified) llvm/test/Transforms/SimplifyCFG/sink-and-convert-switch.ll (+101)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5a694b5e7f204b..5e08d4d3ffe7f8 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1954,6 +1954,16 @@ static bool isLifeTimeMarker(const Instruction *I) {
 // into variables.
 static bool replacingOperandWithVariableIsCheap(const Instruction *I,
                                                 int OpIdx) {
+  switch (I->getOpcode()) {
+    // Divide/Remainder by constant is typically much cheaper than by variable.
+  case Instruction::UDiv:
+  case Instruction::SDiv:
+  case Instruction::URem:
+  case Instruction::SRem:
+    return OpIdx != 1;
+  default:
+    break;
+  }
   return !isa<IntrinsicInst>(I);
 }
 
diff --git a/llvm/test/Transforms/SimplifyCFG/sink-and-convert-switch.ll b/llvm/test/Transforms/SimplifyCFG/sink-and-convert-switch.ll
index 4c93837f1422a9..87d64932ef0935 100644
--- a/llvm/test/Transforms/SimplifyCFG/sink-and-convert-switch.ll
+++ b/llvm/test/Transforms/SimplifyCFG/sink-and-convert-switch.ll
@@ -44,3 +44,104 @@ bb5:
   call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %y)
   ret void
 }
+
+define i64 @dont_make_div_variable(i64 noundef %x, i64 noundef %i) {
+; CHECK-LABEL: define i64 @dont_make_div_variable(
+; CHECK-SAME: i64 noundef [[X:%.*]], i64 noundef [[I:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i64 [[I]], label %[[SW_DEFAULT:.*]] [
+; CHECK-NEXT:      i64 9, label %[[SW_BB:.*]]
+; CHECK-NEXT:      i64 10, label %[[SW_BB1:.*]]
+; CHECK-NEXT:      i64 11, label %[[SW_BB3:.*]]
+; CHECK-NEXT:      i64 12, label %[[SW_BB5:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB]]:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i64 [[X]], 9
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[SW_BB1]]:
+; CHECK-NEXT:    [[DIV2:%.*]] = udiv i64 [[X]], 10
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[SW_BB3]]:
+; CHECK-NEXT:    [[DIV4:%.*]] = udiv i64 [[X]], 11
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[SW_BB5]]:
+; CHECK-NEXT:    [[DIV7:%.*]] = udiv i64 [[X]], 12
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[SW_DEFAULT]]:
+; CHECK-NEXT:    unreachable
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[DIV6:%.*]] = phi i64 [ [[DIV7]], %[[SW_BB5]] ], [ [[DIV4]], %[[SW_BB3]] ], [ [[DIV2]], %[[SW_BB1]] ], [ [[DIV]], %[[SW_BB]] ]
+; CHECK-NEXT:    ret i64 [[DIV6]]
+;
+entry:
+  switch i64 %i, label %sw.default [
+  i64 9, label %sw.bb
+  i64 10, label %sw.bb1
+  i64 11, label %sw.bb3
+  i64 12, label %sw.bb5
+  ]
+
+sw.bb:
+  %div = udiv i64 %x, 9
+  br label %return
+
+sw.bb1:
+  %div2 = udiv i64 %x, 10
+  br label %return
+
+sw.bb3:
+  %div4 = udiv i64 %x, 11
+  br label %return
+
+sw.bb5:
+  %div6 = udiv i64 %x, 12
+  br label %return
+
+sw.default:
+  unreachable
+
+return:
+  %retval.0 = phi i64 [ %div6, %sw.bb5 ], [ %div4, %sw.bb3 ], [ %div2, %sw.bb1 ], [ %div, %sw.bb ]
+  ret i64 %retval.0
+}
+
+define i64 @okay_to_make_div_variable(i64 noundef %x, i64 noundef %i) {
+; CHECK-LABEL: define i64 @okay_to_make_div_variable(
+; CHECK-SAME: i64 noundef [[X:%.*]], i64 noundef [[I:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub nsw i64 [[I]], 9
+; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i64 [[SWITCH_TABLEIDX]], 9
+; CHECK-NEXT:    [[DIV6:%.*]] = udiv i64 [[SWITCH_OFFSET]], [[X]]
+; CHECK-NEXT:    ret i64 [[DIV6]]
+;
+entry:
+  switch i64 %i, label %sw.default [
+  i64 9, label %sw.bb
+  i64 10, label %sw.bb1
+  i64 11, label %sw.bb3
+  i64 12, label %sw.bb5
+  ]
+
+sw.bb:
+  %div = udiv i64 9, %x
+  br label %return
+
+sw.bb1:
+  %div2 = udiv i64 10, %x
+  br label %return
+
+sw.bb3:
+  %div4 = udiv i64 11, %x
+  br label %return
+
+sw.bb5:
+  %div6 = udiv i64 12, %x
+  br label %return
+
+sw.default:
+  unreachable
+
+return:
+  %retval.0 = phi i64 [ %div6, %sw.bb5 ], [ %div4, %sw.bb3 ], [ %div2, %sw.bb1 ], [ %div, %sw.bb ]
+  ret i64 %retval.0
+}

@goldsteinn goldsteinn changed the title goldsteinn/simplify cfg expensive divrem by var [SimplifyCFG] Mark div/rem as not-cheap to sink if we are replacing const denominator Sep 17, 2024
@goldsteinn goldsteinn requested review from nikic and dtcxzyw September 17, 2024 16:07
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

@@ -1954,6 +1954,16 @@ static bool isLifeTimeMarker(const Instruction *I) {
// into variables.
static bool replacingOperandWithVariableIsCheap(const Instruction *I,
int OpIdx) {
switch (I->getOpcode()) {
// Divide/Remainder by constant is typically much cheaper than by variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use I->isIntDivRem() here.

hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
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.

3 participants