@@ -290,12 +290,12 @@ static constexpr IntrinsicHandler handlers[]{
290290 {" atan2pi" , &I::genAtanpi},
291291 {" atand" , &I::genAtand},
292292 {" atanpi" , &I::genAtanpi},
293- {" atomicadd_r2x2 " ,
294- &I::genAtomicAddVector,
293+ {" atomicadd_r4x2 " ,
294+ &I::genAtomicAddVector< 2 > ,
295295 {{{" a" , asAddr}, {" v" , asAddr}}},
296296 false },
297- {" atomicadd_r4x2 " ,
298- &I::genAtomicAddVector,
297+ {" atomicadd_r4x4 " ,
298+ &I::genAtomicAddVector< 4 > ,
299299 {{{" a" , asAddr}, {" v" , asAddr}}},
300300 false },
301301 {" atomicaddd" , &I::genAtomicAdd, {{{" a" , asAddr}, {" v" , asValue}}}, false },
@@ -306,6 +306,14 @@ static constexpr IntrinsicHandler handlers[]{
306306 &I::genAtomicAddR2,
307307 {{{" a" , asAddr}, {" v" , asAddr}}},
308308 false },
309+ {" atomicaddvector_r2x2" ,
310+ &I::genAtomicAddVector<2 >,
311+ {{{" a" , asAddr}, {" v" , asAddr}}},
312+ false },
313+ {" atomicaddvector_r4x2" ,
314+ &I::genAtomicAddVector<2 >,
315+ {{{" a" , asAddr}, {" v" , asAddr}}},
316+ false },
309317 {" atomicandi" , &I::genAtomicAnd, {{{" a" , asAddr}, {" v" , asValue}}}, false },
310318 {" atomiccasd" ,
311319 &I::genAtomicCas,
@@ -3176,44 +3184,51 @@ IntrinsicLibrary::genAtomicAddR2(mlir::Type resultType,
31763184 mlir::ArrayRef<int64_t >{0 });
31773185}
31783186
3187+ template <int extent>
31793188fir::ExtendedValue
31803189IntrinsicLibrary::genAtomicAddVector (mlir::Type resultType,
31813190 llvm::ArrayRef<fir::ExtendedValue> args) {
31823191 assert (args.size () == 2 );
31833192 mlir::Value res = fir::AllocaOp::create (
3184- builder, loc, fir::SequenceType::get ({2 }, resultType));
3193+ builder, loc, fir::SequenceType::get ({extent }, resultType));
31853194 mlir::Value a = fir::getBase (args[0 ]);
31863195 if (mlir::isa<fir::BaseBoxType>(a.getType ())) {
31873196 a = fir::BoxAddrOp::create (builder, loc, a);
31883197 }
3189- auto vecTy = mlir::VectorType::get ({2 }, resultType);
3198+ auto vecTy = mlir::VectorType::get ({extent }, resultType);
31903199 auto refTy = fir::ReferenceType::get (resultType);
31913200 mlir::Type i32Ty = builder.getI32Type ();
31923201 mlir::Type idxTy = builder.getIndexType ();
3193- mlir::Value zero = builder.createIntegerConstant (loc, idxTy, 0 );
3194- mlir::Value one = builder.createIntegerConstant (loc, idxTy, 1 );
3195- mlir::Value v1Coord = fir::CoordinateOp::create (builder, loc, refTy,
3196- fir::getBase (args[1 ]), zero);
3197- mlir::Value v2Coord = fir::CoordinateOp::create (builder, loc, refTy,
3198- fir::getBase (args[1 ]), one);
3199- mlir::Value v1 = fir::LoadOp::create (builder, loc, v1Coord);
3200- mlir::Value v2 = fir::LoadOp::create (builder, loc, v2Coord);
3202+
3203+ // Extract the values from the array.
3204+ llvm::SmallVector<mlir::Value> values;
3205+ for (unsigned i = 0 ; i < extent; ++i) {
3206+ mlir::Value pos = builder.createIntegerConstant (loc, idxTy, i);
3207+ mlir::Value coord = fir::CoordinateOp::create (builder, loc, refTy,
3208+ fir::getBase (args[1 ]), pos);
3209+ mlir::Value value = fir::LoadOp::create (builder, loc, coord);
3210+ values.push_back (value);
3211+ }
3212+ // Pack extracted values into a vector to call the atomic add.
32013213 mlir::Value undef = mlir::LLVM::UndefOp::create (builder, loc, vecTy);
3202- mlir::Value vec1 = mlir::LLVM::InsertElementOp::create (
3203- builder, loc, undef, v1, builder.createIntegerConstant (loc, i32Ty, 0 ));
3204- mlir::Value vec2 = mlir::LLVM::InsertElementOp::create (
3205- builder, loc, vec1, v2, builder.createIntegerConstant (loc, i32Ty, 1 ));
3214+ for (unsigned i = 0 ; i < extent; ++i) {
3215+ mlir::Value insert = mlir::LLVM::InsertElementOp::create (
3216+ builder, loc, undef, values[i],
3217+ builder.createIntegerConstant (loc, i32Ty, i));
3218+ undef = insert;
3219+ }
3220+ // Atomic operation with a vector of values.
32063221 mlir::Value add =
3207- genAtomBinOp (builder, loc, mlir::LLVM::AtomicBinOp::fadd, a, vec2 );
3208- mlir::Value r1 = mlir::LLVM::ExtractElementOp::create (
3209- builder, loc, add, builder. createIntegerConstant (loc, i32Ty, 0 ));
3210- mlir::Value r2 = mlir::LLVM::ExtractElementOp::create (
3211- builder, loc, add, builder.createIntegerConstant (loc, i32Ty, 1 ));
3212- mlir::Value c1 = fir::CoordinateOp::create (builder, loc, refTy, res, zero);
3213- mlir::Value c2 = fir::CoordinateOp::create ( builder, loc, refTy, res, one );
3214- fir::StoreOp::create (builder, loc, r1, c1 );
3215- fir::StoreOp::create (builder, loc, r2, c2);
3216- mlir::Value ext = builder.createIntegerConstant (loc, idxTy, 2 );
3222+ genAtomBinOp (builder, loc, mlir::LLVM::AtomicBinOp::fadd, a, undef );
3223+ // Store results in the result array.
3224+ for ( unsigned i = 0 ; i < extent; ++i) {
3225+ mlir::Value r = mlir::LLVM::ExtractElementOp::create (
3226+ builder, loc, add, builder.createIntegerConstant (loc, i32Ty, i ));
3227+ mlir::Value c = fir::CoordinateOp::create (
3228+ builder, loc, refTy, res, builder. createIntegerConstant (loc, idxTy, i) );
3229+ fir::StoreOp::create (builder, loc, r, c );
3230+ }
3231+ mlir::Value ext = builder.createIntegerConstant (loc, idxTy, extent );
32173232 return fir::ArrayBoxValue (res, {ext});
32183233}
32193234
0 commit comments