@@ -412,19 +412,27 @@ class LazyValueInfoImpl {
412412 BasicBlock *BB);
413413 std::optional<ConstantRange> getRangeFor (Value *V, Instruction *CxtI,
414414 BasicBlock *BB);
415+ std::optional<ConstantFPRange> getFPRangeFor (Value *V, Instruction *CxtI,
416+ BasicBlock *BB);
415417 std::optional<ValueLatticeElement> solveBlockValueBinaryOpImpl (
416418 Instruction *I, BasicBlock *BB,
417419 std::function<ConstantRange(const ConstantRange &, const ConstantRange &)>
418420 OpFn);
419421 std::optional<ValueLatticeElement>
420422 solveBlockValueBinaryOp (BinaryOperator *BBI, BasicBlock *BB);
423+ std::optional<ValueLatticeElement>
424+ solveBlockValueFPBinaryOp (BinaryOperator *BBI, BasicBlock *BB);
421425 std::optional<ValueLatticeElement> solveBlockValueCast (CastInst *CI,
422426 BasicBlock *BB);
427+ std::optional<ValueLatticeElement> solveBlockValueFPCast (CastInst *CI,
428+ BasicBlock *BB);
423429 std::optional<ValueLatticeElement>
424430 solveBlockValueOverflowIntrinsic (WithOverflowInst *WO, BasicBlock *BB);
425431 std::optional<ValueLatticeElement> solveBlockValueIntrinsic (IntrinsicInst *II,
426432 BasicBlock *BB);
427433 std::optional<ValueLatticeElement>
434+ solveBlockValueFPIntrinsic (IntrinsicInst *II, BasicBlock *BB);
435+ std::optional<ValueLatticeElement>
428436 solveBlockValueInsertElement (InsertElementInst *IEI, BasicBlock *BB);
429437 std::optional<ValueLatticeElement>
430438 solveBlockValueExtractValue (ExtractValueInst *EVI, BasicBlock *BB);
@@ -671,6 +679,26 @@ LazyValueInfoImpl::solveBlockValueImpl(Value *Val, BasicBlock *BB) {
671679 return solveBlockValueIntrinsic (II, BB);
672680 }
673681
682+ if (BBI->getType ()->isFPOrFPVectorTy ()) {
683+ if (BBI->getOpcode () == Instruction::FNeg) {
684+ std::optional<ConstantFPRange> OpRes =
685+ getFPRangeFor (BBI->getOperand (0 ), BBI, BB);
686+ if (!OpRes)
687+ // More work to do before applying this transfer rule.
688+ return std::nullopt ;
689+ return ValueLatticeElement::getFPRange (OpRes->negate ());
690+ }
691+
692+ if (auto *CI = dyn_cast<CastInst>(BBI))
693+ return solveBlockValueFPCast (CI, BB);
694+
695+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI))
696+ return solveBlockValueFPBinaryOp (BO, BB);
697+
698+ if (auto *II = dyn_cast<IntrinsicInst>(BBI))
699+ return solveBlockValueFPIntrinsic (II, BB);
700+ }
701+
674702 LLVM_DEBUG (dbgs () << " compute BB '" << BB->getName ()
675703 << " ' - unknown inst def found.\n " );
676704 return getFromRangeMetadata (BBI);
@@ -967,6 +995,14 @@ LazyValueInfoImpl::getRangeFor(Value *V, Instruction *CxtI, BasicBlock *BB) {
967995 return OptVal->asConstantRange (V->getType ());
968996}
969997
998+ std::optional<ConstantFPRange>
999+ LazyValueInfoImpl::getFPRangeFor (Value *V, Instruction *CxtI, BasicBlock *BB) {
1000+ std::optional<ValueLatticeElement> OptVal = getBlockValue (V, BB, CxtI);
1001+ if (!OptVal)
1002+ return std::nullopt ;
1003+ return OptVal->asConstantFPRange (V->getType ());
1004+ }
1005+
9701006std::optional<ValueLatticeElement>
9711007LazyValueInfoImpl::solveBlockValueCast (CastInst *CI, BasicBlock *BB) {
9721008 // Filter out casts we don't know how to reason about before attempting to
@@ -1007,6 +1043,47 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
10071043 return ValueLatticeElement::getRange (Res);
10081044}
10091045
1046+ static void postProcessFPRange (ConstantFPRange &R,
1047+ DenormalMode::DenormalModeKind Mode,
1048+ FastMathFlags FMF) {
1049+ if (FMF.noNaNs ())
1050+ R = R.getWithoutNaN ();
1051+ if (FMF.noInfs ())
1052+ R = R.getWithoutInf ();
1053+ R.flushDenormals (Mode);
1054+ }
1055+
1056+ std::optional<ValueLatticeElement>
1057+ LazyValueInfoImpl::solveBlockValueFPCast (CastInst *CI, BasicBlock *BB) {
1058+ // Filter out casts we don't know how to reason about before attempting to
1059+ // recurse on our operand. This can cut a long search short if we know we're
1060+ // not going to be able to get any useful information anways.
1061+ switch (CI->getOpcode ()) {
1062+ case Instruction::FPExt:
1063+ case Instruction::FPTrunc:
1064+ break ;
1065+ default :
1066+ // Unhandled instructions are overdefined.
1067+ LLVM_DEBUG (dbgs () << " compute BB '" << BB->getName ()
1068+ << " ' - overdefined (unknown cast).\n " );
1069+ return ValueLatticeElement::getOverdefined ();
1070+ }
1071+
1072+ std::optional<ConstantFPRange> OpRes =
1073+ getFPRangeFor (CI->getOperand (0 ), CI, BB);
1074+ if (!OpRes)
1075+ // More work to do before applying this transfer rule.
1076+ return std::nullopt ;
1077+ ConstantFPRange &Op = *OpRes;
1078+ FastMathFlags FMF = CI->getFastMathFlags ();
1079+ auto &Sem = CI->getDestTy ()->getScalarType ()->getFltSemantics ();
1080+ auto DenormalMode = BB->getParent ()->getDenormalMode (Sem);
1081+ postProcessFPRange (Op, DenormalMode.Input , FMF);
1082+ ConstantFPRange Res = Op.cast (Sem);
1083+ postProcessFPRange (Res, DenormalMode.Output , FMF);
1084+ return ValueLatticeElement::getFPRange (std::move (Res));
1085+ }
1086+
10101087std::optional<ValueLatticeElement>
10111088LazyValueInfoImpl::solveBlockValueBinaryOpImpl (
10121089 Instruction *I, BasicBlock *BB,
@@ -1165,6 +1242,46 @@ LazyValueInfoImpl::solveBlockValueBinaryOp(BinaryOperator *BO, BasicBlock *BB) {
11651242 });
11661243}
11671244
1245+ std::optional<ValueLatticeElement>
1246+ LazyValueInfoImpl::solveBlockValueFPBinaryOp (BinaryOperator *BO,
1247+ BasicBlock *BB) {
1248+ FastMathFlags FMF = BO->getFastMathFlags ();
1249+ Function *F = BB->getParent ();
1250+ auto LHSRes = getFPRangeFor (BO->getOperand (0 ), BO, BB);
1251+ if (!LHSRes)
1252+ return std::nullopt ;
1253+ auto RHSRes = getFPRangeFor (BO->getOperand (1 ), BO, BB);
1254+ if (!RHSRes)
1255+ return std::nullopt ;
1256+ auto &LHSRange = *LHSRes;
1257+ auto &RHSRange = *RHSRes;
1258+ auto &Sem = LHSRange.getSemantics ();
1259+ auto DenormalMode = F->getDenormalMode (Sem);
1260+ postProcessFPRange (LHSRange, DenormalMode.Input , FMF);
1261+ postProcessFPRange (RHSRange, DenormalMode.Output , FMF);
1262+ ConstantFPRange Res = ConstantFPRange::getFull (Sem);
1263+ switch (BO->getOpcode ()) {
1264+ case Instruction::FAdd:
1265+ Res = LHSRange.add (RHSRange);
1266+ break ;
1267+ case Instruction::FSub:
1268+ Res = LHSRange.sub (RHSRange);
1269+ break ;
1270+ case Instruction::FMul:
1271+ Res = LHSRange.mul (RHSRange);
1272+ break ;
1273+ case Instruction::FDiv:
1274+ Res = LHSRange.div (RHSRange);
1275+ break ;
1276+ case Instruction::FRem:
1277+ break ;
1278+ default :
1279+ llvm_unreachable (" Unknown FP binary operator." );
1280+ }
1281+ postProcessFPRange (Res, DenormalMode.Output , FMF);
1282+ return ValueLatticeElement::getFPRange (Res);
1283+ }
1284+
11681285std::optional<ValueLatticeElement>
11691286LazyValueInfoImpl::solveBlockValueOverflowIntrinsic (WithOverflowInst *WO,
11701287 BasicBlock *BB) {
@@ -1196,6 +1313,42 @@ LazyValueInfoImpl::solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB) {
11961313 .intersect (MetadataVal);
11971314}
11981315
1316+ std::optional<ValueLatticeElement>
1317+ LazyValueInfoImpl::solveBlockValueFPIntrinsic (IntrinsicInst *II,
1318+ BasicBlock *BB) {
1319+ Intrinsic::ID IID = II->getIntrinsicID ();
1320+ switch (IID) {
1321+ case Intrinsic::fabs:
1322+ case Intrinsic::copysign:
1323+ break ;
1324+ default :
1325+ return ValueLatticeElement::getOverdefined ();
1326+ }
1327+ SmallVector<ConstantFPRange, 2 > OpRanges;
1328+ for (Value *Op : II->args ()) {
1329+ std::optional<ConstantFPRange> Range = getFPRangeFor (Op, II, BB);
1330+ if (!Range)
1331+ return std::nullopt ;
1332+ OpRanges.push_back (*Range);
1333+ }
1334+ switch (IID) {
1335+ case Intrinsic::fabs:
1336+ return ValueLatticeElement::getFPRange (OpRanges[0 ].abs ());
1337+ case Intrinsic::copysign: {
1338+ ConstantFPRange Mag = OpRanges[0 ].abs ();
1339+ std::optional<bool > Sign = OpRanges[1 ].getSignBit ();
1340+ if (Sign.has_value ()) {
1341+ if (*Sign)
1342+ return ValueLatticeElement::getFPRange (Mag.negate ());
1343+ return ValueLatticeElement::getFPRange (Mag);
1344+ }
1345+ return ValueLatticeElement::getFPRange (Mag.negate ().unionWith (Mag));
1346+ }
1347+ default :
1348+ llvm_unreachable (" Unsupported FP intrinsic." );
1349+ }
1350+ }
1351+
11991352std::optional<ValueLatticeElement>
12001353LazyValueInfoImpl::solveBlockValueInsertElement (InsertElementInst *IEI,
12011354 BasicBlock *BB) {
0 commit comments