[PATCH] D140647: Handle simple diamond CFG hoisting in DivRemPairs.

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 27 06:06:29 PST 2022


nikic added a comment.

Can you please add these additional tests for the invoke/catchswitch cases?

  declare void @dummy()
  
  define i32 @invoke_not_willreturn(i32 %a, i32 %b) personality ptr null {
  ; CHECK-LABEL: @invoke_not_willreturn(
  ; CHECK-NEXT:  entry:
  ; CHECK-NEXT:    invoke void @dummy()
  ; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
  ; CHECK:       cont:
  ; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
  ; CHECK-NEXT:    ret i32 [[DIV]]
  ; CHECK:       lpad:
  ; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
  ; CHECK-NEXT:    cleanup
  ; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[A]], [[B]]
  ; CHECK-NEXT:    ret i32 [[REM]]
  ;
  entry:
    invoke void @dummy()
    to label %cont unwind label %lpad
  
  cont:
    %div = sdiv i32 %a, %b
    ret i32 %div
  
  lpad:
    landingpad { ptr, i32 }
    cleanup
    %rem = srem i32 %a, %b
    ret i32 %rem
  }
  
  define i32 @invoke_willreturn(i32 %a, i32 %b) personality ptr null {
  ; CHECK-LABEL: @invoke_willreturn(
  ; CHECK-NEXT:  entry:
  ; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
  ; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[A]], [[B]]
  ; CHECK-NEXT:    invoke void @dummy() #[[ATTR0:[0-9]+]]
  ; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
  ; CHECK:       cont:
  ; CHECK-NEXT:    ret i32 [[DIV]]
  ; CHECK:       lpad:
  ; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
  ; CHECK-NEXT:    cleanup
  ; CHECK-NEXT:    ret i32 [[REM]]
  ;
  entry:
    invoke void @dummy() willreturn
    to label %cont unwind label %lpad
  
  cont:
    %div = sdiv i32 %a, %b
    ret i32 %div
  
  lpad:
    landingpad { ptr, i32 }
    cleanup
    %rem = srem i32 %a, %b
    ret i32 %rem
  }
  
  ; Use this personality function so that catchpad is guaranteed to transfer.
  declare void @ProcessCLRException()
  
  define i32 @catchswitch(i32 %a, i32 %b) personality ptr @ProcessCLRException {
  ; CHECK-LABEL: @catchswitch(
  ; CHECK-NEXT:  entry:
  ; CHECK-NEXT:    invoke void @dummy() #[[ATTR0]]
  ; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
  ; CHECK:       cont:
  ; CHECK-NEXT:    ret i32 0
  ; CHECK:       lpad:
  ; CHECK-NEXT:    [[CS:%.*]] = catchswitch within none [label %cp] unwind label [[LPAD_END:%.*]]
  ; CHECK:       cp:
  ; CHECK-NEXT:    [[TMP0:%.*]] = catchpad within [[CS]] []
  ; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
  ; CHECK-NEXT:    ret i32 [[DIV]]
  ; CHECK:       lpad.end:
  ; CHECK-NEXT:    [[TMP1:%.*]] = cleanuppad within none []
  ; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[A]], [[B]]
  ; CHECK-NEXT:    ret i32 [[REM]]
  ;
  entry:
    invoke void @dummy() willreturn
    to label %cont unwind label %lpad
  
  cont:
    ret i32 0
  
  lpad:
    %cs = catchswitch within none [label %cp] unwind label %lpad.end
  
  cp:
    catchpad within %cs []
    %div = sdiv i32 %a, %b
    ret i32 %div
  
  lpad.end:
    cleanuppad within none []
    %rem = srem i32 %a, %b
    ret i32 %rem
  }

The catchswitch exception was a bit tricky to come up with, because we need both the right personality function and no unwind to caller, otherwise we will fail transfer checks already.



================
Comment at: llvm/lib/Transforms/Scalar/DivRemPairs.cpp:284
+      // sooner. Without a DivRem op, this transformation is unprofitable because
+      // we would end up performing an extra Div on the Rem path.
+      } else if (BasicBlock* RemPredBB = RemBB->getUniquePredecessor()) {
----------------
"extra Div" -> Mul + Sub? I don't think we'd perform an actual div.


================
Comment at: llvm/lib/Transforms/Scalar/DivRemPairs.cpp:285
+      // we would end up performing an extra Div on the Rem path.
+      } else if (BasicBlock* RemPredBB = RemBB->getUniquePredecessor()) {
+        // This hoist is only profitable when the target has a DivRem op.
----------------
nit: `BasicBlock *`


================
Comment at: llvm/lib/Transforms/Scalar/DivRemPairs.cpp:287
+        // This hoist is only profitable when the target has a DivRem op.
+        if (HasDivRemOp && RemPredBB == DivBB->getUniquePredecessor()) {
+          PredBB = RemPredBB;
----------------
nit: No braces for single-line if.


================
Comment at: llvm/lib/Transforms/Scalar/DivRemPairs.cpp:294
+      if (PredBB &&
+          !PredBB->isEHPad() &&
+          isGuaranteedToTransferExecutionToSuccessor(PredBB->getTerminator()) &&
----------------
Hm, this is stricter than what is needed, most exception pads are fine. It looks like we don't really have a dedicated method for this, so just checking `!isa<CatchSwitchInst>(PredBB->getTerminator())` should be fine.


================
Comment at: llvm/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll:411
+  %b.addr.0 = phi i64 [ %add, %foo ], [ %b, %if.end ]
+  %div = udiv i64 %b.addr.0, %c
+  br label %return
----------------
I don't think this tests the right case, because the udiv/urem ops are not the same. We can't have the ops be derived from a phi.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140647/new/

https://reviews.llvm.org/D140647



More information about the llvm-commits mailing list