[llvm] r354443 - [Codegen] Remove dead flags on Physical Defs in machine cse

David Green via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 20 02:22:18 PST 2019


Author: dmgreen
Date: Wed Feb 20 02:22:18 2019
New Revision: 354443

URL: http://llvm.org/viewvc/llvm-project?rev=354443&view=rev
Log:
[Codegen] Remove dead flags on Physical Defs in machine cse

We may leave behind incorrect dead flags on instructions that are CSE'd. Make
sure we remove the dead flags on physical registers to prevent other incorrect
code motion.

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

Added:
    llvm/trunk/test/CodeGen/Thumb/machine-cse-deadreg.mir
Modified:
    llvm/trunk/lib/CodeGen/MachineCSE.cpp

Modified: llvm/trunk/lib/CodeGen/MachineCSE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCSE.cpp?rev=354443&r1=354442&r2=354443&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineCSE.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineCSE.cpp Wed Feb 20 02:22:18 2019
@@ -94,6 +94,7 @@ namespace {
         ScopedHashTable<MachineInstr *, unsigned, MachineInstrExpressionTrait,
                         AllocatorTy>;
     using ScopeType = ScopedHTType::ScopeTy;
+    using PhysDefVector = SmallVector<std::pair<unsigned, unsigned>, 2>;
 
     unsigned LookAheadLimit = 0;
     DenseMap<MachineBasicBlock *, ScopeType *> ScopeMap;
@@ -108,13 +109,11 @@ namespace {
                                 MachineBasicBlock::const_iterator E) const;
     bool hasLivePhysRegDefUses(const MachineInstr *MI,
                                const MachineBasicBlock *MBB,
-                               SmallSet<unsigned,8> &PhysRefs,
-                               SmallVectorImpl<unsigned> &PhysDefs,
-                               bool &PhysUseDef) const;
+                               SmallSet<unsigned, 8> &PhysRefs,
+                               PhysDefVector &PhysDefs, bool &PhysUseDef) const;
     bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
-                          SmallSet<unsigned,8> &PhysRefs,
-                          SmallVectorImpl<unsigned> &PhysDefs,
-                          bool &NonLocal) const;
+                          SmallSet<unsigned, 8> &PhysRefs,
+                          PhysDefVector &PhysDefs, bool &NonLocal) const;
     bool isCSECandidate(MachineInstr *MI);
     bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
                            MachineInstr *CSMI, MachineInstr *MI);
@@ -255,9 +254,9 @@ static bool isCallerPreservedOrConstPhys
 /// instruction does not uses a physical register.
 bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
                                        const MachineBasicBlock *MBB,
-                                       SmallSet<unsigned,8> &PhysRefs,
-                                       SmallVectorImpl<unsigned> &PhysDefs,
-                                       bool &PhysUseDef) const{
+                                       SmallSet<unsigned, 8> &PhysRefs,
+                                       PhysDefVector &PhysDefs,
+                                       bool &PhysUseDef) const {
   // First, add all uses to PhysRefs.
   for (const MachineOperand &MO : MI->operands()) {
     if (!MO.isReg() || MO.isDef())
@@ -277,7 +276,8 @@ bool MachineCSE::hasLivePhysRegDefUses(c
   // (which currently contains only uses), set the PhysUseDef flag.
   PhysUseDef = false;
   MachineBasicBlock::const_iterator I = MI; I = std::next(I);
-  for (const MachineOperand &MO : MI->operands()) {
+  for (const auto &MOP : llvm::enumerate(MI->operands())) {
+    const MachineOperand &MO = MOP.value();
     if (!MO.isReg() || !MO.isDef())
       continue;
     unsigned Reg = MO.getReg();
@@ -292,20 +292,21 @@ bool MachineCSE::hasLivePhysRegDefUses(c
     // common since this pass is run before livevariables. We can scan
     // forward a few instructions and check if it is obviously dead.
     if (!MO.isDead() && !isPhysDefTriviallyDead(Reg, I, MBB->end()))
-      PhysDefs.push_back(Reg);
+      PhysDefs.push_back(std::make_pair(MOP.index(), Reg));
   }
 
   // Finally, add all defs to PhysRefs as well.
   for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i)
-    for (MCRegAliasIterator AI(PhysDefs[i], TRI, true); AI.isValid(); ++AI)
+    for (MCRegAliasIterator AI(PhysDefs[i].second, TRI, true); AI.isValid();
+         ++AI)
       PhysRefs.insert(*AI);
 
   return !PhysRefs.empty();
 }
 
 bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
-                                  SmallSet<unsigned,8> &PhysRefs,
-                                  SmallVectorImpl<unsigned> &PhysDefs,
+                                  SmallSet<unsigned, 8> &PhysRefs,
+                                  PhysDefVector &PhysDefs,
                                   bool &NonLocal) const {
   // For now conservatively returns false if the common subexpression is
   // not in the same basic block as the given instruction. The only exception
@@ -319,7 +320,8 @@ bool MachineCSE::PhysRegDefsReach(Machin
       return false;
 
     for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i) {
-      if (MRI->isAllocatable(PhysDefs[i]) || MRI->isReserved(PhysDefs[i]))
+      if (MRI->isAllocatable(PhysDefs[i].second) ||
+          MRI->isReserved(PhysDefs[i].second))
         // Avoid extending live range of physical registers if they are
         //allocatable or reserved.
         return false;
@@ -535,7 +537,7 @@ bool MachineCSE::ProcessBlock(MachineBas
     // It's also not safe if the instruction uses physical registers.
     bool CrossMBBPhysDef = false;
     SmallSet<unsigned, 8> PhysRefs;
-    SmallVector<unsigned, 2> PhysDefs;
+    PhysDefVector PhysDefs;
     bool PhysUseDef = false;
     if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs,
                                           PhysDefs, PhysUseDef)) {
@@ -634,6 +636,9 @@ bool MachineCSE::ProcessBlock(MachineBas
       // we should make sure it is not dead at CSMI.
       for (unsigned ImplicitDefToUpdate : ImplicitDefsToUpdate)
         CSMI->getOperand(ImplicitDefToUpdate).setIsDead(false);
+      for (auto PhysDef : PhysDefs)
+        if (!MI->getOperand(PhysDef.first).isDead())
+          CSMI->getOperand(PhysDef.first).setIsDead(false);
 
       // Go through implicit defs of CSMI and MI, and clear the kill flags on
       // their uses in all the instructions between CSMI and MI.
@@ -662,9 +667,9 @@ bool MachineCSE::ProcessBlock(MachineBas
         // Add physical register defs now coming in from a predecessor to MBB
         // livein list.
         while (!PhysDefs.empty()) {
-          unsigned LiveIn = PhysDefs.pop_back_val();
-          if (!MBB->isLiveIn(LiveIn))
-            MBB->addLiveIn(LiveIn);
+          auto LiveIn = PhysDefs.pop_back_val();
+          if (!MBB->isLiveIn(LiveIn.second))
+            MBB->addLiveIn(LiveIn.second);
         }
         ++NumCrossBBCSEs;
       }

Added: llvm/trunk/test/CodeGen/Thumb/machine-cse-deadreg.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/machine-cse-deadreg.mir?rev=354443&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb/machine-cse-deadreg.mir (added)
+++ llvm/trunk/test/CodeGen/Thumb/machine-cse-deadreg.mir Wed Feb 20 02:22:18 2019
@@ -0,0 +1,103 @@
+# RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass=machine-cse -verify-machineinstrs -o - %s | FileCheck %s
+
+--- |
+  target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+  target triple = "thumbv6m-arm-none-eabi"
+
+  define i32 @funca(i64 %l1) {
+  entry:
+    %l2 = icmp ult i64 %l1, -177673816660004267
+    %l3 = add i64 %l1, 401100203
+    %rem.i = select i1 %l2, i64 %l1, i64 %l3
+    %conv = trunc i64 %rem.i to i32
+    ret i32 %conv
+  }
+
+  define i32 @funcb(i64 %l1) { ret i32 0 }
+
+...
+---
+name:            funca
+tracksRegLiveness: true
+liveins:
+  - { reg: '$r0', virtual-reg: '%0' }
+  - { reg: '$r1', virtual-reg: '%1' }
+constants:
+  - id:              0
+    value:           i32 401100203
+    alignment:       4
+    isTargetSpecific: false
+  - id:              1
+    value:           i32 41367909
+    alignment:       4
+    isTargetSpecific: false
+body:             |
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+    liveins: $r0, $r1
+
+    %1:tgpr = COPY $r1
+    %0:tgpr = COPY $r0
+    %2:tgpr = tLDRpci %const.0, 14, $noreg :: (load 4 from constant-pool)
+    %3:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
+    %4:tgpr = tLDRpci %const.1, 14, $noreg :: (load 4 from constant-pool)
+    %5:tgpr, $cpsr = tADDrr %0, %2, 14, $noreg
+    %6:tgpr, $cpsr = tADC %1, killed %4, 14, $noreg, implicit $cpsr
+    tBcc %bb.2, 3, $cpsr
+
+  bb.1.entry:
+    successors: %bb.2(0x80000000)
+
+  bb.2.entry:
+    %7:tgpr = PHI %3, %bb.1, %0, %bb.0
+    $r0 = COPY %7
+    tBX_RET 14, $noreg, implicit $r0
+
+# CHECK-LABEL: name: funca
+# cpsr def must not be dead
+# CHECK: %3:tgpr, $cpsr = tADDrr %0, %2
+# CHECK-NOT: %5:tgpr, $cpsr = tADDrr %0, %2
+
+...
+---
+name:            funcb
+tracksRegLiveness: true
+liveins:
+  - { reg: '$r0', virtual-reg: '%0' }
+  - { reg: '$r1', virtual-reg: '%1' }
+constants:
+  - id:              0
+    value:           i32 401100203
+    alignment:       4
+    isTargetSpecific: false
+  - id:              1
+    value:           i32 41367909
+    alignment:       4
+    isTargetSpecific: false
+body:             |
+  bb.0:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+    liveins: $r0, $r1
+
+    %1:tgpr = COPY $r1
+    %0:tgpr = COPY $r0
+    %2:tgpr = tLDRpci %const.0, 14, $noreg :: (load 4 from constant-pool)
+    %3:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
+    %4:tgpr = tLDRpci %const.1, 14, $noreg :: (load 4 from constant-pool)
+    %5:tgpr, dead $cpsr = tADDrr %0, %2, 14, $noreg
+    %6:tgpr, $cpsr = tADDrr %1, killed %4, 14, $noreg
+    tBcc %bb.2, 3, $cpsr
+
+  bb.1:
+    successors: %bb.2(0x80000000)
+
+  bb.2:
+    %7:tgpr = PHI %3, %bb.1, %0, %bb.0
+    $r0 = COPY %7
+    tBX_RET 14, $noreg, implicit $r0
+
+# CHECK-LABEL: name: funcb
+# cpsr def should be dead
+# CHECK: %3:tgpr, dead $cpsr = tADDrr %0, %2
+# CHECK-NOT: %5:tgpr, dead $cpsr = tADDrr %0, %2
+...




More information about the llvm-commits mailing list