Skip to content

[UnifyLoopExits] Never generate phis of only undef values #99924

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
Jul 23, 2024

Conversation

jdoerfert
Copy link
Member

No description provided.

@jdoerfert jdoerfert requested review from arsenm, shiltian and jhuber6 July 22, 2024 19:34
There are (rare) cases we used to emit a PHI node with only `undef`
inputs, that's not helpful.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. flang:openmp llvm:transforms clang:openmp OpenMP related changes to Clang labels Jul 22, 2024
@jdoerfert jdoerfert force-pushed the pr/reconnect_phis branch from 9836e23 to 8e73162 Compare July 22, 2024 19:35
@llvmbot
Copy link
Member

llvmbot commented Jul 22, 2024

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-flang-openmp

@llvm/pr-subscribers-clang-codegen

Author: Johannes Doerfert (jdoerfert)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/BasicBlockUtils.cpp (+9-2)
  • (added) llvm/test/Transforms/UnifyLoopExits/undef-phis.ll (+58)
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 462283c0bfe00..4c8cfa5c6c697 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1909,22 +1909,29 @@ static void reconnectPhis(BasicBlock *Out, BasicBlock *GuardBlock,
     auto NewPhi =
         PHINode::Create(Phi->getType(), Incoming.size(),
                         Phi->getName() + ".moved", FirstGuardBlock->begin());
+    bool AllUndef = true;
     for (auto *In : Incoming) {
       Value *V = UndefValue::get(Phi->getType());
       if (In == Out) {
         V = NewPhi;
       } else if (Phi->getBasicBlockIndex(In) != -1) {
         V = Phi->removeIncomingValue(In, false);
+        AllUndef &= isa<UndefValue>(V);
       }
       NewPhi->addIncoming(V, In);
     }
     assert(NewPhi->getNumIncomingValues() == Incoming.size());
+    Value *NewV = NewPhi;
+    if (AllUndef) {
+      NewPhi->eraseFromParent();
+      NewV = UndefValue::get(Phi->getType());
+    }
     if (Phi->getNumOperands() == 0) {
-      Phi->replaceAllUsesWith(NewPhi);
+      Phi->replaceAllUsesWith(NewV);
       I = Phi->eraseFromParent();
       continue;
     }
-    Phi->addIncoming(NewPhi, GuardBlock);
+    Phi->addIncoming(NewV, GuardBlock);
     ++I;
   }
 }
diff --git a/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll b/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll
new file mode 100644
index 0000000000000..722ccc519a764
--- /dev/null
+++ b/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s
+
+define fastcc void @undef_phi(i64 %i5247, i1 %i4530, i1 %i4936.not) {
+; CHECK-LABEL: define fastcc void @undef_phi(
+; CHECK-SAME: i64 [[I5247:%.*]], i1 [[I4530:%.*]], i1 [[I4936_NOT:%.*]]) {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    br label %[[MBB3932:.*]]
+; CHECK:       [[MBB3932]]:
+; CHECK-NEXT:    br label %[[MBB4454:.*]]
+; CHECK:       [[MBB4321:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[I5247]] to i32
+; CHECK-NEXT:    [[I5290:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[I5290]], label %[[MBB3932]], label %[[LOOP_EXIT_GUARD:.*]]
+; CHECK:       [[MBB4454]]:
+; CHECK-NEXT:    br i1 [[I4530]], label %[[MBB4535:.*]], label %[[LOOP_EXIT_GUARD1:.*]]
+; CHECK:       [[MBB4531:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[MBB4535]]:
+; CHECK-NEXT:    br i1 [[I4936_NOT]], label %[[LOOP_EXIT_GUARD1]], label %[[MBB4454]]
+; CHECK:       [[MBB5291:.*]]:
+; CHECK-NEXT:    [[I5293:%.*]] = insertvalue [2 x i32] zeroinitializer, i32 [[DOTMOVED:%.*]], 1
+; CHECK-NEXT:    store volatile [2 x i32] [[I5293]], ptr addrspace(5) null, align 4
+; CHECK-NEXT:    ret void
+; CHECK:       [[LOOP_EXIT_GUARD]]:
+; CHECK-NEXT:    [[DOTMOVED]] = phi i32 [ [[TMP0]], %[[MBB4321]] ], [ undef, %[[LOOP_EXIT_GUARD1]] ]
+; CHECK-NEXT:    [[GUARD_MBB4531:%.*]] = phi i1 [ false, %[[MBB4321]] ], [ [[GUARD_MBB4531_MOVED:%.*]], %[[LOOP_EXIT_GUARD1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_MBB4531]], label %[[MBB4531]], label %[[MBB5291]]
+; CHECK:       [[LOOP_EXIT_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_MBB4531_MOVED]] = phi i1 [ true, %[[MBB4454]] ], [ undef, %[[MBB4535]] ]
+; CHECK-NEXT:    [[GUARD_LOOP_EXIT_GUARD:%.*]] = phi i1 [ true, %[[MBB4454]] ], [ false, %[[MBB4535]] ]
+; CHECK-NEXT:    br i1 [[GUARD_LOOP_EXIT_GUARD]], label %[[LOOP_EXIT_GUARD]], label %[[MBB4321]]
+;
+mbb:
+  br label %mbb3932
+
+mbb3932:                                           ; preds = %mbb4321, %mbb
+  br label %mbb4454
+
+mbb4321:                                           ; preds = %mbb4535
+  %0 = trunc i64 %i5247 to i32
+  %i5290 = icmp eq i32 %0, 0
+  br i1 %i5290, label %mbb3932, label %mbb5291
+
+mbb4454:                                           ; preds = %mbb4535, %mbb3932
+  br i1 %i4530, label %mbb4535, label %mbb4531
+
+mbb4531:                                           ; preds = %mbb4454
+  ret void
+
+mbb4535:                                           ; preds = %mbb4454
+  br i1 %i4936.not, label %mbb4321, label %mbb4454
+
+mbb5291:                                           ; preds = %mbb4321
+  %i5293 = insertvalue [2 x i32] zeroinitializer, i32 %0, 1
+  store volatile [2 x i32] %i5293, ptr addrspace(5) null, align 4
+  ret void
+}

Value *NewV = NewPhi;
if (AllUndef) {
NewPhi->eraseFromParent();
NewV = UndefValue::get(Phi->getType());
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this try to preserve poison?

Copy link
Member Author

Choose a reason for hiding this comment

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

As of right now, this emits undef by default. We likely want to change both UndefValue::get to poison. Should I include that and track undef/poison separately?

Copy link
Contributor

Choose a reason for hiding this comment

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

It probably makes little difference, can switch these to poison as a second step?

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, let's do this first, then we switch to poison.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't really understand. Are we agreeing that it's okay to temporarily ignore UndefValue that are actually poison in this patch?

Copy link
Contributor

Choose a reason for hiding this comment

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

All poisons are undef. Not all undefs are poison. It's safe, though suboptimal, to replace poison with undef

@arsenm arsenm requested a review from ssahasra July 22, 2024 19:39
@jdoerfert jdoerfert merged commit f227dc9 into llvm:main Jul 23, 2024
7 checks passed
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
Summary: 

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251460
@AZero13
Copy link
Contributor

AZero13 commented Aug 2, 2024

Does this affect codegen correctness or is this an enhancement? If it is the former, should this be backported to 19.x?

@jdoerfert jdoerfert deleted the pr/reconnect_phis branch August 14, 2024 14:37
@jdoerfert
Copy link
Member Author

Does this affect codegen correctness or is this an enhancement? If it is the former, should this be backported to 19.x?

Didn't see this. It's just an enhancement. No functional change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category flang:openmp llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants