Skip to content

Commit

Permalink
[Flang][OpenMP] Add host_eval clause lowering support
Browse files Browse the repository at this point in the history
This patch updates Flang lowering to use the `host_eval` clause in `omp.target`
operations to pass host information into the applicable clauses inside of the
target region, instead of the previous approach where these clauses were
attached to the `omp.target` operation itself.
  • Loading branch information
skatrak committed Oct 22, 2024
1 parent 332c9c5 commit f1120d0
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 467 deletions.
9 changes: 0 additions & 9 deletions flang/include/flang/Lower/OpenMP/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,6 @@ void genObjectList(const ObjectList &objects,
void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
mlir::Location loc);

// TODO: consider moving this to the `omp.loop_nest` op. Would be something like
// this:
//
// ```
// mlir::Value LoopNestOp::calculateTripCount(mlir::OpBuilder &builder,
// mlir::OpBuilder::InsertPoint ip)
// ```
mlir::Value calculateTripCount(fir::FirOpBuilder &builder, mlir::Location loc,
const mlir::omp::LoopRelatedClauseOps &ops);
} // namespace omp
} // namespace lower
} // namespace Fortran
Expand Down
221 changes: 113 additions & 108 deletions flang/lib/Lower/OpenMP/OpenMP.cpp

Large diffs are not rendered by default.

78 changes: 0 additions & 78 deletions flang/lib/Lower/OpenMP/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,84 +538,6 @@ void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
}
}

mlir::Value calculateTripCount(fir::FirOpBuilder &builder, mlir::Location loc,
const mlir::omp::LoopRelatedClauseOps &ops) {
using namespace mlir::arith;
assert(ops.loopLowerBounds.size() == ops.loopUpperBounds.size() &&
ops.loopLowerBounds.size() == ops.loopSteps.size() &&
!ops.loopLowerBounds.empty() && "Invalid bounds or step");

// Get the bit width of an integer-like type.
auto widthOf = [](mlir::Type ty) -> unsigned {
if (mlir::isa<mlir::IndexType>(ty)) {
return mlir::IndexType::kInternalStorageBitWidth;
}
if (auto tyInt = mlir::dyn_cast<mlir::IntegerType>(ty)) {
return tyInt.getWidth();
}
llvm_unreachable("Unexpected type");
};

// For a type that is either IntegerType or IndexType, return the
// equivalent IntegerType. In the former case this is a no-op.
auto asIntTy = [&](mlir::Type ty) -> mlir::IntegerType {
if (ty.isIndex()) {
return mlir::IntegerType::get(ty.getContext(), widthOf(ty));
}
assert(ty.isIntOrIndex() && "Unexpected type");
return mlir::cast<mlir::IntegerType>(ty);
};

// For two given values, establish a common signless IntegerType
// that can represent any value of type of x and of type of y,
// and return the pair of x, y converted to the new type.
auto unifyToSignless =
[&](fir::FirOpBuilder &b, mlir::Value x,
mlir::Value y) -> std::pair<mlir::Value, mlir::Value> {
auto tyX = asIntTy(x.getType()), tyY = asIntTy(y.getType());
unsigned width = std::max(widthOf(tyX), widthOf(tyY));
auto wideTy = mlir::IntegerType::get(b.getContext(), width,
mlir::IntegerType::Signless);
return std::make_pair(b.createConvert(loc, wideTy, x),
b.createConvert(loc, wideTy, y));
};

// Start with signless i32 by default.
auto tripCount = builder.createIntegerConstant(loc, builder.getI32Type(), 1);

for (auto [origLb, origUb, origStep] :
llvm::zip(ops.loopLowerBounds, ops.loopUpperBounds, ops.loopSteps)) {
auto tmpS0 = builder.createIntegerConstant(loc, origStep.getType(), 0);
auto [step, step0] = unifyToSignless(builder, origStep, tmpS0);
auto reverseCond =
builder.create<CmpIOp>(loc, CmpIPredicate::slt, step, step0);
auto negStep = builder.create<SubIOp>(loc, step0, step);
mlir::Value absStep =
builder.create<SelectOp>(loc, reverseCond, negStep, step);

auto [lb, ub] = unifyToSignless(builder, origLb, origUb);
auto start = builder.create<SelectOp>(loc, reverseCond, ub, lb);
auto end = builder.create<SelectOp>(loc, reverseCond, lb, ub);

mlir::Value range = builder.create<SubIOp>(loc, end, start);
auto rangeCond =
builder.create<CmpIOp>(loc, CmpIPredicate::slt, end, start);
std::tie(range, absStep) = unifyToSignless(builder, range, absStep);
// numSteps = (range /u absStep) + 1
auto numSteps = builder.create<AddIOp>(
loc, builder.create<DivUIOp>(loc, range, absStep),
builder.createIntegerConstant(loc, range.getType(), 1));

auto trip0 = builder.createIntegerConstant(loc, numSteps.getType(), 0);
auto loopTripCount =
builder.create<SelectOp>(loc, rangeCond, trip0, numSteps);
auto [totalTC, thisTC] = unifyToSignless(builder, tripCount, loopTripCount);
tripCount = builder.create<MulIOp>(loc, totalTC, thisTC);
}

return tripCount;
}

} // namespace omp
} // namespace lower
} // namespace Fortran
Loading

0 comments on commit f1120d0

Please sign in to comment.