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 @@ -1119,6 +1119,20 @@ } }; +/// Lower `fir.no_reassoc` to LLVM IR dialect. +/// TODO: how do we want to enforce this in LLVM-IR? Can we manipulate the fast +/// math flags? +struct NoReassocOpConversion : public FIROpConversion { + using FIROpConversion::FIROpConversion; + + mlir::LogicalResult + matchAndRewrite(fir::NoReassocOp noreassoc, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOp(noreassoc, adaptor.getOperands()[0]); + return success(); + } +}; + /// Lower `fir.select_type` to LLVM IR dialect. struct SelectTypeOpConversion : public FIROpConversion { using FIROpConversion::FIROpConversion; @@ -2069,12 +2083,12 @@ HasValueOpConversion, GenTypeDescOpConversion, GlobalLenOpConversion, GlobalOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, IsPresentOpConversion, LoadOpConversion, NegcOpConversion, - MulcOpConversion, SelectCaseOpConversion, SelectOpConversion, - SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion, - ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion, - StoreOpConversion, StringLitOpConversion, SubcOpConversion, - UnboxCharOpConversion, UndefOpConversion, UnreachableOpConversion, - ZeroOpConversion>(typeConverter); + NoReassocOpConversion, MulcOpConversion, SelectCaseOpConversion, + SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion, + ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion, + SliceOpConversion, StoreOpConversion, StringLitOpConversion, + SubcOpConversion, UnboxCharOpConversion, UndefOpConversion, + UnreachableOpConversion, ZeroOpConversion>(typeConverter); mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern); mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter, pattern); diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -1530,3 +1530,23 @@ // CHECK: %[[TDESC:.*]] = llvm.mlir.addressof @_QMtest_dinitE.dt.tseq : !llvm.ptr // CHECK: %[[TDESC_CAST:.*]] = llvm.bitcast %22 : !llvm.ptr to !llvm.ptr // CHECK: %{{.*}} = llvm.insertvalue %[[TDESC_CAST]], %{{.*}}[7 : i32] : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)> + +// ----- + +// Check `fir.no_reassoc` conversion to LLVM IR dialect +func @no_reassoc(%arg0: !fir.ref) { + %0 = fir.alloca i32 + %1 = fir.load %arg0 : !fir.ref + %2 = fir.no_reassoc %1 : i32 + fir.store %2 to %0 : !fir.ref + return +} + +// CHECK-LABEL: llvm.func @no_reassoc( +// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr) { +// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[ALLOC:.*]] = llvm.alloca %[[C1]] x i32 {in_type = i32, operand_segment_sizes = dense<0> : vector<2xi32>} : (i64) -> !llvm.ptr +// CHECK-NOT: fir.no_reassoc +// CHECK: %[[LOAD:.*]] = llvm.load %[[ARG0]] : !llvm.ptr +// CHECK: llvm.store %[[LOAD]], %[[ALLOC]] : !llvm.ptr +// CHECK: llvm.return