[llvm-commits] [llvm] r48254 - in /llvm/trunk: lib/Transforms/IPO/IPConstantPropagation.cpp test/Transforms/IPConstantProp/return-constants.ll

Chris Lattner clattner at apple.com
Wed Mar 19 21:43:36 PDT 2008


On Mar 11, 2008, at 3:24 PM, Devang Patel wrote:
> URL: http://llvm.org/viewvc/llvm-project?rev=48254&view=rev
> Log:
> Handle multiple ret values.

>
> +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Tue Mar  
> 11 17:24:29 2008
> @@ -142,22 +143,44 @@
>     return false; // No return value.
>
>   // Check to see if this function returns a constant.
> -  Value *RetVal = 0;
> +  SmallVector<Value *,4> RetVals;
> +  unsigned N = 0;
> +  const StructType *STy = dyn_cast<StructType>(F.getReturnType());
> +  if (STy)
> +    N = STy->getNumElements();
> +  else
> +    N = 1;
> +  for (unsigned i = 0; i < N; ++i)
> +    RetVals.push_back(0);

Instead of introducing N, I'd suggest just using:

> +  if (STy)
> +    RetVals.assign(STy->getNumElements(), 0);
> +  else
> +    RetVals.push_back(0);

then using RetVals.size() instead of N.

>   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
>     if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
> +      assert (N == RI->getNumOperands() && "Invalid ReturnInst  
> operands!");
> +      for (unsigned i = 0; i < N; ++i) {
> +        if (isa<UndefValue>(RI->getOperand(i))) {
> +          // Ignore
> +        } else if (Constant *C = dyn_cast<Constant>(RI- 
> >getOperand(i))) {
> +          Value *RV = RetVals[i];
> +          if (RV == 0)
> +            RetVals[i] = C;
> +          else if (RV != C)
> +            return false; // Does not return the same constant.

This isn't right: some retvals could be constant while others aren't.   
You need a value to represent "not constant".  If this happens, set  
the value to 'not constant' and count how many values get marked 'not  
constant'.  If that count ever equals RetVals.size(), *then* you  
return false.

>
> +        } else {
> +          return false; // Does not return a constant.

Likewise.

> +  if (N == 1) {
> +    if (RetVals[0] == 0)
> +      RetVals[0] = UndefValue::get(F.getReturnType());
> +  } else {
> +    for (unsigned i = 0; i < N; ++i) {
> +      Value *RetVal = RetVals[i];
> +      if (RetVal == 0)
> +        RetVals[i] = UndefValue::get(STy->getElementType(i));
> +    }
> +  }

Why is the N=1 case special here?  Also, the RetVal temporary seems  
unneeded.

> @@ -172,8 +195,18 @@
>           CS.getCalledFunction() != &F) {
>         ReplacedAllUsers = false;
>       } else {
> +        Instruction *Call = CS.getInstruction();
> +        if (!Call->use_empty()) {
> +          if (N == 1)
> +            Call->replaceAllUsesWith(RetVals[0]);
> +          else {
> +            for(Value::use_iterator CUI = Call->use_begin(), CUE =  
> Call->use_end();
> +                CUI != CUE; ++CUI) {
> +              GetResultInst *GR = cast<GetResultInst>(CUI);
> +              GR->replaceAllUsesWith(RetVals[GR->getIndex()]);
> +              GR->eraseFromParent();

This can crash, because there may be some values that are still null.

>
> +            }
> +          }
>           MadeChange = true;
>         }
>       }

IPCP should handle invoke too.

> @@ -182,15 +215,20 @@
>   // If we replace all users with the returned constant, and there  
> can be no
>   // other callers of the function, replace the constant being  
> returned in the
>   // function with an undef value.
> +  if (ReplacedAllUsers && F.hasInternalLinkage()) {
> +    for (unsigned i = 0; i < N; ++i) {
> +      Value *RetVal = RetVals[i];
> +      if (isa<UndefValue>(RetVal))
> +        continue;
> +      Value *RV = UndefValue::get(RetVal->getType());
> +      for (Function::iterator BB = F.begin(), E = F.end(); BB != E;  
> ++BB)
> +        if (ReturnInst *RI = dyn_cast<ReturnInst>(BB- 
> >getTerminator())) {
> +          if (RI->getOperand(i) != RV) {
> +            RI->setOperand(i, RV);
> +            MadeChange = true;
> +          }
>         }

This loop is nested wrong.  You should loop over the whole function  
once, and for each return, you should loop over the ret vals.  This is  
much more efficient.

-Chris



More information about the llvm-commits mailing list