summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2015-08-28 06:09:05 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2015-08-28 06:09:05 +0000
commit117fb35cf7348c04f824a1f971cdb8ac78ab370c (patch)
treeeb94f3fe46d44a6b48281638e90abf6fd240aa2e /clang/lib
parent8cff17469fa144bd7e8f19fa30aa881eb85983a3 (diff)
downloadbcm5719-llvm-117fb35cf7348c04f824a1f971cdb8ac78ab370c.tar.gz
bcm5719-llvm-117fb35cf7348c04f824a1f971cdb8ac78ab370c.zip
[OPENMP 4.0] Codegen for array sections.
Added codegen for array section in 'depend' clause of 'task' directive. It emits to pointers, one for the begin of array section and another for the end of array section. Size of the section is calculated as (end + 1 - start) * sizeof(basic_element_type). llvm-svn: 246278
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp127
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp46
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
3 files changed, 169 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index a0d004d315c..bf660b448c3 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -911,6 +911,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitUnaryOpLValue(cast<UnaryOperator>(E));
case Expr::ArraySubscriptExprClass:
return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+ case Expr::OMPArraySectionExprClass:
+ return EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E));
case Expr::ExtVectorElementExprClass:
return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E));
case Expr::MemberExprClass:
@@ -2559,6 +2561,131 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
return LV;
}
+LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
+ bool LowerBound) {
+ LValue Base;
+ if (auto *ASE =
+ dyn_cast<OMPArraySectionExpr>(E->getBase()->IgnoreParenImpCasts()))
+ Base = EmitOMPArraySectionExpr(ASE, LowerBound);
+ else
+ Base = EmitLValue(E->getBase());
+ QualType BaseTy = Base.getType();
+ llvm::Value *Idx;
+ QualType ResultExprTy;
+ if (auto *AT = getContext().getAsArrayType(BaseTy))
+ ResultExprTy = AT->getElementType();
+ else
+ ResultExprTy = BaseTy->getPointeeType();
+ if (LowerBound) {
+ Idx = E->getLowerBound()
+ ? Builder.CreateIntCast(EmitScalarExpr(E->getLowerBound()),
+ IntPtrTy,
+ E->getLowerBound()
+ ->getType()
+ ->hasSignedIntegerRepresentation())
+ : llvm::ConstantInt::getNullValue(IntPtrTy);
+ } else {
+ auto &C = CGM.getContext();
+ auto *Length = E->getLength();
+ if (Length || E->getColonLoc().isInvalid()) {
+ // Idx = LowerBound + Length - 1;
+ auto *One = llvm::ConstantInt::get(IntPtrTy, /*V=*/1);
+ if (Length) {
+ Idx = Builder.CreateIntCast(
+ EmitScalarExpr(Length), IntPtrTy,
+ Length->getType()->hasSignedIntegerRepresentation());
+ }
+ auto *LowerBound = E->getLowerBound();
+ llvm::APSInt ConstLowerBound;
+ if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C))
+ LowerBound = nullptr;
+ if (LowerBound && ConstLowerBound.getZExtValue() != 0) {
+ auto *LowerBoundVal = Builder.CreateIntCast(
+ EmitScalarExpr(LowerBound), IntPtrTy,
+ LowerBound->getType()->hasSignedIntegerRepresentation());
+ if (E->getColonLoc().isValid()) {
+ if (getLangOpts().isSignedOverflowDefined())
+ Idx = Builder.CreateAdd(Idx, LowerBoundVal);
+ else
+ Idx = Builder.CreateNSWAdd(Idx, LowerBoundVal);
+ } else
+ Idx = LowerBoundVal;
+ }
+ if (E->getColonLoc().isValid()) {
+ if (getLangOpts().isSignedOverflowDefined())
+ Idx = Builder.CreateSub(Idx, One);
+ else
+ Idx = Builder.CreateNSWSub(Idx, One);
+ }
+ } else if (auto *VAT = C.getAsVariableArrayType(BaseTy)) {
+ // Idx = ArrSize - 1;
+ Length = VAT->getSizeExpr();
+ Idx = Builder.CreateIntCast(
+ EmitScalarExpr(Length), IntPtrTy,
+ Length->getType()->hasSignedIntegerRepresentation());
+ auto *One = llvm::ConstantInt::get(IntPtrTy, /*V=*/1);
+ if (getLangOpts().isSignedOverflowDefined())
+ Idx = Builder.CreateSub(Idx, One);
+ else
+ Idx = Builder.CreateNSWSub(Idx, One);
+ } else {
+ // Idx = ArrSize - 1;
+ auto *CAT = C.getAsConstantArrayType(BaseTy);
+ Idx = llvm::ConstantInt::get(IntPtrTy, CAT->getSize().getZExtValue() - 1);
+ }
+ }
+
+ llvm::Value *Address;
+ CharUnits ArrayAlignment;
+ if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
+ // The element count here is the total number of non-VLA elements.
+ llvm::Value *numElements = getVLASize(VLA).first;
+
+ // Effectively, the multiply by the VLA size is part of the GEP.
+ // GEP indexes are signed, and scaling an index isn't permitted to
+ // signed-overflow, so we use the same semantics for our explicit
+ // multiply. We suppress this if overflow is not undefined behavior.
+ if (getLangOpts().isSignedOverflowDefined()) {
+ Idx = Builder.CreateMul(Idx, numElements);
+ Address = Builder.CreateGEP(Base.getAddress(), Idx, "arrayidx");
+ } else {
+ Idx = Builder.CreateNSWMul(Idx, numElements);
+ Address = Builder.CreateInBoundsGEP(Base.getAddress(), Idx, "arrayidx");
+ }
+ } else if (BaseTy->isConstantArrayType()) {
+ llvm::Value *ArrayPtr = Base.getAddress();
+ llvm::Value *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
+ llvm::Value *Args[] = {Zero, Idx};
+
+ // Propagate the alignment from the array itself to the result.
+ ArrayAlignment = Base.getAlignment();
+
+ if (getLangOpts().isSignedOverflowDefined())
+ Address = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
+ else
+ Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
+ } else {
+ // The base must be a pointer, which is not an aggregate. Emit it.
+ if (getLangOpts().isSignedOverflowDefined())
+ Address = Builder.CreateGEP(Base.getAddress(), Idx, "arrayidx");
+ else
+ Address = Builder.CreateInBoundsGEP(Base.getAddress(), Idx, "arrayidx");
+ }
+
+ // Limit the alignment to that of the result type.
+ LValue LV;
+ if (!ArrayAlignment.isZero()) {
+ CharUnits Align = getContext().getTypeAlignInChars(ResultExprTy);
+ ArrayAlignment = std::min(Align, ArrayAlignment);
+ LV = MakeAddrLValue(Address, ResultExprTy, ArrayAlignment);
+ } else
+ LV = MakeNaturalAlignAddrLValue(Address, ResultExprTy);
+
+ LV.getQuals().setAddressSpace(BaseTy.getAddressSpace());
+
+ return LV;
+}
+
LValue CodeGenFunction::
EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
// Emit the base vector as an l-value.
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index f734298360b..f4148db7519 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2091,6 +2091,27 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
return TaskPrivatesMap;
}
+llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
+ auto &C = CGF.getContext();
+ llvm::Value *Size;
+ auto SizeInChars = C.getTypeSizeInChars(Ty);
+ if (SizeInChars.isZero()) {
+ // getTypeSizeInChars() returns 0 for a VLA.
+ Size = nullptr;
+ while (auto *VAT = C.getAsVariableArrayType(Ty)) {
+ llvm::Value *ArraySize;
+ std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
+ Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
+ }
+ SizeInChars = C.getTypeSizeInChars(Ty);
+ assert(!SizeInChars.isZero());
+ Size = CGF.Builder.CreateNUWMul(
+ Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
+ } else
+ Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
+ return Size;
+}
+
static int array_pod_sort_comparator(const PrivateDataTy *P1,
const PrivateDataTy *P2) {
return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
@@ -2328,19 +2349,30 @@ void CGOpenMPRuntime::emitTaskCall(
// kmp_depend_info[<Dependences.size()>] deps;
DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy);
for (unsigned i = 0; i < DependencesNumber; ++i) {
- auto Addr = CGF.EmitLValue(Dependences[i].second);
- auto *Size = llvm::ConstantInt::get(
- CGF.SizeTy,
- C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity());
+ auto *E = Dependences[i].second;
+ LValue Addr = CGF.EmitLValue(E);
+ llvm::Value *Size;
+ QualType Ty = E->getType();
+ auto *DestAddr = Addr.getAddress();
+ if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
+ LValue UpAddrLVal =
+ CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
+ llvm::Value *UpAddr =
+ CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getAddress(), /*Idx0=*/1);
+ llvm::Value *LowIntPtr =
+ CGF.Builder.CreatePtrToInt(DestAddr, CGM.SizeTy);
+ llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
+ Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
+ } else
+ Size = getTypeSize(CGF, Ty);
auto Base = CGF.MakeNaturalAlignAddrLValue(
CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i),
KmpDependInfoTy);
// deps[i].base_addr = &<Dependences[i].second>;
auto BaseAddrLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
- CGF.EmitStoreOfScalar(
- CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy),
- BaseAddrLVal);
+ CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(DestAddr, CGF.IntPtrTy),
+ BaseAddrLVal);
// deps[i].len = sizeof(<Dependences[i].second>);
auto LenLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), Len));
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 26ce8e72afa..ca3d3c40dec 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -24,6 +24,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/CapturedStmt.h"
@@ -2427,6 +2428,8 @@ public:
LValue EmitUnaryOpLValue(const UnaryOperator *E);
LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
bool Accessed = false);
+ LValue EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
+ bool LowerBound = true);
LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E);
LValue EmitMemberExpr(const MemberExpr *E);
LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
OpenPOWER on IntegriCloud