[llvm-commits] [llvm] r47508 - in /llvm/trunk: include/llvm/Instructions.h include/llvm/User.h lib/AsmParser/llvmAsmParser.y lib/VMCore/AsmWriter.cpp lib/VMCore/Instructions.cpp lib/VMCore/Verifier.cpp

Chris Lattner clattner at apple.com
Mon Feb 25 10:34:11 PST 2008


> URL: http://llvm.org/viewvc/llvm-project?rev=47508&view=rev
> Log:
> To support multiple return values, now ret instruction supports  
> multiple operands instead of one aggregate operand.

Some more details:

> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/include/llvm/Instructions.h (original)
> +++ llvm/trunk/include/llvm/Instructions.h Fri Feb 22 18:35:18 2008
> @@ -1379,9 +1379,9 @@
> /// does not continue in this function any longer.
> ///
> class ReturnInst : public TerminatorInst {
> -  Use RetVal;  // Return Value: null if 'void'.
>   ReturnInst(const ReturnInst &RI);
>   void init(Value *RetVal);
> +  void init(std::vector<Value *> &RetVals);

I'd suggest deleting the first version of 'init' here, and just use:

   void init(Value * const *RetVals, unsigned NumRetVals);

which allows you to efficiently handle both with one function.

> @@ -1397,21 +1397,15 @@
>   // if it was passed NULL.
>   explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore =  
> 0);
>   ReturnInst(Value *retVal, BasicBlock *InsertAtEnd);
> +  ReturnInst(std::vector<Value *> &retVals);
> +  ReturnInst(std::vector<Value *> &retVals, Instruction  
> *InsertBefore);
> +  ReturnInst(std::vector<Value *> &retVals, BasicBlock *InsertAtEnd);

These should all take const vectors by reference.  It would also be  
useful to provide versions that take pointer to pointer + num results  
to allow clients to use arrays and smallvectors or some other linear  
container.


> Modified: llvm/trunk/lib/VMCore/Instructions.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=47508&r1=47507&r2=47508&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/lib/VMCore/Instructions.cpp (original)
> +++ llvm/trunk/lib/VMCore/Instructions.cpp Fri Feb 22 18:35:18 2008
> @@ -573,34 +573,75 @@
>
> ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
> -  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0,  
> InsertBefore) {
> +  : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0,  
> InsertBefore) {

This should pass up null instead of OperandList.  At this point,  
OperandList is uninitialized and you're initializing it with itself.   
Likewise for the other ctors.

> void ReturnInst::init(Value *retVal) {
>   if (retVal && retVal->getType() != Type::VoidTy) {

This is very strange.  I know it's not your fault, but could you check  
to see whether you can change this to:

    if (retVal) {
      assert(retVal->getType() != VoidTy);

It doesn't make sense to support passing in a void value to create a  
void return.

>     assert(!isa<BasicBlock>(retVal) &&
>            "Cannot return basic block.  Probably using the incorrect  
> ctor");
>     NumOperands = 1;
> -    RetVal.init(retVal, this);
> +    Use *OL = OperandList = new Use[1];
> +    OL[0].init(retVal, this);

As an important optimization for the common case, please put a single  
'Use' in the return instruction.  It should only be used it if there  
is one return value: in the case when there are multiple retvals, just  
ignore it.  The old version of ReturnInst did this optimization: in  
the case of 'ret void' the operand went unused.

> +void ReturnInst::init(std::vector<Value *> &retVals) {

As above, please merge the two 'init' methods.

> +Value *ReturnInst::getReturnValue(unsigned n) const {

This should assert that n < NumOperands, and drop the return of null.   
If existing clients depend on the return of null behavior, they will  
need to be updated.  Once you do this, this should be moved inline.

Also, const methods should return const Value*'s.  You'll need to  
duplicate this into two methods.  One that is const and returns const,  
one that is not const and returns nonconst.

> +ReturnInst::~ReturnInst() {
> +  if (NumOperands)
> +    delete [] OperandList;
> +}

This will need to be:
   if (NumOperands != 1) delete [] OperandList;

> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/lib/VMCore/Verifier.cpp (original)
> +++ llvm/trunk/lib/VMCore/Verifier.cpp Fri Feb 22 18:35:18 2008
> @@ -576,14 +576,22 @@
>
> void Verifier::visitReturnInst(ReturnInst &RI) {
>   Function *F = RI.getParent()->getParent();
> -  if (RI.getNumOperands() == 0)
> +  unsigned N = RI.getNumOperands();
> +  if (N == 0)
>     Assert2(F->getReturnType() == Type::VoidTy,
>             "Found return instr that returns void in Function of non- 
> void "
>             "return type!", &RI, F->getReturnType());
> -  else
> +  else if (N == 1)
>     Assert2(F->getReturnType() == RI.getOperand(0)->getType(),
>             "Function return type does not match operand "
>             "type of return inst!", &RI, F->getReturnType());
> +  else {
> +    const StructType *STy = cast<StructType>(F->getReturnType());

This cast assumes that if the return has multiple operands that the  
function returns multiple results.  The verifier should check  
assumptions like this.

>
> +    for (unsigned i = 0; i < N; i++)

You should also check that the number of elements in the struct match  
up with # return operands.

-Chris



More information about the llvm-commits mailing list