Numerous bug fixes:
authorVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 19 May 2002 15:25:51 +0000 (15:25 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Sun, 19 May 2002 15:25:51 +0000 (15:25 +0000)
-- correct sign extensions for integer casts and for shift-by-constant
   instructions generated for integer multiply
-- passing FP arguments to functions with more than 6 arguments
-- passing FP arguments to varargs functions
-- passing FP arguments to functions with no prototypes
-- incorrect stack frame size when padding a section
-- folding getelementptr operations with mixed array and struct indexes
-- use uint64_t instead of uint for constant offsets in mem operands
-- incorrect coloring for CC registers (both int and FP): interferences
   were being completely ignored for int CC and were considered but no
   spills were marked for fp CC!

Also some code improvements:
-- better interface to generating machine instr for common cases
   (many places still need to be updated to use this interface)
-- annotations on MachineInstr to communicate information from
   one codegen phase to another (now used to pass information about
   CALL/JMPLCALL operands from selection to register allocation)
-- all sizes and offests in class TargetData are uint64_t instead of uint

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2640 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SparcV9/SparcV9AsmPrinter.cpp
lib/Target/SparcV9/SparcV9InstrInfo.cpp
lib/Target/SparcV9/SparcV9InstrSelection.cpp
lib/Target/SparcV9/SparcV9InstrSelectionSupport.h
lib/Target/SparcV9/SparcV9Internals.h
lib/Target/SparcV9/SparcV9RegClassInfo.cpp
lib/Target/SparcV9/SparcV9RegClassInfo.h
lib/Target/SparcV9/SparcV9RegInfo.cpp

index 868f8710d89bfd9b6da938cb384b6604e3a326bb..74b7f73da36f74c71a56af027150651a79c5866e 100644 (file)
@@ -312,9 +312,9 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
     case MachineOperand::MO_PCRelativeDisp:
       {
         const Value *Val = op.getVRegValue();
-        if (!Val)
-          toAsm << "\t<*NULL Value*>";
-        else if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
+        assert(Val && "\tNULL Value in SparcFunctionAsmPrinter");
+        
+        if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
           toAsm << getID(BB);
         else if (const Function *M = dyn_cast<Function>(Val))
           toAsm << getID(M);
@@ -323,13 +323,16 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
         else if (const Constant *CV = dyn_cast<Constant>(Val))
           toAsm << getID(CV);
         else
-          toAsm << "<unknown value=" << Val << ">";
+          assert(0 && "Unrecognized value in SparcFunctionAsmPrinter");
         break;
       }
     
     case MachineOperand::MO_SignExtendedImmed:
+      toAsm << op.getImmedValue();
+      break;
+
     case MachineOperand::MO_UnextendedImmed:
-      toAsm << (long)op.getImmedValue();
+      toAsm << (uint64_t) op.getImmedValue();
       break;
     
     default:
@@ -486,7 +489,9 @@ static string getAsCString(ConstantArray *CPA) {
       (unsigned char)cast<ConstantSInt>(CPA->getOperand(i))->getValue() :
       (unsigned char)cast<ConstantUInt>(CPA->getOperand(i))->getValue();
 
-    if (isprint(C)) {
+    if (C == '"') {
+      Result += "\\\"";
+    } else if (isprint(C)) {
       Result += C;
     } else {
       switch(C) {
@@ -666,13 +671,13 @@ SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV)
   else if (CPA)
     { // Not a string.  Print the values in successive locations
       const std::vector<Use> &constValues = CPA->getValues();
-      for (unsigned i=1; i < constValues.size(); i++)
+      for (unsigned i=0; i < constValues.size(); i++)
         this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
     }
   else if (ConstantStruct *CPS = dyn_cast<ConstantStruct>(CV))
     { // Print the fields in successive locations
       const std::vector<Use>& constValues = CPS->getValues();
-      for (unsigned i=1; i < constValues.size(); i++)
+      for (unsigned i=0; i < constValues.size(); i++)
         this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
     }
   else
index fd18841dc18daa1e7c9391339c8c20a25866643b..5fbced0f9f1096a0e03486d9ad6ce0799f76db6d 100644 (file)
 #include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
 #include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Instruction.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 
 //************************ Internal Functions ******************************/
 
 
-static inline MachineInstr*
-CreateIntSetInstruction(int64_t C, Value* dest,
-                        std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateIntSetInstruction(const TargetMachine& target, Function* F,
+                        int64_t C, Instruction* dest,
+                        std::vector<MachineInstr*>& mvec,
+                        MachineCodeForInstruction& mcfi)
 {
-  MachineInstr* minstr;
+  assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
+  
+  MachineInstr* M;
   uint64_t absC = (C >= 0)? C : -C;
   if (absC > (unsigned int) ~0)
     { // C does not fit in 32 bits
       TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
-                                   /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      M = new MachineInstr(SETX);
+      M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                                 /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      mvec.push_back(M);
     }
   else
     {
-      minstr = new MachineInstr(SETSW);
-      minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+      M = Create2OperandInstr_SImmed(SETSW, C, dest);
+      mvec.push_back(M);
     }
-  
-  return minstr;
 }
 
-static inline MachineInstr*
-CreateUIntSetInstruction(uint64_t C, Value* dest,
-                         std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateUIntSetInstruction(const TargetMachine& target, Function* F,
+                         uint64_t C, Instruction* dest,
+                         std::vector<MachineInstr*>& mvec,
+                         MachineCodeForInstruction& mcfi)
 {
-  MachineInstr* minstr;
+  assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
+  unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
+  MachineInstr* M;
+  
   if (C > (unsigned int) ~0)
     { // C does not fit in 32 bits
       assert(dest->getType() == Type::ULongTy && "Sign extension problems");
       TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
-                                   tmpReg, /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+      M = new MachineInstr(SETX);
+      M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                              /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
+      mvec.push_back(M);
     }
-  else if (dest->getType() == Type::ULongTy)
+  else
     {
-      minstr = new MachineInstr(SETUW);
-      minstr->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+      // If the destination is smaller than the standard integer reg. size,
+      // we have to extend the sign-bit into upper bits of dest, so we
+      // need to put the result of the SETUW into a temporary.
+      // 
+      Value* setuwDest = dest;
+      if (destSize < target.DataLayout.getIntegerRegize())
+        {
+          setuwDest = new TmpInstruction(dest, NULL, "setTmp");
+          mcfi.addTemp(setuwDest);
+        }
+      
+      M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
+      mvec.push_back(M);
+      
+      if (setuwDest != dest)
+        { // extend the sign-bit of the result into all upper bits of dest
+          assert(8*destSize <= 32 &&
+                 "Unexpected type size > 4 and < IntRegSize?");
+          target.getInstrInfo().
+            CreateSignExtensionInstructions(target, F,
+                                            setuwDest, 8*destSize, dest,
+                                            mvec, mcfi);
+        }
     }
+  
+#define USE_DIRECT_SIGN_EXTENSION_INSTRS
+#ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
   else
     { // cast to signed type of the right length and use signed op (SETSW)
       // to get correct sign extension
@@ -103,8 +137,7 @@ CreateUIntSetInstruction(uint64_t C, Value* dest,
           break;
         }
     }
-  
-  return minstr;
+#endif USE_DIRECT_SIGN_EXTENSION_INSTRS
 }
 
 //************************* External Classes *******************************/
@@ -131,17 +164,18 @@ UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
 // Create an instruction sequence to put the constant `val' into
 // the virtual register `dest'.  `val' may be a Constant or a
 // GlobalValue, viz., the constant address of a global variable or function.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
+UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
+                                           Function* F,
+                                           Value* val,
                                            Instruction* dest,
-                                           std::vector<MachineInstr*>&minstrVec,
-                                    std::vector<TmpInstruction*>& tempVec) const
+                                           std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const
 {
-  MachineInstr* minstr;
-  
   assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
          "I only know about constant values and global addresses");
   
@@ -153,19 +187,18 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
   
   if (valType->isIntegral() || valType == Type::BoolTy)
     {
-      if (ConstantUInt* uval = dyn_cast<ConstantUInt>(val))
+      if (! val->getType()->isSigned())
         {
-          uint64_t C = uval->getValue();
-          minstr = CreateUIntSetInstruction(C, dest, tempVec);
+          uint64_t C = cast<ConstantUInt>(val)->getValue();
+          CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
         }
       else
         {
           bool isValidConstant;
           int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
           assert(isValidConstant && "Unrecognized constant");
-          minstr = CreateIntSetInstruction(C, dest, tempVec);
+          CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
         }
-      minstrVec.push_back(minstr);
     }
   else
     {
@@ -180,42 +213,35 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
       
       TmpInstruction* tmpReg =
         new TmpInstruction(PointerType::get(val->getType()), val);
-      tempVec.push_back(tmpReg);
+      mcfi.addTemp(tmpReg);
       
       if (isa<Constant>(val))
         {
           // Create another TmpInstruction for the hidden integer register
           TmpInstruction* addrReg =
             new TmpInstruction(PointerType::get(val->getType()), val);
-          tempVec.push_back(addrReg);
+          mcfi.addTemp(addrReg);
           addrVal = addrReg;
         }
       else
         addrVal = dest;
       
-      minstr = new MachineInstr(SETX);
-      minstr->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,tmpReg,
-                                   /*isdef*/ true);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
-                                   addrVal);
-      minstrVec.push_back(minstr);
+      MachineInstr* M = new MachineInstr(SETX);
+      M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
+      M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+                              /*isdef*/ true);
+      M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
+      mvec.push_back(M);
       
       if (isa<Constant>(val))
         {
           // Make sure constant is emitted to constant pool in assembly code.
-          MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-          mcinfo.addToConstantPool(cast<Constant>(val));
+          MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
           
           // Generate the load instruction
-          minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
-          minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
-                                       addrVal);
-          minstr->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
-                                       zeroOffset);
-          minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
-                                       dest);
-          minstrVec.push_back(minstr);
+          M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
+                                         addrVal, zeroOffset, dest);
+          mvec.push_back(M);
         }
     }
 }
@@ -224,24 +250,24 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
 // Create an instruction sequence to copy an integer value `val'
 // to a floating point value `dest' by copying to memory and back.
 // val must be an integral type.  dest must be a Float or Double.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
-                                         Value* val,
-                                         Instruction* dest,
-                                         std::vector<MachineInstr*>& minstrVec,
-                                         std::vector<TmpInstruction*>& tempVec,
-                                         TargetMachine& target) const
+UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
+                                        Function* F,
+                                        Value* val,
+                                        Instruction* dest,
+                                        std::vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
 {
   assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
          && "Source type must be integral");
   assert(dest->getType()->isFloatingPoint()
          && "Dest type must be float/double");
   
-  MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-  int offset = mcinfo.allocateLocalVar(target, val); 
+  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
   
   // Store instruction stores `val' to [%fp+offset].
   // The store and load opCodes are based on the value being copied, and
@@ -254,8 +280,8 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
   MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
-  store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed, offset);
-  minstrVec.push_back(store);
+  store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
+  mvec.push_back(store);
 
   // Load instruction loads [%fp+offset] to `dest'.
   // 
@@ -263,29 +289,30 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
   load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
-  minstrVec.push_back(load);
+  mvec.push_back(load);
 }
 
 
 // Similarly, create an instruction sequence to copy an FP value
 // `val' to an integer value `dest' by copying to memory and back.
-// See the previous function for information about return values.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
 // 
 void
-UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
+UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
+                                        Function* F,
                                         Value* val,
                                         Instruction* dest,
-                                        std::vector<MachineInstr*>& minstrVec,
-                                        std::vector<TmpInstruction*>& tempVec,
-                                        TargetMachine& target) const
+                                        std::vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
 {
   assert(val->getType()->isFloatingPoint()
          && "Source type must be float/double");
   assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
          && "Dest type must be integral");
   
-  MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
-  int offset = mcinfo.allocateLocalVar(target, val); 
+  int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
   
   // Store instruction stores `val' to [%fp+offset].
   // The store and load opCodes are based on the value being copied, and
@@ -298,13 +325,113 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
   store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
-  minstrVec.push_back(store);
+  mvec.push_back(store);
   
   // Load instruction loads [%fp+offset] to `dest'.
   // 
   MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
-  load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, offset);
+  load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
-  minstrVec.push_back(load);
+  mvec.push_back(load);
+}
+
+
+// Create instruction(s) to copy src to dest, for arbitrary types
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+// 
+void
+UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
+                                                  Function *F,
+                                                  Value* src,
+                                                  Instruction* dest,
+                                                  vector<MachineInstr*>& mvec,
+                                          MachineCodeForInstruction& mcfi) const
+{
+  bool loadConstantToReg = false;
+  
+  const Type* resultType = dest->getType();
+  
+  MachineOpCode opCode = ChooseAddInstructionByType(resultType);
+  if (opCode == INVALID_OPCODE)
+    {
+      assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
+      return;
+    }
+  
+  // if `src' is a constant that doesn't fit in the immed field or if it is
+  // a global variable (i.e., a constant address), generate a load
+  // instruction instead of an add
+  // 
+  if (isa<Constant>(src))
+    {
+      unsigned int machineRegNum;
+      int64_t immedValue;
+      MachineOperand::MachineOperandType opType =
+        ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
+                         machineRegNum, immedValue);
+      
+      if (opType == MachineOperand::MO_VirtualRegister)
+        loadConstantToReg = true;
+    }
+  else if (isa<GlobalValue>(src))
+    loadConstantToReg = true;
+  
+  if (loadConstantToReg)
+    { // `src' is constant and cannot fit in immed field for the ADD
+      // Insert instructions to "load" the constant into a register
+      target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
+                                                  mvec, mcfi);
+    }
+  else
+    { // Create an add-with-0 instruction of the appropriate type.
+      // Make `src' the second operand, in case it is a constant
+      // Use (unsigned long) 0 for a NULL pointer value.
+      // 
+      const Type* zeroValueType =
+        isa<PointerType>(resultType) ? Type::ULongTy : resultType;
+      MachineInstr* minstr =
+        Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
+                            src, dest);
+      mvec.push_back(minstr);
+    }
+}
+
+
+// Create instruction sequence to produce a sign-extended register value
+// from an arbitrary sized value (sized in bits, not bytes).
+// For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+// 
+void
+UltraSparcInstrInfo::CreateSignExtensionInstructions(
+                                        const TargetMachine& target,
+                                        Function* F,
+                                        Value* unsignedSrcVal,
+                                        unsigned int srcSizeInBits,
+                                        Value* dest,
+                                        vector<MachineInstr*>& mvec,
+                                        MachineCodeForInstruction& mcfi) const
+{
+  MachineInstr* M;
+  
+  assert(srcSizeInBits > 0 && srcSizeInBits <= 32
+     && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
+  
+  if (srcSizeInBits < 32)
+    { // SLL is needed since operand size is < 32 bits.
+      TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
+                                                unsignedSrcVal, dest,"make32");
+      mcfi.addTemp(tmpI);
+      M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
+      mvec.push_back(M);
+      unsignedSrcVal = tmpI;
+    }
+  
+  M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
+  mvec.push_back(M);
 }
index 7109ba4a35cf7eef0fa944edf6c3f96284bc385e..668ac4a566798c573b1f2f8c72b5a2f1dd939985 100644 (file)
@@ -15,6 +15,7 @@
 #include "SparcRegClassInfo.h"
 #include "llvm/CodeGen/InstrSelectionSupport.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrAnnot.h"
 #include "llvm/CodeGen/InstrForest.h"
 #include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/MachineCodeForMethod.h"
@@ -38,6 +39,7 @@ static void SetMemOperands_Internal     (vector<MachineInstr*>& mvec,
                                          const InstructionNode* vmInstrNode,
                                          Value* ptrVal,
                                          std::vector<Value*>& idxVec,
+                                         bool allConstantIndices,
                                          const TargetMachine& target);
 
 
@@ -176,7 +178,9 @@ ChooseBccInstruction(const InstructionNode* instrNode,
   BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
   const Type* setCCType = setCCInstr->getOperand(0)->getType();
   
-  if (setCCType->isFloatingPoint())
+  isFPBranch = setCCType->isFloatingPoint(); // Return value: don't delete!
+  
+  if (isFPBranch)
     return ChooseBFpccInstruction(instrNode, setCCInstr);
   else
     return ChooseBpccInstruction(instrNode, setCCInstr);
@@ -326,31 +330,6 @@ CreateConvertToIntInstr(OpLabel vopCode, Value* srcVal, Value* destVal)
   return M;
 }
 
-static inline MachineOpCode 
-ChooseAddInstructionByType(const Type* resultType)
-{
-  MachineOpCode opCode = INVALID_OPCODE;
-  
-  if (resultType->isIntegral() ||
-      isa<PointerType>(resultType) ||
-      isa<FunctionType>(resultType) ||
-      resultType == Type::LabelTy ||
-      resultType == Type::BoolTy)
-    {
-      opCode = ADD;
-    }
-  else
-    switch(resultType->getPrimitiveID())
-      {
-      case Type::FloatTyID:  opCode = FADDS; break;
-      case Type::DoubleTyID: opCode = FADDD; break;
-      default: assert(0 && "Invalid type for ADD instruction"); break; 
-      }
-  
-  return opCode;
-}
-
-
 static inline MachineOpCode 
 ChooseAddInstruction(const InstructionNode* instrNode)
 {
@@ -383,12 +362,11 @@ CreateAddConstInstruction(const InstructionNode* instrNode)
   // (1) Add with 0 for float or double: use an FMOV of appropriate type,
   //    instead of an FADD (1 vs 3 cycles).  There is no integer MOV.
   // 
-  const Type* resultType = instrNode->getInstruction()->getType();
-  
   if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
       double dval = FPC->getValue();
       if (dval == 0.0)
-        minstr = CreateMovFloatInstruction(instrNode, resultType);
+        minstr = CreateMovFloatInstruction(instrNode,
+                                   instrNode->getInstruction()->getType());
     }
   
   return minstr;
@@ -428,12 +406,11 @@ CreateSubConstInstruction(const InstructionNode* instrNode)
   // (1) Sub with 0 for float or double: use an FMOV of appropriate type,
   //    instead of an FSUB (1 vs 3 cycles).  There is no integer MOV.
   // 
-  const Type* resultType = instrNode->getInstruction()->getType();
-  
   if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
     double dval = FPC->getValue();
     if (dval == 0.0)
-      minstr = CreateMovFloatInstruction(instrNode, resultType);
+      minstr = CreateMovFloatInstruction(instrNode,
+                                        instrNode->getInstruction()->getType());
   }
   
   return minstr;
@@ -506,19 +483,71 @@ CreateIntNegInstruction(const TargetMachine& target,
 }
 
 
+// Create instruction sequence for any shift operation.
+// SLL or SLLX on an operand smaller than the integer reg. size (64bits)
+// requires a second instruction for explicit sign-extension.
+// Note that we only have to worry about a sign-bit appearing in the
+// most significant bit of the operand after shifting (e.g., bit 32 of
+// Int or bit 16 of Short), so we do not have to worry about results
+// that are as large as a normal integer register.
+// 
+static inline void
+CreateShiftInstructions(const TargetMachine& target,
+                        Function* F,
+                        MachineOpCode shiftOpCode,
+                        Value* argVal1,
+                        Value* optArgVal2, /* Use optArgVal2 if not NULL */
+                        unsigned int optShiftNum, /* else use optShiftNum */
+                        Instruction* destVal,
+                        vector<MachineInstr*>& mvec,
+                        MachineCodeForInstruction& mcfi)
+{
+  assert((optArgVal2 != NULL || optShiftNum <= 64) &&
+         "Large shift sizes unexpected, but can be handled below: "
+         "You need to check whether or not it fits in immed field below");
+  
+  // If this is a logical left shift of a type smaller than the standard
+  // integer reg. size, we have to extend the sign-bit into upper bits
+  // of dest, so we need to put the result of the SLL into a temporary.
+  // 
+  Value* shiftDest = destVal;
+  const Type* opType = argVal1->getType();
+  unsigned opSize = target.DataLayout.getTypeSize(argVal1->getType());
+  if ((shiftOpCode == SLL || shiftOpCode == SLLX)
+      && opSize < target.DataLayout.getIntegerRegize())
+    { // put SLL result into a temporary
+      shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp");
+      mcfi.addTemp(shiftDest);
+    }
+  
+  MachineInstr* M = (optArgVal2 != NULL)
+    ? Create3OperandInstr(shiftOpCode, argVal1, optArgVal2, shiftDest)
+    : Create3OperandInstr_UImmed(shiftOpCode, argVal1, optShiftNum, shiftDest);
+  mvec.push_back(M);
+  
+  if (shiftDest != destVal)
+    { // extend the sign-bit of the result into all upper bits of dest
+      assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?");
+      target.getInstrInfo().
+        CreateSignExtensionInstructions(target, F, shiftDest, 8*opSize,
+                                        destVal, mvec, mcfi);
+    }
+}
+
+
 // Does not create any instructions if we cannot exploit constant to
 // create a cheaper instruction.
 // This returns the approximate cost of the instructions generated,
 // which is used to pick the cheapest when both operands are constant.
 static inline unsigned int
-CreateMulConstInstruction(const TargetMachine &target,
-                          Value* lval, Value* rval, Value* destVal,
-                          vector<MachineInstr*>& mvec)
+CreateMulConstInstruction(const TargetMachine &target, Function* F,
+                          Value* lval, Value* rval, Instruction* destVal,
+                          vector<MachineInstr*>& mvec,
+                          MachineCodeForInstruction& mcfi)
 {
-  /* An integer multiply is generally more costly than FP multiply */ 
+  /* Use max. multiply cost, viz., cost of MULX */
   unsigned int cost = target.getInstrInfo().minLatency(MULX);
-  MachineInstr* minstr1 = NULL;
-  MachineInstr* minstr2 = NULL;
+  unsigned int firstNewInstr = mvec.size();
   
   Value* constOp = rval;
   if (! isa<Constant>(constOp))
@@ -532,11 +561,11 @@ CreateMulConstInstruction(const TargetMachine &target,
   
   if (resultType->isIntegral() || isa<PointerType>(resultType))
     {
-      unsigned pow;
       bool isValidConst;
       int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
       if (isValidConst)
         {
+          unsigned pow;
           bool needNeg = false;
           if (C < 0)
             {
@@ -547,30 +576,28 @@ CreateMulConstInstruction(const TargetMachine &target,
           if (C == 0 || C == 1)
             {
               cost = target.getInstrInfo().minLatency(ADD);
-              minstr1 = new MachineInstr(ADD);
-              if (C == 0)
-                minstr1->SetMachineOperandReg(0,
-                              target.getRegInfo().getZeroRegNum());
-              else
-                minstr1->SetMachineOperandVal(0,
-                              MachineOperand::MO_VirtualRegister, lval);
-              minstr1->SetMachineOperandReg(1,
-                                        target.getRegInfo().getZeroRegNum());
+              MachineInstr* M = (C == 0)
+                ? Create3OperandInstr_Reg(ADD,
+                                          target.getRegInfo().getZeroRegNum(),
+                                          target.getRegInfo().getZeroRegNum(),
+                                          destVal)
+                : Create3OperandInstr_Reg(ADD, lval,
+                                          target.getRegInfo().getZeroRegNum(),
+                                          destVal);
+              mvec.push_back(M);
             }
           else if (IsPowerOf2(C, pow))
             {
-              minstr1 = new MachineInstr((resultType == Type::LongTy)
-                                         ? SLLX : SLL);
-              minstr1->SetMachineOperandVal(0,
-                                MachineOperand::MO_VirtualRegister, lval);
-              minstr1->SetMachineOperandConst(1,
-                                MachineOperand::MO_UnextendedImmed, pow);
+              unsigned int opSize = target.DataLayout.getTypeSize(resultType);
+              MachineOpCode opCode = (opSize <= 32)? SLL : SLLX;
+              CreateShiftInstructions(target, F, opCode, lval, NULL, pow,
+                                      destVal, mvec, mcfi); 
             }
           
-          if (minstr1 && needNeg)
+          if (mvec.size() > 0 && needNeg)
             { // insert <reg = SUB 0, reg> after the instr to flip the sign
-              minstr2 = CreateIntNegInstruction(target, destVal);
-              cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
+              MachineInstr* M = CreateIntNegInstruction(target, destVal);
+              mvec.push_back(M);
             }
         }
     }
@@ -581,34 +608,20 @@ CreateMulConstInstruction(const TargetMachine &target,
           double dval = FPC->getValue();
           if (fabs(dval) == 1)
             {
-              bool needNeg = (dval < 0);
-              
-              MachineOpCode opCode = needNeg
+              MachineOpCode opCode =  (dval < 0)
                 ? (resultType == Type::FloatTy? FNEGS : FNEGD)
                 : (resultType == Type::FloatTy? FMOVS : FMOVD);
-              
-              minstr1 = new MachineInstr(opCode);
-              minstr1->SetMachineOperandVal(0,
-                                            MachineOperand::MO_VirtualRegister,
-                                            lval);
+              MachineInstr* M = Create2OperandInstr(opCode, lval, destVal);
+              mvec.push_back(M);
             } 
         }
     }
   
-  if (minstr1 != NULL)
-    minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
-                                  destVal);   
-  
-  if (minstr1)
+  if (firstNewInstr < mvec.size())
     {
-      mvec.push_back(minstr1);
-      cost = target.getInstrInfo().minLatency(minstr1->getOpCode());
-    }
-  if (minstr2)
-    {
-      assert(minstr1 && "Otherwise cost needs to be initialized to 0");
-      cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
-      mvec.push_back(minstr2);
+      cost = 0;
+      for (unsigned int i=firstNewInstr; i < mvec.size(); ++i)
+        cost += target.getInstrInfo().minLatency(mvec[i]->getOpCode());
     }
   
   return cost;
@@ -620,17 +633,20 @@ CreateMulConstInstruction(const TargetMachine &target,
 // 
 static inline void
 CreateCheapestMulConstInstruction(const TargetMachine &target,
-                                  Value* lval, Value* rval, Value* destVal,
-                                  vector<MachineInstr*>& mvec)
+                                  Function* F,
+                                  Value* lval, Value* rval,
+                                  Instruction* destVal,
+                                  vector<MachineInstr*>& mvec,
+                                  MachineCodeForInstruction& mcfi)
 {
   Value* constOp;
   if (isa<Constant>(lval) && isa<Constant>(rval))
     { // both operands are constant: try both orders!
       vector<MachineInstr*> mvec1, mvec2;
-      unsigned int lcost = CreateMulConstInstruction(target, lval, rval,
-                                                     destVal, mvec1);
-      unsigned int rcost = CreateMulConstInstruction(target, rval, lval,
-                                                     destVal, mvec2);
+      unsigned int lcost = CreateMulConstInstruction(target, F, lval, rval,
+                                                     destVal, mvec1, mcfi);
+      unsigned int rcost = CreateMulConstInstruction(target, F, rval, lval,
+                                                     destVal, mvec2, mcfi);
       vector<MachineInstr*>& mincostMvec =  (lcost <= rcost)? mvec1 : mvec2;
       vector<MachineInstr*>& maxcostMvec =  (lcost <= rcost)? mvec2 : mvec1;
       mvec.insert(mvec.end(), mincostMvec.begin(), mincostMvec.end()); 
@@ -639,9 +655,9 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
         delete maxcostMvec[i];
     }
   else if (isa<Constant>(rval))         // rval is constant, but not lval
-    CreateMulConstInstruction(target, lval, rval, destVal, mvec);
+    CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
   else if (isa<Constant>(lval))         // lval is constant, but not rval
-    CreateMulConstInstruction(target, lval, rval, destVal, mvec);
+    CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
   
   // else neither is constant
   return;
@@ -649,13 +665,14 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
 
 // Return NULL if we cannot exploit constant to create a cheaper instruction
 static inline void
-CreateMulInstruction(const TargetMachine &target,
-                     Value* lval, Value* rval, Value* destVal,
+CreateMulInstruction(const TargetMachine &target, Function* F,
+                     Value* lval, Value* rval, Instruction* destVal,
                      vector<MachineInstr*>& mvec,
+                     MachineCodeForInstruction& mcfi,
                      MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
 {
   unsigned int L = mvec.size();
-  CreateCheapestMulConstInstruction(target, lval, rval, destVal, mvec);
+  CreateCheapestMulConstInstruction(target,F, lval, rval, destVal, mvec, mcfi);
   if (mvec.size() == L)
     { // no instructions were added so create MUL reg, reg, reg.
       // Use FSMULD if both operands are actually floats cast to doubles.
@@ -889,6 +906,8 @@ CreateCodeForFixedSizeAlloca(const TargetMachine& target,
 
 
 
+
+
 //------------------------------------------------------------------------ 
 // Function SetOperandsForMemInstr
 //
@@ -913,15 +932,14 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
 {
   MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
   
-  // Variables to hold the index vector, ptr value, and offset value.
+  // Variables to hold the index vector and ptr value.
   // The major work here is to extract these for all 3 instruction types
-  // and then call the common function SetMemOperands_Internal().
-  // 
-  Value* ptrVal = memInst->getPointerOperand();
-  
-  // Start with the index vector of this instruction, if any.
+  // and to try to fold chains of constant indices into a single offset.
+  // After that, we call SetMemOperands_Internal(), which creates the
+  // appropriate operands for the machine instruction.
   vector<Value*> idxVec;
-  idxVec.insert(idxVec.end(), memInst->idx_begin(), memInst->idx_end());
+  bool allConstantIndices = true;
+  Value* ptrVal = memInst->getPointerOperand();
   
   // If there is a GetElemPtr instruction to fold in to this instr,
   // it must be in the left child for Load and GetElemPtr, and in the
@@ -930,17 +948,40 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
                              ? vmInstrNode->rightChild()
                              : vmInstrNode->leftChild()); 
   
-  // Fold chains of GetElemPtr instructions for structure references.
-  if (isa<StructType>(cast<PointerType>(ptrVal->getType())->getElementType())
-      && (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
-          ptrChild->getOpLabel() == GetElemPtrIdx))
+  // Check if all indices are constant for this instruction
+  for (MemAccessInst::op_iterator OI=memInst->idx_begin();
+       OI != memInst->idx_end(); ++OI)
+    if (! isa<ConstantUInt>(*OI))
+      {
+        allConstantIndices = false; 
+        break;
+      }
+  
+  // If we have only constant indices, fold chains of constant indices
+  // in this and any preceding GetElemPtr instructions.
+  if (allConstantIndices &&
+      ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+      ptrChild->getOpLabel() == GetElemPtrIdx)
     {
       Value* newPtr = FoldGetElemChain((InstructionNode*) ptrChild, idxVec);
       if (newPtr)
         ptrVal = newPtr;
     }
   
-  SetMemOperands_Internal(mvec, mvecI, vmInstrNode, ptrVal, idxVec, target);
+  // Append the index vector of the current instruction, if any.
+  // Discard any leading [0] index.
+  if (memInst->idx_begin() != memInst->idx_end())
+    {
+      ConstantUInt* CV = dyn_cast<ConstantUInt>(* memInst->idx_begin());
+      unsigned zeroOrIOne = (CV && CV->getType() == Type::UIntTy &&
+                             (CV->getValue() == 0))? 1 : 0;
+      idxVec.insert(idxVec.end(),
+                    memInst->idx_begin()+zeroOrIOne, memInst->idx_end());
+    }
+  
+  // Now create the appropriate operands for the machine instruction
+  SetMemOperands_Internal(mvec, mvecI, vmInstrNode,
+                          ptrVal, idxVec, allConstantIndices, target);
 }
 
 
@@ -953,6 +994,7 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
                         const InstructionNode* vmInstrNode,
                         Value* ptrVal,
                         vector<Value*>& idxVec,
+                        bool allConstantIndices,
                         const TargetMachine& target)
 {
   MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
@@ -967,35 +1009,31 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
   // 
   if (idxVec.size() > 0)
     {
-      unsigned offset = 0;
-      
       const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
       
-      // Handle special common case of leading [0] index.
-      bool firstIndexIsZero =
-        bool(isa<ConstantUInt>(idxVec.front()) &&
-             cast<ConstantUInt>(idxVec.front())->getValue() == 0);
-      
-      // This is a real structure reference if the ptr target is a
-      // structure type, and the first offset is [0] (eliminate that offset).
-      if (firstIndexIsZero && isa<StructType>(ptrType->getElementType()))
+      // If all indices are constant, compute the combined offset directly.
+      if (allConstantIndices)
         {
           // Compute the offset value using the index vector. Create a
           // virtual reg. for it since it may not fit in the immed field.
-          assert(idxVec.size() >= 2);
-          idxVec.erase(idxVec.begin());
-          unsigned offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
-          valueForRegOffset = ConstantSInt::get(Type::IntTy, offset);
+          uint64_t offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
+          valueForRegOffset = ConstantSInt::get(Type::LongTy, offset);
         }
       else
         {
-          // It is an array ref, and must have been lowered to a single offset.
+          // There is at least one non-constant offset.  Therefore, this must
+          // be an array ref, and must have been lowered to a single offset.
           assert((memInst->getNumOperands()
                   == (unsigned) 1 + memInst->getFirstIndexOperandNumber())
                  && "Array refs must be lowered before Instruction Selection");
           
           Value* arrayOffsetVal =  * memInst->idx_begin();
           
+          // Handle special common case of leading [0] index.
+          ConstantUInt* CV = dyn_cast<ConstantUInt>(idxVec.front());
+          bool firstIndexIsZero = bool(CV && CV->getType() == Type::UIntTy &&
+                                       (CV->getValue() == 0));
+      
           // If index is 0, the offset value is just 0.  Otherwise, 
           // generate a MUL instruction to compute address from index.
           // The call to getTypeSize() will fail if size is not constant.
@@ -1018,10 +1056,13 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
               ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);
               
               CreateMulInstruction(target,
+                                   memInst->getParent()->getParent(),
                                    arrayOffsetVal, /* lval, not likely const */
                                    eltVal,         /* rval, likely constant */
                                    addr,           /* result*/
-                                   mulVec, INVALID_MACHINE_OPCODE);
+                                   mulVec,
+                                   MachineCodeForInstruction::get(memInst),
+                                   INVALID_MACHINE_OPCODE);
               assert(mulVec.size() > 0 && "No multiply instruction created?");
               for (vector<MachineInstr*>::const_iterator I = mulVec.begin();
                    I != mulVec.end(); ++I)
@@ -1116,7 +1157,6 @@ ForwardOperand(InstructionNode* treeNode,
     }
   else
     {
-      bool fwdSuccessful = false;
       for (unsigned i=0, N=mvec.size(); i < N; i++)
         {
           MachineInstr* minstr = mvec[i];
@@ -1125,93 +1165,32 @@ ForwardOperand(InstructionNode* treeNode,
               const MachineOperand& mop = minstr->getOperand(i);
               if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
                   mop.getVRegValue() == unusedOp)
-                {
-                  minstr->SetMachineOperandVal(i,
+                minstr->SetMachineOperandVal(i,
                                 MachineOperand::MO_VirtualRegister, fwdOp);
-                  fwdSuccessful = true;
-                }
             }
           
           for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); i<numOps; ++i)
             if (minstr->getImplicitRef(i) == unusedOp)
-              {
-                minstr->setImplicitRef(i, fwdOp,
-                                       minstr->implicitRefIsDefined(i));
-                fwdSuccessful = true;
-              }
+              minstr->setImplicitRef(i, fwdOp,
+                                     minstr->implicitRefIsDefined(i));
         }
-      assert(fwdSuccessful && "Value to be forwarded is never used!");
     }
 }
 
 
-void UltraSparcInstrInfo::
-CreateCopyInstructionsByType(const TargetMachine& target,
-                             Function *F,
-                             Value* src,
-                             Instruction* dest,
-                             vector<MachineInstr*>& minstrVec) const
+inline bool
+AllUsesAreBranches(const Instruction* setccI)
 {
-  bool loadConstantToReg = false;
-  
-  const Type* resultType = dest->getType();
-  
-  MachineOpCode opCode = ChooseAddInstructionByType(resultType);
-  if (opCode == INVALID_OPCODE)
-    {
-      assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
-      return;
-    }
-  
-  // if `src' is a constant that doesn't fit in the immed field or if it is
-  // a global variable (i.e., a constant address), generate a load
-  // instruction instead of an add
-  // 
-  if (isa<Constant>(src))
-    {
-      unsigned int machineRegNum;
-      int64_t immedValue;
-      MachineOperand::MachineOperandType opType =
-        ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
-                         machineRegNum, immedValue);
-      
-      if (opType == MachineOperand::MO_VirtualRegister)
-        loadConstantToReg = true;
-    }
-  else if (isa<GlobalValue>(src))
-    loadConstantToReg = true;
-  
-  if (loadConstantToReg)
-    { // `src' is constant and cannot fit in immed field for the ADD
-      // Insert instructions to "load" the constant into a register
-      vector<TmpInstruction*> tempVec;
-      target.getInstrInfo().CreateCodeToLoadConst(F, src, dest,
-                                                  minstrVec, tempVec);
-      for (unsigned i=0; i < tempVec.size(); i++)
-        MachineCodeForInstruction::get(dest).addTemp(tempVec[i]);
-    }
-  else
-    { // Create an add-with-0 instruction of the appropriate type.
-      // Make `src' the second operand, in case it is a constant
-      // Use (unsigned long) 0 for a NULL pointer value.
-      // 
-      const Type* zeroValueType =
-        isa<PointerType>(resultType) ? Type::ULongTy : resultType;
-      MachineInstr* minstr = new MachineInstr(opCode);
-      minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
-                                   Constant::getNullValue(zeroValueType));
-      minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, src);
-      minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
-      minstrVec.push_back(minstr);
-    }
+  for (Value::use_const_iterator UI=setccI->use_begin(), UE=setccI->use_end();
+       UI != UE; ++UI)
+    if (! isa<TmpInstruction>(*UI)     // ignore tmp instructions here
+        && cast<Instruction>(*UI)->getOpcode() != Instruction::Br)
+      return false;
+  return true;
 }
 
-
-
 //******************* Externally Visible Functions *************************/
 
-
-
 //------------------------------------------------------------------------ 
 // External Function: ThisIsAChainRule
 //
@@ -1521,11 +1500,33 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
       case 27: // reg:   ToUIntTy(reg)
       case 29: // reg:   ToULongTy(reg)
       {
+        Instruction* destI =  subtreeRoot->getInstruction();
+        Value* opVal = subtreeRoot->leftChild()->getValue();
         const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
         assert(opType->isIntegral() ||
                isa<PointerType>(opType) ||
                opType == Type::BoolTy && "Cast is illegal for other types");
-        forwardOperandNum = 0;          // forward first operand to user
+        
+        unsigned opSize = target.DataLayout.getTypeSize(opType);
+        unsigned destSize = target.DataLayout.getTypeSize(destI->getType());
+        
+        if (opSize > destSize ||
+            (opType->isSigned()
+             && destSize < target.DataLayout.getIntegerRegize()))
+          { // operand is larger than dest,
+            //    OR both are equal but smaller than the full register size
+            //       AND operand is signed, so it may have extra sign bits:
+            // mask high bits using AND
+            // 
+            M = Create3OperandInstr(AND, opVal,
+                                    ConstantUInt::get(Type::ULongTy,
+                                          ((uint64_t) 1 << 8*destSize) - 1),
+                                    destI);
+            mvec.push_back(M);
+          }
+        else
+          forwardOperandNum = 0;          // forward first operand to user
+        
         break;
       }
       
@@ -1534,18 +1535,49 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
       case 28: // reg:   ToIntTy(reg)
       case 30: // reg:   ToLongTy(reg)
       {
-        const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
+        unsigned int oldMvecSize = mvec.size(); // to check if it grew
+        Instruction* destI =  subtreeRoot->getInstruction();
+        Value* opVal = subtreeRoot->leftChild()->getValue();
+        MachineCodeForInstruction& mcfi =MachineCodeForInstruction::get(destI);
+        
+        const Type* opType = opVal->getType();
         if (opType->isIntegral()
             || isa<PointerType>(opType)
             || opType == Type::BoolTy)
           {
-            forwardOperandNum = 0;          // forward first operand to user
+            // These operand types have the same format as the destination,
+            // but may have different size: add sign bits or mask as needed.
+            // 
+            const Type* destType = destI->getType();
+            unsigned opSize = target.DataLayout.getTypeSize(opType);
+            unsigned destSize = target.DataLayout.getTypeSize(destType);
+            if (opSize <= destSize && !opType->isSigned())
+              { // operand is smaller than or same size as dest:
+                // -- if operand is signed (checked above), nothing to do
+                // -- if operand is unsigned, sign-extend the value:
+                // 
+                target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), opVal, 8*opSize, destI, mvec, mcfi);
+              }
+            else if (opSize > destSize)
+              { // operand is larger than dest: mask high bits using AND
+                // and then sign-extend using SRA by 0!
+                // 
+                TmpInstruction *tmpI = new TmpInstruction(destType, opVal,
+                                                          destI, "maskHi");
+                mcfi.addTemp(tmpI);
+                M = Create3OperandInstr(AND, opVal,
+                                        ConstantUInt::get(Type::UIntTy,
+                                              ((uint64_t) 1 << 8*destSize)-1),
+                                        tmpI);
+                mvec.push_back(M);
+                
+                target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), tmpI, 8*destSize, destI, mvec, mcfi);
+              }
           }
         else
           {
             // If the source operand is an FP type, the int result must be
             // copied from float to int register via memory!
-            Instruction *dest = subtreeRoot->getInstruction();
             Value* leftVal = subtreeRoot->leftChild()->getValue();
             Value* destForCast;
             vector<MachineInstr*> minstrVec;
@@ -1559,21 +1591,18 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                 // double-prec for a 64-bit int.
                 // 
                 const Type* destTypeToUse =
-                  (dest->getType() == Type::LongTy)? Type::DoubleTy
+                  (destI->getType() == Type::LongTy)? Type::DoubleTy
                                                    : Type::FloatTy;
                 destForCast = new TmpInstruction(destTypeToUse, leftVal);
                 MachineCodeForInstruction &destMCFI = 
-                  MachineCodeForInstruction::get(dest);
+                  MachineCodeForInstruction::get(destI);
                 destMCFI.addTemp(destForCast);
                 
-                vector<TmpInstruction*> tempVec;
-                target.getInstrInfo().CreateCodeToCopyFloatToInt(
-                    dest->getParent()->getParent(),
-                    (TmpInstruction*) destForCast, dest,
-                    minstrVec, tempVec, target);
-                
-                for (unsigned i=0; i < tempVec.size(); ++i)
-                  destMCFI.addTemp(tempVec[i]);
+                target.getInstrInfo().
+                  CreateCodeToCopyFloatToInt(target,
+                                             destI->getParent()->getParent(),
+                                             (TmpInstruction*) destForCast,
+                                             destI, minstrVec, destMCFI);
               }
             else
               destForCast = leftVal;
@@ -1585,6 +1614,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
             // Append the copy code, if any, after the conversion instr.
             mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
           }
+        
+        if (oldMvecSize == mvec.size()) // no instruction was generated
+          forwardOperandNum = 0;  // forward first operand to user
+        
         break;
       }  
       
@@ -1620,7 +1653,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                 Instruction *dest = subtreeRoot->getInstruction();
                 Value* srcForCast;
                 int n = 0;
-                if (opType->isFloatingPoint())
+                if (opType->isFloatingPoint())
                   {
                     // Create a temporary to represent the FP register
                     // into which the integer will be copied via memory.
@@ -1637,17 +1670,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                       MachineCodeForInstruction::get(dest);
                     destMCFI.addTemp(srcForCast);
                     
-                    vector<MachineInstr*> minstrVec;
-                    vector<TmpInstruction*> tempVec;
-                    target.getInstrInfo().CreateCodeToCopyIntToFloat(
+                    target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
                          dest->getParent()->getParent(),
                          leftVal, (TmpInstruction*) srcForCast,
-                         minstrVec, tempVec, target);
-                    
-                    mvec.insert(mvec.end(), minstrVec.begin(),minstrVec.end());
-                    
-                    for (unsigned i=0; i < tempVec.size(); ++i)
-                       destMCFI.addTemp(tempVec[i]);
+                         mvec, destMCFI);
                   }
                 else
                   srcForCast = leftVal;
@@ -1705,11 +1731,12 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
                                  ? FSMULD
                                  : INVALID_MACHINE_OPCODE);
-        CreateMulInstruction(target,
+        Instruction* mulInstr = subtreeRoot->getInstruction();
+        CreateMulInstruction(target, mulInstr->getParent()->getParent(),
                              subtreeRoot->leftChild()->getValue(),
                              subtreeRoot->rightChild()->getValue(),
-                             subtreeRoot->getInstruction(),
-                             mvec, forceOp);
+                             mulInstr, mvec,
+                             MachineCodeForInstruction::get(mulInstr),forceOp);
         break;
       }
       case 335:        // reg:   Mul(todouble, todoubleConst)
@@ -1721,11 +1748,13 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
                                  ? FSMULD
                                  : INVALID_MACHINE_OPCODE);
-        CreateMulInstruction(target,
+        Instruction* mulInstr = subtreeRoot->getInstruction();
+        CreateMulInstruction(target, mulInstr->getParent()->getParent(),
                              subtreeRoot->leftChild()->getValue(),
                              subtreeRoot->rightChild()->getValue(),
-                             subtreeRoot->getInstruction(),
-                             mvec, forceOp);
+                             mulInstr, mvec,
+                             MachineCodeForInstruction::get(mulInstr),
+                             forceOp);
         break;
       }
       case 236:        // reg:   Div(reg, Constant)
@@ -1793,7 +1822,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
       case 239:        // bool:   Or(bool, boolconst)
       case 339:        // reg :   BOr(reg, reg)
       case 539:        // reg :   BOr(reg, Constant)
-        mvec.push_back(new MachineInstr(ORN));
+        mvec.push_back(new MachineInstr(OR));
         Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
         break;
 
@@ -1829,7 +1858,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         // a result register, and setting a condition code.
         // 
         // If the boolean result of the SetCC is used by anything other
-        // than a single branch instruction, the boolean must be
+        // than a branch instruction, the boolean must be
         // computed and stored in the result register.  Otherwise, discard
         // the difference (by using %g0) and keep only the condition code.
         // 
@@ -1840,9 +1869,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         // 
         InstructionNode* parentNode = (InstructionNode*) subtreeRoot->parent();
         Instruction* setCCInstr = subtreeRoot->getInstruction();
-        bool keepBoolVal = (parentNode == NULL ||
-                            parentNode->getInstruction()->getOpcode()
-                                != Instruction::Br);
+        
+        bool keepBoolVal = ! AllUsesAreBranches(setCCInstr);
         bool subValIsBoolVal = setCCInstr->getOpcode() == Instruction::SetNE;
         bool keepSubVal = keepBoolVal && subValIsBoolVal;
         bool computeBoolVal = keepBoolVal && ! subValIsBoolVal;
@@ -2008,7 +2036,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         Value *callee = callInstr->getCalledValue();
         
         // Create hidden virtual register for return address, with type void*. 
-        Instruction* retAddrReg =
+        TmpInstruction* retAddrReg =
           new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
         MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
         
@@ -2036,49 +2064,68 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         
         mvec.push_back(M);
 
-        // WARNING: Operands 0..N-1 must go in slots 0..N-1 of implicitUses.
-        //          The result value must go in slot N.  This is assumed
-        //          in register allocation.
-        // 
-        // Add the call operands and return value as implicit refs
-        // const Type* funcType = isa<Function>(callee)? callee->getType()
-        //   : cast<PointerType>(callee->getType())->getElementType();
-        const Type* funcType = callee->getType();
-        bool isVarArgs = cast<FunctionType>(cast<PointerType>(funcType)
-                                            ->getElementType())->isVarArg();
+        const FunctionType* funcType =
+          cast<FunctionType>(cast<PointerType>(callee->getType())
+                             ->getElementType());
+        bool isVarArgs = funcType->isVarArg();
+        bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
         
-        for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
-          if (callInstr->getOperand(i) != callee)
-            {
-              Value* argVal = callInstr->getOperand(i);
-              
-              // Check for FP arguments to varargs functions
-              if (isVarArgs && argVal->getType()->isFloatingPoint())
-                { // Add a copy-float-to-int instruction
-                  MachineCodeForInstruction &destMCFI = 
-                    MachineCodeForInstruction::get(callInstr);   
-                  Instruction* intArgReg =
-                    new TmpInstruction(Type::IntTy, argVal);
-                  destMCFI.addTemp(intArgReg);
-                  
-                  vector<MachineInstr*> minstrVec;
-                  vector<TmpInstruction*> tempVec;
-                  target.getInstrInfo().CreateCodeToCopyFloatToInt(
-                         callInstr->getParent()->getParent(),
-                         argVal, (TmpInstruction*) intArgReg,
-                         minstrVec, tempVec, target);
-                  
-                  mvec.insert(mvec.begin(), minstrVec.begin(),minstrVec.end());
-                  
-                  for (unsigned i=0; i < tempVec.size(); ++i)
-                    destMCFI.addTemp(tempVec[i]);
-                  
-                  argVal = intArgReg;
-                }
-              
-              mvec.back()->addImplicitRef(argVal);
-            }
+        // Use an annotation to pass information about call arguments
+        // to the register allocator.
+        CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
+                                         retAddrReg, isVarArgs, noPrototype);
+        M->addAnnotation(argDesc);
+        
+        assert(callInstr->getOperand(0) == callee
+               && "This is assumed in the loop below!");
         
+        for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
+          {
+            Value* argVal = callInstr->getOperand(i);
+            Instruction* intArgReg = NULL;
+            
+            // Check for FP arguments to varargs functions.
+            // Any such argument in the first $K$ args must be passed in an
+            // integer register, where K = #integer argument registers.
+            if (isVarArgs && argVal->getType()->isFloatingPoint())
+              {
+                // If it is a function with no prototype, pass value
+                // as an FP value as well as a varargs value
+                if (noPrototype)
+                  argDesc->getArgInfo(i-1).setUseFPArgReg();
+                
+                // If this arg. is in the first $K$ regs, add a copy
+                // float-to-int instruction to pass the value as an integer.
+                if (i < target.getRegInfo().GetNumOfIntArgRegs())
+                  {
+                    MachineCodeForInstruction &destMCFI = 
+                      MachineCodeForInstruction::get(callInstr);   
+                    intArgReg = new TmpInstruction(Type::IntTy, argVal);
+                    destMCFI.addTemp(intArgReg);
+                    
+                    vector<MachineInstr*> copyMvec;
+                    target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
+                                           callInstr->getParent()->getParent(),
+                                           argVal, (TmpInstruction*) intArgReg,
+                                           copyMvec, destMCFI);
+                    mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
+                    
+                    argDesc->getArgInfo(i-1).setUseIntArgReg();
+                    argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
+                  }
+                else
+                  // Cannot fit in first $K$ regs so pass the arg on the stack
+                  argDesc->getArgInfo(i-1).setUseStackSlot();
+              }
+            
+            if (intArgReg)
+              mvec.back()->addImplicitRef(intArgReg);
+            
+            mvec.back()->addImplicitRef(argVal);
+          }
+        
+        // Add the return value as an implicit ref.  The call operands
+        // were added above.
         if (callInstr->getType() != Type::VoidTy)
           mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
         
@@ -2090,20 +2137,29 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
         mvec.push_back(new MachineInstr(NOP));
         break;
       }
-
+      
       case 62: // reg:   Shl(reg, reg)
-      { const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
+      {
+        Value* argVal1 = subtreeRoot->leftChild()->getValue();
+        Value* argVal2 = subtreeRoot->rightChild()->getValue();
+        Instruction* shlInstr = subtreeRoot->getInstruction();
+        
+        const Type* opType = argVal1->getType();
         assert(opType->isIntegral()
-               || isa<PointerType>(opType)&& "Shl unsupported for other types");
-        mvec.push_back(new MachineInstr((opType == Type::LongTy)? SLLX : SLL));
-        Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
+               || opType == Type::BoolTy
+               || isa<PointerType>(opType)&&"Shl unsupported for other types");
+        
+        CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
+                                (opType == Type::LongTy)? SLLX : SLL,
+                                argVal1, argVal2, 0, shlInstr, mvec,
+                                MachineCodeForInstruction::get(shlInstr));
         break;
       }
       
       case 63: // reg:   Shr(reg, reg)
       { const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
         assert(opType->isIntegral()
-               || isa<PointerType>(opType) &&"Shr unsupported for other types");
+               || isa<PointerType>(opType)&&"Shr unsupported for other types");
         mvec.push_back(new MachineInstr((opType->isSigned()
                                    ? ((opType == Type::LongTy)? SRAX : SRA)
                                    : ((opType == Type::LongTy)? SRLX : SRL))));
@@ -2150,14 +2206,15 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
       else
         {
           vector<MachineInstr*> minstrVec;
-          target.getInstrInfo().CreateCopyInstructionsByType(target, 
-                subtreeRoot->getInstruction()->getParent()->getParent(),
-                subtreeRoot->getInstruction()->getOperand(forwardOperandNum),
-                subtreeRoot->getInstruction(), minstrVec);
+          Instruction* instr = subtreeRoot->getInstruction();
+          target.getInstrInfo().
+            CreateCopyInstructionsByType(target,
+                                         instr->getParent()->getParent(),
+                                         instr->getOperand(forwardOperandNum),
+                                         instr, minstrVec,
+                                        MachineCodeForInstruction::get(instr));
           assert(minstrVec.size() > 0);
           mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
         }
     }
 }
-
-
index 848ddddd384ff4871c8d152bd95d369f1e8f3a66..2ee92945b7c5aef5765cf107d14019610f1eb83c 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef SPARC_INSTR_SELECTION_SUPPORT_h
 #define SPARC_INSTR_SELECTION_SUPPORT_h
 
+#include "llvm/DerivedTypes.h"
+#include "llvm/Value.h"
 
 inline MachineOpCode
 ChooseLoadInstruction(const Type *DestTy)
@@ -58,4 +60,29 @@ ChooseStoreInstruction(const Type *DestTy)
   return 0;
 }
 
+
+inline MachineOpCode 
+ChooseAddInstructionByType(const Type* resultType)
+{
+  MachineOpCode opCode = INVALID_OPCODE;
+  
+  if (resultType->isIntegral() ||
+      isa<PointerType>(resultType) ||
+      isa<FunctionType>(resultType) ||
+      resultType == Type::LabelTy ||
+      resultType == Type::BoolTy)
+    {
+      opCode = ADD;
+    }
+  else
+    switch(resultType->getPrimitiveID())
+      {
+      case Type::FloatTyID:  opCode = FADDS; break;
+      case Type::DoubleTyID: opCode = FADDD; break;
+      default: assert(0 && "Invalid type for ADD instruction"); break; 
+      }
+  
+  return opCode;
+}
+
 #endif
index 4ca66163ac16151441a246aed61ea2d1dc227e7c..b85b58f39becc8541044108ec4d5bc72bba6b01f 100644 (file)
@@ -123,47 +123,69 @@ public:
   //-------------------------------------------------------------------------
   
   // Create an instruction sequence to put the constant `val' into
-  // the virtual register `dest'.  The generated instructions are
-  // returned in `minstrVec'.  Any temporary registers (TmpInstruction)
-  // created are returned in `tempVec'.
+  // the virtual register `dest'.  `val' may be a Constant or a
+  // GlobalValue, viz., the constant address of a global variable or function.
+  // The generated instructions are returned in `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+  // Any stack space required is allocated via mcff.
   // 
-  virtual void  CreateCodeToLoadConst(Function *F,
+  virtual void  CreateCodeToLoadConst(const TargetMachine& target,
+                                      Function* F,
                                       Value* val,
                                       Instruction* dest,
-                                      std::vector<MachineInstr*>& minstrVec,
-                                      std::vector<TmpInstruction*>& tmp) const;
+                                      std::vector<MachineInstr*>& mvec,
+                                      MachineCodeForInstruction& mcfi) const;
 
-  
   // Create an instruction sequence to copy an integer value `val'
   // to a floating point value `dest' by copying to memory and back.
   // val must be an integral type.  dest must be a Float or Double.
-  // The generated instructions are returned in `minstrVec'.
-  // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+  // The generated instructions are returned in `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+  // Any stack space required is allocated via mcff.
   // 
-  virtual void  CreateCodeToCopyIntToFloat(Function* F,
-                                           Value* val,
-                                           Instruction* dest,
-                                           std::vector<MachineInstr*>& minstr,
-                                           std::vector<TmpInstruction*>& temp,
-                                           TargetMachine& target) const;
+  virtual void  CreateCodeToCopyIntToFloat(const TargetMachine& target,
+                                       Function* F,
+                                       Value* val,
+                                       Instruction* dest,
+                                       std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const;
 
   // Similarly, create an instruction sequence to copy an FP value
   // `val' to an integer value `dest' by copying to memory and back.
-  // See the previous function for information about return values.
+  // The generated instructions are returned in `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+  // Any stack space required is allocated via mcff.
+  // 
+  virtual void  CreateCodeToCopyFloatToInt(const TargetMachine& target,
+                                       Function* F,
+                                       Value* val,
+                                       Instruction* dest,
+                                       std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const;
+  
+  // Create instruction(s) to copy src to dest, for arbitrary types
+  // The generated instructions are returned in `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+  // Any stack space required is allocated via mcff.
   // 
-  virtual void  CreateCodeToCopyFloatToInt(Function* F,
-                                           Value* val,
-                                           Instruction* dest,
-                                           std::vector<MachineInstr*>& minstr,
-                                           std::vector<TmpInstruction*>& temp,
-                                           TargetMachine& target) const;
-
- // create copy instruction(s)
   virtual void CreateCopyInstructionsByType(const TargetMachine& target,
-                                            Function* F,
-                                            Value* src,
-                                            Instruction* dest,
-                                            std::vector<MachineInstr*>& minstr) const;
+                                       Function* F,
+                                       Value* src,
+                                       Instruction* dest,
+                                       std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const;
+
+  // Create instruction sequence to produce a sign-extended register value
+  // from an arbitrary sized value (sized in bits, not bytes).
+  // Any stack space required is allocated via mcff.
+  // 
+  virtual void CreateSignExtensionInstructions(const TargetMachine& target,
+                                       Function* F,
+                                       Value* unsignedSrcVal,
+                                       unsigned int srcSizeInBits,
+                                       Value* dest,
+                                       std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const;
 };
 
 
@@ -240,18 +262,16 @@ class UltraSparcRegInfo : public MachineRegInfo {
   void suggestReg4CallAddr(const MachineInstr *CallMI, LiveRangeInfo &LRI,
                           std::vector<RegClass *> RCList) const;
 
-
-
-  // The following methods are used to find the addresses etc. contained
-  // in specail machine instructions like CALL/RET
-  //
-  Value *getValue4ReturnAddr(const MachineInstr *MInst) const;
-  const Value *getCallInstRetAddr(const MachineInstr *CallMI) const;
-  unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
-
-
-  // The following 3 methods are used to find the RegType (see enum above)
+  void InitializeOutgoingArg(const MachineInstr* CallMI, AddedInstrns *CallAI,
+                             PhyRegAlloc &PRA, LiveRange* LR,
+                             unsigned regType, unsigned RegClassID,
+                             int  UniArgReg, unsigned int argNo,
+                             std::vector<MachineInstr *>& AddedInstrnsBefore)
+    const;
+  
+  // The following 4 methods are used to find the RegType (see enum above)
   // of a LiveRange, Value and using the unified RegClassID
+  int getRegType(unsigned regClassID, const Type* type) const;
   int getRegType(const LiveRange *LR) const;
   int getRegType(const Value *Val) const;
   int getRegType(int reg) const;
@@ -353,8 +373,12 @@ public:
   //
   unsigned getReturnAddressReg() const;
 
-
-
+  // Number of registers used for passing int args (usually 6: %o0 - %o5)
+  // and float args (usually 32: %f0 - %f31)
+  //
+  unsigned const GetNumOfIntArgRegs() const   { return NumOfIntArgRegs; }
+  unsigned const GetNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
+  
   // The following methods are used to color special live ranges (e.g.
   // function args and return values etc.) with specific hardware registers
   // as required. See SparcRegInfo.cpp for the implementation for Sparc.
@@ -427,21 +451,20 @@ public:
   const Value * getCallInstRetVal(const MachineInstr *CallMI) const;
   const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const;
 
-
   // The following methods are used to generate "copy" machine instructions
   // for an architecture.
   //
-  MachineInstr * cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
-                            int RegType) const;
+  void cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
+                   int RegType, vector<MachineInstr*>& mvec) const;
   
-  MachineInstr * cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
-                            int Offset, int RegType) const;
-
-  MachineInstr * cpMem2RegMI(unsigned SrcPtrReg, int Offset,
-                            unsigned DestReg, int RegType) const;
+  void cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
+                   int Offset, int RegType, vector<MachineInstr*>& mvec) const;
 
-  MachineInstr* cpValue2Value(Value *Src, Value *Dest) const;
+  void cpMem2RegMI(unsigned SrcPtrReg, int Offset, unsigned DestReg,
+                   int RegType, vector<MachineInstr*>& mvec) const;
 
+  void cpValue2Value(Value *Src, Value *Dest,
+                     vector<MachineInstr*>& mvec) const;
 
   // To see whether a register is a volatile (i.e., whehter it must be
   // preserved acorss calls)
index 6f645b1df7ca7b0e88ebb1720532bcdad1781311..11a82511587b74b2ec34919623755042e822ec36 100644 (file)
@@ -20,22 +20,6 @@ using std::cerr;
 //-----------------------------------------------------------------------------
 void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
   LiveRange *LR = Node->getParentLR();
-  unsigned NumNeighbors =  Node->getNumOfNeighbors();   // total # of neighbors
-
-  for (unsigned n=0; n < NumNeighbors; n++) {            // for each neigh 
-    IGNode *NeighIGNode = Node->getAdjIGNode(n);
-    LiveRange *NeighLR = NeighIGNode->getParentLR();
-
-    if(NeighLR->hasColor())                        // if has a color
-      IsColorUsedArr[NeighLR->getColor()] = true; // record that color
-
-    else if (NeighLR->hasSuggestedColor()) {
-
-      // if the neighbout can use the suggested color 
-      if(NeighLR->isSuggestedColorUsable()) 
-        IsColorUsedArr[NeighLR->getSuggestedColor()] = true; 
-    }    
-  }
 
   if( DEBUG_RA ) {
     cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:"; 
@@ -148,38 +132,35 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
 //----------------------------------------------------------------------------
 void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
   LiveRange *LR = Node->getParentLR();
-  unsigned NumNeighbors =  Node->getNumOfNeighbors();   // total # of neighbors
 
+  // Mark the second color for double-precision registers:
+  // This is UGLY and should be merged into nearly identical code
+  // in RegClass::colorIGNode that handles the first color.
+  // 
+  unsigned NumNeighbors =  Node->getNumOfNeighbors();   // total # of neighbors
   for(unsigned n=0; n < NumNeighbors; n++) {            // for each neigh 
     IGNode *NeighIGNode = Node->getAdjIGNode(n);
     LiveRange *NeighLR = NeighIGNode->getParentLR();
-
-      if( NeighLR->hasColor() )   {                     // if neigh has a color
-       IsColorUsedArr[ NeighLR->getColor() ] = true; // record that color
-       if (NeighLR->getType() == Type::DoubleTy)
-         IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;  
-      }
-      else if( NeighLR->hasSuggestedColor() )   {   // if neigh has sugg color
-
-       if( NeighLR-> isSuggestedColorUsable() ) {
-
-         // if the neighbout can use the suggested color 
-         
+    
+    if( NeighLR->hasColor() &&
+       NeighLR->getType() == Type::DoubleTy) {
+      IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;  
+      
+    } else if (NeighLR->hasSuggestedColor() &&
+               NeighLR-> isSuggestedColorUsable() ) {
+
+         // if the neighbour can use the suggested color 
          IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true;
          if (NeighLR->getType() == Type::DoubleTy)
            IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true;  
-       }
-
-      }
-
+    }
   }
 
-
   // **NOTE: We don't check for call interferences in allocating suggested
   // color in this class since ALL registers are volatile. If this fact
   // changes, we should change the following part 
   //- see SparcIntRegClass::colorIGNode()
-
+  // 
   if( LR->hasSuggestedColor() ) {
     if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
       LR->setColor(  LR->getSuggestedColor() );
@@ -244,10 +225,8 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
                                IsColorUsedArr);
   }
 
-
-
   if( ColorFound >= 0 ) {
-    LR->setColor(ColorFound);         // first color found in preffered order
+    LR->setColor(ColorFound);         // first color found in prefered order
     LR->markForSaveAcrossCalls();  
   } else {
     // we are here because no color could be found
index 67d3f334bd71f63a391531fbdf6101aae6ee7c69..ab5b35c8010e0c92cfbd724621092225834ab897 100644 (file)
@@ -191,15 +191,17 @@ struct  SparcIntCCRegOrder {
 struct SparcIntCCRegClass : public MachineRegClassInfo {
   SparcIntCCRegClass(unsigned ID) 
     : MachineRegClassInfo(ID, 1, 2) {  }
-
+  
   inline void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
-    Node->setColor(0);    // only one int cc reg is available
+    if (IsColorUsedArr[0])
+      Node->getParentLR()->markForSpill();
+    else
+      Node->setColor(0);    // only one int cc reg is available
   }
-
+  
   // according to  Sparc 64 ABI,  %ccr is volatile
   //
   inline bool isRegVolatile(int Reg) const { return true; }
-
 };
 
 
@@ -231,11 +233,13 @@ struct SparcFloatCCRegClass : public MachineRegClassInfo {
 
   void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
     int c;
-    for(c=0; c < 4  && IsColorUsedArr[c] ; ++c) ; // find color
-    assert ((c < 4)  && "Can allocate only 4 float cc registers");
-    Node->setColor(c);   
+    for(c=0; c < 4  && IsColorUsedArr[c] ; ++c) ; // find unused color
+    if (c < 4)
+      Node->setColor(c);   
+    else
+      Node->getParentLR()->markForSpill();
   }
-
+  
   // according to  Sparc 64 ABI, all %fp CC regs are volatile
   //
   inline bool isRegVolatile(int Reg) const { return true; }
index b660e89805fb1b218ab16f97b1ff4002381769a7..63498e79aefa51c82f7548a2012a0246bb4c1de1 100644 (file)
@@ -10,7 +10,9 @@
 #include "llvm/Target/Sparc.h"
 #include "llvm/CodeGen/MachineCodeForMethod.h"
 #include "llvm/CodeGen/PhyRegAlloc.h"
+#include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrAnnot.h"
 #include "llvm/CodeGen/RegAllocCommon.h"
 #include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h"
 #include "llvm/iTerminators.h"
@@ -127,14 +129,11 @@ UltraSparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall,
                                    unsigned intArgNo, unsigned fpArgNo,
                                    unsigned& regClassId) const
 {
-  int firstArgReg = inCallee? SparcIntRegOrder::i0 : SparcIntRegOrder::o0;
+  regClassId = IntRegClassID;
   if (argNo >= NumOfIntArgRegs)
     return InvalidRegNum;
-  else {
-    regClassId = IntRegClassID;
-    return isVarArgsCall? firstArgReg + argNo
-                        : firstArgReg + intArgNo;
-  }
+  else
+    return argNo + (inCallee? SparcIntRegOrder::i0 : SparcIntRegOrder::o0);
 }
 
 // Get the register number for the specified FP arg#,
@@ -153,128 +152,54 @@ UltraSparcRegInfo::regNumForFPArg(unsigned regType,
                                   unsigned intArgNo, unsigned fpArgNo,
                                   unsigned& regClassId) const
 {
-  if (isVarArgsCall) {
-    assert(! isVarArgsCall &&
-           "FP arguments to a varargs function should be explicitly copied "
-           "to/from int registers by instruction selection!");
-    return InvalidRegNum; 
-  }
-  else {
-    regClassId = FloatRegClassID;
-    if (regType == FPSingleRegType)
-      return (fpArgNo*2+1 >= NumOfFloatArgRegs)?
-        InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2 + 1);
-    else if (regType == FPDoubleRegType)
-      return (fpArgNo*2 >= NumOfFloatArgRegs)?
-        InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2);
-    else
-      assert(0 && "Illegal FP register type");
-  }
-}
-
-//---------------------------------------------------------------------------
-// Finds the return value of a sparc specific call instruction
-//---------------------------------------------------------------------------
-
-const Value * 
-UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const {
-  unsigned OpCode = CallMI->getOpCode();
-  unsigned NumOfImpRefs = CallMI->getNumImplicitRefs();
-
-  if (OpCode == CALL) {
-
-    // The one before the last implicit operand is the return value of 
-    // a CALL instr
-    //
-    if( NumOfImpRefs > 1 )
-      if (CallMI->implicitRefIsDefined(NumOfImpRefs-2)) 
-       return CallMI->getImplicitRef(NumOfImpRefs-2); 
-
-  } else if (OpCode == JMPLCALL) {
-
-    // The last implicit operand is the return value of a JMPL
-    // 
-    if(NumOfImpRefs > 0)
-      if (CallMI->implicitRefIsDefined(NumOfImpRefs-1))
-       return CallMI->getImplicitRef(NumOfImpRefs-1); 
-  } else
-    assert(0 && "OpCode must be CALL/JMPL for a call instr");
-
-  return NULL;
-}
-
-
-const Value * 
-UltraSparcRegInfo::getCallInstIndirectAddrVal(const MachineInstr *CallMI) const
-{
-  return (CallMI->getOpCode() == JMPLCALL)?
-    CallMI->getOperand(0).getVRegValue() : NULL;
+  if (isVarArgsCall)
+    return regNumForIntArg(inCallee, isVarArgsCall, argNo, intArgNo, fpArgNo,
+                           regClassId);
+  else
+    {
+      regClassId = FloatRegClassID;
+      if (regType == FPSingleRegType)
+        return (argNo*2+1 >= NumOfFloatArgRegs)?
+          InvalidRegNum : SparcFloatRegOrder::f0 + (argNo * 2 + 1);
+      else if (regType == FPDoubleRegType)
+        return (argNo*2 >= NumOfFloatArgRegs)?
+          InvalidRegNum : SparcFloatRegOrder::f0 + (argNo * 2);
+      else
+        assert(0 && "Illegal FP register type");
+    }
 }
 
 
 //---------------------------------------------------------------------------
 // Finds the return address of a call sparc specific call instruction
 //---------------------------------------------------------------------------
-const Value *
-UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI) const {
-  unsigned OpCode = CallMI->getOpCode();
-
-  if (OpCode == CALL) {
-    unsigned NumOfImpRefs =  CallMI->getNumImplicitRefs();
 
-    assert( NumOfImpRefs && "CALL instr must have at least on ImpRef");
-
-    // The last implicit operand is the return address of a CALL instr
-    //
-    return CallMI->getImplicitRef(NumOfImpRefs-1); 
-
-  } else if(OpCode == JMPLCALL) {
-    MachineOperand &MO = (MachineOperand &)CallMI->getOperand(2);
-    return MO.getVRegValue();
-  }
-  
-  assert(0 && "OpCode must be CALL/JMPL for a call instr");
-  return 0;
-}
-
-// The following 3  methods are used to find the RegType (see enum above)
-// of a LiveRange, Value and using the unified RegClassID
+// The following 4  methods are used to find the RegType (see enum above)
+// of a LiveRange, a Value, and for a given register unified reg number.
 //
-int UltraSparcRegInfo::getRegType(const LiveRange *LR) const {
-  switch (LR->getRegClass()->getID()) {
+int UltraSparcRegInfo::getRegType(unsigned regClassID,
+                                  const Type* type) const {
+  switch (regClassID) {
   case IntRegClassID: return IntRegType; 
   case FloatRegClassID: {
-    const Type *Typ = LR->getType();
-    if (Typ == Type::FloatTy) 
+    if (type == Type::FloatTy) 
       return FPSingleRegType;
-    else if (Typ == Type::DoubleTy)
+    else if (type == Type::DoubleTy)
       return FPDoubleRegType;
     assert(0 && "Unknown type in FloatRegClass");
   }
-  case IntCCRegClassID: return IntCCRegType; 
+  case IntCCRegClassID:   return IntCCRegType; 
   case FloatCCRegClassID: return FloatCCRegType; 
-  default: assert( 0 && "Unknown reg class ID");
-    return 0;
+  default: assert( 0 && "Unknown reg class ID"); return 0;
   }
 }
 
+int UltraSparcRegInfo::getRegType(const LiveRange *LR) const {
+  return getRegType(LR->getRegClass()->getID(), LR->getType());
+}
+
 int UltraSparcRegInfo::getRegType(const Value *Val) const {
-  unsigned Typ;
-  
-  switch (getRegClassIDOfValue(Val)) {
-  case IntRegClassID: return IntRegType; 
-  case FloatRegClassID:
-    if (Val->getType() == Type::FloatTy)
-      return FPSingleRegType;
-    else if (Val->getType() == Type::DoubleTy)
-      return FPDoubleRegType;
-    assert(0 && "Unknown type in FloatRegClass");
-    
-  case IntCCRegClassID:   return IntCCRegType; 
-  case FloatCCRegClassID: return FloatCCRegType; 
-  default: assert(0 && "Unknown reg class ID");
-    return 0;
-  }
+  return getRegType(getRegClassIDOfValue(Val), Val->getType());
 }
 
 int UltraSparcRegInfo::getRegType(int reg) const {
@@ -294,47 +219,6 @@ int UltraSparcRegInfo::getRegType(int reg) const {
 }
 
 
-
-
-
-//---------------------------------------------------------------------------
-// Finds the # of actual arguments of the call instruction
-//---------------------------------------------------------------------------
-unsigned 
-UltraSparcRegInfo::getCallInstNumArgs(const MachineInstr *CallMI) const {
-
-  unsigned OpCode = CallMI->getOpCode();
-  unsigned NumOfImpRefs = CallMI->getNumImplicitRefs();
-
-  if (OpCode == CALL) {
-    switch (NumOfImpRefs) {
-    case 0: assert(0 && "A CALL inst must have at least one ImpRef (RetAddr)");
-    case 1: return 0;
-    default:  // two or more implicit refs
-      if (CallMI->implicitRefIsDefined(NumOfImpRefs-2)) 
-       return NumOfImpRefs - 2;
-      else 
-       return NumOfImpRefs - 1;
-    }
-  } else if (OpCode == JMPLCALL) {
-
-    // The last implicit operand is the return value of a JMPL instr
-    if( NumOfImpRefs > 0 ) {
-      if (CallMI->implicitRefIsDefined(NumOfImpRefs-1)) 
-       return NumOfImpRefs - 1;
-      else 
-       return NumOfImpRefs;
-    }
-    else 
-      return NumOfImpRefs;
-  }
-
-  assert(0 && "OpCode must be CALL/JMPL for a call instr");
-  return 0;
-}
-
-
-
 //---------------------------------------------------------------------------
 // Suggests a register for the ret address in the RET machine instruction.
 // We always suggest %i7 by convention.
@@ -372,13 +256,11 @@ void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr *RetMI,
 void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI,
                                            LiveRangeInfo& LRI,
                                         std::vector<RegClass *> RCList) const {
-
-
-  const Value *RetAddrVal = getCallInstRetAddr( CallMI );
-
-  // RetAddrVal cannot be NULL (asserted in  getCallInstRetAddr)
-  // create a new LR for the return address and color it
+  CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); 
+  const Value *RetAddrVal = argDesc->getReturnAddrReg();
+  assert(RetAddrVal && "Return address value is required");
   
+  // create a new LR for the return address and color it
   LiveRange * RetAddrLR = new LiveRange();  
   RetAddrLR->insert( RetAddrVal );
   unsigned RegClassID = getRegClassIDOfValue( RetAddrVal );
@@ -419,8 +301,10 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth,
       unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused)
       
       int regNum = (regType == IntRegType)
-        ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
-        : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
+        ? regNumForIntArg(/*inCallee*/ true, isVarArgs,
+                          argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+        : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs,
+                         argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
       
       if(regNum != InvalidRegNum)
         LR->setSuggestedColor(regNum);
@@ -428,7 +312,6 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth,
 }
 
 
-
 //---------------------------------------------------------------------------
 // This method is called after graph coloring to move incoming args to
 // the correct hardware registers if they did not receive the correct
@@ -463,8 +346,10 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
     unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg
     
     int regNum = (regType == IntRegType)
-      ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
-      : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
+      ? regNumForIntArg(/*inCallee*/ true, isVarArgs,
+                        argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+      : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs,
+                       argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
     
     if(regNum != InvalidRegNum) {
       isArgInReg = true;
@@ -489,12 +374,8 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
       // the UniLRReg register
       //
       if( isArgInReg ) {
-       AdMI = cpReg2RegMI( UniArgReg, UniLRReg, regType );
-
        if( regClassIDOfArgReg != RegClassID ) {
-          assert(0 &&
-                 "FP arguments to a varargs function should be explicitly "
-                 "copied to/from int registers by instruction selection!");
+          assert(0 && "This could should work but it is not tested yet");
           
          // It is a variable argument call: the float reg must go in a %o reg.
          // We have to move an int reg to a float reg via memory.
@@ -506,15 +387,14 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
           
          int TmpOff = MachineCodeForMethod::get(Meth).pushTempValue(target,  
                                                 getSpilledRegSize(regType));
-         AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), TmpOff, IntRegType);
-          FirstAI->InstrnsBefore.push_back(AdMI);   
+         cpReg2MemMI(UniArgReg, getFramePointer(), TmpOff, IntRegType,
+                      FirstAI->InstrnsBefore);
           
-         AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniLRReg, regType);
-          FirstAI->InstrnsBefore.push_back(AdMI);   
+         cpMem2RegMI(getFramePointer(), TmpOff, UniLRReg, regType,
+                      FirstAI->InstrnsBefore);
        }
        else {  
-         AdMI = cpReg2RegMI(UniArgReg, UniLRReg, regType );
-          FirstAI->InstrnsBefore.push_back( AdMI );   
+         cpReg2RegMI(UniArgReg, UniLRReg, regType, FirstAI->InstrnsBefore);
        }
       }
       else {
@@ -527,9 +407,8 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
           frameInfo.getIncomingArgOffset(MachineCodeForMethod::get(Meth),
                                          argNo);
         
-       AdMI = cpMem2RegMI(getFramePointer(), offsetFromFP, 
-                          UniLRReg, regType );
-        FirstAI->InstrnsBefore.push_back( AdMI );   
+       cpMem2RegMI(getFramePointer(), offsetFromFP, UniLRReg, regType,
+                    FirstAI->InstrnsBefore);
       }
       
     } // if LR received a color
@@ -554,15 +433,13 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
           assert(isVarArgs && regClassIDOfArgReg == IntRegClassID &&
                  "This should only be an Int register for an FP argument");
           
-          AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), 
-                             LR->getSpillOffFromFP(), IntRegType );
+          cpReg2MemMI(UniArgReg, getFramePointer(), LR->getSpillOffFromFP(),
+                      IntRegType, FirstAI->InstrnsBefore);
         }
         else {
-          AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), 
-                             LR->getSpillOffFromFP(), regType );
+           cpReg2MemMI(UniArgReg, getFramePointer(), LR->getSpillOffFromFP(),
+                       regType, FirstAI->InstrnsBefore);
         }
-        
-        FirstAI->InstrnsBefore.push_back( AdMI );   
       }
 
       else {
@@ -598,12 +475,10 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
                                         std::vector<RegClass *> RCList) const {
   assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
 
-  // check if this is a varArgs function. needed for choosing regs.
-  bool isVarArgs = isVarArgsCall(CallMI);
+  CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); 
   
   suggestReg4CallAddr(CallMI, LRI, RCList);
 
-
   // First color the return value of the call instruction. The return value
   // will be in %o0 if the value is an integer type, or in %f0 if the 
   // value is a float type.
@@ -614,9 +489,7 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
   // if type is not void,  create a new live range and set its 
   // register class and add to LRI
 
-
-  const Value *RetVal = getCallInstRetVal( CallMI );
-
+  const Value *RetVal = argDesc->getReturnValue();
 
   if (RetVal) {
     assert ((!LRI.getLiveRangeForValue(RetVal)) && 
@@ -644,16 +517,16 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
   // the number of registers allocated for argument passing.
   // Now, go thru call args - implicit operands of the call MI
 
-  unsigned NumOfCallArgs =  getCallInstNumArgs( CallMI );
+  unsigned NumOfCallArgs = argDesc->getNumArgs();
   
   for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0;
        i < NumOfCallArgs; ++i, ++argNo) {    
 
-    const Value *CallArg = CallMI->getImplicitRef(i);
+    const Value *CallArg = argDesc->getArgInfo(i).getArgVal();
     
     // get the LR of call operand (parameter)
     LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); 
-
+    
     // not possible to have a null LR since all args (even consts)  
     // must be defined before
     if (!LR) {          
@@ -663,23 +536,136 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
     
     unsigned regType = getRegType( LR );
     unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused)
-
+    
     // Choose a register for this arg depending on whether it is
-    // an INT or FP value, and if it is a varargs call
+    // an INT or FP value.  Here we ignore whether or not it is a
+    // varargs calls, because FP arguments will be explicitly copied
+    // to an integer Value and handled under (argCopy != NULL) below.
     int regNum = (regType == IntRegType)
-      ? regNumForIntArg(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
-      : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
+      ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false,
+                        argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+      : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false,
+                       argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
     
     // If a register could be allocated, use it.
     // If not, do NOTHING as this will be colored as a normal value.
     if(regNum != InvalidRegNum)
       LR->setSuggestedColor(regNum);
     
+    // Repeat for the second copy of the argument, which would be
+    // an FP argument being passed to a function with no prototype
+    const Value *argCopy = argDesc->getArgInfo(i).getArgCopy();
+    if (argCopy != NULL)
+      {
+        assert(regType != IntRegType && argCopy->getType()->isIntegral()
+               && "Must be passing copy of FP argument in int register");
+        int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false,
+                                         argNo, intArgNo, fpArgNo-1,
+                                         regClassIDOfArgReg);
+        assert(copyRegNum != InvalidRegNum); 
+        LiveRange *const copyLR = LRI.getLiveRangeForValue(argCopy); 
+        copyLR->setSuggestedColor(copyRegNum);
+      }
+    
   } // for all call arguments
 
 }
 
 
+//---------------------------------------------------------------------------
+// Helper method for UltraSparcRegInfo::colorCallArgs().
+//---------------------------------------------------------------------------
+    
+void
+UltraSparcRegInfo::InitializeOutgoingArg(const MachineInstr* CallMI,
+                             AddedInstrns *CallAI,
+                             PhyRegAlloc &PRA, LiveRange* LR,
+                             unsigned regType, unsigned RegClassID,
+                             int UniArgRegOrNone, unsigned int argNo,
+                             std::vector<MachineInstr *>& AddedInstrnsBefore)
+  const
+{
+  MachineInstr *AdMI;
+  bool isArgInReg = false;
+  unsigned UniArgReg = MAXINT;          // unused unless initialized below
+  if (UniArgRegOrNone != InvalidRegNum)
+    {
+      isArgInReg = true;
+      UniArgReg = (unsigned) UniArgRegOrNone;
+    }
+  
+  if (LR->hasColor()) {
+    unsigned UniLRReg = getUnifiedRegNum(RegClassID, LR->getColor());
+    
+    // if LR received the correct color, nothing to do
+    if( isArgInReg && UniArgReg == UniLRReg )
+      return;
+    
+    // The LR is allocated to a register UniLRReg and must be copied
+    // to UniArgReg or to the stack slot.
+    // 
+    if( isArgInReg ) {
+      // Copy UniLRReg to UniArgReg
+      cpReg2RegMI(UniLRReg, UniArgReg, regType, AddedInstrnsBefore);
+    }
+    else {
+      // Copy UniLRReg to the stack to pass the arg on stack.
+      const MachineFrameInfo& frameInfo = target.getFrameInfo();
+      int argOffset = frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+      cpReg2MemMI(UniLRReg, getStackPointer(), argOffset, regType,
+                  CallAI->InstrnsBefore);
+    }
+
+  } else {                          // LR is not colored (i.e., spilled)      
+    
+    if( isArgInReg ) {
+      // Insert a load instruction to load the LR to UniArgReg
+      cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
+                  UniArgReg, regType, AddedInstrnsBefore);
+                                        // Now add the instruction
+    }
+      
+    else {
+      // Now, we have to pass the arg on stack. Since LR  also did NOT
+      // receive a register we have to move an argument in memory to 
+      // outgoing parameter on stack.
+      // Use TReg to load and store the value.
+      // Use TmpOff to save TReg, since that may have a live value.
+      // 
+      int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI );
+      int TmpOff = PRA.mcInfo.pushTempValue(target,  
+                                            getSpilledRegSize(getRegType(LR)));
+      const MachineFrameInfo& frameInfo = target.getFrameInfo();
+      int argOffset = frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+      
+      MachineInstr *Ad1, *Ad2, *Ad3, *Ad4;
+        
+      // Sequence:
+      // (1) Save TReg on stack    
+      // (2) Load LR value into TReg from stack pos of LR
+      // (3) Store Treg on outgoing Arg pos on stack
+      // (4) Load the old value of TReg from stack to TReg (restore it)
+      // 
+      // OPTIMIZE THIS:
+      // When reverse pointers in MahineInstr are introduced: 
+      // Call PRA.getUnusedRegAtMI(....) to get an unused reg. Step 1 is
+      // needed only if this fails. Currently, we cannot call the
+      // above method since we cannot find LVSetBefore without the BB 
+      // 
+      // NOTE: We directly add to CallAI->InstrnsBefore instead of adding to
+      // AddedInstrnsBefore since these instructions must not be reordered.
+      cpReg2MemMI(TReg, getFramePointer(), TmpOff, regType,
+                  CallAI->InstrnsBefore);
+      cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), TReg, regType,
+                  CallAI->InstrnsBefore); 
+      cpReg2MemMI(TReg, getStackPointer(), argOffset, regType,
+                  CallAI->InstrnsBefore);
+      cpMem2RegMI(getFramePointer(), TmpOff, TReg, regType,
+                  CallAI->InstrnsBefore); 
+    }
+  }
+}
+
 //---------------------------------------------------------------------------
 // After graph coloring, we have call this method to see whehter the return
 // value and the call args received the correct colors. If not, we have
@@ -694,20 +680,22 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
 
   assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
 
+  CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI); 
+  
   // First color the return value of the call.
   // If there is a LR for the return value, it means this
   // method returns a value
   
   MachineInstr *AdMI;
 
-  const Value *RetVal = getCallInstRetVal( CallMI );
+  const Value *RetVal = argDesc->getReturnValue();
 
   if (RetVal) {
     LiveRange *RetValLR = LRI.getLiveRangeForValue( RetVal );
 
     if (!RetValLR) {
       cerr << "\nNo LR for:" << RAV(RetVal) << "\n";
-      assert(0 && "ERR:No LR for non-void return value");
+      assert(RetValLR && "ERR:No LR for non-void return value");
     }
 
     unsigned RegClassID = (RetValLR->getRegClass())->getID();    
@@ -748,7 +736,7 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
        // the return value is coming in UniRetReg but has to go into
        // the UniRetLRReg
 
-       AdMI = cpReg2RegMI( UniRetReg, UniRetLRReg, regType );  
+       cpReg2RegMI(UniRetReg, UniRetLRReg, regType, CallAI->InstrnsAfter);
 
       } // if LR has color
       else {
@@ -756,12 +744,10 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
        // if the LR did NOT receive a color, we have to move the return
        // value coming in UniRetReg to the stack pos of spilled LR
        
-       AdMI =  cpReg2MemMI(UniRetReg, getFramePointer(), 
-                           RetValLR->getSpillOffFromFP(), regType );
+        cpReg2MemMI(UniRetReg, getFramePointer(),RetValLR->getSpillOffFromFP(),
+                    regType, CallAI->InstrnsAfter);
       }
 
-      CallAI->InstrnsAfter.push_back( AdMI );
-      
     } // the LR didn't receive the suggested color  
     
   } // if there a return value
@@ -772,190 +758,82 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
   //-------------------------------------------
 
   std::vector<MachineInstr *> AddedInstrnsBefore;
-
-  unsigned NumOfCallArgs =  getCallInstNumArgs( CallMI );
-
-  bool isVarArgs = isVarArgsCall(CallMI);
-  if (DEBUG_RA && isVarArgs) cerr << "\nVar arg call found!!\n";
-
+  
+  unsigned NumOfCallArgs = argDesc->getNumArgs();
+  
   for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0;
       i < NumOfCallArgs; ++i, ++argNo) {    
 
-    const Value *CallArg = CallMI->getImplicitRef(i);
-
+    const Value *CallArg = argDesc->getArgInfo(i).getArgVal();
+    
     // get the LR of call operand (parameter)
     LiveRange *const LR = LRI.getLiveRangeForValue(CallArg); 
 
-    unsigned regType = getRegType( CallArg );
     unsigned RegClassID = getRegClassIDOfValue( CallArg);
+    unsigned regType = getRegType( RegClassID, CallArg->getType() );
     
-    // find whether this argument is coming in a register (if not, on stack)
+    // Find whether this argument is coming in a register (if not, on stack)
     // Also find the correct register the argument must use (UniArgReg)
     //
     bool isArgInReg = false;
-    unsigned UniArgReg = InvalidRegNum;        // reg that LR MUST be colored with
+    unsigned UniArgReg = InvalidRegNum;          // reg that LR MUST be colored with
     unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg
     
+    // Find the register that must be used for this arg, depending on
+    // whether it is an INT or FP value.  Here we ignore whether or not it
+    // is a varargs calls, because FP arguments will be explicitly copied
+    // to an integer Value and handled under (argCopy != NULL) below.
     int regNum = (regType == IntRegType)
-      ? regNumForIntArg(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
-      : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
+      ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false,
+                        argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+      : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false,
+                       argNo, intArgNo, fpArgNo++, regClassIDOfArgReg); 
     
     if(regNum != InvalidRegNum) {
       isArgInReg = true;
       UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum);
+      assert(regClassIDOfArgReg == RegClassID &&
+             "Moving values between reg classes must happen during selection");
     }
     
     // not possible to have a null LR since all args (even consts)  
     // must be defined before
     if (!LR) {          
       cerr << " ERROR: In call instr, no LR for arg:  " << RAV(CallArg) <<"\n";
-      assert(0 && "NO LR for call arg");  
+      assert(LR && "NO LR for call arg");  
     }
-
-    if (LR->hasColor()) {
-      unsigned UniLRReg = getUnifiedRegNum( RegClassID,  LR->getColor() );
-
-      // if LR received the correct color, nothing to do
-      if( UniLRReg == UniArgReg )
-       continue;
-
-      // We are here because though the LR is allocated a register, it
-      // was not allocated the suggested register. So, we have to copy %ix reg 
-      // (or stack pos of arg) to the register it was colored with
-
-      // the LR is colored with UniLRReg but has to go into  UniArgReg
-      // to pass it as an argument
-
-      if( isArgInReg ) {
-
-       if( regClassIDOfArgReg != RegClassID ) {
-          assert(0 &&
-                 "FP arguments to a varargs function should be explicitly "
-                 "copied to/from int registers by instruction selection!");
-          
-         // It must be a float arg for a variable argument call, which
-          // must come in a %o reg.
-         // We have to move a float reg to an int reg via memory.
-          // 
-          assert(isVarArgs &&
-                 RegClassID == FloatRegClassID && 
-                 regClassIDOfArgReg == IntRegClassID &&
-                 "This should only be an Int register for an FP argument");
-          
-         // The store instruction will be directly added to  
-         // CallAI->InstrnsBefore since it does not need reordering
-         // 
-         int TmpOff = PRA.mcInfo.pushTempValue(target,  
-                                                getSpilledRegSize(regType));
-          
-         AdMI = cpReg2MemMI(UniLRReg, getFramePointer(), TmpOff, regType );
-         CallAI->InstrnsBefore.push_back( AdMI ); 
-
-         AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniArgReg, IntRegType);
-         AddedInstrnsBefore.push_back( AdMI ); 
-       }
-
-       else {  
-         AdMI = cpReg2RegMI(UniLRReg, UniArgReg, regType );
-         AddedInstrnsBefore.push_back( AdMI ); 
-       }
-
-      } else {
-       // Now, we have to pass the arg on stack. Since LR received a register
-       // we just have to move that register to the stack position where
-       // the argument must be passed
-
-        const MachineFrameInfo& frameInfo = target.getFrameInfo();
-       int argOffset =
-          frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
-        
-       AdMI = cpReg2MemMI(UniLRReg, getStackPointer(), argOffset, regType );
-
-       // Now add the instruction. We can directly add to
-       // CallAI->InstrnsBefore since we are just saving a reg on stack
-       //
-       CallAI->InstrnsBefore.push_back( AdMI ); 
-
-       //cerr << "\nCaution: Passing a reg on stack";
-      }
-
-
-    } else {                          // LR is not colored (i.e., spilled)      
-      
-      if( isArgInReg ) {
-
-       // Now the LR did NOT recieve a register but has a stack poistion.
-       // Since, the outgoing arg goes in a register we just have to insert
-       // a load instruction to load the LR to outgoing register
-
-       if( regClassIDOfArgReg != RegClassID ) {
-          assert(isVarArgs && regClassIDOfArgReg == IntRegClassID &&
-                 "This should only be an Int register for an FP argument");
-          
-         AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
-                            UniArgReg, IntRegType );
-        }
-       else
-         AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
-                            UniArgReg, regType );
-        
-       cerr << "\nCaution: Loading a spilled val to a reg as a call arg";
-       AddedInstrnsBefore.push_back( AdMI );  // Now add the instruction
-      }
-      
-      else {
-       // Now, we have to pass the arg on stack. Since LR  also did NOT
-       // receive a register we have to move an argument in memory to 
-       // outgoing parameter on stack.
-       
-       // Optimize: Optimize when reverse pointers in MahineInstr are
-       // introduced. 
-       // call PRA.getUnusedRegAtMI(....) to get an unused reg. Only if this
-       // fails, then use the following code. Currently, we cannot call the
-       // above method since we cannot find LVSetBefore without the BB 
-       
-       int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI );
-
-       int TmpOff = PRA.mcInfo.pushTempValue(target,  
-                                   getSpilledRegSize(getRegType(LR)) );
-
-        
-        const MachineFrameInfo& frameInfo = target.getFrameInfo();
-       int argOffset =
-          frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+    
+    InitializeOutgoingArg(CallMI, CallAI, PRA, LR, regType, RegClassID,
+                          UniArgReg, argNo, AddedInstrnsBefore);
+    
+    // Repeat for the second copy of the argument, which would be
+    // an FP argument being passed to a function with no prototype.
+    const Value *argCopy = argDesc->getArgInfo(i).getArgCopy();
+    if (argCopy != NULL)
+      {
+        assert(regType != IntRegType && argCopy->getType()->isIntegral()
+               && "Must be passing copy of FP argument in int register");
         
-       MachineInstr *Ad1, *Ad2, *Ad3, *Ad4;
+        unsigned copyRegClassID = getRegClassIDOfValue(argCopy);
+        unsigned copyRegType = getRegType(copyRegClassID, argCopy->getType());
         
-       // Sequence:
-       // (1) Save TReg on stack    
-       // (2) Load LR value into TReg from stack pos of LR
-       // (3) Store Treg on outgoing Arg pos on stack
-       // (4) Load the old value of TReg from stack to TReg (restore it)
-
-       Ad1 = cpReg2MemMI(TReg, getFramePointer(), TmpOff, regType );
-       Ad2 = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), 
-                         TReg, regType ); 
-       Ad3 = cpReg2MemMI(TReg, getStackPointer(), argOffset, regType );
-       Ad4 = cpMem2RegMI(getFramePointer(), TmpOff, TReg, regType ); 
-
-       // We directly add to CallAI->InstrnsBefore instead of adding to
-       // AddedInstrnsBefore since these instructions must not be
-       // reordered.
+        int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false,
+                                         argNo, intArgNo, fpArgNo-1,
+                                         regClassIDOfArgReg);
+        assert(copyRegNum != InvalidRegNum); 
+        assert(regClassIDOfArgReg == copyRegClassID &&
+           "Moving values between reg classes must happen during selection");
         
-       CallAI->InstrnsBefore.push_back( Ad1 );  
-       CallAI->InstrnsBefore.push_back( Ad2 );  
-       CallAI->InstrnsBefore.push_back( Ad3 );  
-       CallAI->InstrnsBefore.push_back( Ad4 );  
-
-       cerr << "\nCaution: Call arg moved from stack2stack for: " << *CallMI ;
+        InitializeOutgoingArg(CallMI, CallAI, PRA,
+                              LRI.getLiveRangeForValue(argCopy), copyRegType,
+                              copyRegClassID, copyRegNum, argNo,
+                              AddedInstrnsBefore);
       }
-    }
   }  // for each parameter in call instruction
 
-
-  // if we added any instruction before the call instruction, verify
+  // If we added any instruction before the call instruction, verify
   // that they are in the proper order and if not, reorder them
-
+  // 
   if (!AddedInstrnsBefore.empty()) {
 
     if (DEBUG_RA) {
@@ -977,8 +855,7 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
     for(unsigned i=0; i < TmpVec.size(); i++)
       CallAI->InstrnsBefore.push_back( TmpVec[i] );
   }
-
-
+  
   // now insert caller saving code for this call instruction
   //
   insertCallerSavingCode(CallMI, BB, PRA);
@@ -1076,13 +953,11 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI,
 
       // the LR received  UniLRReg but must be colored with UniRetReg
       // to pass as the return value
-      RetAI->InstrnsBefore.push_back(cpReg2RegMI(UniLRReg, UniRetReg, regType));
+      cpReg2RegMI(UniLRReg, UniRetReg, regType, RetAI->InstrnsBefore);
     }
     else {                              // if the LR is spilled
-      MachineInstr *AdMI = cpMem2RegMI(getFramePointer(),
-                                       LR->getSpillOffFromFP(), 
-                                       UniRetReg, regType); 
-      RetAI->InstrnsBefore.push_back(AdMI);
+      cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
+                  UniRetReg, regType, RetAI->InstrnsBefore);
       cerr << "\nCopied the return value from stack\n";
     }
   
@@ -1096,25 +971,30 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI,
 // register number
 //---------------------------------------------------------------------------
 
-MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
-                                              unsigned DestReg,
-                                             int RegType) const {
+void
+UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
+                               unsigned DestReg,
+                               int RegType,
+                               vector<MachineInstr*>& mvec) const {
   assert( ((int)SrcReg != InvalidRegNum) && ((int)DestReg != InvalidRegNum) &&
          "Invalid Register");
   
   MachineInstr * MI = NULL;
-
+  
   switch( RegType ) {
     
-  case IntRegType:
   case IntCCRegType:
   case FloatCCRegType: 
+    assert(0 && "This code was bogus and needs to be fixed!");
+    break;
+    
+  case IntRegType:
     MI = new MachineInstr(ADD, 3);
     MI->SetMachineOperandReg(0, SrcReg, false);
     MI->SetMachineOperandReg(1, this->getZeroRegNum(), false);
     MI->SetMachineOperandReg(2, DestReg, true);
     break;
-
+    
   case FPSingleRegType:
     MI = new MachineInstr(FMOVS, 2);
     MI->SetMachineOperandReg(0, SrcReg, false);
@@ -1128,10 +1008,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
     break;
 
   default:
-    assert(0 && "Unknow RegType");
+    assert(0 && "Unknown RegType");
   }
-
-  return MI;
+  
+  if (MI)
+    mvec.push_back(MI);
 }
 
 //---------------------------------------------------------------------------
@@ -1140,9 +1021,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
 //---------------------------------------------------------------------------
 
 
-MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg, 
-                                             unsigned DestPtrReg,
-                                             int Offset, int RegType) const {
+void
+UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg, 
+                               unsigned DestPtrReg,
+                               int Offset, int RegType,
+                               vector<MachineInstr*>& mvec) const {
   MachineInstr * MI = NULL;
   switch( RegType ) {
   case IntRegType:
@@ -1174,10 +1057,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
     assert( 0 && "Cannot directly store %ccr to memory");
     
   default:
-    assert(0 && "Unknow RegType in cpReg2MemMI");
+    assert(0 && "Unknown RegType in cpReg2MemMI");
   }
 
-  return MI;
+  if (MI)
+    mvec.push_back(MI);
 }
 
 
@@ -1187,10 +1071,12 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
 //---------------------------------------------------------------------------
 
 
-MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,      
-                                             int Offset,
-                                             unsigned DestReg,
-                                             int RegType) const {
+void
+UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,     
+                               int Offset,
+                               unsigned DestReg,
+                               int RegType,
+                               vector<MachineInstr*>& mvec) const {
   MachineInstr * MI = NULL;
   switch (RegType) {
   case IntRegType:
@@ -1226,20 +1112,21 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,
     assert(0 && "Unknown RegType in cpMem2RegMI");
   }
 
-  return MI;
+  if (MI)
+    mvec.push_back(MI);
 }
 
 
-
-
-
 //---------------------------------------------------------------------------
 // Generate a copy instruction to copy a value to another. Temporarily
 // used by PhiElimination code.
 //---------------------------------------------------------------------------
 
 
-MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
+void
+UltraSparcRegInfo::cpValue2Value(Value *Src,
+                                 Value *Dest,
+                                 vector<MachineInstr*>& mvec) const {
   int RegType = getRegType( Src );
 
   assert( (RegType==getRegType(Src))  && "Src & Dest are diff types");
@@ -1271,7 +1158,8 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
     assert(0 && "Unknow RegType in CpValu2Value");
   }
 
-  return MI;
+  if (MI)
+    mvec.push_back(MI);
 }
 
 
@@ -1293,14 +1181,18 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
 //----------------------------------------------------------------------------
 
 
-void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst
+void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *CallMI
                                               const BasicBlock *BB,
                                               PhyRegAlloc &PRA) const {
 
+  assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
+  
   // has set to record which registers were saved/restored
   //
   std::hash_set<unsigned> PushedRegSet;
 
+  CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
+  
   // Now find the LR of the return value of the call
   // The last *implicit operand* is the return value of a call
   // Insert it to to he PushedRegSet since we must not save that register
@@ -1309,8 +1201,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
   // to determine, which LRs must be saved across calls. The return value
   // of the call is live in this set - but we must not save/restore it.
 
-
-  const Value *RetVal = getCallInstRetVal( MInst );
+  const Value *RetVal = argDesc->getReturnValue();
 
   if (RetVal) {
     LiveRange *RetValLR = PRA.LRI.getLiveRangeForValue( RetVal );
@@ -1323,7 +1214,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
   }
 
 
-  const ValueSet &LVSetAft =  PRA.LVI->getLiveVarSetAfterMInst(MInst, BB);
+  const ValueSet &LVSetAft =  PRA.LVI->getLiveVarSetAfterMInst(CallMI, BB);
   ValueSet::const_iterator LIt = LVSetAft.begin();
 
   // for each live var in live variable set after machine inst
@@ -1374,25 +1265,28 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
              // push %ccr on to the stack
 
              const ValueSet &LVSetBef = 
-               PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB);
+               PRA.LVI->getLiveVarSetBeforeMInst(CallMI, BB);
 
              // get a free INTEGER register
              int FreeIntReg = 
                PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /*LR->getRegClass()*/,
-                                        IntRegType, MInst, &LVSetBef, AdIBefCC, AdIAftCC);
+                                        IntRegType, CallMI, &LVSetBef, AdIBefCC, AdIAftCC);
               
              // insert the instructions in reverse order since we are
              // adding them to the front of InstrnsBefore
-
+              AddedInstrns& addedI = PRA.AddedInstrMap[CallMI];
              if(AdIAftCC)
-               PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIAftCC);
-
+               addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+                                            AdIAftCC);
+              
              AdICpCC = cpCCR2IntMI(FreeIntReg);
-             PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdICpCC);
-
+             addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+                                          AdICpCC);
+              
              if(AdIBefCC)
-               PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBefCC);
-
+               addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+                                            AdIBefCC);
+              
              if(DEBUG_RA) {
                cerr << "\n!! Inserted caller saving (push) inst for %ccr:";
                if(AdIBefCC) cerr << "\t" <<  *(AdIBefCC);
@@ -1402,8 +1296,8 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
 
            } else  {  
              // for any other register type, just add the push inst
-             AdIBef = cpReg2MemMI(Reg, getFramePointer(), StackOff, RegType );
-             PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBef);
+             cpReg2MemMI(Reg, getFramePointer(), StackOff, RegType,
+                          PRA.AddedInstrMap[CallMI].InstrnsBefore);
            }
 
 
@@ -1417,16 +1311,16 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
              // get a free INT register
              int FreeIntReg = 
                PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /* LR->getRegClass()*/,
-                                        IntRegType, MInst, &LVSetAft, AdIBefCC, AdIAftCC);
+                                        IntRegType, CallMI, &LVSetAft, AdIBefCC, AdIAftCC);
              
              if(AdIBefCC)
-               PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIBefCC);
+               PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdIBefCC);
 
              AdICpCC = cpInt2CCRMI(FreeIntReg);
-             PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdICpCC);
+             PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdICpCC);
            
              if(AdIAftCC)
-               PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAftCC);
+               PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdIAftCC);
 
              if(DEBUG_RA) {
 
@@ -1438,14 +1332,14 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
 
            } else {
              // for any other register type, just add the pop inst
-             AdIAft = cpMem2RegMI(getFramePointer(), StackOff, Reg, RegType );
-             PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAft);
+             cpMem2RegMI(getFramePointer(), StackOff, Reg, RegType,
+                          PRA.AddedInstrMap[CallMI].InstrnsAfter);
            }
            
            PushedRegSet.insert(Reg);
 
            if(DEBUG_RA) {
-             cerr << "\nFor call inst:" << *MInst;
+             cerr << "\nFor call inst:" << *CallMI;
              cerr << " -inserted caller saving instrs:\n\t ";
               if( RegType == IntCCRegType ) {
                if(AdIBefCC) cerr << *AdIBefCC << "\t";
@@ -1535,21 +1429,20 @@ void UltraSparcRegInfo::printReg(const LiveRange *LR) {
 // The unordered instructions come in the UnordVec. These instructions are
 // instructions inserted by RegAlloc. All such instruction MUST have 
 // their USES BEFORE THE DEFS after reordering.
-
+// 
 // The UnordVec & OrdVec must be DISTINCT. The OrdVec must be empty when
 // this method is called.
-
+// 
 // This method uses two vectors for efficiency in accessing
-
+// 
 // Since instructions are inserted in RegAlloc, this assumes that the 
 // first operand is the source reg and the last operand is the dest reg.
-
+// 
 // All the uses are before THE def to a register
-
-
 //---------------------------------------------------------------------------
-void UltraSparcRegInfo::OrderAddedInstrns(std::vector<MachineInstr *> &UnordVec,
-                                         std::vector<MachineInstr *> &OrdVec,
+
+void UltraSparcRegInfo::OrderAddedInstrns(std::vector<MachineInstr*> &UnordVec,
+                                         std::vector<MachineInstr*> &OrdVec,
                                           PhyRegAlloc &PRA) const{
 
   /*
@@ -1719,9 +1612,12 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector<MachineInstr *> &OrdVec,
                                         getSpilledRegSize(RegType));
          
          // Save the UReg (%ox) on stack before it's destroyed
-         AdIBef=cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType);
-         OrdIt = OrdVec.insert( OrdIt, AdIBef);
-         OrdIt++;  // points to current instr we processed
+          vector<MachineInstr*> mvec;
+         cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType, mvec);
+          for (vector<MachineInstr*>::iterator MI=mvec.begin(); MI != mvec.end(); ++MI) {
+            OrdIt = OrdVec.insert(OrdIt, *MI);
+            ++OrdIt; // OrdIt must still point to current instr we processed
+          }
          
          // Load directly into DReg (%oy)
          MachineOperand&  DOp=
@@ -1729,8 +1625,7 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector<MachineInstr *> &OrdVec,
          assert(DOp.opIsDef() && "Last operand is not the def");
          const int DReg = DOp.getMachineRegNum();
          
-         AdIAft=cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType);
-         OrdVec.push_back(AdIAft);
+         cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType, OrdVec);
            
          cerr << "\nFixed CIRCULAR references by reordering";