[GlobalISel] Implement lowering for G_ISNAN + use it in AArch64
GlobalISel equivalent to `TargetLowering::expandISNAN`.
Use it in AArch64 and add a testcase.
Differential Revision: https://reviews.llvm.org/D108227
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 2ce3274..611cf10 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@@ -3486,6 +3487,8 @@
case G_ROTL:
case G_ROTR:
return lowerRotate(MI);
+ case G_ISNAN:
+ return lowerIsNaN(MI);
}
}
@@ -7355,3 +7358,34 @@
MI.eraseFromParent();
return Legalized;
}
+
+LegalizerHelper::LegalizeResult LegalizerHelper::lowerIsNaN(MachineInstr &MI) {
+ Register Dst = MI.getOperand(0).getReg();
+ Register Src = MI.getOperand(1).getReg();
+ LLT SrcTy = MRI.getType(Src);
+ if (MI.getFlags() & MachineInstr::NoFPExcept) {
+ // Lower to an unordered comparison.
+ auto Zero = MIRBuilder.buildFConstant(SrcTy, 0.0);
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_UNO, Dst, Src, Zero);
+ MI.eraseFromParent();
+ return Legalized;
+ }
+
+ // Use integer operations to avoid traps if the argument is SNaN.
+
+ // NaN has all exp bits set and a non zero significand. Therefore:
+ // isnan(V) == exp mask < abs(V)
+ auto FPToSI = MIRBuilder.buildFPTOSI(SrcTy, Src);
+ auto Mask = APInt::getSignedMaxValue(SrcTy.getScalarSizeInBits());
+ auto MaskCst = MIRBuilder.buildConstant(SrcTy, Mask);
+ auto AbsV = MIRBuilder.buildAnd(SrcTy, FPToSI, MaskCst);
+ auto *FloatTy = getFloatTypeForLLT(MI.getMF()->getFunction().getContext(),
+ SrcTy.getScalarType());
+ if (!FloatTy)
+ return UnableToLegalize;
+ auto ExpMask = APFloat::getInf(FloatTy->getFltSemantics()).bitcastToAPInt();
+ auto ExpMaskCst = MIRBuilder.buildConstant(SrcTy, ExpMask);
+ MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_SLT, Dst, ExpMaskCst, AbsV);
+ MI.eraseFromParent();
+ return Legalized;
+}