After reading memory that's already freed.
authorEvan Cheng <evan.cheng@apple.com>
Wed, 16 Apr 2008 20:24:25 +0000 (20:24 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 16 Apr 2008 20:24:25 +0000 (20:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49810 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SimpleRegisterCoalescing.cpp
lib/CodeGen/SimpleRegisterCoalescing.h
test/CodeGen/PowerPC/2008-04-16-CoalescerBug.ll [new file with mode: 0644]

index 15aae580700b94f9b805b11f68bb7d4c5ae35e67..e9a5e25afc2948763ed61fe9a6d44319d8e96f98 100644 (file)
@@ -560,8 +560,8 @@ static void removeRange(LiveInterval &li, unsigned Start, unsigned End,
 
 /// removeIntervalIfEmpty - Check if the live interval of a physical register
 /// is empty, if so remove it and also remove the empty intervals of its
-/// sub-registers.
-static void removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_,
+/// sub-registers. Return true if live interval is removed.
+static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_,
                                   const TargetRegisterInfo *tri_) {
   if (li.empty()) {
     if (TargetRegisterInfo::isPhysicalRegister(li.reg))
@@ -573,25 +573,28 @@ static void removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_,
           li_->removeInterval(*SR);
       }
     li_->removeInterval(li.reg);
+    return true;
   }
+  return false;
 }
 
 /// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy.
-///
-void SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
+/// Return true if live interval is removed.
+bool SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li,
                                                         MachineInstr *CopyMI) {
   unsigned CopyIdx = li_->getInstructionIndex(CopyMI);
   LiveInterval::iterator MLR =
     li.FindLiveRangeContaining(li_->getDefIndex(CopyIdx));
   if (MLR == li.end())
-    return;  // Already removed by ShortenDeadCopySrcLiveRange.
+    return false;  // Already removed by ShortenDeadCopySrcLiveRange.
   unsigned RemoveStart = MLR->start;
   unsigned RemoveEnd = MLR->end;
   // Remove the liverange that's defined by this.
   if (RemoveEnd == li_->getDefIndex(CopyIdx)+1) {
     removeRange(li, RemoveStart, RemoveEnd, li_, tri_);
-    removeIntervalIfEmpty(li, li_, tri_);
+    return removeIntervalIfEmpty(li, li_, tri_);
   }
+  return false;
 }
 
 /// PropagateDeadness - Propagate the dead marker to the instruction which
@@ -614,8 +617,8 @@ static void PropagateDeadness(LiveInterval &li, MachineInstr *CopyMI,
 /// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially
 /// extended by a dead copy. Mark the last use (if any) of the val# as kill
 /// as ends the live range there. If there isn't another use, then this
-/// live range is dead.
-void
+/// live range is dead. Return true if live interval is removed.
+bool
 SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
                                                       MachineInstr *CopyMI) {
   unsigned CopyIdx = li_->getInstructionIndex(CopyMI);
@@ -627,20 +630,19 @@ SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
     mf_->begin()->removeLiveIn(li.reg);
     const LiveRange *LR = li.getLiveRangeContaining(CopyIdx);
     removeRange(li, LR->start, LR->end, li_, tri_);
-    removeIntervalIfEmpty(li, li_, tri_);
-    return;
+    return removeIntervalIfEmpty(li, li_, tri_);
   }
 
   LiveInterval::iterator LR = li.FindLiveRangeContaining(CopyIdx-1);
   if (LR == li.end())
     // Livein but defined by a phi.
-    return;
+    return false;
 
   unsigned RemoveStart = LR->start;
   unsigned RemoveEnd = li_->getDefIndex(CopyIdx)+1;
   if (LR->end > RemoveEnd)
     // More uses past this copy? Nothing to do.
-    return;
+    return false;
 
   unsigned LastUseIdx;
   MachineOperand *LastUse = lastRegisterUse(LR->start, CopyIdx-1, li.reg,
@@ -658,7 +660,7 @@ SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
       int DeadIdx = LastUseMI->findRegisterDefOperandIdx(li.reg, false, tri_);
       LastUseMI->getOperand(DeadIdx).setIsDead();
     }
-    return;
+    return false;
   }
 
   // Is it livein?
@@ -678,7 +680,7 @@ SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
     PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
 
   removeRange(li, RemoveStart, LR->end, li_, tri_);
-  removeIntervalIfEmpty(li, li_, tri_);
+  return removeIntervalIfEmpty(li, li_, tri_);
 }
 
 /// CanCoalesceWithImpDef - Returns true if the specified copy instruction
@@ -1952,8 +1954,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
       }
       if (CopyMI->registerDefIsDead(DstReg)) {
         LiveInterval &li = li_->getInterval(DstReg);
-        ShortenDeadCopySrcLiveRange(li, CopyMI);
-        ShortenDeadCopyLiveRange(li, CopyMI);
+        if (!ShortenDeadCopySrcLiveRange(li, CopyMI))
+          ShortenDeadCopyLiveRange(li, CopyMI);
       }
       li_->RemoveMachineInstrFromMaps(*I);
       (*I)->eraseFromParent();
@@ -1979,8 +1981,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
           // If def of this move instruction is dead, remove its live range
           // from the dstination register's live interval.
           if (mii->registerDefIsDead(dstReg)) {
-            ShortenDeadCopySrcLiveRange(RegInt, mii);
-            ShortenDeadCopyLiveRange(RegInt, mii);
+            if (!ShortenDeadCopySrcLiveRange(RegInt, mii))
+              ShortenDeadCopyLiveRange(RegInt, mii);
           }
         }
         li_->RemoveMachineInstrFromMaps(mii);
index fa63159d1c86b0c4a1cf2d23ac7f1c67458a67b7..5b3d6b67a91b8291f3adb9eddaeadf30c3e009f4 100644 (file)
@@ -232,14 +232,14 @@ namespace llvm {
     void RemoveUnnecessaryKills(unsigned Reg, LiveInterval &LI);
 
     /// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy.
-    ///
-    void ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI);
+    /// Return true if live interval is removed.
+    bool ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI);
 
     /// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially
     /// extended by a dead copy. Mark the last use (if any) of the val# as kill
     /// as ends the live range there. If there isn't another use, then this
-    /// live range is dead.
-    void ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI);
+    /// live range is dead. Return true if live interval is removed.
+    bool ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI);
 
     /// lastRegisterUse - Returns the last use of the specific register between
     /// cycles Start and End or NULL if there are no uses.
diff --git a/test/CodeGen/PowerPC/2008-04-16-CoalescerBug.ll b/test/CodeGen/PowerPC/2008-04-16-CoalescerBug.ll
new file mode 100644 (file)
index 0000000..357ab10
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llc -mtriple=powerpc-apple-darwin
+; Avoid reading memory that's already freed.
+
+@llvm.used = appending global [1 x i8*] [ i8* bitcast (i32 (i64)* @_Z13GetSectorSizey to i8*) ], section "llvm.metadata"               ; <[1 x i8*]*> [#uses=0]
+
+define i32 @_Z13GetSectorSizey(i64 %Base) nounwind  {
+entry:
+       br i1 false, label %bb, label %UnifiedReturnBlock
+bb:            ; preds = %entry
+       %tmp10 = and i64 0, %Base               ; <i64> [#uses=0]
+       ret i32 0
+UnifiedReturnBlock:            ; preds = %entry
+       ret i32 131072
+}