Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -181,10 +181,19 @@ OptionalAttr:$order_val, UnitAttr:$inclusive); + let skipDefaultBuilders = 1; + let builders = [ OpBuilder<(ins "ValueRange":$lowerBound, "ValueRange":$upperBound, - "ValueRange":$step, - CArg<"ArrayRef", "{}">:$attributes)> + "ValueRange":$step, + CArg<"ArrayRef", "{}">:$attributes)>, + OpBuilder<(ins "TypeRange":$resultTypes, "ValueRange":$lowerBound, "ValueRange":$upperBound, + "ValueRange":$step, "ValueRange":$privateVars, "ValueRange":$firstprivateVars, + "ValueRange":$lastprivate_vars, "ValueRange":$linear_vars, "ValueRange":$linear_step_vars, + "StringAttr":$schedule_val, "Value":$schedule_chunk_var, "IntegerAttr":$collapse_val, + "UnitAttr":$nowait, "IntegerAttr":$ordered_val, "StringAttr":$order_val, + "UnitAttr":$inclusive, CArg<"bool", "true">:$buildBody)>, + OpBuilder<(ins "TypeRange":$resultTypes, "ValueRange":$operands, CArg<"ArrayRef", "{}">:$attributes)> ]; let regions = (region AnyRegion:$region); @@ -193,6 +202,8 @@ /// Returns the number of loops in the workshape loop nest. unsigned getNumLoops() { return lowerBound().size(); } }]; + let parser = [{ return parseWsLoopOp(parser, result); }]; + let printer = [{ return printWsLoopOp(p, *this); }]; } def YieldOp : OpenMP_Op<"yield", [NoSideEffect, ReturnLike, Terminator, Index: mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp =================================================================== --- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -17,6 +17,7 @@ #include "mlir/IR/OperationSupport.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -373,6 +374,328 @@ return success(); } +static ParseResult +parseLinearClause(OpAsmParser &parser, + SmallVectorImpl &vars, + SmallVectorImpl &types, + SmallVectorImpl &stepVars) { + if (parser.parseLParen()) + return failure(); + + do { + OpAsmParser::OperandType var; + Type type; + OpAsmParser::OperandType stepVar; + if (parser.parseOperand(var) || parser.parseEqual() || + parser.parseOperand(stepVar) || parser.parseColonType(type)) + return failure(); + + vars.push_back(var); + types.push_back(type); + stepVars.push_back(stepVar); + } while (succeeded(parser.parseOptionalComma())); + + if (parser.parseRParen()) + return failure(); + + return success(); +} + +static ParseResult +parseScheduleClause(OpAsmParser &parser, llvm::SmallString<8> &schedule, + llvm::Optional &chunkSize) { + if (parser.parseLParen()) + return failure(); + + llvm::StringRef keyword; + if (parser.parseKeyword(&keyword)) + return failure(); + + schedule = keyword; + if (keyword == "static" || keyword == "dynamic" || keyword == "guided") { + if (succeeded(parser.parseOptionalEqual())) { + chunkSize = OpAsmParser::OperandType{}; + if (parser.parseOperand(*chunkSize)) + return failure(); + } else { + chunkSize = llvm::NoneType::None; + } + } else if (keyword == "auto" || keyword == "runtime") { + chunkSize = llvm::NoneType::None; + } else { + return parser.emitError(parser.getNameLoc()) << " expected schedule kind"; + } + + if (parser.parseRParen()) + return failure(); + + return success(); +} + +/// Parses an OpenMP Workshare Loop operation +/// +/// operation ::= `omp.do` clause-list +static ParseResult parseWsLoopOp(OpAsmParser &parser, OperationState &result) { + auto &builder = parser.getBuilder(); + Type indexType = builder.getIndexType(); + Type integerType32 = builder.getIntegerType(32); + Type integerType64 = builder.getIntegerType(64); + Type llvmIntegerType32 = IntegerType::get(builder.getContext(), 32); + Type llvmIntegerType64 = IntegerType::get(builder.getContext(), 64); + + // Parse an opening `(` followed by induction variables followed by `)` + SmallVector ivs; + if (parser.parseRegionArgumentList(ivs, /*requiredOperandCount=*/-1, + OpAsmParser::Delimiter::Paren)) + return failure(); + + // Parse loop bounds. + SmallVector lower; + if (parser.parseEqual() || + parser.parseOperandList(lower, ivs.size(), + OpAsmParser::Delimiter::Paren) || + (parser.resolveOperands(lower, indexType, result.operands) && + parser.resolveOperands(lower, integerType32, result.operands) && + parser.resolveOperands(lower, integerType64, result.operands) && + parser.resolveOperands(lower, llvmIntegerType32, result.operands) && + parser.resolveOperands(lower, llvmIntegerType64, result.operands))) + return failure(); + + SmallVector upper; + if (parser.parseKeyword("to") || + parser.parseOperandList(upper, ivs.size(), + OpAsmParser::Delimiter::Paren) || + (parser.resolveOperands(upper, indexType, result.operands) && + parser.resolveOperands(upper, integerType32, result.operands) && + parser.resolveOperands(upper, integerType64, result.operands) && + parser.resolveOperands(upper, llvmIntegerType32, result.operands) && + parser.resolveOperands(upper, llvmIntegerType64, result.operands))) + return failure(); + + // Parse step values. + SmallVector steps; + if (parser.parseKeyword("step") || + parser.parseOperandList(steps, ivs.size(), + OpAsmParser::Delimiter::Paren) || + (parser.resolveOperands(steps, indexType, result.operands) && + parser.resolveOperands(steps, integerType32, result.operands) && + parser.resolveOperands(steps, integerType64, result.operands) && + parser.resolveOperands(steps, llvmIntegerType32, result.operands) && + parser.resolveOperands(steps, llvmIntegerType64, result.operands))) + return failure(); + + SmallVector privates; + SmallVector privateTypes; + SmallVector firstprivates; + SmallVector firstprivateTypes; + SmallVector lastprivates; + SmallVector lastprivateTypes; + SmallVector linears; + SmallVector linearTypes; + SmallVector linearSteps; + llvm::SmallString<8> schedule; + llvm::Optional scheduleChunkSize; + std::array segments{1, 1, 1, 0, 0, 0, 0, 0, 0}; + + const llvm::StringRef opName = result.name.getStringRef(); + llvm::StringRef keyword; + + enum SegmentPos { + lbPos = 0, + ubPos, + stepPos, + privateClausePos, + firstprivateClausePos, + lastprivateClausePos, + linearClausePos, + linearStepPos, + scheduleClausePos, + }; + + while (succeeded(parser.parseOptionalKeyword(&keyword))) { + if (keyword == "private") { + if (segments[privateClausePos]) + return allowedOnce(parser, "private", opName); + if (parseOperandAndTypeList(parser, privates, privateTypes)) + return failure(); + segments[privateClausePos] = privates.size(); + } else if (keyword == "firstprivate") { + // fail if there was already another firstprivate clause + if (segments[firstprivateClausePos]) + return allowedOnce(parser, "firstprivate", opName); + if (parseOperandAndTypeList(parser, firstprivates, firstprivateTypes)) + return failure(); + segments[firstprivateClausePos] = firstprivates.size(); + } else if (keyword == "lastprivate") { + // fail if there was already another shared clause + if (segments[lastprivateClausePos]) + return allowedOnce(parser, "lastprivate", opName); + if (parseOperandAndTypeList(parser, lastprivates, lastprivateTypes)) + return failure(); + segments[lastprivateClausePos] = lastprivates.size(); + } else if (keyword == "linear") { + // fail if there was already another linear clause + if (segments[linearClausePos]) + return allowedOnce(parser, "linear", opName); + if (parseLinearClause(parser, linears, linearTypes, linearSteps)) + return failure(); + segments[linearClausePos] = linears.size(); + segments[linearStepPos] = linearSteps.size(); + } else if (keyword == "schedule") { + if (!schedule.empty()) + return allowedOnce(parser, "schedule", opName); + if (parseScheduleClause(parser, schedule, scheduleChunkSize)) + return failure(); + if (scheduleChunkSize) { + segments[scheduleClausePos] = 1; + } + } else if (keyword == "collapse") { + auto type = parser.getBuilder().getI64Type(); + mlir::IntegerAttr attr; + if (parser.parseLParen() || parser.parseAttribute(attr, type) || + parser.parseRParen()) + return failure(); + result.addAttribute("collapse_val", attr); + } else if (keyword == "nowait") { + auto attr = UnitAttr::get(parser.getBuilder().getContext()); + result.addAttribute("nowait", attr); + } else if (keyword == "ordered") { + mlir::IntegerAttr attr; + if (succeeded(parser.parseOptionalLParen())) { + auto type = parser.getBuilder().getI64Type(); + if (parser.parseAttribute(attr, type)) + return failure(); + if (parser.parseRParen()) + return failure(); + } else { + // Use 0 to represent no ordered parameter was specified + attr = parser.getBuilder().getI64IntegerAttr(0); + } + result.addAttribute("ordered_val", attr); + } else if (keyword == "order") { + llvm::StringRef order; + if (parser.parseLParen() || parser.parseKeyword(&order) || + parser.parseRParen()) + return failure(); + auto attr = parser.getBuilder().getStringAttr(order); + result.addAttribute("order", attr); + } else if (keyword == "inclusive") { + auto attr = UnitAttr::get(parser.getBuilder().getContext()); + result.addAttribute("inclusive", attr); + } + } + + if (segments[privateClausePos]) { + parser.resolveOperands(privates, privateTypes, privates[0].location, + result.operands); + } + + if (segments[firstprivateClausePos]) { + parser.resolveOperands(firstprivates, firstprivateTypes, + firstprivates[0].location, result.operands); + } + + if (segments[lastprivateClausePos]) { + parser.resolveOperands(lastprivates, lastprivateTypes, + lastprivates[0].location, result.operands); + } + + if (segments[linearClausePos]) { + parser.resolveOperands(linears, linearTypes, linears[0].location, + result.operands); + auto linearStepType = parser.getBuilder().getI32Type(); + parser.resolveOperands(linearSteps, linearStepType, linears[0].location, + result.operands); + } + + if (!schedule.empty()) { + schedule[0] = llvm::toUpper(schedule[0]); + auto attr = parser.getBuilder().getStringAttr(schedule); + result.addAttribute("schedule_val", attr); + if (scheduleChunkSize) { + auto chunkSizeType = parser.getBuilder().getI32Type(); + parser.resolveOperand(*scheduleChunkSize, chunkSizeType, result.operands); + } + } + + result.addAttribute("operand_segment_sizes", + parser.getBuilder().getI32VectorAttr(segments)); + + // Now parse the body. + Region *body = result.addRegion(); + SmallVector typesIndex(ivs.size(), builder.getIndexType()); + SmallVector typesInt32(ivs.size(), builder.getIntegerType(32)); + SmallVector typesInt64(ivs.size(), builder.getIntegerType(64)); + SmallVector typesLLVMInt32( + ivs.size(), IntegerType::get(builder.getContext(), 32)); + SmallVector typesLLVMInt64( + ivs.size(), IntegerType::get(builder.getContext(), 64)); + if (parser.parseRegion(*body, ivs, typesIndex) && + parser.parseRegion(*body, ivs, typesInt32) && + parser.parseRegion(*body, ivs, typesInt64) && + parser.parseRegion(*body, ivs, typesLLVMInt32) && + parser.parseRegion(*body, ivs, typesLLVMInt64)) + return failure(); + return success(); +} + +static void printWsLoopOp(OpAsmPrinter &p, WsLoopOp op) { + p << op.getOperationName() << " (" << op.getRegion().front().getArguments() + << ") = (" << op.lowerBound() << ") to (" << op.upperBound() << ") step (" + << op.step() << ")"; + + // Print private, firstprivate, shared and copyin parameters + auto printDataVars = [&p](StringRef name, OperandRange vars) { + if (vars.size()) { + p << " " << name << "("; + for (unsigned i = 0; i < vars.size(); ++i) { + std::string separator = i == vars.size() - 1 ? ")" : ", "; + p << vars[i] << " : " << vars[i].getType() << separator; + } + } + }; + printDataVars("private", op.private_vars()); + printDataVars("firstprivate", op.firstprivate_vars()); + printDataVars("lastprivate", op.lastprivate_vars()); + + auto linearVars = op.linear_vars(); + if (linearVars.size()) { + p << " " + << "linear" + << "("; + for (unsigned i = 0; i < linearVars.size(); ++i) { + std::string separator = i == linearVars.size() - 1 ? ")" : ", "; + p << linearVars[i] << " = " << op.linear_step_vars()[i] << " : " + << linearVars[i].getType() << separator; + } + } + + if (auto sched = op.schedule_val()) { + auto sched_lower = sched->lower(); + p << " schedule(" << sched_lower; + if (auto chunk = op.schedule_chunk_var()) { + p << " = " << chunk; + } + p << ")"; + } + + if (auto collapse = op.collapse_val()) + p << " collapse(" << collapse << ")"; + + if (op.nowait()) + p << " nowait"; + + if (auto ordered = op.ordered_val()) { + p << " ordered(" << ordered << ")"; + } + + if (op.inclusive()) { + p << " inclusive"; + } + + p.printRegion(op.region(), /*printEntryBlockArgs=*/false); +} + //===----------------------------------------------------------------------===// // WsLoopOp //===----------------------------------------------------------------------===// @@ -386,9 +709,72 @@ /*linear_vars=*/ValueRange(), /*linear_step_vars=*/ValueRange(), /*schedule_val=*/nullptr, /*schedule_chunk_var=*/nullptr, /*collapse_val=*/nullptr, - /*nowait=*/false, /*ordered_val=*/nullptr, /*order_val=*/nullptr, - /*inclusive=*/false); + /*nowait=*/nullptr, /*ordered_val=*/nullptr, /*order_val=*/nullptr, + /*inclusive=*/nullptr, /*buildBody=*/false); + state.addAttributes(attributes); +} + +void WsLoopOp::build(OpBuilder &, OperationState &state, TypeRange resultTypes, + ValueRange operands, ArrayRef attributes) { + state.addOperands(operands); state.addAttributes(attributes); + for (unsigned i = 0; i != 1; ++i) + (void)state.addRegion(); + assert(resultTypes.size() == 0u && "mismatched number of return types"); + state.addTypes(resultTypes); +} + +void WsLoopOp::build(OpBuilder &builder, OperationState &result, + TypeRange typeRange, ValueRange lowerBounds, + ValueRange upperBounds, ValueRange steps, + ValueRange privateVars, ValueRange firstprivateVars, + ValueRange lastprivateVars, ValueRange linearVars, + ValueRange linearStepVars, StringAttr scheduleVal, + Value scheduleChunkVar, IntegerAttr collapseVal, + UnitAttr nowait, IntegerAttr orderedVal, + StringAttr orderVal, UnitAttr inclusive, bool buildBody) { + result.addOperands(lowerBounds); + result.addOperands(upperBounds); + result.addOperands(steps); + result.addOperands(privateVars); + result.addOperands(firstprivateVars); + result.addOperands(linearVars); + result.addOperands(linearStepVars); + if (scheduleChunkVar) + result.addOperands(scheduleChunkVar); + + if (scheduleVal) + result.addAttribute("schedule_val", scheduleVal); + if (collapseVal) + result.addAttribute("collapse_val", collapseVal); + if (nowait) + result.addAttribute("nowait", nowait); + if (orderedVal) + result.addAttribute("ordered_val", orderedVal); + if (orderVal) + result.addAttribute("order", orderVal); + if (inclusive) + result.addAttribute("inclusive", inclusive); + result.addAttribute( + WsLoopOp::getOperandSegmentSizeAttr(), + builder.getI32VectorAttr( + {static_cast(lowerBounds.size()), + static_cast(upperBounds.size()), + static_cast(steps.size()), + static_cast(privateVars.size()), + static_cast(firstprivateVars.size()), + static_cast(lastprivateVars.size()), + static_cast(linearVars.size()), + static_cast(linearStepVars.size()), + static_cast(scheduleChunkVar != nullptr ? 1 : 0)})); + + Region *bodyRegion = result.addRegion(); + if (buildBody) { + OpBuilder::InsertionGuard guard(builder); + unsigned numIVs = steps.size(); + SmallVector argTypes(numIVs, steps.getType().front()); + builder.createBlock(bodyRegion, {}, argTypes); + } } #define GET_OP_CLASSES Index: mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir =================================================================== --- mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir +++ mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir @@ -34,10 +34,8 @@ func @wsloop(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index) { // CHECK: omp.parallel omp.parallel { - // CHECK: omp.wsloop - // CHECK: (%[[ARG0]], %[[ARG1]], %[[ARG2]], %[[ARG3]], %[[ARG4]], %[[ARG5]]) + // CHECK: omp.wsloop (%[[ARG6:.*]], %[[ARG7:.*]]) = (%[[ARG0]], %[[ARG1]]) to (%[[ARG2]], %[[ARG3]]) step (%[[ARG4]], %[[ARG5]]) { "omp.wsloop"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) ( { - // CHECK: ^{{.*}}(%[[ARG6:.*]]: i64, %[[ARG7:.*]]: i64): ^bb0(%arg6: index, %arg7: index): // no predecessors // CHECK: "test.payload"(%[[ARG6]], %[[ARG7]]) : (i64, i64) -> () "test.payload"(%arg6, %arg7) : (index, index) -> () Index: mlir/test/Conversion/SCFToOpenMP/scf-to-openmp.mlir =================================================================== --- mlir/test/Conversion/SCFToOpenMP/scf-to-openmp.mlir +++ mlir/test/Conversion/SCFToOpenMP/scf-to-openmp.mlir @@ -4,9 +4,9 @@ func @parallel(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index) { // CHECK: omp.parallel { - // CHECK: "omp.wsloop"({{.*}}) ( { + // CHECK: omp.wsloop (%[[LVAR1:.*]], %[[LVAR2:.*]]) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %arg5) { scf.parallel (%i, %j) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %arg5) { - // CHECK: test.payload + // CHECK: "test.payload"(%[[LVAR1]], %[[LVAR2]]) : (index, index) -> () "test.payload"(%i, %j) : (index, index) -> () // CHECK: omp.yield // CHECK: } @@ -20,12 +20,12 @@ func @nested_loops(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index) { // CHECK: omp.parallel { - // CHECK: "omp.wsloop"({{.*}}) ( { + // CHECK: omp.wsloop (%[[LVAR_OUT1:.*]]) = (%arg0) to (%arg2) step (%arg4) { // CHECK-NOT: omp.parallel scf.parallel (%i) = (%arg0) to (%arg2) step (%arg4) { - // CHECK: "omp.wsloop"({{.*}}) ( { + // CHECK: omp.wsloop (%[[LVAR_IN1:.*]]) = (%arg1) to (%arg3) step (%arg5) { scf.parallel (%j) = (%arg1) to (%arg3) step (%arg5) { - // CHECK: test.payload + // CHECK: "test.payload"(%[[LVAR_OUT1]], %[[LVAR_IN1]]) : (index, index) -> () "test.payload"(%i, %j) : (index, index) -> () // CHECK: omp.yield // CHECK: } @@ -41,9 +41,9 @@ func @adjacent_loops(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index) { // CHECK: omp.parallel { - // CHECK: "omp.wsloop"({{.*}}) ( { + // CHECK: omp.wsloop (%[[LVAR_AL1:.*]]) = (%arg0) to (%arg2) step (%arg4) { scf.parallel (%i) = (%arg0) to (%arg2) step (%arg4) { - // CHECK: test.payload1 + // CHECK: "test.payload1"(%[[LVAR_AL1]]) : (index) -> () "test.payload1"(%i) : (index) -> () // CHECK: omp.yield // CHECK: } @@ -52,9 +52,9 @@ // CHECK: } // CHECK: omp.parallel { - // CHECK: "omp.wsloop"({{.*}}) ( { + // CHECK: omp.wsloop (%[[LVAR_AL2:.*]]) = (%arg1) to (%arg3) step (%arg5) { scf.parallel (%j) = (%arg1) to (%arg3) step (%arg5) { - // CHECK: test.payload2 + // CHECK: "test.payload2"(%[[LVAR_AL2]]) : (index) -> () "test.payload2"(%j) : (index) -> () // CHECK: omp.yield // CHECK: } Index: mlir/test/Dialect/OpenMP/ops.mlir =================================================================== --- mlir/test/Dialect/OpenMP/ops.mlir +++ mlir/test/Dialect/OpenMP/ops.mlir @@ -89,77 +89,102 @@ } func @omp_parallel_pretty(%data_var : memref, %if_cond : i1, %num_threads : si32, %allocator : si32) -> () { - // CHECK: omp.parallel - omp.parallel { - omp.terminator - } - - // CHECK: omp.parallel num_threads(%{{.*}} : si32) - omp.parallel num_threads(%num_threads : si32) { - omp.terminator - } - - // CHECK: omp.parallel allocate(%{{.*}} : memref -> %{{.*}} : memref) - omp.parallel allocate(%data_var : memref -> %data_var : memref) { - omp.terminator - } - - // CHECK: omp.parallel private(%{{.*}} : memref, %{{.*}} : memref) firstprivate(%{{.*}} : memref) - omp.parallel private(%data_var : memref, %data_var : memref) firstprivate(%data_var : memref) { - omp.terminator - } - - // CHECK omp.parallel shared(%{{.*}} : memref) copyin(%{{.*}} : memref, %{{.*}} : memref) - omp.parallel shared(%data_var : memref) copyin(%data_var : memref, %data_var : memref) { - omp.parallel if(%if_cond: i1) { - omp.terminator - } - omp.terminator - } - - // CHECK omp.parallel if(%{{.*}}) num_threads(%{{.*}} : si32) private(%{{.*}} : memref) proc_bind(close) - omp.parallel num_threads(%num_threads : si32) if(%if_cond: i1) - private(%data_var : memref) proc_bind(close) { - omp.terminator - } - - return + // CHECK: omp.parallel + omp.parallel { + omp.terminator + } + + // CHECK: omp.parallel num_threads(%{{.*}} : si32) + omp.parallel num_threads(%num_threads : si32) { + omp.terminator + } + + // CHECK: omp.parallel allocate(%{{.*}} : memref -> %{{.*}} : memref) + omp.parallel allocate(%data_var : memref -> %data_var : memref) { + omp.terminator + } + + // CHECK: omp.parallel private(%{{.*}} : memref, %{{.*}} : memref) firstprivate(%{{.*}} : memref) + omp.parallel private(%data_var : memref, %data_var : memref) firstprivate(%data_var : memref) { + omp.terminator + } + + // CHECK omp.parallel shared(%{{.*}} : memref) copyin(%{{.*}} : memref, %{{.*}} : memref) + omp.parallel shared(%data_var : memref) copyin(%data_var : memref, %data_var : memref) { + omp.parallel if(%if_cond: i1) { + omp.terminator + } + omp.terminator + } + + // CHECK omp.parallel if(%{{.*}}) num_threads(%{{.*}} : si32) private(%{{.*}} : memref) proc_bind(close) + omp.parallel num_threads(%num_threads : si32) if(%if_cond: i1) + private(%data_var : memref) proc_bind(close) { + omp.terminator + } + + return } -func @omp_wsloop(%lb : index, %ub : index, %step : index, - %data_var : memref, %linear_var : si32, %chunk_var : si32) -> () { +// CHECK-LABEL: omp_wsloop +func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref, %linear_var : i32, %chunk_var : i32) -> () { - // CHECK: "omp.wsloop"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private(%{{.*}} : memref) collapse(2) ordered(1) "omp.wsloop" (%lb, %ub, %step, %data_var) ({ - omp.yield + ^bb0(%iv: index): + omp.yield }) {operand_segment_sizes = dense<[1,1,1,1,0,0,0,0,0]> : vector<9xi32>, collapse_val = 2, ordered_val = 1} : (index, index, index, memref) -> () - // CHECK: "omp.wsloop"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) - "omp.wsloop" (%lb, %lb, %ub, %ub, %step, %step, %data_var) ({ - omp.yield - }) {operand_segment_sizes = dense<[2,2,2,1,0,0,0,0,0]> : vector<9xi32>, collapse_val = 2, ordered_val = 1} : - (index, index, index, index, index, index, memref) -> () - - - // CHECK: "omp.wsloop"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) linear(%{{.*}} = %{{.*}} : memref) schedule(static) "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var) ({ - omp.yield + ^bb0(%iv: index): + omp.yield }) {operand_segment_sizes = dense<[1,1,1,0,0,0,1,1,0]> : vector<9xi32>, schedule_val = "Static"} : - (index, index, index, memref, si32) -> () + (index, index, index, memref, i32) -> () - // CHECK: "omp.wsloop"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private(%{{.*}} : memref) firstprivate(%{{.*}} : memref) lastprivate(%{{.*}} : memref) linear(%{{.*}} = %{{.*}} : memref) schedule(dynamic = %{{.*}}) collapse(3) ordered(2) "omp.wsloop" (%lb, %ub, %step, %data_var, %data_var, %data_var, %data_var, %linear_var, %chunk_var) ({ - omp.yield + ^bb0(%iv: index): + omp.yield }) {operand_segment_sizes = dense<[1,1,1,1,1,1,1,1,1]> : vector<9xi32>, schedule_val = "Dynamic", collapse_val = 3, ordered_val = 2} : - (index, index, index, memref, memref, memref, memref, si32, si32) -> () + (index, index, index, memref, memref, memref, memref, i32, i32) -> () - // CHECK: "omp.wsloop"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private(%{{.*}} : memref) schedule(auto) nowait "omp.wsloop" (%lb, %ub, %step, %data_var) ({ - omp.yield + ^bb0(%iv: index): + omp.yield }) {operand_segment_sizes = dense<[1,1,1,1,0,0,0,0,0]> : vector<9xi32>, nowait, schedule_val = "Auto"} : (index, index, index, memref) -> () + return +} + +// CHECK-LABEL: omp_wsloop_pretty +func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, + %data_var : memref, %linear_var : i32, %chunk_var : i32) -> () { + + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private(%{{.*}} : memref) + omp.wsloop (%iv) = (%lb) to (%ub) step (%step) private(%data_var : memref) collapse(2) ordered(2) { + omp.yield + } + + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) linear(%{{.*}} = %{{.*}} : memref) schedule(static) + omp.wsloop (%iv) = (%lb) to (%ub) step (%step) schedule(static) lastprivate(%data_var : memref) linear(%data_var = %linear_var : memref) { + omp.yield + } + + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private(%{{.*}} : memref) firstprivate(%{{.*}} : memref) lastprivate(%{{.*}} : memref) linear(%{{.*}} = %{{.*}} : memref) schedule(static = %{{.*}}) collapse(3) ordered(2) + omp.wsloop (%iv) = (%lb) to (%ub) step (%step) ordered(2) private(%data_var : memref) + firstprivate(%data_var : memref) lastprivate(%data_var : memref) linear(%data_var = %linear_var : memref) + schedule(static = %chunk_var) collapse(3) { + omp.yield + } + + // CHECK: omp.wsloop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) private({{.*}} : memref) + omp.wsloop (%iv) = (%lb) to (%ub) step (%step) private(%data_var : memref) { + omp.yield + } return }