[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