[llvm] r350435 - [BDCE] Remove dead uses of arguments

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 4 13:21:43 PST 2019


Author: nikic
Date: Fri Jan  4 13:21:43 2019
New Revision: 350435

URL: http://llvm.org/viewvc/llvm-project?rev=350435&view=rev
Log:
[BDCE] Remove dead uses of arguments

In addition to finding dead uses of instructions, also find dead uses
of function arguments, and replace them with zero as well.

I'm changing the way the known bits are computed here to remove the
coupling between the transfer function and the algorithm. It previously
relied on the first op being visited first and computing known bits --
unless the first op is not an instruction, in which case they're computed
on the second op. I could have adjusted this to check for "instruction
or argument", but I think it's better to avoid the repeated calculation
with an explicit flag.

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

Modified:
    llvm/trunk/include/llvm/Analysis/DemandedBits.h
    llvm/trunk/lib/Analysis/DemandedBits.cpp
    llvm/trunk/lib/Transforms/Scalar/BDCE.cpp
    llvm/trunk/test/Transforms/BDCE/dead-uses.ll

Modified: llvm/trunk/include/llvm/Analysis/DemandedBits.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/DemandedBits.h?rev=350435&r1=350434&r2=350435&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/DemandedBits.h (original)
+++ llvm/trunk/include/llvm/Analysis/DemandedBits.h Fri Jan  4 13:21:43 2019
@@ -65,9 +65,9 @@ public:
 private:
   void performAnalysis();
   void determineLiveOperandBits(const Instruction *UserI,
-    const Instruction *I, unsigned OperandNo,
+    const Value *Val, unsigned OperandNo,
     const APInt &AOut, APInt &AB,
-    KnownBits &Known, KnownBits &Known2);
+    KnownBits &Known, KnownBits &Known2, bool &KnownBitsComputed);
 
   Function &F;
   AssumptionCache ∾

Modified: llvm/trunk/lib/Analysis/DemandedBits.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DemandedBits.cpp?rev=350435&r1=350434&r2=350435&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/DemandedBits.cpp (original)
+++ llvm/trunk/lib/Analysis/DemandedBits.cpp Fri Jan  4 13:21:43 2019
@@ -85,8 +85,9 @@ static bool isAlwaysLive(Instruction *I)
 }
 
 void DemandedBits::determineLiveOperandBits(
-    const Instruction *UserI, const Instruction *I, unsigned OperandNo,
-    const APInt &AOut, APInt &AB, KnownBits &Known, KnownBits &Known2) {
+    const Instruction *UserI, const Value *Val, unsigned OperandNo,
+    const APInt &AOut, APInt &AB, KnownBits &Known, KnownBits &Known2,
+    bool &KnownBitsComputed) {
   unsigned BitWidth = AB.getBitWidth();
 
   // We're called once per operand, but for some instructions, we need to
@@ -97,7 +98,11 @@ void DemandedBits::determineLiveOperandB
   // provided here.
   auto ComputeKnownBits =
       [&](unsigned BitWidth, const Value *V1, const Value *V2) {
-        const DataLayout &DL = I->getModule()->getDataLayout();
+        if (KnownBitsComputed)
+          return;
+        KnownBitsComputed = true;
+
+        const DataLayout &DL = UserI->getModule()->getDataLayout();
         Known = KnownBits(BitWidth);
         computeKnownBits(V1, Known, DL, 0, &AC, UserI, &DT);
 
@@ -129,7 +134,7 @@ void DemandedBits::determineLiveOperandB
           // We need some output bits, so we need all bits of the
           // input to the left of, and including, the leftmost bit
           // known to be one.
-          ComputeKnownBits(BitWidth, I, nullptr);
+          ComputeKnownBits(BitWidth, Val, nullptr);
           AB = APInt::getHighBitsSet(BitWidth,
                  std::min(BitWidth, Known.countMaxLeadingZeros()+1));
         }
@@ -139,7 +144,7 @@ void DemandedBits::determineLiveOperandB
           // We need some output bits, so we need all bits of the
           // input to the right of, and including, the rightmost bit
           // known to be one.
-          ComputeKnownBits(BitWidth, I, nullptr);
+          ComputeKnownBits(BitWidth, Val, nullptr);
           AB = APInt::getLowBitsSet(BitWidth,
                  std::min(BitWidth, Known.countMaxTrailingZeros()+1));
         }
@@ -234,14 +239,11 @@ void DemandedBits::determineLiveOperandB
     // other operand are dead (unless they're both zero, in which
     // case they can't both be dead, so just mark the LHS bits as
     // dead).
-    if (OperandNo == 0) {
-      ComputeKnownBits(BitWidth, I, UserI->getOperand(1));
+    ComputeKnownBits(BitWidth, UserI->getOperand(0), UserI->getOperand(1));
+    if (OperandNo == 0)
       AB &= ~Known2.Zero;
-    } else {
-      if (!isa<Instruction>(UserI->getOperand(0)))
-        ComputeKnownBits(BitWidth, UserI->getOperand(0), I);
+    else
       AB &= ~(Known.Zero & ~Known2.Zero);
-    }
     break;
   case Instruction::Or:
     AB = AOut;
@@ -250,14 +252,11 @@ void DemandedBits::determineLiveOperandB
     // other operand are dead (unless they're both one, in which
     // case they can't both be dead, so just mark the LHS bits as
     // dead).
-    if (OperandNo == 0) {
-      ComputeKnownBits(BitWidth, I, UserI->getOperand(1));
+    ComputeKnownBits(BitWidth, UserI->getOperand(0), UserI->getOperand(1));
+    if (OperandNo == 0)
       AB &= ~Known2.One;
-    } else {
-      if (!isa<Instruction>(UserI->getOperand(0)))
-        ComputeKnownBits(BitWidth, UserI->getOperand(0), I);
+    else
       AB &= ~(Known.One & ~Known2.One);
-    }
     break;
   case Instruction::Xor:
   case Instruction::PHI:
@@ -368,33 +367,40 @@ void DemandedBits::performAnalysis() {
       Visited.insert(UserI);
 
     KnownBits Known, Known2;
+    bool KnownBitsComputed = false;
     // Compute the set of alive bits for each operand. These are anded into the
     // existing set, if any, and if that changes the set of alive bits, the
     // operand is added to the work-list.
     for (Use &OI : UserI->operands()) {
-      if (Instruction *I = dyn_cast<Instruction>(OI)) {
-        Type *T = I->getType();
-        if (T->isIntOrIntVectorTy()) {
-          unsigned BitWidth = T->getScalarSizeInBits();
-          APInt AB = APInt::getAllOnesValue(BitWidth);
-          if (UserI->getType()->isIntOrIntVectorTy() && !AOut &&
-              !isAlwaysLive(UserI)) {
-            // If all bits of the output are dead, then all bits of the input
-            // are also dead.
-            AB = APInt(BitWidth, 0);
-          } else {
-            // Bits of each operand that are used to compute alive bits of the
-            // output are alive, all others are dead.
-            determineLiveOperandBits(UserI, I, OI.getOperandNo(), AOut, AB,
-                                     Known, Known2);
-
-            // Keep track of uses which have no demanded bits.
-            if (AB.isNullValue())
-              DeadUses.insert(&OI);
-            else
-              DeadUses.erase(&OI);
-          }
+      // We also want to detect dead uses of arguments, but will only store
+      // demanded bits for instructions.
+      Instruction *I = dyn_cast<Instruction>(OI);
+      if (!I && !isa<Argument>(OI))
+        continue;
+
+      Type *T = OI->getType();
+      if (T->isIntOrIntVectorTy()) {
+        unsigned BitWidth = T->getScalarSizeInBits();
+        APInt AB = APInt::getAllOnesValue(BitWidth);
+        if (UserI->getType()->isIntOrIntVectorTy() && !AOut &&
+            !isAlwaysLive(UserI)) {
+          // If all bits of the output are dead, then all bits of the input
+          // are also dead.
+          AB = APInt(BitWidth, 0);
+        } else {
+          // Bits of each operand that are used to compute alive bits of the
+          // output are alive, all others are dead.
+          determineLiveOperandBits(UserI, OI, OI.getOperandNo(), AOut, AB,
+                                   Known, Known2, KnownBitsComputed);
+
+          // Keep track of uses which have no demanded bits.
+          if (AB.isNullValue())
+            DeadUses.insert(&OI);
+          else
+            DeadUses.erase(&OI);
+        }
 
+        if (I) {
           // If we've added to the set of alive bits (or the operand has not
           // been previously visited), then re-queue the operand to be visited
           // again.
@@ -408,9 +414,9 @@ void DemandedBits::performAnalysis() {
             AliveBits[I] = std::move(ABNew);
             Worklist.push_back(I);
           }
-        } else if (!Visited.count(I)) {
-          Worklist.push_back(I);
         }
+      } else if (I && !Visited.count(I)) {
+        Worklist.push_back(I);
       }
     }
   }

Modified: llvm/trunk/lib/Transforms/Scalar/BDCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/BDCE.cpp?rev=350435&r1=350434&r2=350435&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/BDCE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/BDCE.cpp Fri Jan  4 13:21:43 2019
@@ -114,8 +114,7 @@ static bool bitTrackingDCE(Function &F,
       if (!U->getType()->isIntOrIntVectorTy())
         continue;
 
-      // TODO: We could also find dead non-instruction uses, e.g. arguments.
-      if (!isa<Instruction>(U))
+      if (!isa<Instruction>(U) && !isa<Argument>(U))
         continue;
 
       if (!DB.isUseDead(&U))

Modified: llvm/trunk/test/Transforms/BDCE/dead-uses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BDCE/dead-uses.ll?rev=350435&r1=350434&r2=350435&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/BDCE/dead-uses.ll (original)
+++ llvm/trunk/test/Transforms/BDCE/dead-uses.ll Fri Jan  4 13:21:43 2019
@@ -45,7 +45,7 @@ define <2 x i32> @pr39771_fshr_multi_use
 ; First fshr operand is dead, but it comes from an argument, not instruction.
 define i32 @pr39771_fshr_multi_use_arg(i32 %a) {
 ; CHECK-LABEL: @pr39771_fshr_multi_use_arg(
-; CHECK-NEXT:    [[B:%.*]] = tail call i32 @llvm.fshr.i32(i32 [[A:%.*]], i32 [[A]], i32 1)
+; CHECK-NEXT:    [[B:%.*]] = tail call i32 @llvm.fshr.i32(i32 0, i32 [[A:%.*]], i32 1)
 ; CHECK-NEXT:    [[C:%.*]] = lshr i32 [[B]], 23
 ; CHECK-NEXT:    [[D:%.*]] = xor i32 [[C]], [[B]]
 ; CHECK-NEXT:    [[E:%.*]] = and i32 [[D]], 31
@@ -58,11 +58,10 @@ define i32 @pr39771_fshr_multi_use_arg(i
   ret i32 %e
 }
 
-; Second or operand is dead, but BDCE does not realize this.
 define i32 @pr39771_expanded_fshr_multi_use(i32 %a) {
 ; CHECK-LABEL: @pr39771_expanded_fshr_multi_use(
 ; CHECK-NEXT:    [[TMP:%.*]] = lshr i32 [[A:%.*]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[A]], 31
+; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 0, 31
 ; CHECK-NEXT:    [[B:%.*]] = or i32 [[TMP]], [[TMP2]]
 ; CHECK-NEXT:    [[C:%.*]] = lshr i32 [[B]], 23
 ; CHECK-NEXT:    [[D:%.*]] = xor i32 [[C]], [[B]]




More information about the llvm-commits mailing list