Skip to content

Commit b24abaa

Browse files
authored
[flang][OpenMP] Duplicate the utils needed by DoConcurrentConversion (llvm#88)
This adds a temporary (but more localy workaround) for the linker issue resulted from linking with `OpenMP/Utils.cpp`. This duplicates the required functions until we find a proper CMake solution.
1 parent 2f58864 commit b24abaa

File tree

2 files changed

+109
-5
lines changed

2 files changed

+109
-5
lines changed

flang/lib/Optimizer/Transforms/CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ add_flang_library(FIRTransforms
2424
FunctionAttr.cpp
2525
DebugTypeGenerator.cpp
2626
DoConcurrentConversion.cpp
27-
# TODO Find a cleaner solution for this. This is a workaround to expose
28-
# `Utils.cpp` so that it be used the `DoConcurrentConversion` pass. We should
29-
# probably split this is a shared lib.
30-
../../Lower/OpenMP/Utils.cpp
3127

3228
DEPENDS
3329
FIRDialect

flang/lib/Optimizer/Transforms/DoConcurrentConversion.cpp

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "flang/Lower/OpenMP/Utils.h"
109
#include "flang/Optimizer/Builder/FIRBuilder.h"
1110
#include "flang/Optimizer/Builder/Todo.h"
1211
#include "flang/Optimizer/Dialect/FIRDialect.h"
@@ -35,6 +34,115 @@ namespace fir {
3534

3635
#define DEBUG_TYPE "fopenmp-do-concurrent-conversion"
3736

37+
namespace Fortran {
38+
namespace lower {
39+
namespace omp {
40+
mlir::omp::MapInfoOp
41+
createMapInfoOp(mlir::OpBuilder &builder, mlir::Location loc,
42+
mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name,
43+
llvm::ArrayRef<mlir::Value> bounds,
44+
llvm::ArrayRef<mlir::Value> members,
45+
mlir::DenseIntElementsAttr membersIndex, uint64_t mapType,
46+
mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy,
47+
bool partialMap = false) {
48+
if (auto boxTy = llvm::dyn_cast<fir::BaseBoxType>(baseAddr.getType())) {
49+
baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
50+
retTy = baseAddr.getType();
51+
}
52+
53+
mlir::TypeAttr varType = mlir::TypeAttr::get(
54+
llvm::cast<mlir::omp::PointerLikeType>(retTy).getElementType());
55+
56+
mlir::omp::MapInfoOp op = builder.create<mlir::omp::MapInfoOp>(
57+
loc, retTy, baseAddr, varType, varPtrPtr, members, membersIndex, bounds,
58+
builder.getIntegerAttr(builder.getIntegerType(64, false), mapType),
59+
builder.getAttr<mlir::omp::VariableCaptureKindAttr>(mapCaptureType),
60+
builder.getStringAttr(name), builder.getBoolAttr(partialMap));
61+
62+
return op;
63+
}
64+
65+
mlir::Value calculateTripCount(fir::FirOpBuilder &builder, mlir::Location loc,
66+
const mlir::omp::CollapseClauseOps &ops) {
67+
using namespace mlir::arith;
68+
assert(ops.loopLBVar.size() == ops.loopUBVar.size() &&
69+
ops.loopLBVar.size() == ops.loopStepVar.size() &&
70+
!ops.loopLBVar.empty() && "Invalid bounds or step");
71+
72+
// Get the bit width of an integer-like type.
73+
auto widthOf = [](mlir::Type ty) -> unsigned {
74+
if (mlir::isa<mlir::IndexType>(ty)) {
75+
return mlir::IndexType::kInternalStorageBitWidth;
76+
}
77+
if (auto tyInt = mlir::dyn_cast<mlir::IntegerType>(ty)) {
78+
return tyInt.getWidth();
79+
}
80+
llvm_unreachable("Unexpected type");
81+
};
82+
83+
// For a type that is either IntegerType or IndexType, return the
84+
// equivalent IntegerType. In the former case this is a no-op.
85+
auto asIntTy = [&](mlir::Type ty) -> mlir::IntegerType {
86+
if (ty.isIndex()) {
87+
return mlir::IntegerType::get(ty.getContext(), widthOf(ty));
88+
}
89+
assert(ty.isIntOrIndex() && "Unexpected type");
90+
return mlir::cast<mlir::IntegerType>(ty);
91+
};
92+
93+
// For two given values, establish a common signless IntegerType
94+
// that can represent any value of type of x and of type of y,
95+
// and return the pair of x, y converted to the new type.
96+
auto unifyToSignless =
97+
[&](fir::FirOpBuilder &b, mlir::Value x,
98+
mlir::Value y) -> std::pair<mlir::Value, mlir::Value> {
99+
auto tyX = asIntTy(x.getType()), tyY = asIntTy(y.getType());
100+
unsigned width = std::max(widthOf(tyX), widthOf(tyY));
101+
auto wideTy = mlir::IntegerType::get(b.getContext(), width,
102+
mlir::IntegerType::Signless);
103+
return std::make_pair(b.createConvert(loc, wideTy, x),
104+
b.createConvert(loc, wideTy, y));
105+
};
106+
107+
// Start with signless i32 by default.
108+
auto tripCount = builder.createIntegerConstant(loc, builder.getI32Type(), 1);
109+
110+
for (auto [origLb, origUb, origStep] :
111+
llvm::zip(ops.loopLBVar, ops.loopUBVar, ops.loopStepVar)) {
112+
auto tmpS0 = builder.createIntegerConstant(loc, origStep.getType(), 0);
113+
auto [step, step0] = unifyToSignless(builder, origStep, tmpS0);
114+
auto reverseCond =
115+
builder.create<CmpIOp>(loc, CmpIPredicate::slt, step, step0);
116+
auto negStep = builder.create<SubIOp>(loc, step0, step);
117+
mlir::Value absStep =
118+
builder.create<SelectOp>(loc, reverseCond, negStep, step);
119+
120+
auto [lb, ub] = unifyToSignless(builder, origLb, origUb);
121+
auto start = builder.create<SelectOp>(loc, reverseCond, ub, lb);
122+
auto end = builder.create<SelectOp>(loc, reverseCond, lb, ub);
123+
124+
mlir::Value range = builder.create<SubIOp>(loc, end, start);
125+
auto rangeCond =
126+
builder.create<CmpIOp>(loc, CmpIPredicate::slt, end, start);
127+
std::tie(range, absStep) = unifyToSignless(builder, range, absStep);
128+
// numSteps = (range /u absStep) + 1
129+
auto numSteps = builder.create<AddIOp>(
130+
loc, builder.create<DivUIOp>(loc, range, absStep),
131+
builder.createIntegerConstant(loc, range.getType(), 1));
132+
133+
auto trip0 = builder.createIntegerConstant(loc, numSteps.getType(), 0);
134+
auto loopTripCount =
135+
builder.create<SelectOp>(loc, rangeCond, trip0, numSteps);
136+
auto [totalTC, thisTC] = unifyToSignless(builder, tripCount, loopTripCount);
137+
tripCount = builder.create<MulIOp>(loc, totalTC, thisTC);
138+
}
139+
140+
return tripCount;
141+
}
142+
} // namespace omp
143+
} // namespace lower
144+
} // namespace Fortran
145+
38146
namespace {
39147
class DoConcurrentConversion : public mlir::OpConversionPattern<fir::DoLoopOp> {
40148
public:

0 commit comments

Comments
 (0)