[llvm] [DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select (PR #71082)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 2 10:16:10 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: XChy (XChy)

<details>
<summary>Changes</summary>

Fixes #<!-- -->65222.
When unfolding select into diamond-like control flow, we need to remove the StartBlock from all phis in EndBlock.

Something irrelevant:
Transforms like loopboundsplit,newgvn and DFAJumpThreading hold many bugs, but lack tests because they are not added to pipeline. But I didn't find the discussions about that on discourse or issues. 

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


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp (+7-3) 
- (modified) llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll (+71-6) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
index c06564d45b06430..edfeb36f3422e2e 100644
--- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
@@ -249,16 +249,20 @@ void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
     FT = FalseBlock;
 
     // Update the phi node of SI.
-    SIUse->removeIncomingValue(StartBlock, /* DeletePHIIfEmpty = */ false);
     SIUse->addIncoming(SI->getTrueValue(), TrueBlock);
     SIUse->addIncoming(SI->getFalseValue(), FalseBlock);
 
     // Update any other PHI nodes in EndBlock.
     for (PHINode &Phi : EndBlock->phis()) {
       if (&Phi != SIUse) {
-        Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), TrueBlock);
-        Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), FalseBlock);
+        Value *OrigValue = Phi.getIncomingValueForBlock(StartBlock);
+        Phi.addIncoming(OrigValue, TrueBlock);
+        Phi.addIncoming(OrigValue, FalseBlock);
       }
+
+      // Remove incoming place of original StartBlock, which comes in a indirect
+      // way (through TrueBlock and FalseBlock) now.
+      Phi.removeIncomingValue(StartBlock, /* DeletePHIIfEmpty = */ false);
     }
   } else {
     BasicBlock *NewBlock = nullptr;
diff --git a/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll b/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll
index c7bce505b717892..bcb067b7c6eba33 100644
--- a/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll
+++ b/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll
@@ -15,8 +15,8 @@ define i32 @test1(i32 %num) {
 ; CHECK-NEXT:    [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
 ; CHECK-NEXT:    [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
 ; CHECK-NEXT:    switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
-; CHECK-NEXT:    i32 1, label [[CASE1:%.*]]
-; CHECK-NEXT:    i32 2, label [[CASE2:%.*]]
+; CHECK-NEXT:      i32 1, label [[CASE1:%.*]]
+; CHECK-NEXT:      i32 2, label [[CASE2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       for.body.jt2:
 ; CHECK-NEXT:    [[COUNT_JT2:%.*]] = phi i32 [ [[INC_JT2:%.*]], [[FOR_INC_JT2:%.*]] ]
@@ -91,8 +91,8 @@ define i32 @test2(i32 %num) {
 ; CHECK-NEXT:    [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
 ; CHECK-NEXT:    [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
 ; CHECK-NEXT:    switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
-; CHECK-NEXT:    i32 1, label [[CASE1:%.*]]
-; CHECK-NEXT:    i32 2, label [[CASE2:%.*]]
+; CHECK-NEXT:      i32 1, label [[CASE1:%.*]]
+; CHECK-NEXT:      i32 2, label [[CASE2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       for.body.jt3:
 ; CHECK-NEXT:    [[COUNT_JT3:%.*]] = phi i32 [ [[INC_JT3:%.*]], [[FOR_INC_JT3:%.*]] ]
@@ -192,8 +192,8 @@ define i32 @test3(i32 %num) {
 ; CHECK-NEXT:    [[COUNT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
 ; CHECK-NEXT:    [[STATE:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ poison, [[FOR_INC]] ]
 ; CHECK-NEXT:    switch i32 [[STATE]], label [[FOR_INC_JT1:%.*]] [
-; CHECK-NEXT:    i32 1, label [[CASE1:%.*]]
-; CHECK-NEXT:    i32 2, label [[CASE2:%.*]]
+; CHECK-NEXT:      i32 1, label [[CASE1:%.*]]
+; CHECK-NEXT:      i32 2, label [[CASE2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       for.body.jt4:
 ; CHECK-NEXT:    [[COUNT_JT4:%.*]] = phi i32 [ [[INC_JT4:%.*]], [[FOR_INC_JT4:%.*]] ]
@@ -316,3 +316,68 @@ for.cond:                                         ; preds = %lor.end, %entry
 lor.end:                                          ; preds = %for.cond
   br label %for.cond
 }
+
+define ptr @pr65222(i32 %flags, i1 %cmp82, i1 %tobool85.not, i1 %cond111) {
+; CHECK-LABEL: @pr65222(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[INWORD_03:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 0, [[IF_END143:%.*]] ], [ [[SPEC_SELECT:%.*]], [[SW_BB147:%.*]] ]
+; CHECK-NEXT:    [[START_04:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[FLAGS:%.*]], [[IF_END143]] ], [ 0, [[SW_BB147]] ]
+; CHECK-NEXT:    br i1 [[CMP82:%.*]], label [[IF_THEN84:%.*]], label [[IF_END143]]
+; CHECK:       if.then84:
+; CHECK-NEXT:    [[TOBOOL87_NOT:%.*]] = icmp eq i32 [[INWORD_03]], 0
+; CHECK-NEXT:    [[CMP89_INV:%.*]] = icmp slt i32 [[START_04]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL85_NOT:%.*]], label [[SI_UNFOLD_TRUE:%.*]], label [[SI_UNFOLD_FALSE:%.*]]
+; CHECK:       si.unfold.true:
+; CHECK-NEXT:    br i1 [[CMP89_INV]], label [[IF_END143]], label [[SI_UNFOLD_FALSE2:%.*]]
+; CHECK:       si.unfold.false:
+; CHECK-NEXT:    br i1 [[TOBOOL87_NOT]], label [[IF_END143]], label [[SI_UNFOLD_FALSE1:%.*]]
+; CHECK:       si.unfold.false1:
+; CHECK-NEXT:    br label [[IF_END143]]
+; CHECK:       si.unfold.false2:
+; CHECK-NEXT:    br label [[IF_END143]]
+; CHECK:       if.end143:
+; CHECK-NEXT:    [[NOP_1:%.*]] = phi i32 [ [[FLAGS]], [[WHILE_COND]] ], [ 2, [[SI_UNFOLD_TRUE]] ], [ 2, [[SI_UNFOLD_FALSE]] ], [ 0, [[SI_UNFOLD_FALSE1]] ], [ 1, [[SI_UNFOLD_FALSE2]] ]
+; CHECK-NEXT:    [[INWORD_1:%.*]] = phi i32 [ [[FLAGS]], [[WHILE_COND]] ], [ 0, [[SI_UNFOLD_TRUE]] ], [ 0, [[SI_UNFOLD_FALSE]] ], [ 0, [[SI_UNFOLD_FALSE1]] ], [ 0, [[SI_UNFOLD_FALSE2]] ]
+; CHECK-NEXT:    switch i32 [[NOP_1]], label [[WHILE_COND]] [
+; CHECK-NEXT:      i32 1, label [[SW_BB173:%.*]]
+; CHECK-NEXT:      i32 0, label [[SW_BB147]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb147:
+; CHECK-NEXT:    [[SPEC_SELECT]] = select i1 [[COND111:%.*]], i32 [[INWORD_1]], i32 0
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       sw.bb173:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %sw.bb147, %if.end143, %entry
+  %inword.03 = phi i32 [ 0, %entry ], [ 0, %if.end143 ], [ %spec.select, %sw.bb147 ]
+  %start.04 = phi i32 [ 0, %entry ], [ %flags, %if.end143 ], [ 0, %sw.bb147 ]
+  br i1 %cmp82, label %if.then84, label %if.end143
+
+if.then84:                                        ; preds = %while.cond
+  %tobool87.not = icmp eq i32 %inword.03, 0
+  %cond = select i1 %tobool87.not, i32 2, i32 0
+  %cmp89.inv = icmp slt i32 %start.04, 0
+  %cond91 = select i1 %cmp89.inv, i32 2, i32 1
+  %nop.0 = select i1 %tobool85.not, i32 %cond91, i32 %cond
+  br label %if.end143
+
+if.end143:                                        ; preds = %if.then84, %while.cond
+  %nop.1 = phi i32 [ %nop.0, %if.then84 ], [ %flags, %while.cond ]
+  %inword.1 = phi i32 [ 0, %if.then84 ], [ %flags, %while.cond ]
+  switch i32 %nop.1, label %while.cond [
+  i32 1, label %sw.bb173
+  i32 0, label %sw.bb147
+  ]
+
+sw.bb147:                                         ; preds = %if.end143
+  %spec.select = select i1 %cond111, i32 %inword.1, i32 0
+  br label %while.cond
+
+sw.bb173:                                         ; preds = %if.end143
+  ret ptr null
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/71082


More information about the llvm-commits mailing list