[llvm] 248a5db - Change callbr to only define its output SSA variable on the normal

James Y Knight via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 23 16:37:10 PDT 2020


Author: James Y Knight
Date: 2020-04-23T19:36:44-04:00
New Revision: 248a5db3f2e5ff8e4c37b9578bfda8c4d97eaedc

URL: https://github.com/llvm/llvm-project/commit/248a5db3f2e5ff8e4c37b9578bfda8c4d97eaedc
DIFF: https://github.com/llvm/llvm-project/commit/248a5db3f2e5ff8e4c37b9578bfda8c4d97eaedc.diff

LOG: Change callbr to only define its output SSA variable on the normal
path, not the indirect targets.

Fixes: PR45565.

Differential Revision: https://reviews.llvm.org/D78341

Added: 
    llvm/test/CodeGen/X86/callbr-codegenprepare.ll

Modified: 
    llvm/docs/LangRef.rst
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/lib/IR/Dominators.cpp
    llvm/test/Verifier/dominates.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index af95d060f6f0..8d86c0610a2b 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -7366,9 +7366,8 @@ instruction in most regards. The primary 
diff erence is that it
 establishes an association with additional labels to define where control
 flow goes after the call.
 
-Outputs of a '``callbr``' instruction are valid only on the '``fallthrough``'
-path.  Use of outputs on the '``indirect``' path(s) results in :ref:`poison
-values <poisonvalues>`.
+The output values of a '``callbr``' instruction are available only to
+the '``fallthrough``' block, not to any '``indirect``' blocks(s).
 
 The only use of this today is to implement the "goto" feature of gcc inline
 assembly where additional labels can be provided as locations for the inline

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f023899484fb..d1970d45a686 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -222,7 +222,7 @@ static bool valueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
   // Otherwise, if the instruction is in the entry block and is not an invoke,
   // then it obviously dominates all phi nodes.
   if (I->getParent() == &I->getFunction()->getEntryBlock() &&
-      !isa<InvokeInst>(I))
+      !isa<InvokeInst>(I) && !isa<CallBrInst>(I))
     return true;
 
   return false;

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b31a11afcd06..ddce360e3da6 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4641,7 +4641,7 @@ bool llvm::canCreatePoison(const Instruction *I) {
   case Instruction::CallBr:
   case Instruction::Invoke:
     // Function calls can return a poison value even if args are non-poison
-    // values. CallBr returns poison when jumping to indirect labels.
+    // values.
     return true;
   case Instruction::InsertElement:
   case Instruction::ExtractElement: {

diff  --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp
index 4062ade645ba..d4a2026726b8 100644
--- a/llvm/lib/IR/Dominators.cpp
+++ b/llvm/lib/IR/Dominators.cpp
@@ -134,7 +134,7 @@ bool DominatorTree::dominates(const Instruction *Def,
   // dominates every instruction in UseBB.
   // A PHI is dominated only if the instruction dominates every possible use in
   // the UseBB.
-  if (isa<InvokeInst>(Def) || isa<PHINode>(User))
+  if (isa<InvokeInst>(Def) || isa<CallBrInst>(Def) || isa<PHINode>(User))
     return dominates(Def, UseBB);
 
   if (DefBB != UseBB)
@@ -168,6 +168,13 @@ bool DominatorTree::dominates(const Instruction *Def,
     return dominates(E, UseBB);
   }
 
+  // Callbr results are similarly only usable in the default destination.
+  if (const auto *CBI = dyn_cast<CallBrInst>(Def)) {
+    BasicBlock *NormalDest = CBI->getDefaultDest();
+    BasicBlockEdge E(DefBB, NormalDest);
+    return dominates(E, UseBB);
+  }
+
   return dominates(DefBB, UseBB);
 }
 
@@ -273,6 +280,13 @@ bool DominatorTree::dominates(const Instruction *Def, const Use &U) const {
     return dominates(E, U);
   }
 
+  // Callbr results are similarly only usable in the default destination.
+  if (const auto *CBI = dyn_cast<CallBrInst>(Def)) {
+    BasicBlock *NormalDest = CBI->getDefaultDest();
+    BasicBlockEdge E(DefBB, NormalDest);
+    return dominates(E, U);
+  }
+
   // If the def and use are in 
diff erent blocks, do a simple CFG dominator
   // tree query.
   if (DefBB != UseBB)
@@ -371,4 +385,3 @@ void DominatorTreeWrapperPass::verifyAnalysis() const {
 void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
   DT.print(OS);
 }
-

diff  --git a/llvm/test/CodeGen/X86/callbr-codegenprepare.ll b/llvm/test/CodeGen/X86/callbr-codegenprepare.ll
new file mode 100644
index 000000000000..d8755f682a8e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/callbr-codegenprepare.ll
@@ -0,0 +1,26 @@
+;; RUN: opt -S -codegenprepare < %s | FileCheck %s
+
+;; Ensure that codegenprepare (via InstSimplify) doesn't eliminate the
+;; phi here (which would cause a module verification error).
+
+;; CHECK: phi
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @foo(i32)
+
+define dso_local i32 @futex_lock_pi_atomic() local_unnamed_addr {
+entry:
+  %0 = callbr i32 asm "", "=r,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@futex_lock_pi_atomic, %b.exit))
+          to label %asm.fallthrough.i [label %b.exit]
+
+asm.fallthrough.i:
+  br label %b.exit
+
+b.exit:
+  %g.0 = phi i32 [ %0, %asm.fallthrough.i ], [ undef, %entry ]
+  tail call void @foo(i32 %g.0)
+  ret i32 undef
+}
+

diff  --git a/llvm/test/Verifier/dominates.ll b/llvm/test/Verifier/dominates.ll
index 6b0c67f7a2b7..3f2f698b4b28 100644
--- a/llvm/test/Verifier/dominates.ll
+++ b/llvm/test/Verifier/dominates.ll
@@ -68,3 +68,16 @@ next:
 ; CHECK-NEXT:  %y = phi i32 [ 0, %entry ]
 ; CHECK-NEXT:  %x = phi i32 [ %y, %entry ]
 }
+
+define i32 @f6(i32 %x) {
+bb0:
+  %y1 = callbr i32 asm "", "=r"() to label %bb1 [label %bb2]
+bb1:
+  ret i32 0
+bb2:
+  ret i32 %y1
+; CHECK: Instruction does not dominate all uses!
+; CHECK-NEXT:  %y1 = callbr i32 asm "", "=r"()
+; CHECK-NEXT:        to label %bb1 [label %bb2]
+; CHECK-NEXT:  ret i32 %y1
+}


        


More information about the llvm-commits mailing list