summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
commit5563df30b9c8d1fe87a54baae0d6bd86642563f4 (patch)
tree3fdd91eae574e32453a4baf462961c742df2691a /lib/CodeGen/CGExprScalar.cpp
parente5557c18e5d41b4b62f2af8a24af20eba40b0225 (diff)
downloadFreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.zip
FreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.tar.gz
Update clang to r84949.
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--lib/CodeGen/CGExprScalar.cpp256
1 files changed, 202 insertions, 54 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index cc81256..69604f9 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) {
OpenPOWER on IntegriCloud