[Polly] Remove support for code generated by gfortran+DragonEgg.

DragonEgg is not maintained anymore, hence there is no need for this
functionality.

Fixes llvm.org/PR52173
This commit is contained in:
Michael Kruse 2021-10-14 14:06:20 -05:00
parent a5e52ce3f2
commit 19db33c06e
20 changed files with 10 additions and 1229 deletions

View file

@ -21,3 +21,7 @@ In Polly 14 the following important changes have been incorporated.
This will agressively try to fuse any loop regardless of
profitability. The is what users might have expected what
-polly-opt-fusion=max would do.
- Support for gfortran-generated code has been removed. This includes
Fortran Array Descriptors (-polly-detect-fortran-arrays) and the
-polly-rewrite-byref-params pass.

View file

@ -78,13 +78,6 @@ public:
void addParameters(__isl_take isl_set *Context);
/// Create Values which hold the sizes of the outermost dimension of all
/// Fortran arrays in the current scop.
///
/// @returns False, if a problem occurred and a Fortran array was not
/// materialized. True otherwise.
bool materializeFortranArrayOutermostDimension();
/// Generate code that evaluates @p Condition at run-time.
///
/// This function is typically called to generate the LLVM-IR for the

View file

@ -43,7 +43,6 @@ llvm::Pass *createPolyhedralInfoPass();
llvm::Pass *createScopDetectionWrapperPassPass();
llvm::Pass *createScopInfoRegionPassPass();
llvm::Pass *createScopInfoWrapperPassPass();
llvm::Pass *createRewriteByrefParamsWrapperPass();
llvm::Pass *createIslAstInfoWrapperPassPass();
llvm::Pass *createCodeGenerationPass();
#ifdef GPU_CODEGEN
@ -88,7 +87,6 @@ struct PollyForcePassLinking {
polly::createScopInfoRegionPassPass();
polly::createPollyCanonicalizePass();
polly::createPolyhedralInfoPass();
polly::createRewriteByrefParamsWrapperPass();
polly::createIslAstInfoWrapperPassPass();
polly::createCodeGenerationPass();
#ifdef GPU_CODEGEN
@ -117,7 +115,6 @@ void initializeJSONExporterPass(llvm::PassRegistry &);
void initializeJSONImporterPass(llvm::PassRegistry &);
void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &);
void initializeCodeGenerationPass(llvm::PassRegistry &);
void initializeRewriteByrefParamsWrapperPassPass(llvm::PassRegistry &);
#ifdef GPU_CODEGEN
void initializePPCGCodeGenerationPass(llvm::PassRegistry &);
void initializeManagedMemoryRewritePassPass(llvm::PassRegistry &);

View file

@ -1,38 +0,0 @@
//===- RewriteByReferenceParameters.h -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
#ifndef POLLY_REWRITEBYREFERENCEPARAMETERS_H
#define POLLY_REWRITEBYREFERENCEPARAMETERS_H
#include "polly/ScopPass.h"
namespace llvm {
class PassRegistry;
class Pass;
class raw_ostream;
} // namespace llvm
namespace polly {
llvm::Pass *createRewriteByrefParamsWrapperPass();
struct RewriteByrefParamsPass : llvm::PassInfoMixin<RewriteByrefParamsPass> {
RewriteByrefParamsPass() {}
llvm::PreservedAnalyses run(llvm::Function &F,
llvm::FunctionAnalysisManager &FAM);
};
} // namespace polly
namespace llvm {
void initializeRewriteByrefParamsWrapperPassPass(llvm::PassRegistry &);
} // namespace llvm
#endif /* POLLY_REWRITEBYREFERENCEPARAMETERS_H */

View file

@ -74,65 +74,6 @@ class ScopBuilder {
/// only be simplified later on.
RecordedAssumptionsTy RecordedAssumptions;
// Methods for pattern matching against Fortran code generated by dragonegg.
// @{
/// Try to match for the descriptor of a Fortran array whose allocation
/// is not visible. That is, we can see the load/store into the memory, but
/// we don't actually know where the memory is allocated. If ALLOCATE had been
/// called on the Fortran array, then we will see the lowered malloc() call.
/// If not, this is dubbed as an "invisible allocation".
///
/// "<descriptor>" is the descriptor of the Fortran array.
///
/// Pattern match for "@descriptor":
/// 1. %mem = load double*, double** bitcast (%"struct.array1_real(kind=8)"*
/// <descriptor> to double**), align 32
///
/// 2. [%slot = getelementptr inbounds i8, i8* %mem, i64 <index>]
/// 2 is optional because if you are writing to the 0th index, you don't
/// need a GEP.
///
/// 3.1 store/load <memtype> <val>, <memtype>* %slot
/// 3.2 store/load <memtype> <val>, <memtype>* %mem
///
/// @see polly::MemoryAccess, polly::ScopArrayInfo
///
/// @note assumes -polly-canonicalize has been run.
///
/// @param Inst The LoadInst/StoreInst that accesses the memory.
///
/// @returns Reference to <descriptor> on success, nullptr on failure.
Value *findFADAllocationInvisible(MemAccInst Inst);
/// Try to match for the descriptor of a Fortran array whose allocation
/// call is visible. When we have a Fortran array, we try to look for a
/// Fortran array where we can see the lowered ALLOCATE call. ALLOCATE
/// is materialized as a malloc(...) which we pattern match for.
///
/// Pattern match for "%untypedmem":
/// 1. %untypedmem = i8* @malloc(...)
///
/// 2. %typedmem = bitcast i8* %untypedmem to <memtype>
///
/// 3. [%slot = getelementptr inbounds i8, i8* %typedmem, i64 <index>]
/// 3 is optional because if you are writing to the 0th index, you don't
/// need a GEP.
///
/// 4.1 store/load <memtype> <val>, <memtype>* %slot, align 8
/// 4.2 store/load <memtype> <val>, <memtype>* %mem, align 8
///
/// @see polly::MemoryAccess, polly::ScopArrayInfo
///
/// @note assumes -polly-canonicalize has been run.
///
/// @param Inst The LoadInst/StoreInst that accesses the memory.
///
/// @returns Reference to %untypedmem on success, nullptr on failure.
Value *findFADAllocationVisible(MemAccInst Inst);
// @}
// Build the SCoP for Region @p R.
void buildScop(Region &R, AssumptionCache &AC);
@ -417,9 +358,6 @@ class ScopBuilder {
/// all memory accesses have been modeled and canonicalized.
void assumeNoOutOfBounds();
/// Mark arrays that have memory accesses with FortranArrayDescriptor.
void markFortranArrays();
/// Build the alias checks for this SCoP.
bool buildAliasChecks();

View file

@ -264,16 +264,6 @@ public:
/// with old sizes
bool updateSizes(ArrayRef<const SCEV *> Sizes, bool CheckConsistency = true);
/// Make the ScopArrayInfo model a Fortran array.
/// It receives the Fortran array descriptor and stores this.
/// It also adds a piecewise expression for the outermost dimension
/// since this information is available for Fortran arrays at runtime.
void applyAndSetFAD(Value *FAD);
/// Get the FortranArrayDescriptor corresponding to this array if it exists,
/// nullptr otherwise.
Value *getFortranArrayDescriptor() const { return this->FAD; }
/// Set the base pointer to @p BP.
void setBasePtr(Value *BP) { BasePtr = BP; }
@ -440,10 +430,6 @@ private:
/// The scop this SAI object belongs to.
Scop &S;
/// If this array models a Fortran array, then this points
/// to the Fortran array descriptor.
Value *FAD = nullptr;
};
/// Represent memory accesses in statements.
@ -636,13 +622,6 @@ private:
/// Updated access relation read from JSCOP file.
isl::map NewAccessRelation;
/// Fortran arrays whose sizes are not statically known are stored in terms
/// of a descriptor struct. This maintains a raw pointer to the memory,
/// along with auxiliary fields with information such as dimensions.
/// We hold a reference to the descriptor corresponding to a MemoryAccess
/// into a Fortran array. FAD for "Fortran Array Descriptor"
AssertingVH<Value> FAD;
// @}
isl::basic_map createBasicAccessMap(ScopStmt *Statement);
@ -935,10 +914,6 @@ public:
/// the dimension of the innermost loop containing the statement.
isl::set getStride(isl::map Schedule) const;
/// Get the FortranArrayDescriptor corresponding to this memory access if
/// it exists, and nullptr otherwise.
Value *getFortranArrayDescriptor() const { return this->FAD; }
/// Is the stride of the access equal to a certain width? Schedule is a map
/// from the statement to a schedule where the innermost dimension is the
/// dimension of the innermost loop containing the statement.
@ -1061,10 +1036,6 @@ public:
/// Get the reduction type of this access
ReductionType getReductionType() const { return RedType; }
/// Set the array descriptor corresponding to the Array on which the
/// memory access is performed.
void setFortranArrayDescriptor(Value *FAD);
/// Update the original access relation.
///
/// We need to update the original access relation during scop construction,

View file

@ -129,11 +129,6 @@ static cl::opt<std::string> UserContextStr(
cl::desc("Provide additional constraints on the context parameters"),
cl::init(""), cl::cat(PollyCategory));
static cl::opt<bool> DetectFortranArrays(
"polly-detect-fortran-arrays",
cl::desc("Detect Fortran arrays and use this for code generation"),
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
static cl::opt<bool> DetectReductions("polly-detect-reductions",
cl::desc("Detect and exploit reductions"),
cl::Hidden, cl::ZeroOrMore,
@ -1333,189 +1328,6 @@ void ScopBuilder::buildEscapingDependences(Instruction *Inst) {
ensureValueWrite(Inst);
}
/// Check that a value is a Fortran Array descriptor.
///
/// We check if V has the following structure:
/// %"struct.array1_real(kind=8)" = type { i8*, i<zz>, i<zz>,
/// [<num> x %struct.descriptor_dimension] }
///
///
/// %struct.descriptor_dimension = type { i<zz>, i<zz>, i<zz> }
///
/// 1. V's type name starts with "struct.array"
/// 2. V's type has layout as shown.
/// 3. Final member of V's type has name "struct.descriptor_dimension",
/// 4. "struct.descriptor_dimension" has layout as shown.
/// 5. Consistent use of i<zz> where <zz> is some fixed integer number.
///
/// We are interested in such types since this is the code that dragonegg
/// generates for Fortran array descriptors.
///
/// @param V the Value to be checked.
///
/// @returns True if V is a Fortran array descriptor, False otherwise.
bool isFortranArrayDescriptor(Value *V) {
PointerType *PTy = dyn_cast<PointerType>(V->getType());
if (!PTy)
return false;
Type *Ty = PTy->getElementType();
assert(Ty && "Ty expected to be initialized");
auto *StructArrTy = dyn_cast<StructType>(Ty);
if (!(StructArrTy && StructArrTy->hasName()))
return false;
if (!StructArrTy->getName().startswith("struct.array"))
return false;
if (StructArrTy->getNumElements() != 4)
return false;
const ArrayRef<Type *> ArrMemberTys = StructArrTy->elements();
// i8* match
if (ArrMemberTys[0] != Type::getInt8PtrTy(V->getContext()))
return false;
// Get a reference to the int type and check that all the members
// share the same int type
Type *IntTy = ArrMemberTys[1];
if (ArrMemberTys[2] != IntTy)
return false;
// type: [<num> x %struct.descriptor_dimension]
ArrayType *DescriptorDimArrayTy = dyn_cast<ArrayType>(ArrMemberTys[3]);
if (!DescriptorDimArrayTy)
return false;
// type: %struct.descriptor_dimension := type { ixx, ixx, ixx }
StructType *DescriptorDimTy =
dyn_cast<StructType>(DescriptorDimArrayTy->getElementType());
if (!(DescriptorDimTy && DescriptorDimTy->hasName()))
return false;
if (DescriptorDimTy->getName() != "struct.descriptor_dimension")
return false;
if (DescriptorDimTy->getNumElements() != 3)
return false;
for (auto MemberTy : DescriptorDimTy->elements()) {
if (MemberTy != IntTy)
return false;
}
return true;
}
Value *ScopBuilder::findFADAllocationVisible(MemAccInst Inst) {
// match: 4.1 & 4.2 store/load
if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
return nullptr;
// match: 4
if (Inst.getAlignment() != 8)
return nullptr;
Value *Address = Inst.getPointerOperand();
const BitCastInst *Bitcast = nullptr;
// [match: 3]
if (auto *Slot = dyn_cast<GetElementPtrInst>(Address)) {
Value *TypedMem = Slot->getPointerOperand();
// match: 2
Bitcast = dyn_cast<BitCastInst>(TypedMem);
} else {
// match: 2
Bitcast = dyn_cast<BitCastInst>(Address);
}
if (!Bitcast)
return nullptr;
auto *MallocMem = Bitcast->getOperand(0);
// match: 1
auto *MallocCall = dyn_cast<CallInst>(MallocMem);
if (!MallocCall)
return nullptr;
Function *MallocFn = MallocCall->getCalledFunction();
if (!(MallocFn && MallocFn->hasName() && MallocFn->getName() == "malloc"))
return nullptr;
// Find all uses the malloc'd memory.
// We are looking for a "store" into a struct with the type being the Fortran
// descriptor type
for (auto user : MallocMem->users()) {
/// match: 5
auto *MallocStore = dyn_cast<StoreInst>(user);
if (!MallocStore)
continue;
auto *DescriptorGEP =
dyn_cast<GEPOperator>(MallocStore->getPointerOperand());
if (!DescriptorGEP)
continue;
// match: 5
auto DescriptorType =
dyn_cast<StructType>(DescriptorGEP->getSourceElementType());
if (!(DescriptorType && DescriptorType->hasName()))
continue;
Value *Descriptor = dyn_cast<Value>(DescriptorGEP->getPointerOperand());
if (!Descriptor)
continue;
if (!isFortranArrayDescriptor(Descriptor))
continue;
return Descriptor;
}
return nullptr;
}
Value *ScopBuilder::findFADAllocationInvisible(MemAccInst Inst) {
// match: 3
if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
return nullptr;
Value *Slot = Inst.getPointerOperand();
LoadInst *MemLoad = nullptr;
// [match: 2]
if (auto *SlotGEP = dyn_cast<GetElementPtrInst>(Slot)) {
// match: 1
MemLoad = dyn_cast<LoadInst>(SlotGEP->getPointerOperand());
} else {
// match: 1
MemLoad = dyn_cast<LoadInst>(Slot);
}
if (!MemLoad)
return nullptr;
auto *BitcastOperator =
dyn_cast<BitCastOperator>(MemLoad->getPointerOperand());
if (!BitcastOperator)
return nullptr;
Value *Descriptor = dyn_cast<Value>(BitcastOperator->getOperand(0));
if (!Descriptor)
return nullptr;
if (!isFortranArrayDescriptor(Descriptor))
return nullptr;
return Descriptor;
}
void ScopBuilder::addRecordedAssumptions() {
for (auto &AS : llvm::reverse(RecordedAssumptions)) {
@ -2350,17 +2162,8 @@ void ScopBuilder::addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst,
ArrayRef<const SCEV *> Sizes,
Value *AccessValue) {
ArrayBasePointers.insert(BaseAddress);
auto *MemAccess = addMemoryAccess(Stmt, MemAccInst, AccType, BaseAddress,
ElementType, IsAffine, AccessValue,
Subscripts, Sizes, MemoryKind::Array);
if (!DetectFortranArrays)
return;
if (Value *FAD = findFADAllocationInvisible(MemAccInst))
MemAccess->setFortranArrayDescriptor(FAD);
else if (Value *FAD = findFADAllocationVisible(MemAccInst))
MemAccess->setFortranArrayDescriptor(FAD);
addMemoryAccess(Stmt, MemAccInst, AccType, BaseAddress, ElementType, IsAffine,
AccessValue, Subscripts, Sizes, MemoryKind::Array);
}
/// Check if @p Expr is divisible by @p Size.
@ -2490,29 +2293,11 @@ void ScopBuilder::foldSizeConstantsToRight() {
}
}
void ScopBuilder::markFortranArrays() {
for (ScopStmt &Stmt : *scop) {
for (MemoryAccess *MemAcc : Stmt) {
Value *FAD = MemAcc->getFortranArrayDescriptor();
if (!FAD)
continue;
// TODO: const_cast-ing to edit
ScopArrayInfo *SAI =
const_cast<ScopArrayInfo *>(MemAcc->getLatestScopArrayInfo());
assert(SAI && "memory access into a Fortran array does not "
"have an associated ScopArrayInfo");
SAI->applyAndSetFAD(FAD);
}
}
}
void ScopBuilder::finalizeAccesses() {
updateAccessDimensionality();
foldSizeConstantsToRight();
foldAccessRelations();
assumeNoOutOfBounds();
markFortranArrays();
}
void ScopBuilder::updateAccessDimensionality() {

View file

@ -298,32 +298,6 @@ void ScopArrayInfo::updateElementType(Type *NewElementType) {
}
}
/// Make the ScopArrayInfo model a Fortran Array
void ScopArrayInfo::applyAndSetFAD(Value *FAD) {
assert(FAD && "got invalid Fortran array descriptor");
if (this->FAD) {
assert(this->FAD == FAD &&
"receiving different array descriptors for same array");
return;
}
assert(DimensionSizesPw.size() > 0 && DimensionSizesPw[0].is_null());
assert(!this->FAD);
this->FAD = FAD;
isl::space Space(S.getIslCtx(), 1, 0);
std::string param_name = getName();
param_name += "_fortranarr_size";
isl::id IdPwAff = isl::id::alloc(S.getIslCtx(), param_name, this);
Space = Space.set_dim_id(isl::dim::param, 0, IdPwAff);
isl::pw_aff PwAff =
isl::aff::var_on_domain(isl::local_space(Space), isl::dim::param, 0);
DimensionSizesPw[0] = PwAff;
}
bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes,
bool CheckConsistency) {
int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
@ -372,12 +346,8 @@ LLVM_DUMP_METHOD void ScopArrayInfo::dump() const { print(errs()); }
void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const {
OS.indent(8) << *getElementType() << " " << getName();
unsigned u = 0;
// If this is a Fortran array, then we can print the outermost dimension
// as a isl_pw_aff even though there is no SCEV information.
bool IsOutermostSizeKnown = SizeAsPwAff && FAD;
if (!IsOutermostSizeKnown && getNumberOfDimensions() > 0 &&
!getDimensionSize(0)) {
if (getNumberOfDimensions() > 0 && !getDimensionSize(0)) {
OS << "[*]";
u++;
}
@ -894,7 +864,7 @@ MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst),
AccessValue(AccessValue), IsAffine(Affine),
Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(),
NewAccessRelation(), FAD(nullptr) {
NewAccessRelation() {
static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
const std::string Access = TypeStrings[AccType] + utostr(Stmt->size());
@ -904,8 +874,7 @@ MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
MemoryAccess::MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel)
: Kind(MemoryKind::Array), AccType(AccType), Statement(Stmt),
InvalidDomain(), AccessRelation(), NewAccessRelation(AccRel),
FAD(nullptr) {
InvalidDomain(), AccessRelation(), NewAccessRelation(AccRel) {
isl::id ArrayInfoId = NewAccessRelation.get_tuple_id(isl::dim::out);
auto *SAI = ScopArrayInfo::getFromId(ArrayInfoId);
Sizes.push_back(nullptr);
@ -949,8 +918,6 @@ raw_ostream &polly::operator<<(raw_ostream &OS,
return OS;
}
void MemoryAccess::setFortranArrayDescriptor(Value *FAD) { this->FAD = FAD; }
void MemoryAccess::print(raw_ostream &OS) const {
switch (AccType) {
case READ:
@ -966,11 +933,6 @@ void MemoryAccess::print(raw_ostream &OS) const {
OS << "[Reduction Type: " << getReductionType() << "] ";
if (FAD) {
OS << "[Fortran array descriptor: " << FAD->getName();
OS << "] ";
};
OS << "[Scalar: " << isScalarKind() << "]\n";
OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
if (hasNewAccessRelation())
@ -1539,41 +1501,6 @@ void Scop::addParameterBounds() {
intersectDefinedBehavior(Context, AS_ASSUMPTION);
}
static std::vector<isl::id> getFortranArrayIds(Scop::array_range Arrays) {
std::vector<isl::id> OutermostSizeIds;
for (auto Array : Arrays) {
// To check if an array is a Fortran array, we check if it has a isl_pw_aff
// for its outermost dimension. Fortran arrays will have this since the
// outermost dimension size can be picked up from their runtime description.
// TODO: actually need to check if it has a FAD, but for now this works.
if (Array->getNumberOfDimensions() > 0) {
isl::pw_aff PwAff = Array->getDimensionSizePw(0);
if (PwAff.is_null())
continue;
isl::id Id = PwAff.get_dim_id(isl::dim::param, 0);
assert(!Id.is_null() &&
"Invalid Id for PwAff expression in Fortran array");
OutermostSizeIds.push_back(Id);
}
}
return OutermostSizeIds;
}
// The FORTRAN array size parameters are known to be non-negative.
static isl::set boundFortranArrayParams(isl::set Context,
Scop::array_range Arrays) {
std::vector<isl::id> OutermostSizeIds;
OutermostSizeIds = getFortranArrayIds(Arrays);
for (isl::id Id : OutermostSizeIds) {
int dim = Context.find_dim_by_id(isl::dim::param, Id);
Context = Context.lower_bound_si(isl::dim::param, dim, 0);
}
return Context;
}
void Scop::realignParams() {
if (PollyIgnoreParamBounds)
return;
@ -1586,9 +1513,6 @@ void Scop::realignParams() {
AssumedContext = AssumedContext.align_params(Space);
InvalidContext = InvalidContext.align_params(Space);
// Bound the size of the fortran array dimensions.
Context = boundFortranArrayParams(Context, arrays());
// As all parameters are known add bounds to them.
addParameterBounds();
@ -1901,11 +1825,8 @@ isl::set Scop::getContext() const { return Context; }
isl::space Scop::getParamSpace() const { return getContext().get_space(); }
isl::space Scop::getFullParamSpace() const {
std::vector<isl::id> FortranIDs;
FortranIDs = getFortranArrayIds(arrays());
isl::space Space = isl::space::params_alloc(
getIslCtx(), ParameterIds.size() + FortranIDs.size());
isl::space Space = isl::space::params_alloc(getIslCtx(), ParameterIds.size());
unsigned PDim = 0;
for (const SCEV *Parameter : Parameters) {
@ -1913,9 +1834,6 @@ isl::space Scop::getFullParamSpace() const {
Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
}
for (isl::id Id : FortranIDs)
Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
return Space;
}

View file

@ -97,7 +97,6 @@ add_llvm_pass_plugin(Polly
Transform/ZoneAlgo.cpp
Transform/Simplify.cpp
Transform/MaximalStaticExpansion.cpp
Transform/RewriteByReferenceParameters.cpp
Transform/ScopInliner.cpp
Transform/ManualOptimizer.cpp
Transform/MatmulOptimizer.cpp

View file

@ -1160,84 +1160,6 @@ bool IslNodeBuilder::materializeParameters() {
return true;
}
/// Generate the computation of the size of the outermost dimension from the
/// Fortran array descriptor (in this case, `@g_arr`). The final `%size`
/// contains the size of the array.
///
/// %arrty = type { i8*, i64, i64, [3 x %desc.dimensionty] }
/// %desc.dimensionty = type { i64, i64, i64 }
/// @g_arr = global %arrty zeroinitializer, align 32
/// ...
/// %0 = load i64, i64* getelementptr inbounds
/// (%arrty, %arrty* @g_arr, i64 0, i32 3, i64 0, i32 2)
/// %1 = load i64, i64* getelementptr inbounds
/// (%arrty, %arrty* @g_arr, i64 0, i32 3, i64 0, i32 1)
/// %2 = sub nsw i64 %0, %1
/// %size = add nsw i64 %2, 1
static Value *buildFADOutermostDimensionLoad(Value *GlobalDescriptor,
PollyIRBuilder &Builder,
std::string ArrayName) {
assert(GlobalDescriptor && "invalid global descriptor given");
Type *Ty = GlobalDescriptor->getType()->getPointerElementType();
Value *endIdx[4] = {Builder.getInt64(0), Builder.getInt32(3),
Builder.getInt64(0), Builder.getInt32(2)};
Value *endPtr = Builder.CreateInBoundsGEP(Ty, GlobalDescriptor, endIdx,
ArrayName + "_end_ptr");
Type *type = cast<GEPOperator>(endPtr)->getResultElementType();
assert(isa<IntegerType>(type) && "expected type of end to be integral");
Value *end = Builder.CreateLoad(type, endPtr, ArrayName + "_end");
Value *beginIdx[4] = {Builder.getInt64(0), Builder.getInt32(3),
Builder.getInt64(0), Builder.getInt32(1)};
Value *beginPtr = Builder.CreateInBoundsGEP(Ty, GlobalDescriptor, beginIdx,
ArrayName + "_begin_ptr");
Value *begin = Builder.CreateLoad(type, beginPtr, ArrayName + "_begin");
Value *size =
Builder.CreateNSWSub(end, begin, ArrayName + "_end_begin_delta");
size = Builder.CreateNSWAdd(
end, ConstantInt::get(type, 1, /* signed = */ true), ArrayName + "_size");
return size;
}
bool IslNodeBuilder::materializeFortranArrayOutermostDimension() {
for (ScopArrayInfo *Array : S.arrays()) {
if (Array->getNumberOfDimensions() == 0)
continue;
Value *FAD = Array->getFortranArrayDescriptor();
if (!FAD)
continue;
isl_pw_aff *ParametricPwAff = Array->getDimensionSizePw(0).release();
assert(ParametricPwAff && "parametric pw_aff corresponding "
"to outermost dimension does not "
"exist");
isl_id *Id = isl_pw_aff_get_dim_id(ParametricPwAff, isl_dim_param, 0);
isl_pw_aff_free(ParametricPwAff);
assert(Id && "pw_aff is not parametric");
if (IDToValue.count(Id)) {
isl_id_free(Id);
continue;
}
Value *FinalValue =
buildFADOutermostDimensionLoad(FAD, Builder, Array->getName());
assert(FinalValue && "unable to build Fortran array "
"descriptor load of outermost dimension");
IDToValue[Id] = FinalValue;
isl_id_free(Id);
}
return true;
}
Value *IslNodeBuilder::preloadUnconditionally(isl_set *AccessRange,
isl_ast_build *Build,
Instruction *AccInst) {
@ -1569,12 +1491,6 @@ void IslNodeBuilder::addParameters(__isl_take isl_set *Context) {
// Materialize values for the parameters of the SCoP.
materializeParameters();
// materialize the outermost dimension parameters for a Fortran array.
// NOTE: materializeParameters() does not work since it looks through
// the SCEVs. We don't have a corresponding SCEV for the array size
// parameter
materializeFortranArrayOutermostDimension();
// Generate values for the current loop iteration for all surrounding loops.
//
// We may also reference loops outside of the scop which do not contain the

View file

@ -264,7 +264,6 @@ void initializePollyPasses(PassRegistry &Registry) {
initializeScopInlinerPass(Registry);
initializeScopInfoRegionPassPass(Registry);
initializeScopInfoWrapperPassPass(Registry);
initializeRewriteByrefParamsWrapperPassPass(Registry);
initializeCodegenCleanupPass(Registry);
initializeFlattenSchedulePass(Registry);
initializeForwardOpTreeWrapperPassPass(Registry);

View file

@ -15,7 +15,6 @@
#include "polly/Canonicalization.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/RewriteByReferenceParameters.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/IR/LegacyPassManager.h"
@ -42,7 +41,6 @@ static cl::opt<bool>
void polly::registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM) {
bool UseMemSSA = true;
PM.add(polly::createRewriteByrefParamsWrapperPass());
PM.add(llvm::createPromoteMemoryToRegisterPass());
PM.add(llvm::createEarlyCSEPass(UseMemSSA));
PM.add(llvm::createInstructionCombiningPass());
@ -98,7 +96,6 @@ polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM,
FunctionPassManager FPM;
bool UseMemSSA = true;
FPM.addPass(RewriteByrefParamsPass());
FPM.addPass(PromotePass());
FPM.addPass(EarlyCSEPass(UseMemSSA));
FPM.addPass(InstCombinePass());

View file

@ -1,112 +0,0 @@
//===------ RewriteByReferenceParameters.cpp --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass introduces separate 'alloca' instructions for read-only
// by-reference function parameters to indicate that these paramters are
// read-only. After this transformation -mem2reg has more freedom to promote
// variables to registers, which allows SCEV to work in more cases.
//
//===----------------------------------------------------------------------===//
#include "polly/RewriteByReferenceParameters.h"
#include "polly/LinkAllPasses.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#define DEBUG_TYPE "polly-rewrite-byref-params"
using namespace llvm;
namespace {
static void tryRewriteInstruction(Instruction &Inst) {
BasicBlock *Entry = &Inst.getParent()->getParent()->getEntryBlock();
auto *Call = dyn_cast<CallInst>(&Inst);
if (!Call)
return;
llvm::Function *F = Call->getCalledFunction();
if (!F)
return;
// We currently match for a very specific function. In case this proves
// useful, we can make this code dependent on readonly metadata.
if (!F->hasName() || F->getName() != "_gfortran_transfer_integer_write")
return;
auto *BitCast = dyn_cast<BitCastInst>(Call->getOperand(1));
if (!BitCast)
return;
auto *Alloca = dyn_cast<AllocaInst>(BitCast->getOperand(0));
if (!Alloca)
return;
std::string InstName = Alloca->getName().str();
auto NewAlloca =
new AllocaInst(Alloca->getAllocatedType(), 0,
"polly_byref_alloca_" + InstName, &*Entry->begin());
auto *LoadedVal = new LoadInst(Alloca->getAllocatedType(), Alloca,
"polly_byref_load_" + InstName, &Inst);
new StoreInst(LoadedVal, NewAlloca, &Inst);
auto *NewBitCast = new BitCastInst(NewAlloca, BitCast->getType(),
"polly_byref_cast_" + InstName, &Inst);
Call->setOperand(1, NewBitCast);
}
static void runRewriteByrefParams(Function &F) {
for (BasicBlock &BB : F)
for (Instruction &Inst : BB)
tryRewriteInstruction(Inst);
}
class RewriteByrefParamsWrapperPass : public FunctionPass {
private:
RewriteByrefParamsWrapperPass(const RewriteByrefParamsWrapperPass &) = delete;
const RewriteByrefParamsWrapperPass &
operator=(const RewriteByrefParamsWrapperPass &) = delete;
public:
static char ID;
explicit RewriteByrefParamsWrapperPass() : FunctionPass(ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const override {}
virtual bool runOnFunction(Function &F) override {
runRewriteByrefParams(F);
return true;
}
};
char RewriteByrefParamsWrapperPass::ID;
} // anonymous namespace
Pass *polly::createRewriteByrefParamsWrapperPass() {
return new RewriteByrefParamsWrapperPass();
}
llvm::PreservedAnalyses
polly ::RewriteByrefParamsPass::run(llvm::Function &F,
llvm::FunctionAnalysisManager &FAM) {
runRewriteByrefParams(F);
return PreservedAnalyses::none();
}
INITIALIZE_PASS_BEGIN(RewriteByrefParamsWrapperPass,
"polly-rewrite-byref-params",
"Polly - Rewrite by reference parameters", false, false)
INITIALIZE_PASS_END(RewriteByrefParamsWrapperPass, "polly-rewrite-byref-params",
"Polly - Rewrite by reference parameters", false, false)

View file

@ -1,77 +0,0 @@
; Check that the runtime size computation is generated for Fortran arrays.
; Regular code generation backend:
; RUN: opt %loadPolly -S -polly-detect-fortran-arrays \
; RUN: -polly-codegen < %s | FileCheck %s
; What the input fortran code should look like. NOTE: this is fake, the
; .ll file was hand-written.
;
; MODULE testmod
; USE data_parameters, ONLY : &
; IMPLICIT NONE
;
; INTEGER (KIND=iintegers), ALLOCATABLE, PRIVATE :: &
; arrin(:), arrout(:)
; CONTAINS
;
; SUBROUTINE test()
; INTEGER (KIND=iintegers) :: i
;
; DO i = 1, 100
; arrout(i) = arrin(i) * arrin(i)
; END DO
; END SUBROUTINE test
; END MODULE testmod
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i32:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_real(kind=8)" = type { i8*, i32, i32, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i32, i32, i32 }
@arrin = unnamed_addr global %"struct.array1_real(kind=8)" zeroinitializer, align 32
@arrout = unnamed_addr global %"struct.array1_real(kind=8)" zeroinitializer, align 32
; Function Attrs: nounwind uwtable
define void @__src_soil_MOD_terra1() unnamed_addr #0 {
entry:
br label %entry.split
entry.split: ; preds = %entry
%rawmemin1 = load i32*, i32** bitcast (%"struct.array1_real(kind=8)"* @arrin to i32**), align 32, !tbaa !0
%rawmemout2 = load i32*, i32** bitcast (%"struct.array1_real(kind=8)"* @arrout to i32**), align 32, !tbaa !0
br label %for.body
for.body: ; preds = %entry.split, %for.body
%indvars.iv = phi i64 [ 1, %entry.split ], [ %indvars.iv.next4, %for.body ]
%inslot = getelementptr inbounds i32, i32* %rawmemin1, i64 %indvars.iv
%inval = load i32, i32* %inslot, align 8
%outslot = getelementptr inbounds i32, i32* %rawmemout2, i64 %indvars.iv
%out = mul nsw i32 %inval, %inval
store i32 %out, i32* %outslot, align 8
%indvars.iv.next4 = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next4, 100
br i1 %exitcond, label %return, label %for.body
return: ; preds = %for.body
ret void
}
attributes #0 = { nounwind uwtable }
!0 = !{!1, !1, i32 0}
!1 = !{!"alias set 3: void*", !2}
!2 = distinct !{!2}
; CHECK: %MemRef_rawmemin1_end = load i32, i32* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @arrin, i64 0, i32 3, i64 0, i32 2)
; CHECK-NEXT: %MemRef_rawmemin1_begin = load i32, i32* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @arrin, i64 0, i32 3, i64 0, i32 1)
; CHECK-NEXT: %MemRef_rawmemin1_end_begin_delta = sub nsw i32 %MemRef_rawmemin1_end, %MemRef_rawmemin1_begin
; CHECK-NEXT: %MemRef_rawmemin1_size = add nsw i32 %MemRef_rawmemin1_end, 1
; CHECK-NEXT: %MemRef_rawmemout2_end = load i32, i32* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @arrout, i64 0, i32 3, i64 0, i32 2)
; CHECK-NEXT: %MemRef_rawmemout2_begin = load i32, i32* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @arrout, i64 0, i32 3, i64 0, i32 1)
; CHECK-NEXT: %MemRef_rawmemout2_end_begin_delta = sub nsw i32 %MemRef_rawmemout2_end, %MemRef_rawmemout2_begin
; CHECK-NEXT: %MemRef_rawmemout2_size = add nsw i32 %MemRef_rawmemout2_end, 1

View file

@ -1,103 +0,0 @@
; RUN: opt %loadPolly -analyze -polly-scops \
; RUN: -polly-detect-fortran-arrays \
; RUN: -polly-invariant-load-hoisting \
; RUN: -polly-use-llvm-names \
; RUN: -polly-stmt-granularity=bb \
; RUN: < %s | FileCheck %s --check-prefix=SCOP
; RUN: opt %loadPolly -S \
; RUN: -polly-detect-fortran-arrays \
; RUN: -polly-codegen-ppcg \
; RUN: -polly-invariant-load-hoisting \
; RUN: -polly-use-llvm-names \
; RUN: -polly-acc-fail-on-verify-module-failure \
; RUN: < %s | FileCheck %s --check-prefix=HOST-IR
; REQUIRES: pollyacc
; In Polly, we specifically add a parameter to represent the outermost dimension
; size of fortran arrays. We do this because this information is statically
; available from the fortran metadata generated by dragonegg.
; However, we were only materializing these parameters (meaning, creating an
; llvm::Value to back the isl_id) from *memory accesses*. This is wrong,
; we should materialize parameters from *scop array info*.
; It is wrong because if there is a case where we detect 2 fortran arrays,
; but only one of them is accessed, we may not materialize the other array's
; dimensions at all.
; This test case checks that we do not fail if there is an array that does
; not have an access (In this case, `memory`), we still generate the
; parameter.
; Check that we detect the function as a Scop.
; SCOP: Function: f
; SCOP-NEXT: Region: %loop.prepare---%for.exit
; SCOP-NEXT: Max Loop Depth: 1
; Check that we detect fortran arrays.
; SCOP: Arrays (Bounds as pw_affs) {
; SCOP: double* MemRef_global_arr[*]; // Element size 8
; SCOP-NEXT: double MemRef_memory[ [MemRef_memory_fortranarr_size] -> { [] -> [(MemRef_memory_fortranarr_size)] } ]; [BasePtrOrigin: MemRef_global_arr] // Element size 8
; SCOP-NEXT: double MemRef_memory2[ [MemRef_memory2_fortranarr_size] -> { [] -> [(MemRef_memory2_fortranarr_size)] } ]; [BasePtrOrigin: MemRef_global_arr] // Element size 8
; SCOP-NEXT: }
; Check that we have writes *only* into memory2, not into memory.
; SCOP: Statements {
; SCOP: Stmt_for_body
; SCOP: MustWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: global_arr] [Scalar: 0]
; SCOP-NEXT: [start_val, end_val, offset, MemRef_memory_fortranarr_size, MemRef_memory2_fortranarr_size] -> { Stmt_for_body[i0] -> MemRef_memory2[start_val + offset + i0] };
; SCOP-NEXT: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: global_arr] [Scalar: 0]
; SCOP-NEXT: [start_val, end_val, offset, MemRef_memory_fortranarr_size, MemRef_memory2_fortranarr_size] -> { Stmt_for_body[i0] -> MemRef_memory2[start_val + offset + i0] };
; SCOP-NEXT: }
; Check that we materialize the sizes and send it across to the kernel.
; HOST-IR: store i64 %MemRef_memory_size, i64* %polly_launch_0_param_4
; HOST-IR: store i64 %MemRef_memory2_size, i64* %polly_launch_0_param_5
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_real(kind=8)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i64, i64, i64 }
@global_arr = external unnamed_addr global %"struct.array1_real(kind=8)", align 32
; Function Attrs: nounwind uwtable
define void @f(i32* noalias %ipstart, i32* noalias %ipend) unnamed_addr #0 {
entry:
br label %loop.prepare
loop.prepare: ; preds = %"6", %"3.preheader"
%start.val = load i32, i32* %ipstart, align 4
%end.val = load i32, i32* %ipend, align 4
%should.loop = icmp sgt i32 %start.val, %end.val
br i1 %should.loop, label %for.exit, label %for.body
for.body: ; preds = %for.body, %"4.preheader"
%i = phi i32 [ %i.next, %for.body ], [ %start.val, %loop.prepare ]
%i.sext = sext i32 %i to i64
%memory = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @global_arr to double**), align 32
%offset = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @global_arr, i64 0, i32 1), align 8
%idx = add i64 %offset, %i.sext
%slot = getelementptr double, double* %memory, i64 %idx
store double 1.0, double* %slot, align 8
%memory2 = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @global_arr to double**), align 32
%offset2 = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @global_arr, i64 0, i32 1), align 8
%idx2 = add i64 %offset2, %i.sext
%slot2 = getelementptr double, double* %memory2, i64 %idx2
%val = load double, double* %slot2, align 8
%should.loopexit = icmp eq i32 %i, %end.val
%i.next = add i32 %i, 1
br i1 %should.loopexit, label %for.exit, label %for.body
for.exit: ; preds = %for.body
ret void
}
attributes #0 = { nounwind uwtable }

View file

@ -1,40 +0,0 @@
; RUN: opt %loadPolly -polly-rewrite-byref-params -S < %s \
; RUN: | FileCheck %s
; Verify that we rewrite the read-only by-reference into a separate alloca slot.
; This is useful in case %j3 is an induction variable, which should be promoted
; by -mem2reg into a register.
; CHECK: define void @foo(%struct.__st_parameter_dt* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %polly_byref_alloca_j3 = alloca i32
; CHECK-NEXT: %j3 = alloca i32, align 4
; CHECK-NEXT: %tmp = bitcast i32* %j3 to i8*
; CHECK-NEXT: br label %bb
; CHECK: bb: ; preds = %entry
; CHECK-NEXT: %polly_byref_load_j3 = load i32, i32* %j3
; CHECK-NEXT: store i32 %polly_byref_load_j3, i32* %polly_byref_alloca_j3
; CHECK-NEXT: %polly_byref_cast_j3 = bitcast i32* %polly_byref_alloca_j3 to i8*
; CHECK-NEXT: call void @_gfortran_transfer_integer_write(%struct.__st_parameter_dt* %p, i8* %polly_byref_cast_j3, i32 4)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
%struct.__st_parameter_dt = type { }
declare void @_gfortran_transfer_integer_write(%struct.__st_parameter_dt*, i8*, i32)
define void @foo(%struct.__st_parameter_dt* %p) {
entry:
%j3 = alloca i32, align 4
%tmp = bitcast i32* %j3 to i8*
br label %bb
bb:
call void @_gfortran_transfer_integer_write(%struct.__st_parameter_dt* %p, i8* %tmp, i32 4)
ret void
}

View file

@ -1,116 +0,0 @@
; RUN: opt %loadPolly -analyze -S -polly-detect-fortran-arrays \
; RUN: -polly-process-unprofitable -polly-scops < %s | FileCheck %s
; MODULE src_soil
; USE data_parameters, ONLY : &
; wp, & ! KIND-type parameter for real variables
; iintegers ! KIND-type parameter for standard integer variables
; IMPLICIT NONE
; REAL (KIND = wp), ALLOCATABLE, PRIVATE :: &
; xdzs (:)
; CONTAINS
; SUBROUTINE terra1(n)
; INTEGER, intent(in) :: n
; INTEGER (KIND=iintegers) :: &
; j
; Allocate(xdzs(n));
; DO j = 2, n
; xdzs(j) = xdzs(j) * xdzs(j) + xdzs(j - 1)
; END DO
; END SUBROUTINE terra1
; END MODULE src_soil
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_real(kind=8)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i64, i64, i64 }
@__src_soil_MOD_xdzs = unnamed_addr global %"struct.array1_real(kind=8)" zeroinitializer, align 32
@.cst = private unnamed_addr constant [67 x i8] c"Integer overflow when calculating the amount of memory to allocate\00", align 64
@.cst1 = private unnamed_addr constant [37 x i8] c"Allocation would exceed memory limit\00", align 64
@.cst2 = private unnamed_addr constant [93 x i8] c"At line 23 of file /home/siddhart/cosmo-self-installation/cosmo-pompa/cosmo/src/src_soil.f90\00", align 64
@.cst3 = private unnamed_addr constant [55 x i8] c"Attempting to allocate already allocated variable '%s'\00", align 64
@.cst4 = private unnamed_addr constant [5 x i8] c"xdzs\00", align 8
; Function Attrs: nounwind uwtable
define void @__src_soil_MOD_terra1(i32* noalias nocapture %n) unnamed_addr #0 {
entry:
br label %entry.split
entry.split: ; preds = %entry
store i64 537, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 2), align 16, !tbaa !0
store i64 1, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 3, i64 0, i32 1), align 8, !tbaa !0
%tmp = load i32, i32* %n, align 4, !tbaa !3
%tmp1 = sext i32 %tmp to i64
store i64 %tmp1, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 3, i64 0, i32 2), align 8, !tbaa !0
store i64 1, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 3, i64 0, i32 0), align 8, !tbaa !0
%tmp2 = icmp slt i32 %tmp, 1
%tmp3 = zext i32 %tmp to i64
%tmp4 = shl nuw nsw i64 %tmp3, 3
%.24 = select i1 %tmp2, i64 0, i64 %tmp4
%tmp5 = icmp ne i64 %.24, 0
%tmp6 = select i1 %tmp5, i64 %.24, i64 1
%tmp7 = tail call noalias i8* @malloc(i64 %tmp6) #2
store i8* %tmp7, i8** getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 0), align 32, !tbaa !5
store i64 -1, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 1), align 8, !tbaa !0
%tmp8 = icmp sgt i32 %tmp, 1
br i1 %tmp8, label %"21.preheader", label %return
"21.preheader": ; preds = %entry.split
%tmp9 = bitcast i8* %tmp7 to double*
%tmp10 = add i32 %tmp, 1
br label %"21"
"21": ; preds = %"21", %"21.preheader"
%tmp11 = phi double [ undef, %"21.preheader" ], [ %tmp16, %"21" ]
%indvars.iv = phi i64 [ 2, %"21.preheader" ], [ %indvars.iv.next, %"21" ]
%tmp12 = add nsw i64 %indvars.iv, -1
%tmp13 = getelementptr inbounds double, double* %tmp9, i64 %tmp12
%tmp14 = load double, double* %tmp13, align 8, !tbaa !7
%tmp15 = fmul double %tmp14, %tmp14
%tmp16 = fadd double %tmp11, %tmp15
store double %tmp16, double* %tmp13, align 8, !tbaa !7
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
%exitcond2 = icmp eq i32 %lftr.wideiv1, %tmp10
br i1 %exitcond2, label %return.loopexit, label %"21"
return.loopexit: ; preds = %"21"
br label %return
return: ; preds = %return.loopexit, %entry.split
ret void
}
; Function Attrs: noreturn
declare void @_gfortran_runtime_error(i8*, ...) #1
; Function Attrs: nounwind
declare noalias i8* @malloc(i64) #2
; Function Attrs: noreturn
declare void @_gfortran_os_error(i8*) #1
; Function Attrs: noreturn
declare void @_gfortran_runtime_error_at(i8*, i8*, ...) #1
attributes #0 = { nounwind uwtable }
attributes #1 = { noreturn }
attributes #2 = { nounwind }
!0 = !{!1, !1, i64 0}
!1 = !{!"alias set 4: integer(kind=8)", !2}
!2 = distinct !{!2}
!3 = !{!4, !4, i64 0}
!4 = !{!"alias set 11: integer(kind=4)", !2}
!5 = !{!6, !6, i64 0}
!6 = !{!"alias set 3: void*", !2}
!7 = !{!8, !8, i64 0}
!8 = !{!"alias set 18: real(kind=8)", !2}
; CHECK: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: __src_soil_MOD_xdzs] [Scalar: 0]
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: __src_soil_MOD_xdzs] [Scalar: 0]

View file

@ -1,89 +0,0 @@
; RUN: opt %loadPolly -analyze -S -polly-detect-fortran-arrays \
; RUN: -polly-process-unprofitable -polly-scops < %s | FileCheck %s
; MODULE src_soil
; USE data_parameters, ONLY : &
; wp, & ! KIND-type parameter for real variables
; iintegers ! KIND-type parameter for standard integer variables
; IMPLICIT NONE
; REAL (KIND = wp), ALLOCATABLE, PRIVATE :: &
; xdzs (:)
; CONTAINS
;
; SUBROUTINE terra1(n)
; INTEGER, intent(in) :: n
;
; INTEGER (KIND=iintegers) :: &
; j
;
; DO j = 22, n
; xdzs(j) = xdzs(j) * xdzs(j) + xdzs(j - 1)
; END DO
; END SUBROUTINE terra1
; END MODULE src_soil
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_real(kind=8)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i64, i64, i64 }
@__src_soil_MOD_xdzs = unnamed_addr global %"struct.array1_real(kind=8)" zeroinitializer, align 32
; Function Attrs: nounwind uwtable
define void @__src_soil_MOD_terra1(i32* noalias nocapture %n) unnamed_addr #0 {
entry:
br label %entry.split
entry.split: ; preds = %entry
%tmp = load i32, i32* %n, align 4, !tbaa !0
%tmp1 = icmp sgt i32 %tmp, 21
br i1 %tmp1, label %"3.preheader", label %return
"3.preheader": ; preds = %entry.split
%tmp2 = load i64, i64* getelementptr inbounds (%"struct.array1_real(kind=8)", %"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs, i64 0, i32 1), align 8, !tbaa !3
%tmp3 = load double*, double** bitcast (%"struct.array1_real(kind=8)"* @__src_soil_MOD_xdzs to double**), align 32, !tbaa !5
%tmp4 = add i32 %tmp, 1
br label %"3"
"3": ; preds = %"3", %"3.preheader"
%indvars.iv = phi i64 [ 22, %"3.preheader" ], [ %indvars.iv.next, %"3" ]
%tmp5 = add nsw i64 %indvars.iv, %tmp2
%tmp6 = getelementptr inbounds double, double* %tmp3, i64 %tmp5
%tmp7 = load double, double* %tmp6, align 8, !tbaa !7
%tmp8 = fmul double %tmp7, %tmp7
%tmp9 = add i64 %tmp2, -1
%tmp10 = add i64 %tmp9, %indvars.iv
%tmp11 = getelementptr inbounds double, double* %tmp3, i64 %tmp10
%tmp12 = load double, double* %tmp11, align 8, !tbaa !7
%tmp13 = fadd double %tmp8, %tmp12
store double %tmp13, double* %tmp6, align 8, !tbaa !7
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
%exitcond2 = icmp eq i32 %lftr.wideiv1, %tmp4
br i1 %exitcond2, label %return.loopexit, label %"3"
return.loopexit: ; preds = %"3"
br label %return
return: ; preds = %return.loopexit, %entry.split
ret void
}
attributes #0 = { nounwind uwtable }
!0 = !{!1, !1, i64 0}
!1 = !{!"alias set 11: integer(kind=4)", !2}
!2 = distinct !{!2}
!3 = !{!4, !4, i64 0}
!4 = !{!"alias set 4: integer(kind=8)", !2}
!5 = !{!6, !6, i64 0}
!6 = !{!"alias set 3: void*", !2}
!7 = !{!8, !8, i64 0}
!8 = !{!"alias set 18: real(kind=8)", !2}
; CHECK: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: __src_soil_MOD_xdzs] [Scalar: 0]
; CHECK: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: __src_soil_MOD_xdzs] [Scalar: 0]
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: __src_soil_MOD_xdzs] [Scalar: 0]

View file

@ -1,68 +0,0 @@
; RUN: opt %loadPolly -analyze -polly-detect-fortran-arrays \
; RUN: -polly-scops -polly-allow-nonaffine -polly-invariant-load-hoisting < %s | FileCheck %s
; This testcase is the corresponding LLVM for testfunc:
; PROGRAM main
; INTEGER, DIMENSION(1) :: xs
;
; CALL testfunc(xs, 10)
; CONTAINS
; SUBROUTINE func(xs, n)
; IMPLICIT NONE
; INTEGER, DIMENSION(:), INTENT(INOUT) :: xs
; INTEGER, INTENT(IN) :: n
; INTEGER :: i
; DO i = 1, n
; xs(i) = 1
; END DO
;
; END SUBROUTINE func
; END PROGRAM
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_integer(kind=4)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i64, i64, i64 }
define internal void @testfunc(%"struct.array1_integer(kind=4)"* noalias %xs, i32* noalias %n) {
entry:
br label %entry.split
entry.split: ; preds = %entry
%tmp = getelementptr inbounds %"struct.array1_integer(kind=4)", %"struct.array1_integer(kind=4)"* %xs, i64 0, i32 3, i64 0, i32 0
%tmp1 = load i64, i64* %tmp, align 8
%tmp2 = icmp eq i64 %tmp1, 0
%tmp3 = select i1 %tmp2, i64 1, i64 %tmp1
%tmp4 = bitcast %"struct.array1_integer(kind=4)"* %xs to i32**
%tmp5 = load i32*, i32** %tmp4, align 8
%tmp6 = load i32, i32* %n, align 4
%tmp7 = icmp sgt i32 %tmp6, 0
br i1 %tmp7, label %"6.preheader", label %return
"6.preheader": ; preds = %entry.split
br label %"6"
"6": ; preds = %"6", %"6.preheader"
%tmp8 = phi i32 [ %tmp14, %"6" ], [ 1, %"6.preheader" ]
%tmp9 = sext i32 %tmp8 to i64
%tmp10 = mul i64 %tmp3, %tmp9
%tmp11 = sub i64 %tmp10, %tmp3
%tmp12 = getelementptr i32, i32* %tmp5, i64 %tmp11
; store
store i32 1, i32* %tmp12, align 4
%tmp13 = icmp eq i32 %tmp8, %tmp6
%tmp14 = add i32 %tmp8, 1
br i1 %tmp13, label %return.loopexit, label %"6"
return.loopexit: ; preds = %"6"
br label %return
return: ; preds = %return.loopexit, %entry.split
ret void
}
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: xs] [Scalar: 0]

View file

@ -1,93 +0,0 @@
; RUN: opt %loadPolly -analyze -polly-detect-fortran-arrays \
; RUN: -polly-scops -polly-allow-nonaffine -polly-ignore-aliasing < %s | FileCheck %s
; PROGRAM main
; ...
; CONTAINS
; SUBROUTINE copy(xs, ys, n)
; IMPLICIT NONE
; INTEGER, DIMENSION(:), INTENT(INOUT) :: xs, ys
; INTEGER, INTENT(IN) :: n
; INTEGER :: i
;
; DO i = 1, n
; ys(i * i) = xs(i * i)
; END DO
;
; END SUBROUTINE copy
; END PROGRAM
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
module asm "\09.ident\09\22GCC: (GNU) 4.6.4 LLVM: 3.3.1\22"
%"struct.array1_integer(kind=4)" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.descriptor_dimension = type { i64, i64, i64 }
%"struct.array1_integer(kind=4).0" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%"struct.array1_integer(kind=4).1" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%"struct.array1_integer(kind=4).2" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
%struct.__st_parameter_dt = type { %struct.__st_parameter_common, i64, i64*, i64*, i8*, i8*, i32, i32, i8*, i8*, i32, i32, i8*, [256 x i8], i32*, i64, i8*, i32, i32, i8*, i8*, i32, i32, i8*, i8*, i32, i32, i8*, i8*, i32, [4 x i8] }
%struct.__st_parameter_common = type { i32, i32, i8*, i32, i32, i8*, i32* }
%"struct.array1_integer(kind=4).3" = type { i8*, i64, i64, [1 x %struct.descriptor_dimension] }
@0 = internal constant i32 10
@.cst = private constant [12 x i8] c"program.f90\00", align 8
@options.12.1603 = internal constant [8 x i32] [i32 68, i32 511, i32 0, i32 0, i32 0, i32 1, i32 0, i32 1], align 32
; Function Attrs: nounwind uwtable
define internal void @copy.1550(%"struct.array1_integer(kind=4)"* noalias %xs, %"struct.array1_integer(kind=4).0"* noalias %ys, i32* noalias %n) {
entry:
br label %entry.split
entry.split: ; preds = %entry
%0 = getelementptr inbounds %"struct.array1_integer(kind=4).0", %"struct.array1_integer(kind=4).0"* %ys, i64 0, i32 3, i64 0, i32 0
%1 = load i64, i64* %0, align 8
%2 = icmp eq i64 %1, 0
%3 = select i1 %2, i64 1, i64 %1
%4 = bitcast %"struct.array1_integer(kind=4).0"* %ys to i32**
%5 = load i32*, i32** %4, align 8
%6 = getelementptr inbounds %"struct.array1_integer(kind=4)", %"struct.array1_integer(kind=4)"* %xs, i64 0, i32 3, i64 0, i32 0
%7 = load i64, i64* %6, align 8
%8 = icmp eq i64 %7, 0
%. = select i1 %8, i64 1, i64 %7
%9 = bitcast %"struct.array1_integer(kind=4)"* %xs to i32**
%10 = load i32*, i32** %9, align 8
%11 = load i32, i32* %n, align 4
%12 = icmp sgt i32 %11, 0
br i1 %12, label %"9.preheader", label %return
"9.preheader": ; preds = %entry.split
br label %"9"
"9": ; preds = %"9.preheader", %"9"
%13 = phi i32 [ %26, %"9" ], [ 1, %"9.preheader" ]
%14 = mul i32 %13, %13
%15 = sext i32 %14 to i64
%16 = mul i64 %3, %15
%17 = sub i64 %16, %3
%18 = mul i32 %13, %13
%19 = sext i32 %18 to i64
%20 = mul i64 %., %19
%21 = sub i64 %20, %.
%22 = getelementptr i32, i32* %10, i64 %21
; load
%23 = load i32, i32* %22, align 4
%24 = getelementptr i32, i32* %5, i64 %17
; write
store i32 %23, i32* %24, align 4
%25 = icmp eq i32 %13, %11
%26 = add i32 %13, 1
br i1 %25, label %return.loopexit, label %"9"
return.loopexit: ; preds = %"9"
br label %return
return: ; preds = %return.loopexit, %entry.split
ret void
}
; CHECK: ReadAccess := [Reduction Type: NONE] [Fortran array descriptor: xs] [Scalar: 0]
; CHECK-NEXT: [p_0_loaded_from_n, MemRef0_fortranarr_size, MemRef1_fortranarr_size] -> { Stmt_9[i0] -> MemRef0[o0] };
; CHECK-NEXT: MayWriteAccess := [Reduction Type: NONE] [Fortran array descriptor: ys] [Scalar: 0]
; CHECK-NEXT: [p_0_loaded_from_n, MemRef0_fortranarr_size, MemRef1_fortranarr_size] -> { Stmt_9[i0] -> MemRef1[o0] };