diff options
author | jeanPerier <jperier@nvidia.com> | 2025-01-30 14:24:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-30 14:24:45 +0100 |
commit | 2e581dc54b8983122528ade578824d70ec42b503 (patch) | |
tree | 4f9c90987347b9b0b9206d556968b04cd2aacb75 | |
parent | 104c2b86a5e9f4871707b25399735f0e5db58745 (diff) | |
download | llvm-2e581dc54b8983122528ade578824d70ec42b503.zip llvm-2e581dc54b8983122528ade578824d70ec42b503.tar.gz llvm-2e581dc54b8983122528ade578824d70ec42b503.tar.bz2 |
[flang][NFC] make IR generation for ieee_next deterministic (#125055)
C++ function call argument evaluation order is unspecified. When piping
functions that generates IR, this creates indeterminism in the IR
generated by flang (e.g., depend which C++ compiler compiled flang).
While it has interesting fuzzing property for flang (Initially, most of
expression lowering used that pattern for binary operation where Fortran
also does not specify any order, and we did found bugs exposed by some
of the IR version and not the other), it is not ideal for lit tests (I
found this because of a CI failure when not properly adding `-DAG` [in
test updates](https://github.com/llvm/llvm-project/pull/124966)), and
many people also really value bit to bit reproducibility from compilers.
-rw-r--r-- | flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 970fb2b..a6a77dd 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -6366,10 +6366,12 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, mlir::FloatType xType = mlir::dyn_cast<mlir::FloatType>(x.getType()); const unsigned xBitWidth = xType.getWidth(); mlir::Type i1Ty = builder.getI1Type(); - if constexpr (proc == NearestProc::NextAfter) + if constexpr (proc == NearestProc::NextAfter) { // If isNan(Y), set X to a qNaN that will propagate to the resultIsX result. - x = builder.create<mlir::arith::SelectOp>( - loc, genIsFPClass(i1Ty, args[1], nanTest), genQNan(xType), x); + mlir::Value qNan = genQNan(xType); + mlir::Value isFPClass = genIsFPClass(i1Ty, args[1], nanTest); + x = builder.create<mlir::arith::SelectOp>(loc, isFPClass, qNan, x); + } mlir::Value resultIsX = genIsFPClass(i1Ty, x, nanTest); mlir::Type intType = builder.getIntegerType(xBitWidth); mlir::Value one = builder.createIntegerConstant(loc, intType, 1); @@ -6489,12 +6491,11 @@ mlir::Value IntrinsicLibrary::genNearest(mlir::Type resultType, } else { // Kind 2, 3, 4, 8, 16. Increment or decrement X cast to integer. mlir::Value intX = builder.create<mlir::arith::BitcastOp>(loc, intType, x); + mlir::Value add = builder.create<mlir::arith::AddIOp>(loc, intX, one); + mlir::Value sub = builder.create<mlir::arith::SubIOp>(loc, intX, one); result = builder.create<mlir::arith::BitcastOp>( loc, resultType, - builder.create<mlir::arith::SelectOp>( - loc, magnitudeUp, - builder.create<mlir::arith::AddIOp>(loc, intX, one), - builder.create<mlir::arith::SubIOp>(loc, intX, one))); + builder.create<mlir::arith::SelectOp>(loc, magnitudeUp, add, sub)); if constexpr (proc == NearestProc::Nearest || proc == NearestProc::NextAfter) { genRaiseExcept(_FORTRAN_RUNTIME_IEEE_OVERFLOW | |