It's not always safe to fold movsd into xorpd, etc. Check the alignment of the load...
authorEvan Cheng <evan.cheng@apple.com>
Fri, 8 Feb 2008 21:20:40 +0000 (21:20 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Fri, 8 Feb 2008 21:20:40 +0000 (21:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46893 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
include/llvm/Target/TargetInstrInfo.h
lib/Target/ARM/ARMInstrInfo.cpp
lib/Target/ARM/ARMInstrInfo.h
lib/Target/Alpha/AlphaInstrInfo.cpp
lib/Target/Alpha/AlphaInstrInfo.h
lib/Target/CellSPU/SPUInstrInfo.cpp
lib/Target/CellSPU/SPUInstrInfo.h
lib/Target/Mips/MipsInstrInfo.cpp
lib/Target/Mips/MipsInstrInfo.h
lib/Target/PowerPC/PPCInstrInfo.cpp
lib/Target/PowerPC/PPCInstrInfo.h
lib/Target/Sparc/SparcInstrInfo.cpp
lib/Target/Sparc/SparcInstrInfo.h
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86InstrInfo.h
test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll [new file with mode: 0644]

index e18b3665f69b708f5c012856b73d9ca22970793f..f9b361f59b98c6609f2d2bde17e5fae99949cb5f 100644 (file)
@@ -262,7 +262,8 @@ public:
   /// operand folded, otherwise NULL is returned. The client is responsible for
   /// removing the old instruction and adding the new one in the instruction
   /// stream.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const {
     return 0;
@@ -271,7 +272,8 @@ public:
   /// foldMemoryOperand - Same as the previous version except it allows folding
   /// of any load and store from / to any address, not just from a specific
   /// stack slot.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index 9ecd7c76bcf5b054bc2db46c138223d60c4d8741..4d1819de873a2f9bff1e876654d9af47a7916b84 100644 (file)
@@ -640,9 +640,10 @@ bool ARMInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
   return true;
 }
 
-MachineInstr *ARMInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FI) const {
+MachineInstr *ARMInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
+                                              SmallVectorImpl<unsigned> &Ops,
+                                              int FI) const {
   if (Ops.size() != 1) return NULL;
 
   unsigned OpNum = Ops[0];
@@ -721,7 +722,7 @@ MachineInstr *ARMInstrInfo::foldMemoryOperand(MachineInstr *MI,
 }
 
 bool ARMInstrInfo::canFoldMemoryOperand(MachineInstr *MI,
-                                         SmallVectorImpl<unsigned> &Ops) const {
+                                        SmallVectorImpl<unsigned> &Ops) const {
   if (Ops.size() != 1) return false;
 
   unsigned OpNum = Ops[0];
index 60d9640b8daf4d506d25034760ed727cf034a537..31216e49ebac6eaa8cc0ea7c5ba3b9e48ef774f7 100644 (file)
@@ -191,11 +191,13 @@ public:
                                            MachineBasicBlock::iterator MI,
                                  const std::vector<CalleeSavedInfo> &CSI) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index 53d710487039dc7c831e0f78cf6b078356670ab1..48e23f9d3816e89866de44999b15ef4dc45840b6 100644 (file)
@@ -250,9 +250,10 @@ void AlphaInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
   NewMIs.push_back(MIB);
 }
 
-MachineInstr *AlphaInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FrameIndex) const {
+MachineInstr *AlphaInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                                MachineInstr *MI,
+                                                SmallVectorImpl<unsigned> &Ops,
+                                                int FrameIndex) const {
    if (Ops.size() != 1) return NULL;
 
    // Make sure this is a reg-reg copy.
index 3477ae06f346317f1bb79ddbec07bff52579398a..20d6388e737e07b1a65c4141220c709f24c056dc 100644 (file)
@@ -67,11 +67,13 @@ public:
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index ac9b9b88ff43559bc0702e1af48da1b9ad64b7a2..64f6225f707e0a95b21e6e779d93980b34f4da5c 100644 (file)
@@ -391,9 +391,10 @@ void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
 /// foldMemoryOperand - SPU, like PPC, can only fold spills into
 /// copy instructions, turning them into load/store instructions.
 MachineInstr *
-SPUInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                   SmallVectorImpl<unsigned> &Ops,
-                                   int FrameIndex) const
+SPUInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                MachineInstr *MI,
+                                SmallVectorImpl<unsigned> &Ops,
+                                int FrameIndex) const
 {
 #if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN
   if (Ops.size() != 1) return NULL;
index 10c39a0545ec9a186e1f064cfb2803325fa4f64d..39237eef61bc82f012a10b22bdc995a8e074dc15 100644 (file)
@@ -77,12 +77,14 @@ namespace llvm {
                                  SmallVectorImpl<MachineInstr*> &NewMIs) const;
     
     //! Fold spills into load/store instructions
-    virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+    virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                            MachineInstr* MI,
                                             SmallVectorImpl<unsigned> &Ops,
                                             int FrameIndex) const;
 
     //! Fold any load/store to an operand
-    virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+    virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                            MachineInstr* MI,
                                             SmallVectorImpl<unsigned> &Ops,
                                             MachineInstr* LoadMI) const {
       return 0;
index 85c1048d347e91e876698d55d1aea572df8e9809..fa5d8b3bd77a1180ee9e060da35c5ad76df0e3d9 100644 (file)
@@ -370,7 +370,8 @@ void MipsInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
 }
 
 MachineInstr *MipsInstrInfo::
-foldMemoryOperand(MachineInstr* MI,
+foldMemoryOperand(MachineFunction &MF,
+                  MachineInstr* MI,
                   SmallVectorImpl<unsigned> &Ops, int FI) const 
 {
   if (Ops.size() != 1) return NULL;
index 69ab7955c16823d8d4c115226bdd44fd85ae14d9..d894b208a08e4c5ce46b1b396da2c453e0311306 100644 (file)
@@ -106,11 +106,13 @@ public:
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index 47e28710176f2fc579fc4b74d27ff6f9afe8f96a..81c1003310be22d28b2b6a42460c4fe0c07e81e6 100644 (file)
@@ -536,7 +536,8 @@ void PPCInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
 
 /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into
 /// copy instructions, turning them into load/store instructions.
-MachineInstr *PPCInstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr *PPCInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               int FrameIndex) const {
   if (Ops.size() != 1) return NULL;
@@ -594,7 +595,7 @@ MachineInstr *PPCInstrInfo::foldMemoryOperand(MachineInstr *MI,
 }
 
 bool PPCInstrInfo::canFoldMemoryOperand(MachineInstr *MI,
-                                         SmallVectorImpl<unsigned> &Ops) const {
+                                        SmallVectorImpl<unsigned> &Ops) const {
   if (Ops.size() != 1) return false;
 
   // Make sure this is a reg-reg copy.  Note that we can't handle MCRF, because
index 02d8bba369a8b6bf40fe874c401c79b4d984a224..9f289e4ff83ef8ff1e5ad0d20b2c84c6fb37fba2 100644 (file)
@@ -131,11 +131,13 @@ public:
   
   /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into
   /// copy instructions, turning them into load/store instructions.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index 56727bb56cd18f738d16aa3e8aab66bc4a9ac30e..79fc912919065f37da81f69c029c45ec3b23bb8e 100644 (file)
@@ -222,9 +222,10 @@ void SparcInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
   return;
 }
 
-MachineInstr *SparcInstrInfo::foldMemoryOperand(MachineInstr* MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FI) const {
+MachineInstr *SparcInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                                MachineInstr* MI,
+                                                SmallVectorImpl<unsigned> &Ops,
+                                                int FI) const {
   if (Ops.size() != 1) return NULL;
 
   unsigned OpNum = Ops[0];
index 0ed7fab4ed400b622b5ffe6b2861976fbf4e7b26..14c3b4a254fd160b716fef910fad4ea151d8b5d9 100644 (file)
@@ -94,11 +94,13 @@ public:
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
index 0c9a5c6f7f6acfa9f3ef0a51ffb06ec042a624d2..42c994a0a61aa2e4a7c41dc1abeb663d3a670e46 100644 (file)
@@ -1670,7 +1670,7 @@ static MachineInstr *MakeM0Inst(const TargetInstrInfo &TII, unsigned Opcode,
 
 MachineInstr*
 X86InstrInfo::foldMemoryOperand(MachineInstr *MI, unsigned i,
-                                   SmallVector<MachineOperand,4> &MOs) const {
+                                SmallVector<MachineOperand,4> &MOs) const {
   const DenseMap<unsigned*, unsigned> *OpcodeTablePtr = NULL;
   bool isTwoAddrFold = false;
   unsigned NumOps = MI->getDesc().getNumOperands();
@@ -1730,12 +1730,33 @@ X86InstrInfo::foldMemoryOperand(MachineInstr *MI, unsigned i,
 }
 
 
-MachineInstr* X86InstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr* X86InstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               int FrameIndex) const {
   // Check switch flag 
   if (NoFusing) return NULL;
 
+  const MachineFrameInfo *MFI = MF.getFrameInfo();
+  unsigned Alignment = MFI->getObjectAlignment(FrameIndex);
+  // FIXME: Move alignment requirement into tables?
+  if (Alignment < 16) {
+    switch (MI->getOpcode()) {
+    default: break;
+    // Not always safe to fold movsd into these instructions since their load
+    // folding variants expects the address to be 16 byte aligned.
+    case X86::FsANDNPDrr:
+    case X86::FsANDNPSrr:
+    case X86::FsANDPDrr:
+    case X86::FsANDPSrr:
+    case X86::FsORPDrr:
+    case X86::FsORPSrr:
+    case X86::FsXORPDrr:
+    case X86::FsXORPSrr:
+      return NULL;
+    }
+  }
+
   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
     unsigned NewOpc = 0;
     switch (MI->getOpcode()) {
@@ -1756,12 +1777,39 @@ MachineInstr* X86InstrInfo::foldMemoryOperand(MachineInstr *MI,
   return foldMemoryOperand(MI, Ops[0], MOs);
 }
 
-MachineInstr* X86InstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr* X86InstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               MachineInstr *LoadMI) const {
   // Check switch flag 
   if (NoFusing) return NULL;
 
+  unsigned Alignment = 0;
+  for (unsigned i = 0, e = LoadMI->getNumMemOperands(); i != e; ++i) {
+    const MemOperand &MRO = LoadMI->getMemOperand(i);
+    unsigned Align = MRO.getAlignment();
+    if (Align > Alignment)
+      Alignment = Align;
+  }
+
+  // FIXME: Move alignment requirement into tables?
+  if (Alignment < 16) {
+    switch (MI->getOpcode()) {
+    default: break;
+    // Not always safe to fold movsd into these instructions since their load
+    // folding variants expects the address to be 16 byte aligned.
+    case X86::FsANDNPDrr:
+    case X86::FsANDNPSrr:
+    case X86::FsANDPDrr:
+    case X86::FsANDPSrr:
+    case X86::FsORPDrr:
+    case X86::FsORPSrr:
+    case X86::FsXORPDrr:
+    case X86::FsXORPSrr:
+      return NULL;
+    }
+  }
+
   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
     unsigned NewOpc = 0;
     switch (MI->getOpcode()) {
index 68f166474678585d69acec9df89b5ff81a51f2a8..4a62e9e2fcf701a24dbd2f062c5113ddb8f52404 100644 (file)
@@ -324,14 +324,16 @@ public:
   /// folding and return true, otherwise it should return false.  If it folds
   /// the instruction, it is likely that the MachineInstruction the iterator
   /// references has been changed.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
   /// foldMemoryOperand - Same as the previous version except it allows folding
   /// of any load and store from / to any address, not just from a specific
   /// stack slot.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                   SmallVectorImpl<unsigned> &Ops,
                                   MachineInstr* LoadMI) const;
 
diff --git a/test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll b/test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll
new file mode 100644 (file)
index 0000000..b3fe9ab
--- /dev/null
@@ -0,0 +1,99 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep andpd | not grep esp
+
+declare double @llvm.sqrt.f64(double) nounwind readnone 
+
+declare fastcc void @ApplyGivens(double**, double, double, i32, i32, i32, i32) nounwind 
+
+declare double @fabs(double)
+
+define void @main_bb114_2E_outer_2E_i_bb3_2E_i27(double** %tmp12.sub.i.i, [51 x double*]* %tmp12.i.i.i, i32 %i.0.reg2mem.0.ph.i, i32 %tmp11688.i, i32 %tmp19.i, i32 %tmp24.i, [51 x double*]* %tmp12.i.i) {
+newFuncRoot:
+       br label %bb3.i27
+
+bb111.i77.bb121.i_crit_edge.exitStub:          ; preds = %bb111.i77
+       ret void
+
+bb3.i27:               ; preds = %bb111.i77.bb3.i27_crit_edge, %newFuncRoot
+       %indvar94.i = phi i32 [ 0, %newFuncRoot ], [ %tmp113.i76, %bb111.i77.bb3.i27_crit_edge ]                ; <i32> [#uses=6]
+       %tmp6.i20 = getelementptr [51 x double*]* %tmp12.i.i, i32 0, i32 %indvar94.i            ; <double**> [#uses=1]
+       %tmp7.i21 = load double** %tmp6.i20, align 4            ; <double*> [#uses=2]
+       %tmp10.i = add i32 %indvar94.i, %i.0.reg2mem.0.ph.i             ; <i32> [#uses=5]
+       %tmp11.i22 = getelementptr double* %tmp7.i21, i32 %tmp10.i              ; <double*> [#uses=1]
+       %tmp12.i23 = load double* %tmp11.i22, align 8           ; <double> [#uses=4]
+       %tmp20.i24 = add i32 %tmp19.i, %indvar94.i              ; <i32> [#uses=3]
+       %tmp21.i = getelementptr double* %tmp7.i21, i32 %tmp20.i24              ; <double*> [#uses=1]
+       %tmp22.i25 = load double* %tmp21.i, align 8             ; <double> [#uses=3]
+       %tmp1.i.i26 = fcmp oeq double %tmp12.i23, 0.000000e+00          ; <i1> [#uses=1]
+       br i1 %tmp1.i.i26, label %bb3.i27.Givens.exit.i49_crit_edge, label %bb5.i.i31
+
+bb5.i.i31:             ; preds = %bb3.i27
+       %tmp7.i.i28 = call double @fabs( double %tmp12.i23 ) nounwind           ; <double> [#uses=1]
+       %tmp9.i.i29 = call double @fabs( double %tmp22.i25 ) nounwind           ; <double> [#uses=1]
+       %tmp10.i.i30 = fcmp ogt double %tmp7.i.i28, %tmp9.i.i29         ; <i1> [#uses=1]
+       br i1 %tmp10.i.i30, label %bb13.i.i37, label %bb30.i.i43
+
+bb13.i.i37:            ; preds = %bb5.i.i31
+       %tmp15.i.i32 = sub double -0.000000e+00, %tmp22.i25             ; <double> [#uses=1]
+       %tmp17.i.i33 = fdiv double %tmp15.i.i32, %tmp12.i23             ; <double> [#uses=3]
+       %tmp20.i4.i = mul double %tmp17.i.i33, %tmp17.i.i33             ; <double> [#uses=1]
+       %tmp21.i.i34 = add double %tmp20.i4.i, 1.000000e+00             ; <double> [#uses=1]
+       %tmp22.i.i35 = call double @llvm.sqrt.f64( double %tmp21.i.i34 ) nounwind               ; <double> [#uses=1]
+       %tmp23.i5.i = fdiv double 1.000000e+00, %tmp22.i.i35            ; <double> [#uses=2]
+       %tmp28.i.i36 = mul double %tmp23.i5.i, %tmp17.i.i33             ; <double> [#uses=1]
+       br label %Givens.exit.i49
+
+bb30.i.i43:            ; preds = %bb5.i.i31
+       %tmp32.i.i38 = sub double -0.000000e+00, %tmp12.i23             ; <double> [#uses=1]
+       %tmp34.i.i39 = fdiv double %tmp32.i.i38, %tmp22.i25             ; <double> [#uses=3]
+       %tmp37.i6.i = mul double %tmp34.i.i39, %tmp34.i.i39             ; <double> [#uses=1]
+       %tmp38.i.i40 = add double %tmp37.i6.i, 1.000000e+00             ; <double> [#uses=1]
+       %tmp39.i7.i = call double @llvm.sqrt.f64( double %tmp38.i.i40 ) nounwind                ; <double> [#uses=1]
+       %tmp40.i.i41 = fdiv double 1.000000e+00, %tmp39.i7.i            ; <double> [#uses=2]
+       %tmp45.i.i42 = mul double %tmp40.i.i41, %tmp34.i.i39            ; <double> [#uses=1]
+       br label %Givens.exit.i49
+
+Givens.exit.i49:               ; preds = %bb3.i27.Givens.exit.i49_crit_edge, %bb30.i.i43, %bb13.i.i37
+       %s.0.i44 = phi double [ %tmp45.i.i42, %bb30.i.i43 ], [ %tmp23.i5.i, %bb13.i.i37 ], [ 0.000000e+00, %bb3.i27.Givens.exit.i49_crit_edge ]         ; <double> [#uses=2]
+       %c.0.i45 = phi double [ %tmp40.i.i41, %bb30.i.i43 ], [ %tmp28.i.i36, %bb13.i.i37 ], [ 1.000000e+00, %bb3.i27.Givens.exit.i49_crit_edge ]                ; <double> [#uses=2]
+       %tmp26.i46 = add i32 %tmp24.i, %indvar94.i              ; <i32> [#uses=2]
+       %tmp27.i47 = icmp slt i32 %tmp26.i46, 51                ; <i1> [#uses=1]
+       %min.i48 = select i1 %tmp27.i47, i32 %tmp26.i46, i32 50         ; <i32> [#uses=1]
+       call fastcc void @ApplyGivens( double** %tmp12.sub.i.i, double %s.0.i44, double %c.0.i45, i32 %tmp20.i24, i32 %tmp10.i, i32 %indvar94.i, i32 %min.i48 ) nounwind 
+       br label %codeRepl
+
+codeRepl:              ; preds = %Givens.exit.i49
+       call void @main_bb114_2E_outer_2E_i_bb3_2E_i27_bb_2E_i48_2E_i( i32 %tmp10.i, i32 %tmp20.i24, double %s.0.i44, double %c.0.i45, [51 x double*]* %tmp12.i.i.i )
+       br label %ApplyRGivens.exit49.i
+
+ApplyRGivens.exit49.i:         ; preds = %codeRepl
+       %tmp10986.i = icmp sgt i32 %tmp11688.i, %tmp10.i                ; <i1> [#uses=1]
+       br i1 %tmp10986.i, label %ApplyRGivens.exit49.i.bb52.i57_crit_edge, label %ApplyRGivens.exit49.i.bb111.i77_crit_edge
+
+codeRepl1:             ; preds = %ApplyRGivens.exit49.i.bb52.i57_crit_edge
+       call void @main_bb114_2E_outer_2E_i_bb3_2E_i27_bb52_2E_i57( i32 %tmp10.i, double** %tmp12.sub.i.i, [51 x double*]* %tmp12.i.i.i, i32 %i.0.reg2mem.0.ph.i, i32 %tmp11688.i, i32 %tmp19.i, i32 %tmp24.i, [51 x double*]* %tmp12.i.i )
+       br label %bb105.i.bb111.i77_crit_edge
+
+bb111.i77:             ; preds = %bb105.i.bb111.i77_crit_edge, %ApplyRGivens.exit49.i.bb111.i77_crit_edge
+       %tmp113.i76 = add i32 %indvar94.i, 1            ; <i32> [#uses=2]
+       %tmp118.i = icmp sgt i32 %tmp11688.i, %tmp113.i76               ; <i1> [#uses=1]
+       br i1 %tmp118.i, label %bb111.i77.bb3.i27_crit_edge, label %bb111.i77.bb121.i_crit_edge.exitStub
+
+bb3.i27.Givens.exit.i49_crit_edge:             ; preds = %bb3.i27
+       br label %Givens.exit.i49
+
+ApplyRGivens.exit49.i.bb52.i57_crit_edge:              ; preds = %ApplyRGivens.exit49.i
+       br label %codeRepl1
+
+ApplyRGivens.exit49.i.bb111.i77_crit_edge:             ; preds = %ApplyRGivens.exit49.i
+       br label %bb111.i77
+
+bb105.i.bb111.i77_crit_edge:           ; preds = %codeRepl1
+       br label %bb111.i77
+
+bb111.i77.bb3.i27_crit_edge:           ; preds = %bb111.i77
+       br label %bb3.i27
+}
+
+declare void @main_bb114_2E_outer_2E_i_bb3_2E_i27_bb_2E_i48_2E_i(i32, i32, double, double, [51 x double*]*)
+
+declare void @main_bb114_2E_outer_2E_i_bb3_2E_i27_bb52_2E_i57(i32, double**, [51 x double*]*, i32, i32, i32, i32, [51 x double*]*)