[llvm-commits] [llvm] r58068 - in /llvm/trunk: include/llvm/CodeGen/LiveIntervalAnalysis.h lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/PreAllocSplitting.cpp test/CodeGen/X86/pre-split1.ll test/CodeGen/X86/pre-split2.ll test/CodeGen/X86/pre-split3.ll

Evan Cheng evan.cheng at apple.com
Thu Oct 23 19:05:00 PDT 2008


Author: evancheng
Date: Thu Oct 23 21:05:00 2008
New Revision: 58068

URL: http://llvm.org/viewvc/llvm-project?rev=58068&view=rev
Log:
Avoid splitting an interval multiple times; avoid splitting re-materializable val# (for now).

Added:
    llvm/trunk/test/CodeGen/X86/pre-split1.ll
    llvm/trunk/test/CodeGen/X86/pre-split2.ll
    llvm/trunk/test/CodeGen/X86/pre-split3.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h
    llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
    llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp

Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h?rev=58068&r1=58067&r2=58068&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h (original)
+++ llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h Thu Oct 23 21:05:00 2008
@@ -363,6 +363,11 @@
                             SmallVectorImpl<LiveInterval*> &SpillIs,
                             bool &isLoad);
 
+    /// isReMaterializable - Returns true if the definition MI of the specified
+    /// val# of the specified interval is re-materializable.
+    bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo,
+                            MachineInstr *MI);
+
     /// getRepresentativeReg - Find the largest super register of the specified
     /// physical register.
     unsigned getRepresentativeReg(unsigned Reg) const;

Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=58068&r1=58067&r2=58068&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Thu Oct 23 21:05:00 2008
@@ -948,6 +948,15 @@
   return true;
 }
 
+/// isReMaterializable - Returns true if the definition MI of the specified
+/// val# of the specified interval is re-materializable.
+bool LiveIntervals::isReMaterializable(const LiveInterval &li,
+                                       const VNInfo *ValNo, MachineInstr *MI) {
+  SmallVector<LiveInterval*, 4> Dummy1;
+  bool Dummy2;
+  return isReMaterializable(li, ValNo, MI, Dummy1, Dummy2);
+}
+
 /// isReMaterializable - Returns true if every definition of MI of every
 /// val# of the specified interval is re-materializable.
 bool LiveIntervals::isReMaterializable(const LiveInterval &li,

Modified: llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp?rev=58068&r1=58067&r2=58068&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp (original)
+++ llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp Thu Oct 23 21:05:00 2008
@@ -61,6 +61,9 @@
     // slot was used.
     std::map<std::pair<unsigned, unsigned>, int> LIValNoSSMap;
 
+    // RestoreMIs - All the restores inserted due to live interval splitting.
+    SmallPtrSet<MachineInstr*, 8> RestoreMIs;
+
   public:
     static char ID;
     PreAllocSplitting() : MachineFunctionPass(&ID) {}
@@ -80,6 +83,7 @@
     
     virtual void releaseMemory() {
       LIValNoSSMap.clear();
+      RestoreMIs.clear();
     }
 
     virtual const char *getPassName() const {
@@ -115,11 +119,14 @@
     void UpdateIntervalForSplit(VNInfo*, unsigned, unsigned);
 
     bool ShrinkWrapToLastUse(MachineBasicBlock*,
-                             std::vector<MachineOperand*>&);
+                             SmallVector<MachineOperand*, 4>&,
+                             SmallPtrSet<MachineInstr*, 4>&);
 
     void ShrinkWrapLiveInterval(VNInfo*, MachineBasicBlock*,
                         MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 8>&,
-                            DenseMap<unsigned, std::vector<MachineOperand*> >&);
+                DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >&,
+                  DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >&,
+                                SmallVector<MachineBasicBlock*, 4>&);
 
     bool SplitRegLiveInterval(LiveInterval*);
 
@@ -237,13 +244,15 @@
 /// slot where the val#s are in.
 void PreAllocSplitting::RecordSplit(unsigned Reg, unsigned SpillIndex,
                                     unsigned RestoreIndex, int SS) {
-  LiveInterval::iterator LR =
-    CurrLI->FindLiveRangeContaining(LIs->getUseIndex(SpillIndex));
-  LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, LR->valno->id),
-                                     SS));
-  LR = CurrLI->FindLiveRangeContaining(LIs->getDefIndex(RestoreIndex));
-  LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, LR->valno->id),
-                                     SS));
+  const LiveRange *LR = NULL;
+  if (SpillIndex) {
+    LR = CurrLI->getLiveRangeContaining(LIs->getUseIndex(SpillIndex));
+    LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg,
+                                                      LR->valno->id), SS));
+  }
+  LR = CurrLI->getLiveRangeContaining(LIs->getDefIndex(RestoreIndex));
+  LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg,
+                                                    LR->valno->id), SS));
 }
 
 /// isAlreadySplit - Return if a given val# of a register live interval is already
@@ -273,9 +282,14 @@
   // by the restore, which are defined by the original definition.
   const LiveRange *LR = CurrLI->getLiveRangeContaining(JoinIndex);
   After.push_back(std::make_pair(JoinIndex, LR->end));
+  if (CurrLI->isKill(ValNo, LR->end))
+    AfterKills.push_back(LR->end);
+
   assert(LR->contains(SplitIndex));
-  Before.push_back(std::make_pair(LR->start, SplitIndex));
-  BeforeKills.push_back(SplitIndex);
+  if (SplitIndex > LR->start) {
+    Before.push_back(std::make_pair(LR->start, SplitIndex));
+    BeforeKills.push_back(SplitIndex);
+  }
   Processed.insert(LR);
 
   SmallVector<MachineBasicBlock*, 4> WorkList;
@@ -325,12 +339,19 @@
   MachineInstr *AfterCopy = ValNo->copy;
   bool HasPHIKill = ValNo->hasPHIKill;
   CurrLI->removeValNo(ValNo);
-  VNInfo *BValNo = CurrLI->getNextValue(AfterDef, AfterCopy,
-                                        LIs->getVNInfoAllocator());
-  VNInfo *AValNo = CurrLI->getNextValue(JoinIndex,0, LIs->getVNInfoAllocator());
-  AValNo->hasPHIKill = HasPHIKill;
-  CurrLI->addKills(AValNo, AfterKills);
-  CurrLI->addKills(BValNo, BeforeKills);
+  VNInfo *BValNo = (Before.empty())
+    ? NULL
+    : CurrLI->getNextValue(AfterDef, AfterCopy, LIs->getVNInfoAllocator());
+  if (BValNo)
+    CurrLI->addKills(BValNo, BeforeKills);
+
+  VNInfo *AValNo = (After.empty())
+    ? NULL
+    : CurrLI->getNextValue(JoinIndex,0, LIs->getVNInfoAllocator());
+  if (AValNo) {
+    AValNo->hasPHIKill = HasPHIKill;
+    CurrLI->addKills(AValNo, AfterKills);
+  }
 
   for (unsigned i = 0, e = Before.size(); i != e; ++i) {
     unsigned Start = Before[i].first;
@@ -350,7 +371,8 @@
 /// is, remove from the last use to the barrier.
 bool
 PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB,
-                                       std::vector<MachineOperand*> &Uses) {
+                                       SmallVector<MachineOperand*, 4> &Uses,
+                                       SmallPtrSet<MachineInstr*, 4> &UseMIs) {
   MachineOperand *LastMO = 0;
   MachineInstr *LastMI = 0;
   if (MBB != BarrierMBB && Uses.size() == 1) {
@@ -359,9 +381,6 @@
     LastMO = Uses[0];
     LastMI = LastMO->getParent();
   } else {
-    SmallPtrSet<MachineInstr*, 4> UseMIs;
-    for (unsigned i = 0, e = Uses.size(); i != e; ++i)
-      UseMIs.insert(Uses[i]->getParent());
     MachineBasicBlock::iterator MII;
     if (MBB == BarrierMBB) {
       MII = Barrier;
@@ -396,7 +415,7 @@
     RangeStart = LIs->getMBBStartIdx(MBB);
   }
   if (MBB == BarrierMBB)
-    RangeEnd = LIs->getUseIndex(BarrierIdx);
+    RangeEnd = LIs->getUseIndex(BarrierIdx)+1;
   CurrLI->removeRange(RangeStart, RangeEnd);
 
   // Return true if the last use becomes a new kill.
@@ -408,22 +427,39 @@
 /// new kill indices.
 void
 PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo,
-                      MachineBasicBlock *MBB, MachineBasicBlock *DefMBB,
-                      SmallPtrSet<MachineBasicBlock*, 8> &Visited,
-                      DenseMap<unsigned, std::vector<MachineOperand*> > &Uses) {
+                              MachineBasicBlock *MBB, MachineBasicBlock *DefMBB,
+                                    SmallPtrSet<MachineBasicBlock*, 8> &Visited,
+           DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > &Uses,
+           DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > &UseMIs,
+                                  SmallVector<MachineBasicBlock*, 4> &UseMBBs) {
   if (!Visited.insert(MBB))
     return;
 
-  DenseMap<unsigned, std::vector<MachineOperand*> >::iterator UMII =
-    Uses.find(MBB->getNumber());
+  DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
+    UMII = Uses.find(MBB);
   if (UMII != Uses.end()) {
     // At least one use in this mbb, lets look for the kill.
-    if (ShrinkWrapToLastUse(MBB, UMII->second))
+    DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
+      UMII2 = UseMIs.find(MBB);
+    if (ShrinkWrapToLastUse(MBB, UMII->second, UMII2->second))
       // Found a kill, shrink wrapping of this path ends here.
       return;
+  } else if (MBB == DefMBB) {
+    assert(LIValNoSSMap.find(std::make_pair(CurrLI->reg, ValNo->id)) !=
+           LIValNoSSMap.end() && "Why wasn't def spilled?");
+    // There are no uses after the def.
+    MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def);
+    assert(RestoreMIs.count(DefMI) && "Not defined by a join?");
+    if (UseMBBs.empty()) {
+      // The only use must be below barrier in the barrier block. It's safe to
+      // remove the def.
+      LIs->RemoveMachineInstrFromMaps(DefMI);
+      DefMI->eraseFromParent();
+      CurrLI->removeRange(ValNo->def, LIs->getMBBEndIdx(MBB)+1);
+    }
   } else {
     // Remove entire live range of the bb out of the live interval.
-    CurrLI->removeRange(LIs->getMBBStartIdx(MBB), LIs->getMBBEndIdx(MBB));
+    CurrLI->removeRange(LIs->getMBBStartIdx(MBB), LIs->getMBBEndIdx(MBB)+1);
     abort(); // FIXME
   }
 
@@ -441,7 +477,7 @@
       // Pred is the def bb and the def reaches other val#s, we must
       // allow the value to be live out of the bb.
       continue;
-    ShrinkWrapLiveInterval(ValNo, Pred, DefMBB, Visited, Uses);
+    ShrinkWrapLiveInterval(ValNo, Pred, DefMBB, Visited, Uses, UseMIs, UseMBBs);
   }
 
   return;
@@ -464,6 +500,12 @@
     abort();
   }
 
+  // FIXME: For now, if definition is rematerializable, do not split.
+  MachineInstr *DefMI = (ValNo->def != ~0U)
+    ? LIs->getInstructionFromIndex(ValNo->def) : NULL;
+  if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI))
+    return false;
+
   // Find all references in the barrier mbb.
   SmallPtrSet<MachineInstr*, 4> RefsInMBB;
   for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg),
@@ -481,14 +523,14 @@
     return false;
 
   // Add a spill either before the barrier or after the definition.
-  MachineBasicBlock *DefMBB = NULL;
+  MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL;
   const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg);
   int SS;
   unsigned SpillIndex = 0;
+  MachineInstr *SpillMI = NULL;
   if (isAlreadySplit(CurrLI->reg, ValNo->id, SS)) {
     // If it's already split, just restore the value. There is no need to spill
     // the def again.
-    abort(); // FIXME
   } else if (ValNo->def == ~0U) {
     // If it's defined by a phi, we must split just before the barrier.
     MachineBasicBlock::iterator SpillPt = 
@@ -498,22 +540,22 @@
     // Add spill.
     SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
     TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC);
-    MachineInstr *StoreMI = prior(SpillPt);
-    LIs->InsertMachineInstrInMaps(StoreMI, SpillIndex);
+    SpillMI = prior(SpillPt);
+    LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
   } else {
     // Check if it's possible to insert a spill after the def MI.
-    MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def);
-    DefMBB = DefMI->getParent();
     MachineBasicBlock::iterator SpillPt =
       findNextEmptySlot(DefMBB, DefMI, SpillIndex);
     if (SpillPt == DefMBB->end())
       return false; // No gap to insert spill.
     SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
 
-    // Add spill. The store instruction does *not* kill the register.
-    TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, false, SS, RC);
-    MachineInstr *StoreMI = prior(SpillPt);
-    LIs->InsertMachineInstrInMaps(StoreMI, SpillIndex);
+    // Add spill. The store instruction kills the register if def is before the
+    // barrier in the barrier block.
+    TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg,
+                             DefMBB == BarrierMBB, SS, RC);
+    SpillMI = prior(SpillPt);
+    LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
   }
 
   // Add restore.
@@ -521,11 +563,12 @@
   TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC);
   MachineInstr *LoadMI = prior(RestorePt);
   LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex);
+  RestoreMIs.insert(LoadMI);
 
   // If live interval is spilled in the same block as the barrier, just
   // create a hole in the interval.
   if (!DefMBB ||
-      LIs->getInstructionFromIndex(SpillIndex)->getParent() == BarrierMBB) {
+      (SpillIndex && SpillMI->getParent() == BarrierMBB)) {
     UpdateIntervalForSplit(ValNo, LIs->getUseIndex(SpillIndex)+1,
                            LIs->getDefIndex(RestoreIndex));
 
@@ -539,7 +582,10 @@
   // Shrink wrap the live interval by walking up the CFG and find the
   // new kills.
   // Now let's find all the uses of the val#.
-  DenseMap<unsigned, std::vector<MachineOperand*> > Uses;
+  DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > Uses;
+  DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > UseMIs;
+  SmallPtrSet<MachineBasicBlock*, 4> Seen;
+  SmallVector<MachineBasicBlock*, 4> UseMBBs;
   for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(CurrLI->reg),
          UE = MRI->use_end(); UI != UE; ++UI) {
     MachineOperand &UseMO = UI.getOperand();
@@ -549,28 +595,37 @@
     if (ULR->valno != ValNo)
       continue;
     MachineBasicBlock *UseMBB = UseMI->getParent();
-    unsigned MBBId = UseMBB->getNumber();
-    DenseMap<unsigned, std::vector<MachineOperand*> >::iterator UMII =
-      Uses.find(MBBId);
-    if (UMII != Uses.end())
+    // Remember which other mbb's use this val#.
+    if (Seen.insert(UseMBB) && UseMBB != BarrierMBB)
+      UseMBBs.push_back(UseMBB);
+    DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
+      UMII = Uses.find(UseMBB);
+    if (UMII != Uses.end()) {
+      DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
+        UMII2 = UseMIs.find(UseMBB);
       UMII->second.push_back(&UseMO);
-    else {
-      std::vector<MachineOperand*> Ops;
+      UMII2->second.insert(UseMI);
+    } else {
+      SmallVector<MachineOperand*, 4> Ops;
       Ops.push_back(&UseMO);
-      Uses.insert(std::make_pair(MBBId, Ops));
+      Uses.insert(std::make_pair(UseMBB, Ops));
+      SmallPtrSet<MachineInstr*, 4> MIs;
+      MIs.insert(UseMI);
+      UseMIs.insert(std::make_pair(UseMBB, MIs));
     }
   }
 
   // Walk up the predecessor chains.
   SmallPtrSet<MachineBasicBlock*, 8> Visited;
-  ShrinkWrapLiveInterval(ValNo, BarrierMBB, DefMBB, Visited, Uses);
+  ShrinkWrapLiveInterval(ValNo, BarrierMBB, DefMBB, Visited,
+                         Uses, UseMIs, UseMBBs);
 
   // Remove live range from barrier to the restore. FIXME: Find a better
   // point to re-start the live interval.
   UpdateIntervalForSplit(ValNo, LIs->getUseIndex(BarrierIdx)+1,
                          LIs->getDefIndex(RestoreIndex));
   // Record val# values are in the specific spill slot.
-  RecordSplit(CurrLI->reg, BarrierIdx, RestoreIndex, SS);
+  RecordSplit(CurrLI->reg, SpillIndex, RestoreIndex, SS);
 
   ++NumSplit;
   return true;

Added: llvm/trunk/test/CodeGen/X86/pre-split1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pre-split1.ll?rev=58068&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/pre-split1.ll (added)
+++ llvm/trunk/test/CodeGen/X86/pre-split1.ll Thu Oct 23 21:05:00 2008
@@ -0,0 +1,23 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \
+; RUN:   grep {pre-alloc-split} | grep {Number of intervals split} | grep 1
+
+define void @test(double* %P, i32 %cond) nounwind {
+entry:
+	%0 = load double* %P, align 8		; <double> [#uses=1]
+	%1 = add double %0, 4.000000e+00		; <double> [#uses=2]
+	%2 = icmp eq i32 %cond, 0		; <i1> [#uses=1]
+	br i1 %2, label %bb1, label %bb
+
+bb:		; preds = %entry
+	%3 = add double %1, 4.000000e+00		; <double> [#uses=1]
+	br label %bb1
+
+bb1:		; preds = %bb, %entry
+	%A.0 = phi double [ %3, %bb ], [ %1, %entry ]		; <double> [#uses=1]
+	%4 = mul double %A.0, 4.000000e+00		; <double> [#uses=1]
+	%5 = tail call i32 (...)* @bar() nounwind		; <i32> [#uses=0]
+	store double %4, double* %P, align 8
+	ret void
+}
+
+declare i32 @bar(...)

Added: llvm/trunk/test/CodeGen/X86/pre-split2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pre-split2.ll?rev=58068&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/pre-split2.ll (added)
+++ llvm/trunk/test/CodeGen/X86/pre-split2.ll Thu Oct 23 21:05:00 2008
@@ -0,0 +1,26 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \
+; RUN:   not grep {pre-alloc-split}
+
+define i32 @t() {
+entry:
+	br label %bb6
+
+.noexc6:		; preds = %bb6
+	%0 = and i32 %2, -8		; <i32> [#uses=1]
+	tail call void @llvm.memmove.i32(i8* %3, i8* null, i32 %0, i32 1) nounwind
+	store double %1, double* null, align 8
+	br label %bb6
+
+bb6:		; preds = %.noexc6, %entry
+	%1 = uitofp i32 0 to double		; <double> [#uses=1]
+	%2 = sub i32 0, 0		; <i32> [#uses=1]
+	%3 = invoke i8* @_Znwm(i32 0)
+			to label %.noexc6 unwind label %lpad32		; <i8*> [#uses=1]
+
+lpad32:		; preds = %bb6
+	unreachable
+}
+
+declare void @llvm.memmove.i32(i8*, i8*, i32, i32) nounwind
+
+declare i8* @_Znwm(i32)

Added: llvm/trunk/test/CodeGen/X86/pre-split3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pre-split3.ll?rev=58068&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/pre-split3.ll (added)
+++ llvm/trunk/test/CodeGen/X86/pre-split3.ll Thu Oct 23 21:05:00 2008
@@ -0,0 +1,26 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \
+; RUN:   grep {pre-alloc-split} | grep {Number of intervals split} | grep 2
+
+define i32 @t(i32 %arg) {
+entry:
+	br label %bb6
+
+.noexc6:		; preds = %bb6
+	%0 = and i32 %2, -8		; <i32> [#uses=1]
+	tail call void @llvm.memmove.i32(i8* %3, i8* null, i32 %0, i32 1) nounwind
+	store double %1, double* null, align 8
+	br label %bb6
+
+bb6:		; preds = %.noexc6, %entry
+	%1 = uitofp i32 %arg to double		; <double> [#uses=1]
+	%2 = sub i32 0, 0		; <i32> [#uses=1]
+	%3 = invoke i8* @_Znwm(i32 0)
+			to label %.noexc6 unwind label %lpad32		; <i8*> [#uses=1]
+
+lpad32:		; preds = %bb6
+	unreachable
+}
+
+declare void @llvm.memmove.i32(i8*, i8*, i32, i32) nounwind
+
+declare i8* @_Znwm(i32)





More information about the llvm-commits mailing list