[llvm] 70c68a6 - [NFC] Factor out utilities for manipulating widenable branches

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 19 14:46:32 PST 2019


Author: Philip Reames
Date: 2019-11-19T14:43:13-08:00
New Revision: 70c68a6b0e515967dba5b30f6a60e220a8cd8d2c

URL: https://github.com/llvm/llvm-project/commit/70c68a6b0e515967dba5b30f6a60e220a8cd8d2c
DIFF: https://github.com/llvm/llvm-project/commit/70c68a6b0e515967dba5b30f6a60e220a8cd8d2c.diff

LOG: [NFC] Factor out utilities for manipulating widenable branches

With the widenable condition construct, we have the ability to reason about branches which can be 'widened' (i.e. made to fail more often).  We've got a couple o transforms which leverage this.  This patch just cleans up the API a bit.

This is prep work for generalizing our definition of a widenable branch slightly.  At the moment "br i1 (and A, wc()), ..." is considered widenable, but oddly, neither "br i1 (and wc(), B), ..." or "br i1 wc(), ..." is.  That clearly needs addressed, so first, let's centralize the code in one place.

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/GuardUtils.h
    llvm/include/llvm/Transforms/Utils/GuardUtils.h
    llvm/lib/Analysis/GuardUtils.cpp
    llvm/lib/Transforms/Scalar/GuardWidening.cpp
    llvm/lib/Transforms/Scalar/LoopPredication.cpp
    llvm/lib/Transforms/Utils/GuardUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/GuardUtils.h b/llvm/include/llvm/Analysis/GuardUtils.h
index 41e7b7c06c75..f4492c72ce63 100644
--- a/llvm/include/llvm/Analysis/GuardUtils.h
+++ b/llvm/include/llvm/Analysis/GuardUtils.h
@@ -22,6 +22,10 @@ class Value;
 /// of llvm.experimental.guard intrinsic.
 bool isGuard(const User *U);
 
+/// Returns true iff \p U is a widenable branch (that is, parseWidenableBranch
+/// returns true).
+bool isWidenableBranch(const User *U);
+
 /// Returns true iff \p U has semantics of a guard expressed in a form of a
 /// widenable conditional branch to deopt block.
 bool isGuardAsWidenableBranch(const User *U);

diff  --git a/llvm/include/llvm/Transforms/Utils/GuardUtils.h b/llvm/include/llvm/Transforms/Utils/GuardUtils.h
index 3b365c56a5c0..43cd267f59bc 100644
--- a/llvm/include/llvm/Transforms/Utils/GuardUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/GuardUtils.h
@@ -14,8 +14,10 @@
 
 namespace llvm {
 
+class BranchInst;
 class CallInst;
 class Function;
+class Value;
 
 /// Splits control flow at point of \p Guard, replacing it with explicit branch
 /// by the condition of guard's first argument. The taken branch then goes to
@@ -24,6 +26,16 @@ class Function;
 /// deoptimize function \p DeoptIntrinsic.
 void makeGuardControlFlowExplicit(Function *DeoptIntrinsic, CallInst *Guard);
 
+/// Given a branch we know is widenable (defined per Analysis/GuardUtils.h),
+/// widen it such that condition 'NewCond' is also known to hold on the taken
+/// path.  Branch remains widenable after transform.
+void widenWidenableBranch(BranchInst *WidenableBR, Value *NewCond);
+
+/// Given a branch we know is widenable (defined per Analysis/GuardUtils.h),
+/// *set* it's condition such that (only) 'Cond' is known to hold on the taken
+/// path and that the branch remains widenable after transform.
+void setWidenableBranchCond(BranchInst *WidenableBR, Value *Cond);
+
 } // llvm
 
 #endif // LLVM_TRANSFORMS_UTILS_GUARDUTILS_H

diff  --git a/llvm/lib/Analysis/GuardUtils.cpp b/llvm/lib/Analysis/GuardUtils.cpp
index 863443cea355..6dc2b740ac96 100644
--- a/llvm/lib/Analysis/GuardUtils.cpp
+++ b/llvm/lib/Analysis/GuardUtils.cpp
@@ -19,6 +19,13 @@ bool llvm::isGuard(const User *U) {
   return match(U, m_Intrinsic<Intrinsic::experimental_guard>());
 }
 
+bool llvm::isWidenableBranch(const User *U) {
+  Value *Condition, *WidenableCondition;
+  BasicBlock *GuardedBB, *DeoptBB;
+  return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB,
+                              DeoptBB);
+}
+
 bool llvm::isGuardAsWidenableBranch(const User *U) {
   Value *Condition, *WidenableCondition;
   BasicBlock *GuardedBB, *DeoptBB;

diff  --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
index 27439a206d1e..943cc9ac5938 100644
--- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp
+++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
@@ -58,6 +58,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/GuardUtils.h"
 #include "llvm/Transforms/Utils/LoopUtils.h"
 #include <functional>
 
@@ -277,11 +278,7 @@ class GuardWideningImpl {
     widenCondCommon(getCondition(ToWiden), NewCondition, ToWiden, Result,
                     InvertCondition);
     if (isGuardAsWidenableBranch(ToWiden)) {
-      auto *BI = cast<BranchInst>(ToWiden);
-      auto *And = cast<Instruction>(BI->getCondition());
-      And->setOperand(0, Result);
-      And->moveBefore(ToWiden);
-      assert(isGuardAsWidenableBranch(ToWiden) && "still widenable?");
+      setWidenableBranchCond(cast<BranchInst>(ToWiden), Result);
       return;
     }
     setCondition(ToWiden, Result);

diff  --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp
index 9d67046d7436..1962c8ba39fb 100644
--- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp
@@ -196,6 +196,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/GuardUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Transforms/Utils/LoopUtils.h"
 
@@ -1144,14 +1145,7 @@ bool LoopPredication::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
     // context.
     NewCond = B.CreateFreeze(NewCond);
 
-    Value *Cond, *WC;
-    BasicBlock *IfTrueBB, *IfFalseBB;
-    bool Success =
-        parseWidenableBranch(WidenableBR, Cond, WC, IfTrueBB, IfFalseBB);
-    assert(Success && "implied from above");
-    (void)Success;
-    Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition());
-    WCAnd->setOperand(0, B.CreateAnd(NewCond, Cond));
+    widenWidenableBranch(WidenableBR, NewCond);
 
     Value *OldCond = BI->getCondition();
     BI->setCondition(ConstantInt::get(OldCond->getType(), !ExitIfTrue));

diff  --git a/llvm/lib/Transforms/Utils/GuardUtils.cpp b/llvm/lib/Transforms/Utils/GuardUtils.cpp
index 8069aba1fd13..37fca0d129b0 100644
--- a/llvm/lib/Transforms/Utils/GuardUtils.cpp
+++ b/llvm/lib/Transforms/Utils/GuardUtils.cpp
@@ -10,6 +10,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Utils/GuardUtils.h"
+#include "llvm/Analysis/GuardUtils.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
@@ -62,3 +63,28 @@ void llvm::makeGuardControlFlowExplicit(Function *DeoptIntrinsic,
   DeoptCall->setCallingConv(Guard->getCallingConv());
   DeoptBlockTerm->eraseFromParent();
 }
+
+
+void llvm::widenWidenableBranch(BranchInst *WidenableBR, Value *NewCond) {
+  assert(isWidenableBranch(WidenableBR) && "precondition");
+
+  Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition());
+  // Condition is only guaranteed to dominate branch
+  WCAnd->moveBefore(WidenableBR);
+  Value *OldCond = WCAnd->getOperand(0);
+  IRBuilder<> B(WCAnd);
+  WCAnd->setOperand(0, B.CreateAnd(NewCond, OldCond));
+
+  assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy");
+}
+
+void llvm::setWidenableBranchCond(BranchInst *WidenableBR, Value *NewCond) {
+  assert(isWidenableBranch(WidenableBR) && "precondition");
+
+  Instruction *WCAnd = cast<Instruction>(WidenableBR->getCondition());
+  // Condition is only guaranteed to dominate branch
+  WCAnd->moveBefore(WidenableBR);
+  WCAnd->setOperand(0, NewCond);
+
+  assert(isWidenableBranch(WidenableBR) && "preserve widenabiliy");
+}


        


More information about the llvm-commits mailing list