[llvm] aa5b6c9 - [ConstraintElimination] Initial support for using info from assumes.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 26 02:09:19 PDT 2021


Author: Florian Hahn
Date: 2021-08-26T10:08:00+01:00
New Revision: aa5b6c97793ab4091862f4a1636eb39b31d91b3c

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

LOG: [ConstraintElimination] Initial support for using info from assumes.

This patch adds initial support to use facts from @llvm.assume calls. It
intentionally does not handle all possible cases to keep things simple
initially.

For now, the condition from an assume is made available on entry to the
containing block, if the assume is guaranteed to execute. Otherwise it
is only made available in the successor blocks.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
    llvm/test/Transforms/ConstraintElimination/assumes.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index efd1c025d0cdf..7f2d5d7d99871 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ConstraintSystem.h"
 #include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
@@ -268,6 +269,31 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
       continue;
     WorkList.emplace_back(DT.getNode(&BB));
 
+    // True as long as long as the current instruction is guaranteed to execute.
+    bool GuaranteedToExecute = true;
+    // Scan BB for assume calls.
+    // TODO: also use this scan to queue conditions to simplify, so we can
+    // interleave facts from assumes and conditions to simplify in a single
+    // basic block. And to skip another traversal of each basic block when
+    // simplifying.
+    for (Instruction &I : BB) {
+      Value *Cond;
+      // For now, just handle assumes with a single compare as condition.
+      if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
+          isa<CmpInst>(Cond)) {
+        if (GuaranteedToExecute) {
+          // The assume is guaranteed to execute when BB is entered, hence Cond
+          // holds on entry to BB.
+          WorkList.emplace_back(DT.getNode(&BB), cast<CmpInst>(Cond), false);
+        } else {
+          // Otherwise the condition only holds in the successors.
+          for (BasicBlock *Succ : successors(&BB))
+            WorkList.emplace_back(DT.getNode(Succ), cast<CmpInst>(Cond), false);
+        }
+      }
+      GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
+    }
+
     auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
     if (!Br || !Br->isConditional())
       continue;
@@ -395,8 +421,13 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
             for (auto &E : reverse(DFSInStack))
               dbgs() << "   C " << *E.Condition << " " << E.IsNot << "\n";
           });
-          Cmp->replaceAllUsesWith(
-              ConstantInt::getTrue(F.getParent()->getContext()));
+          Cmp->replaceUsesWithIf(
+              ConstantInt::getTrue(F.getParent()->getContext()), [](Use &U) {
+                // Conditions in an assume trivially simplify to true. Skip uses
+                // in assume calls to not destroy the available information.
+                auto *II = dyn_cast<IntrinsicInst>(U.getUser());
+                return !II || II->getIntrinsicID() != Intrinsic::assume;
+              });
           NumCondsRemoved++;
           Changed = true;
         }

diff  --git a/llvm/test/Transforms/ConstraintElimination/assumes.ll b/llvm/test/Transforms/ConstraintElimination/assumes.ll
index b17b55eb0e766..1d1876bce9c4f 100644
--- a/llvm/test/Transforms/ConstraintElimination/assumes.ll
+++ b/llvm/test/Transforms/ConstraintElimination/assumes.ll
@@ -16,7 +16,7 @@ define i1 @assume_dominates(i8 %a, i8 %b, i1 %c) {
 ; CHECK:       then:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -24,7 +24,7 @@ define i1 @assume_dominates(i8 %a, i8 %b, i1 %c) {
 ; CHECK:       else:
 ; CHECK-NEXT:    [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
+; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -64,7 +64,7 @@ define i1 @assume_dominates_with_may_unwind_call_before_assume(i8 %a, i8 %b, i1
 ; CHECK:       then:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -72,7 +72,7 @@ define i1 @assume_dominates_with_may_unwind_call_before_assume(i8 %a, i8 %b, i1
 ; CHECK:       else:
 ; CHECK-NEXT:    [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
+; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -113,7 +113,7 @@ define i1 @assume_dominates_with_may_unwind_call_after_assume(i8 %a, i8 %b, i1 %
 ; CHECK:       then:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -121,7 +121,7 @@ define i1 @assume_dominates_with_may_unwind_call_after_assume(i8 %a, i8 %b, i1 %
 ; CHECK:       else:
 ; CHECK-NEXT:    [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
+; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -159,7 +159,7 @@ define i1 @assume_single_bb(i8 %a, i8 %b, i1 %c) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_1]])
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -186,7 +186,7 @@ define i1 @assume_same_bb(i8 %a, i8 %b, i1 %c) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_1]])
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -231,7 +231,7 @@ define i1 @assume_same_bb2(i8 %a, i8 %b, i1 %c) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_1]])
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -299,7 +299,7 @@ define i1 @assume_same_bb_before_may_exiting_call(i8 %a, i8 %b, i1 %c) {
 ; CHECK-NEXT:    call void @may_unwind()
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -328,7 +328,7 @@ define i1 @assume_same_bb_after_condition(i8 %a, i8 %b, i1 %c) {
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -394,6 +394,7 @@ exit:
 }
 
 ; The information of from the assume can be used to simplify %t.2.
+; TODO
 define i1 @assume_single_bb_conditions_after_assume(i8 %a, i8 %b, i1 %c) {
 ; CHECK-LABEL: @assume_single_bb_conditions_after_assume(
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
@@ -425,6 +426,7 @@ define i1 @assume_single_bb_conditions_after_assume(i8 %a, i8 %b, i1 %c) {
 }
 
 ; The information of from the assume can be used to simplify %t.2.
+; TODO
 define i1 @assume_single_bb_assume_at_end_after_may_unwind(i8 %a, i8 %b, i1 %c) {
 ; CHECK-LABEL: @assume_single_bb_assume_at_end_after_may_unwind(
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
@@ -457,6 +459,7 @@ define i1 @assume_single_bb_assume_at_end_after_may_unwind(i8 %a, i8 %b, i1 %c)
 
 ; The definition of %t.2 is before the @llvm.assume call, but all uses are
 ; after the call. %t.2 can be simplified.
+; TODO
 define i1 @all_uses_after_assume(i8 %a, i8 %b, i1 %c) {
 ; CHECK-LABEL: @all_uses_after_assume(
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1


        


More information about the llvm-commits mailing list