diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -1168,10 +1168,11 @@ auto typeCodeVal = this->genConstantOffset(loc, rewriter, typeCode); if (width == 8) return {len, typeCodeVal}; - auto byteWidth = this->genConstantOffset(loc, rewriter, width / 8); auto i64Ty = mlir::IntegerType::get(&this->lowerTy().getContext(), 64); + auto byteWidth = genConstantIndex(loc, i64Ty, rewriter, width / 8); + auto len64 = FIROpConversion::integerCast(loc, rewriter, i64Ty, len); auto size = - rewriter.create(loc, i64Ty, byteWidth, len); + rewriter.create(loc, i64Ty, byteWidth, len64); return {size, typeCodeVal}; }; auto getKindMap = [&]() -> fir::KindMapping & { @@ -1382,10 +1383,11 @@ base.getType().cast().getElementType(); if (baseType.isa()) { auto idxTy = this->lowerTy().indexType(); - mlir::Value zero = genConstantIndex(loc, idxTy, rewriter, 0); - gepOperands.push_back(zero); + gepOperands.push_back(genConstantIndex(loc, idxTy, rewriter, 0)); + gepOperands.push_back(lowerBound); + } else { + gepOperands.push_back(lowerBound); } - gepOperands.push_back(lowerBound); return this->genGEP(loc, base.getType(), rewriter, base, gepOperands); } @@ -1468,50 +1470,58 @@ mlir::Location loc = xbox.getLoc(); mlir::Value zero = genConstantIndex(loc, i64Ty, rewriter, 0); mlir::Value one = genConstantIndex(loc, i64Ty, rewriter, 1); - mlir::Value prevDim = integerCast(loc, rewriter, i64Ty, eleSize); mlir::Value prevPtrOff = one; mlir::Type eleTy = boxTy.getEleTy(); const unsigned rank = xbox.getRank(); llvm::SmallVector gepArgs; unsigned constRows = 0; mlir::Value ptrOffset = zero; - if (auto memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType())) - if (auto seqTy = memEleTy.dyn_cast()) { - mlir::Type seqEleTy = seqTy.getEleTy(); - // Adjust the element scaling factor if the element is a dependent type. - if (fir::hasDynamicSize(seqEleTy)) { - if (fir::isa_char(seqEleTy)) { - assert(xbox.lenParams().size() == 1); - prevPtrOff = integerCast(loc, rewriter, i64Ty, - operands[xbox.lenParamOffset()]); - } else if (seqEleTy.isa()) { - TODO(loc, "generate call to calculate size of PDT"); - } else { - return rewriter.notifyMatchFailure(xbox, "unexpected dynamic type"); - } - } else { - constRows = seqTy.getConstantRows(); - } + mlir::Type memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType()); + assert(memEleTy.isa()); + auto seqTy = memEleTy.cast(); + mlir::Type seqEleTy = seqTy.getEleTy(); + // Adjust the element scaling factor if the element is a dependent type. + if (fir::hasDynamicSize(seqEleTy)) { + if (auto charTy = seqEleTy.dyn_cast()) { + assert(xbox.lenParams().size() == 1); + mlir::LLVM::ConstantOp charSize = genConstantIndex( + loc, i64Ty, rewriter, lowerTy().characterBitsize(charTy) / 8); + mlir::Value castedLen = + integerCast(loc, rewriter, i64Ty, operands[xbox.lenParamOffset()]); + auto byteOffset = + rewriter.create(loc, i64Ty, charSize, castedLen); + prevPtrOff = integerCast(loc, rewriter, i64Ty, byteOffset); + } else if (seqEleTy.isa()) { + // prevPtrOff = ; + TODO(loc, "generate call to calculate size of PDT"); + } else { + fir::emitFatalError(loc, "unexpected dynamic type"); } + } else { + constRows = seqTy.getConstantRows(); + } - bool hasSubcomp = !xbox.subcomponent().empty(); - if (!xbox.substr().empty()) - TODO(loc, "codegen of fir.embox with substring"); - - mlir::Value stepExpr; + const auto hasSubcomp = !xbox.subcomponent().empty(); + const bool hasSubstr = !xbox.substr().empty(); + /// Compute initial element stride that will be use to compute the step in + /// each dimension. + mlir::Value prevDimByteStride = integerCast(loc, rewriter, i64Ty, eleSize); if (hasSubcomp) { // We have a subcomponent. The step value needs to be the number of // bytes per element (which is a derived type). - mlir::Type ty0 = base.getType(); - [[maybe_unused]] auto ptrTy = ty0.dyn_cast(); - assert(ptrTy && "expected pointer type"); - mlir::Type memEleTy = fir::dyn_cast_ptrEleTy(xbox.memref().getType()); - assert(memEleTy && "expected fir pointer type"); - auto seqTy = memEleTy.dyn_cast(); - assert(seqTy && "expected sequence type"); - mlir::Type seqEleTy = seqTy.getEleTy(); auto eleTy = mlir::LLVM::LLVMPointerType::get(convertType(seqEleTy)); - stepExpr = computeDerivedTypeSize(loc, eleTy, i64Ty, rewriter); + prevDimByteStride = computeDerivedTypeSize(loc, eleTy, i64Ty, rewriter); + } else if (hasSubstr) { + // We have a substring. The step value needs to be the number of bytes + // per CHARACTER element. + auto charTy = seqEleTy.cast(); + if (fir::hasDynamicSize(charTy)) { + prevDimByteStride = prevPtrOff; + } else { + prevDimByteStride = genConstantIndex( + loc, i64Ty, rewriter, + charTy.getLen() * lowerTy().characterBitsize(charTy) / 8); + } } // Process the array subspace arguments (shape, shift, etc.), if any, @@ -1544,36 +1554,36 @@ } } if (!skipNext) { + // store extent if (hasSlice) extent = computeTripletExtent(rewriter, loc, operands[sliceOffset], operands[sliceOffset + 1], operands[sliceOffset + 2], zero, i64Ty); - // store lower bound (normally 0) for BIND(C) interoperability. + // Lower bound is normalized to 0 for BIND(C) interoperability. mlir::Value lb = zero; const bool isaPointerOrAllocatable = eleTy.isa() || eleTy.isa(); // Lower bound is defaults to 1 for POINTER, ALLOCATABLE, and // denormalized descriptors. - if (isaPointerOrAllocatable || !normalizedLowerBound(xbox)) { + if (isaPointerOrAllocatable || !normalizedLowerBound(xbox)) lb = one; - // If there is a shifted origin, and no fir.slice, and this is not - // a normalized descriptor then use the value from the shift op as - // the lower bound. - if (hasShift && !(hasSlice || hasSubcomp)) { - lb = operands[shiftOffset]; - auto extentIsEmpty = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::eq, extent, zero); - lb = rewriter.create(loc, extentIsEmpty, one, - lb); - } + // If there is a shifted origin, and no fir.slice, and this is not + // a normalized descriptor then use the value from the shift op as + // the lower bound. + if (hasShift && !(hasSlice || hasSubcomp || hasSubstr) && + (isaPointerOrAllocatable || !normalizedLowerBound(xbox))) { + lb = operands[shiftOffset]; + auto extentIsEmpty = rewriter.create( + loc, mlir::LLVM::ICmpPredicate::eq, extent, zero); + lb = rewriter.create(loc, extentIsEmpty, one, + lb); } dest = insertLowerBound(rewriter, loc, dest, descIdx, lb); dest = insertExtent(rewriter, loc, dest, descIdx, extent); // store step (scaled by shaped extent) - - mlir::Value step = hasSubcomp ? stepExpr : prevDim; + mlir::Value step = prevDimByteStride; if (hasSlice) step = rewriter.create(loc, i64Ty, step, operands[sliceOffset + 2]); @@ -1582,8 +1592,8 @@ } // compute the stride and offset for the next natural dimension - prevDim = - rewriter.create(loc, i64Ty, prevDim, outerExtent); + prevDimByteStride = rewriter.create( + loc, i64Ty, prevDimByteStride, outerExtent); if (constRows == 0) prevPtrOff = rewriter.create(loc, i64Ty, prevPtrOff, outerExtent); @@ -1597,7 +1607,7 @@ if (hasSlice) sliceOffset += 3; } - if (hasSlice || hasSubcomp || !xbox.substr().empty()) { + if (hasSlice || hasSubcomp || hasSubstr) { llvm::SmallVector args = {ptrOffset}; args.append(gepArgs.rbegin(), gepArgs.rend()); if (hasSubcomp) { @@ -1613,7 +1623,7 @@ } base = rewriter.create(loc, base.getType(), base, args); - if (!xbox.substr().empty()) + if (hasSubstr) base = shiftSubstringBase(rewriter, loc, base, operands[xbox.substrOffset()]); } diff --git a/flang/test/Fir/embox-write.fir b/flang/test/Fir/embox-write.fir new file mode 100644 --- /dev/null +++ b/flang/test/Fir/embox-write.fir @@ -0,0 +1,19 @@ +// RUN: fir-opt %s | tco | FileCheck %s + +// CHECK-LABEL: @set_all_n +func.func @set_all_n(%n : index, %x : i32) { + %aTmp = fir.alloca i32, %n + %aMem = fir.convert %aTmp : (!fir.ref) -> !fir.ref> + %c1 = arith.constant 1 : index + %aDim = fir.shape %n : (index) -> !fir.shape<1> + %a = fir.embox %aMem(%aDim) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + // CHECK-DAG: %[[IV:.*]] = phi i64 + // CHECK-DAG: %[[LCV:.*]] = phi i64 + // CHECK: icmp sgt i64 %[[LCV]], 0 + fir.do_loop %i = %c1 to %n step %c1 unordered { + %1 = fir.coordinate_of %a, %i : (!fir.box>, index) -> !fir.ref + // CHECK: store i32 %{{.*}}, ptr %{{.*}} + fir.store %x to %1 : !fir.ref + } + return +}