diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-23 14:22:18 +0000 | 
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-23 14:22:18 +0000 | 
| commit | 73490b890977362d28dd6326843a1ecae413921d (patch) | |
| tree | 3fdd91eae574e32453a4baf462961c742df2691a /lib/CodeGen/CGExprScalar.cpp | |
| parent | a5f348eb914e67b51914117fac117c18c1f8d650 (diff) | |
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
| -rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 256 | 
1 files changed, 202 insertions, 54 deletions
| diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index cc81256032afb..69604f9aaaee3 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -106,6 +106,7 @@ public:      return 0;    }    Value *VisitExpr(Expr *S); +      Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }    // Leaves. @@ -181,48 +182,7 @@ public:    Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); } -  Value *VisitInitListExpr(InitListExpr *E) { -    bool Ignore = TestAndClearIgnoreResultAssign(); -    (void)Ignore; -    assert (Ignore == false && "init list ignored"); -    unsigned NumInitElements = E->getNumInits(); - -    if (E->hadArrayRangeDesignator()) { -      CGF.ErrorUnsupported(E, "GNU array range designator extension"); -    } - -    const llvm::VectorType *VType = -      dyn_cast<llvm::VectorType>(ConvertType(E->getType())); - -    // We have a scalar in braces. Just use the first element. -    if (!VType) -      return Visit(E->getInit(0)); - -    unsigned NumVectorElements = VType->getNumElements(); -    const llvm::Type *ElementType = VType->getElementType(); - -    // Emit individual vector element stores. -    llvm::Value *V = llvm::UndefValue::get(VType); - -    // Emit initializers -    unsigned i; -    for (i = 0; i < NumInitElements; ++i) { -      Value *NewV = Visit(E->getInit(i)); -      Value *Idx = -        llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); -      V = Builder.CreateInsertElement(V, NewV, Idx); -    } - -    // Emit remaining default initializers -    for (/* Do not initialize i*/; i < NumVectorElements; ++i) { -      Value *Idx = -        llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); -      llvm::Value *NewV = llvm::Constant::getNullValue(ElementType); -      V = Builder.CreateInsertElement(V, NewV, Idx); -    } - -    return V; -  } +  Value *VisitInitListExpr(InitListExpr *E);    Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {      return llvm::Constant::getNullValue(ConvertType(E->getType())); @@ -404,7 +364,7 @@ public:  /// EmitConversionToBool - Convert the specified expression value to a  /// boolean (i1) truth value.  This is equivalent to "Val != 0".  Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { -  assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs"); +  assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");    if (SrcType->isRealFloatingType()) {      // Compare against 0.0 for fp scalars. @@ -577,6 +537,13 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,  //===----------------------------------------------------------------------===//  Value *ScalarExprEmitter::VisitExpr(Expr *E) { +  if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E)) +    if (BExpr->getOpcode() == BinaryOperator::PtrMemD) { +      LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr); +      Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal(); +      return InVal; +    } +      CGF.ErrorUnsupported(E, "scalar expression");    if (E->getType()->isVoidType())      return 0; @@ -616,6 +583,174 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {    return Builder.CreateExtractElement(Base, Idx, "vecext");  } +static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx, +                                  unsigned Off, const llvm::Type *I32Ty) { +  int MV = SVI->getMaskValue(Idx); +  if (MV == -1)  +    return llvm::UndefValue::get(I32Ty); +  return llvm::ConstantInt::get(I32Ty, Off+MV); +} + +Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { +  bool Ignore = TestAndClearIgnoreResultAssign(); +  (void)Ignore; +  assert (Ignore == false && "init list ignored"); +  unsigned NumInitElements = E->getNumInits(); +   +  if (E->hadArrayRangeDesignator()) +    CGF.ErrorUnsupported(E, "GNU array range designator extension"); +   +  const llvm::VectorType *VType = +    dyn_cast<llvm::VectorType>(ConvertType(E->getType())); +   +  // We have a scalar in braces. Just use the first element. +  if (!VType) +    return Visit(E->getInit(0)); +   +  unsigned ResElts = VType->getNumElements(); +  const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CGF.getLLVMContext()); +   +  // Loop over initializers collecting the Value for each, and remembering  +  // whether the source was swizzle (ExtVectorElementExpr).  This will allow +  // us to fold the shuffle for the swizzle into the shuffle for the vector +  // initializer, since LLVM optimizers generally do not want to touch +  // shuffles. +  unsigned CurIdx = 0; +  bool VIsUndefShuffle = false; +  llvm::Value *V = llvm::UndefValue::get(VType); +  for (unsigned i = 0; i != NumInitElements; ++i) { +    Expr *IE = E->getInit(i); +    Value *Init = Visit(IE); +    llvm::SmallVector<llvm::Constant*, 16> Args; +     +    const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType()); +     +    // Handle scalar elements.  If the scalar initializer is actually one +    // element of a different vector of the same width, use shuffle instead of  +    // extract+insert. +    if (!VVT) { +      if (isa<ExtVectorElementExpr>(IE)) { +        llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init); + +        if (EI->getVectorOperandType()->getNumElements() == ResElts) { +          llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand()); +          Value *LHS = 0, *RHS = 0; +          if (CurIdx == 0) { +            // insert into undef -> shuffle (src, undef) +            Args.push_back(C); +            for (unsigned j = 1; j != ResElts; ++j) +              Args.push_back(llvm::UndefValue::get(I32Ty)); + +            LHS = EI->getVectorOperand(); +            RHS = V; +            VIsUndefShuffle = true; +          } else if (VIsUndefShuffle) { +            // insert into undefshuffle && size match -> shuffle (v, src) +            llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V); +            for (unsigned j = 0; j != CurIdx; ++j) +              Args.push_back(getMaskElt(SVV, j, 0, I32Ty)); +            Args.push_back(llvm::ConstantInt::get(I32Ty,  +                                                  ResElts + C->getZExtValue())); +            for (unsigned j = CurIdx + 1; j != ResElts; ++j) +              Args.push_back(llvm::UndefValue::get(I32Ty)); +             +            LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); +            RHS = EI->getVectorOperand(); +            VIsUndefShuffle = false; +          } +          if (!Args.empty()) { +            llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +            V = Builder.CreateShuffleVector(LHS, RHS, Mask); +            ++CurIdx; +            continue; +          } +        } +      } +      Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx); +      V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); +      VIsUndefShuffle = false; +      ++CurIdx; +      continue; +    } +     +    unsigned InitElts = VVT->getNumElements(); + +    // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's  +    // input is the same width as the vector being constructed, generate an +    // optimized shuffle of the swizzle input into the result. +    if (isa<ExtVectorElementExpr>(IE)) { +      llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init); +      Value *SVOp = SVI->getOperand(0); +      const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType()); +       +      if (OpTy->getNumElements() == ResElts) { +        unsigned Offset = (CurIdx == 0) ? 0 : ResElts; +         +        for (unsigned j = 0; j != CurIdx; ++j) { +          // If the current vector initializer is a shuffle with undef, merge +          // this shuffle directly into it. +          if (VIsUndefShuffle) { +            Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0, +                                      I32Ty)); +          } else { +            Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +          } +        } +        for (unsigned j = 0, je = InitElts; j != je; ++j) +          Args.push_back(getMaskElt(SVI, j, Offset, I32Ty)); +        for (unsigned j = CurIdx + InitElts; j != ResElts; ++j) +          Args.push_back(llvm::UndefValue::get(I32Ty)); + +        if (VIsUndefShuffle) +          V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); + +        Init = SVOp; +      } +    } + +    // Extend init to result vector length, and then shuffle its contribution +    // to the vector initializer into V. +    if (Args.empty()) { +      for (unsigned j = 0; j != InitElts; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +      for (unsigned j = InitElts; j != ResElts; ++j) +        Args.push_back(llvm::UndefValue::get(I32Ty)); +      llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +      Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT), +                                         Mask, "vecext"); + +      Args.clear(); +      for (unsigned j = 0; j != CurIdx; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +      for (unsigned j = 0; j != InitElts; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts)); +      for (unsigned j = CurIdx + InitElts; j != ResElts; ++j) +        Args.push_back(llvm::UndefValue::get(I32Ty)); +    } + +    // If V is undef, make sure it ends up on the RHS of the shuffle to aid +    // merging subsequent shuffles into this one. +    if (CurIdx == 0) +      std::swap(V, Init); +    llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +    V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit"); +    VIsUndefShuffle = isa<llvm::UndefValue>(Init); +    CurIdx += InitElts; +  } +   +  // FIXME: evaluate codegen vs. shuffling against constant null vector. +  // Emit remaining default initializers. +  const llvm::Type *EltTy = VType->getElementType(); +   +  // Emit remaining default initializers +  for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) { +    Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx); +    llvm::Value *Init = llvm::Constant::getNullValue(EltTy); +    V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); +  } +  return V; +} +  // VisitCastExpr - Emit code for an explicit or implicit cast.  Implicit casts  // have to handle a more broad range of conversions than explicit casts, as they  // handle things like function to ptr-to-function decay etc. @@ -700,7 +835,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {    case CastExpr::CK_IntegralToPointer: {      Value *Src = Visit(const_cast<Expr*>(E)); -    return Builder.CreateIntToPtr(Src, ConvertType(DestTy)); +     +    // First, convert to the correct width so that we control the kind of +    // extension. +    const llvm::Type *MiddleTy = +      llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth); +    bool InputSigned = E->getType()->isSignedIntegerType(); +    llvm::Value* IntResult = +      Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); +     +    return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));    }    case CastExpr::CK_PointerToIntegral: { @@ -1379,18 +1523,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {  }  Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { +  const llvm::Type *ResTy = ConvertType(E->getType()); +      // If we have 0 && RHS, see if we can elide RHS, if so, just return 0.    // If we have 1 && X, just emit X without inserting the control flow.    if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {      if (Cond == 1) { // If we have 1 && X, just emit X.        Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); -      // ZExt result to int. -      return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext"); +      // ZExt result to int or bool. +      return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");      } -    // 0 && RHS: If it is safe, just elide the RHS, and return 0. +    // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.      if (!CGF.ContainsLabel(E->getRHS())) -      return llvm::Constant::getNullValue(CGF.LLVMIntTy); +      return llvm::Constant::getNullValue(ResTy);    }    llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end"); @@ -1423,22 +1569,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {    PN->addIncoming(RHSCond, RHSBlock);    // ZExt result to int. -  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext"); +  return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");  }  Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { +  const llvm::Type *ResTy = ConvertType(E->getType()); +      // If we have 1 || RHS, see if we can elide RHS, if so, just return 1.    // If we have 0 || X, just emit X without inserting the control flow.    if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {      if (Cond == -1) { // If we have 0 || X, just emit X.        Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); -      // ZExt result to int. -      return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext"); +      // ZExt result to int or bool. +      return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");      } -    // 1 || RHS: If it is safe, just elide the RHS, and return 1. +    // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.      if (!CGF.ContainsLabel(E->getRHS())) -      return llvm::ConstantInt::get(CGF.LLVMIntTy, 1); +      return llvm::ConstantInt::get(ResTy, 1);    }    llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end"); @@ -1474,7 +1622,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {    PN->addIncoming(RHSCond, RHSBlock);    // ZExt result to int. -  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext"); +  return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");  }  Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { | 
