aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjeanPerier <jperier@nvidia.com>2025-01-30 14:24:45 +0100
committerGitHub <noreply@github.com>2025-01-30 14:24:45 +0100
commit2e581dc54b8983122528ade578824d70ec42b503 (patch)
tree4f9c90987347b9b0b9206d556968b04cd2aacb75
parent104c2b86a5e9f4871707b25399735f0e5db58745 (diff)
downloadllvm-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.cpp15
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 |