[llvm-commits] [llvm] r50279 - in /llvm/trunk: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp lib/Transforms/Scalar/CodeGenPrepare.cpp test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll

Dan Gohman gohman at apple.com
Fri Apr 25 11:27:55 PDT 2008


Author: djg
Date: Fri Apr 25 13:27:55 2008
New Revision: 50279

URL: http://llvm.org/viewvc/llvm-project?rev=50279&view=rev
Log:
Remove the code from CodeGenPrepare that moved getresult instructions
to the block that defines their operands. This doesn't work in the
case that the operand is an invoke, because invoke is a terminator
and must be the last instruction in a block.

Replace it with support in SelectionDAGISel for copying struct values
into sequences of virtual registers.

Added:
    llvm/trunk/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
    llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=50279&r1=50278&r2=50279&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri Apr 25 13:27:55 2008
@@ -90,37 +90,89 @@
 namespace { struct SDISelAsmOperandInfo; }
 
 namespace {
+  /// ComputeValueVTs - Given an LLVM IR type, compute a sequence of
+  /// MVT::ValueTypes that represent all the individual underlying
+  /// non-aggregate types that comprise it.
+  static void ComputeValueVTs(const TargetLowering &TLI,
+                              const Type *Ty,
+                              SmallVectorImpl<MVT::ValueType> &ValueVTs) {
+    // Given a struct type, recursively traverse the elements.
+    if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+      for (StructType::element_iterator EI = STy->element_begin(),
+                                        EB = STy->element_end();
+          EI != EB; ++EI)
+        ComputeValueVTs(TLI, *EI, ValueVTs);
+      return;
+    }
+    // Given an array type, recursively traverse the elements.
+    if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+      const Type *EltTy = ATy->getElementType();
+      for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
+        ComputeValueVTs(TLI, EltTy, ValueVTs);
+      return;
+    }
+    // Base case: we can get an MVT::ValueType for this LLVM IR type.
+    MVT::ValueType VT = TLI.getValueType(Ty);
+    ValueVTs.push_back(VT);
+  }
+
   /// RegsForValue - This struct represents the physical registers that a
   /// particular value is assigned and the type information about the value.
   /// This is needed because values can be promoted into larger registers and
   /// expanded into multiple smaller registers than the value.
   struct VISIBILITY_HIDDEN RegsForValue {
+    /// TLI - The TargetLowering object.
+    const TargetLowering *TLI;
+
     /// Regs - This list holds the register (for legal and promoted values)
     /// or register set (for expanded values) that the value should be assigned
     /// to.
     std::vector<unsigned> Regs;
     
-    /// RegVT - The value type of each register.
+    /// RegVTs - The value types of the registers. This is the same size
+    /// as ValueVTs; every register contributing to a given value must
+    /// have the same type. When Regs contains all virtual registers, the
+    /// contents of RegVTs is redundant with TLI's getRegisterType member
+    /// function, however when Regs contains physical registers, it is
+    /// necessary to have a separate record of the types.
     ///
-    MVT::ValueType RegVT;
-    
-    /// ValueVT - The value type of the LLVM value, which may be promoted from
-    /// RegVT or made from merging the two expanded parts.
-    MVT::ValueType ValueVT;
-    
-    RegsForValue() : RegVT(MVT::Other), ValueVT(MVT::Other) {}
+    SmallVector<MVT::ValueType, 4> RegVTs;
     
-    RegsForValue(unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt)
-      : RegVT(regvt), ValueVT(valuevt) {
-        Regs.push_back(Reg);
-    }
-    RegsForValue(const std::vector<unsigned> &regs, 
+    /// ValueVTs - The value types of the values, which may be promoted
+    /// or synthesized from one or more registers.
+    SmallVector<MVT::ValueType, 4> ValueVTs;
+    
+    RegsForValue() : TLI(0) {}
+    
+    RegsForValue(const TargetLowering &tli,
+                 unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt)
+      : TLI(&tli), Regs(1, Reg), RegVTs(1, regvt), ValueVTs(1, valuevt) {}
+    RegsForValue(const TargetLowering &tli,
+                 const std::vector<unsigned> &regs, 
                  MVT::ValueType regvt, MVT::ValueType valuevt)
-      : Regs(regs), RegVT(regvt), ValueVT(valuevt) {
+      : TLI(&tli), Regs(regs), RegVTs(1, regvt), ValueVTs(1, valuevt) {}
+    RegsForValue(const TargetLowering &tli,
+                 const std::vector<unsigned> &regs, 
+                 const SmallVector<MVT::ValueType, 4> &regvts,
+                 const SmallVector<MVT::ValueType, 4> &valuevts)
+      : TLI(&tli), Regs(regs), RegVTs(regvts), ValueVTs(valuevts) {}
+    RegsForValue(const TargetLowering &tli,
+                 unsigned Reg, const Type *Ty) : TLI(&tli) {
+      ComputeValueVTs(tli, Ty, ValueVTs);
+
+      for (unsigned Value = 0; Value != ValueVTs.size(); ++Value) {
+        MVT::ValueType ValueVT = ValueVTs[Value];
+        unsigned NumRegs = TLI->getNumRegisters(ValueVT);
+        MVT::ValueType RegisterVT = TLI->getRegisterType(ValueVT);
+        for (unsigned i = 0; i != NumRegs; ++i)
+          Regs.push_back(Reg + i);
+        RegVTs.push_back(RegisterVT);
+        Reg += NumRegs;
+      }
     }
     
     /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
-    /// this value and returns the result as a ValueVT value.  This uses 
+    /// this value and returns the result as a ValueVTs value.  This uses 
     /// Chain/Flag as the input and updates them for the output Chain/Flag.
     /// If the Flag pointer is NULL, no flag is used.
     SDOperand getCopyFromRegs(SelectionDAG &DAG,
@@ -310,16 +362,22 @@
 /// the correctly promoted or expanded types.  Assign these registers
 /// consecutive vreg numbers and return the first assigned number.
 unsigned FunctionLoweringInfo::CreateRegForValue(const Value *V) {
-  MVT::ValueType VT = TLI.getValueType(V->getType());
-  
-  unsigned NumRegisters = TLI.getNumRegisters(VT);
-  MVT::ValueType RegisterVT = TLI.getRegisterType(VT);
+  const Type *Ty = V->getType();
+  SmallVector<MVT::ValueType, 4> ValueVTs;
+  ComputeValueVTs(TLI, Ty, ValueVTs);
+
+  unsigned FirstReg = 0;
+  for (unsigned Value = 0; Value != ValueVTs.size(); ++Value) {
+    MVT::ValueType ValueVT = ValueVTs[Value];
+    unsigned NumRegs = TLI.getNumRegisters(ValueVT);
+    MVT::ValueType RegisterVT = TLI.getRegisterType(ValueVT);
 
-  unsigned R = MakeReg(RegisterVT);
-  for (unsigned i = 1; i != NumRegisters; ++i)
-    MakeReg(RegisterVT);
-
-  return R;
+    for (unsigned i = 0; i != NumRegs; ++i) {
+      unsigned R = MakeReg(RegisterVT);
+      if (!FirstReg) FirstReg = R;
+    }
+  }
+  return FirstReg;
 }
 
 //===----------------------------------------------------------------------===//
@@ -986,7 +1044,7 @@
   if (N.Val) return N;
   
   const Type *VTy = V->getType();
-  MVT::ValueType VT = TLI.getValueType(VTy);
+  MVT::ValueType VT = TLI.getValueType(VTy, true);
   if (Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V))) {
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
       visit(CE->getOpcode(), *CE);
@@ -1056,14 +1114,7 @@
   unsigned InReg = FuncInfo.ValueMap[V];
   assert(InReg && "Value not in map!");
   
-  MVT::ValueType RegisterVT = TLI.getRegisterType(VT);
-  unsigned NumRegs = TLI.getNumRegisters(VT);
-
-  std::vector<unsigned> Regs(NumRegs);
-  for (unsigned i = 0; i != NumRegs; ++i)
-    Regs[i] = InReg + i;
-
-  RegsForValue RFV(Regs, RegisterVT, VT);
+  RegsForValue RFV(TLI, InReg, VTy);
   SDOperand Chain = DAG.getEntryNode();
 
   return RFV.getCopyFromRegs(DAG, Chain, NULL);
@@ -3316,6 +3367,13 @@
     setValue(&I, Undef);
   } else {
     SDOperand Call = getValue(I.getOperand(0));
+
+    // To add support for individual return values with aggregate types,
+    // we'd need a way to take a getresult index and determine which
+    // values of the Call SDNode are associated with it.
+    assert(TLI.getValueType(I.getType(), true) != MVT::Other &&
+           "Individual return values must not be aggregates!");
+
     setValue(&I, SDOperand(Call.Val, I.getIndex()));
   }
 }
@@ -3327,21 +3385,32 @@
 /// If the Flag pointer is NULL, no flag is used.
 SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
                                         SDOperand &Chain, SDOperand *Flag)const{
-  // Copy the legal parts from the registers.
-  unsigned NumParts = Regs.size();
-  SmallVector<SDOperand, 8> Parts(NumParts);
-  for (unsigned i = 0; i != NumParts; ++i) {
-    SDOperand Part = Flag ?
-                     DAG.getCopyFromReg(Chain, Regs[i], RegVT, *Flag) :
-                     DAG.getCopyFromReg(Chain, Regs[i], RegVT);
-    Chain = Part.getValue(1);
-    if (Flag)
-      *Flag = Part.getValue(2);
-    Parts[i] = Part;
-  }
-  
-  // Assemble the legal parts into the final value.
-  return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT);
+  // Assemble the legal parts into the final values.
+  SmallVector<SDOperand, 4> Values(ValueVTs.size());
+  for (unsigned Value = 0, Part = 0; Value != ValueVTs.size(); ++Value) {
+    // Copy the legal parts from the registers.
+    MVT::ValueType ValueVT = ValueVTs[Value];
+    unsigned NumRegs = TLI->getNumRegisters(ValueVT);
+    MVT::ValueType RegisterVT = RegVTs[Value];
+
+    SmallVector<SDOperand, 8> Parts(NumRegs);
+    for (unsigned i = 0; i != NumRegs; ++i) {
+      SDOperand P = Flag ?
+                    DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT, *Flag) :
+                    DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT);
+      Chain = P.getValue(1);
+      if (Flag)
+        *Flag = P.getValue(2);
+      Parts[Part+i] = P;
+    }
+  
+    Values[Value] = getCopyFromParts(DAG, &Parts[Part], NumRegs, RegisterVT,
+                                     ValueVT);
+    Part += NumRegs;
+  }
+  return DAG.getNode(ISD::MERGE_VALUES,
+                     DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+                     &Values[0], ValueVTs.size());
 }
 
 /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
@@ -3351,19 +3420,29 @@
 void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG,
                                  SDOperand &Chain, SDOperand *Flag) const {
   // Get the list of the values's legal parts.
-  unsigned NumParts = Regs.size();
-  SmallVector<SDOperand, 8> Parts(NumParts);
-  getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT);
+  unsigned NumRegs = Regs.size();
+  SmallVector<SDOperand, 8> Parts(NumRegs);
+  for (unsigned Value = 0, Part = 0; Value != ValueVTs.size(); ++Value) { 
+    MVT::ValueType ValueVT = ValueVTs[Value];
+    unsigned NumParts = TLI->getNumRegisters(ValueVT);
+    MVT::ValueType RegisterVT = RegVTs[Value];
+
+    getCopyToParts(DAG, Val.getValue(Val.ResNo + Value),
+                   &Parts[Part], NumParts, RegisterVT);
+    Part += NumParts;
+  }
 
   // Copy the parts into the registers.
-  for (unsigned i = 0; i != NumParts; ++i) {
+  SmallVector<SDOperand, 8> Chains(NumRegs);
+  for (unsigned i = 0; i != NumRegs; ++i) {
     SDOperand Part = Flag ?
                      DAG.getCopyToReg(Chain, Regs[i], Parts[i], *Flag) :
                      DAG.getCopyToReg(Chain, Regs[i], Parts[i]);
-    Chain = Part.getValue(0);
+    Chains[i] = Part.getValue(0);
     if (Flag)
       *Flag = Part.getValue(1);
   }
+  Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs);
 }
 
 /// AddInlineAsmOperands - Add this value to the specified inlineasm node
@@ -3373,8 +3452,16 @@
                                         std::vector<SDOperand> &Ops) const {
   MVT::ValueType IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy();
   Ops.push_back(DAG.getTargetConstant(Code | (Regs.size() << 3), IntPtrTy));
-  for (unsigned i = 0, e = Regs.size(); i != e; ++i)
-    Ops.push_back(DAG.getRegister(Regs[i], RegVT));
+  for (unsigned Value = 0, Reg = 0; Value != ValueVTs.size(); ++Value) { 
+    MVT::ValueType ValueVT = ValueVTs[Value];
+    unsigned NumRegs = TLI->getNumRegisters(ValueVT);
+    MVT::ValueType RegisterVT = RegVTs[Value];
+    for (unsigned i = 0; i != NumRegs; ++i) {
+      SDOperand RegOp = DAG.getRegister(Regs[Reg+i], RegisterVT);
+      Ops.push_back(RegOp);
+    }
+    Reg += NumRegs;
+  }
 }
 
 /// isAllocatableRegister - If the specified register is safe to allocate, 
@@ -3440,7 +3527,7 @@
   /// contains the set of register corresponding to the operand.
   RegsForValue AssignedRegs;
   
-  SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info)
+  explicit SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info)
     : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) {
   }
   
@@ -3558,7 +3645,7 @@
         Regs.push_back(*I);
       }
     }
-    OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
+    OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT);
     const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo();
     OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI);
     return;
@@ -3587,7 +3674,7 @@
       for (; NumRegs; --NumRegs)
         Regs.push_back(RegInfo.createVirtualRegister(PhysReg.second));
       
-      OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
+      OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT);
       return;
     }
     
@@ -3637,7 +3724,7 @@
       for (unsigned i = RegStart; i != RegEnd; ++i)
         Regs.push_back(RegClassRegs[i]);
       
-      OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(), 
+      OpInfo.AssignedRegs = RegsForValue(TLI, Regs, *RC->vt_begin(), 
                                          OpInfo.ConstraintVT);
       OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI);
       return;
@@ -3898,8 +3985,9 @@
         if ((NumOps & 7) == 2 /*REGDEF*/) {
           // Add NumOps>>3 registers to MatchedRegs.
           RegsForValue MatchedRegs;
-          MatchedRegs.ValueVT = InOperandVal.getValueType();
-          MatchedRegs.RegVT   = AsmNodeOperands[CurOp+1].getValueType();
+          MatchedRegs.TLI = &TLI;
+          MatchedRegs.ValueVTs.resize(1, InOperandVal.getValueType());
+          MatchedRegs.RegVTs.resize(1, AsmNodeOperands[CurOp+1].getValueType());
           for (unsigned i = 0, e = NumOps>>3; i != e; ++i) {
             unsigned Reg =
               cast<RegisterSDNode>(AsmNodeOperands[++CurOp])->getReg();
@@ -4304,21 +4392,14 @@
   }
   
   // Figure out the result value types. We start by making a list of
-  // the high-level LLVM return types.
-  SmallVector<const Type *, 4> LLVMRetTys;
-  if (const StructType *ST = dyn_cast<StructType>(RetTy))
-    // A struct return type in the LLVM IR means we have multiple return values.
-    LLVMRetTys.insert(LLVMRetTys.end(), ST->element_begin(), ST->element_end());
-  else
-    LLVMRetTys.push_back(RetTy);
-
-  // Then we translate that to a list of lowered codegen result types.
+  // the potentially illegal return value types.
   SmallVector<MVT::ValueType, 4> LoweredRetTys;
   SmallVector<MVT::ValueType, 4> RetTys;
-  for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) {
-    MVT::ValueType VT = getValueType(LLVMRetTys[I]);
-    RetTys.push_back(VT);
+  ComputeValueVTs(*this, RetTy, RetTys);
 
+  // Then we translate that to a list of legal types.
+  for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+    MVT::ValueType VT = RetTys[I];
     MVT::ValueType RegisterVT = getRegisterType(VT);
     unsigned NumRegs = getNumRegisters(VT);
     for (unsigned i = 0; i != NumRegs; ++i)
@@ -4345,8 +4426,8 @@
 
     SmallVector<SDOperand, 4> ReturnValues;
     unsigned RegNo = 0;
-    for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) {
-      MVT::ValueType VT = getValueType(LLVMRetTys[I]);
+    for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+      MVT::ValueType VT = RetTys[I];
       MVT::ValueType RegisterVT = getRegisterType(VT);
       unsigned NumRegs = getNumRegisters(VT);
       unsigned RegNoEnd = NumRegs + RegNo;
@@ -4441,19 +4522,11 @@
           cast<RegisterSDNode>(Op.getOperand(1))->getReg() != Reg) &&
          "Copy from a reg to the same reg!");
   assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Is a physreg");
-  
-  MVT::ValueType SrcVT = Op.getValueType();
-  MVT::ValueType RegisterVT = TLI.getRegisterType(SrcVT);
-  unsigned NumRegs = TLI.getNumRegisters(SrcVT);
-  SmallVector<SDOperand, 8> Regs(NumRegs);
-  SmallVector<SDOperand, 8> Chains(NumRegs);
 
-  // Copy the value by legal parts into sequential virtual registers.
-  getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT);
-  for (unsigned i = 0; i != NumRegs; ++i)
-    Chains[i] = DAG.getCopyToReg(DAG.getEntryNode(), Reg + i, Regs[i]);
-  SDOperand Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs);
-  PendingExports.push_back(Ch);
+  RegsForValue RFV(TLI, Reg, V->getType());
+  SDOperand Chain = DAG.getEntryNode();
+  RFV.getCopyToRegs(Op, DAG, Chain, 0);
+  PendingExports.push_back(Chain);
 }
 
 void SelectionDAGISel::

Modified: llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp?rev=50279&r1=50278&r2=50279&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/CodeGenPrepare.cpp Fri Apr 25 13:27:55 2008
@@ -1127,15 +1127,6 @@
             // Sink address computing for memory operands into the block.
             MadeChange |= OptimizeInlineAsmInst(I, &(*CI), SunkAddrs);
         }
-    } else if (GetResultInst *GRI = dyn_cast<GetResultInst>(I)) {
-      // Ensure that all getresult instructions live in the same basic block
-      // as their associated struct-value instructions. Codegen requires
-      // this, as lowering only works on one basic block at a time.
-      if (Instruction *Agg = dyn_cast<Instruction>(GRI->getAggregateValue())) {
-        BasicBlock *AggBB = Agg->getParent();
-        if (AggBB != GRI->getParent())
-          GRI->moveBefore(AggBB->getTerminator());
-      }
     }
   }
     

Added: llvm/trunk/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll?rev=50279&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll (added)
+++ llvm/trunk/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll Fri Apr 25 13:27:55 2008
@@ -0,0 +1,18 @@
+; RUN: llvm-as < %s | llc
+
+declare { i64, double } @wild()
+
+define void @foo(i64* %p, double* %q) nounwind {
+        %t = invoke { i64, double } @wild() to label %normal unwind label %handler
+
+normal:
+        %mrv_gr = getresult { i64, double } %t, 0
+        store i64 %mrv_gr, i64* %p
+        %mrv_gr12681 = getresult { i64, double } %t, 1   
+        store double %mrv_gr12681, double* %q
+	ret void
+  
+handler:
+	ret void
+}
+





More information about the llvm-commits mailing list