7878#include < cstdint>
7979#include < optional>
8080#include < utility>
81+ #include < variant>
8182
8283using namespace llvm ;
8384using namespace llvm ::PatternMatch;
@@ -87,6 +88,9 @@ using namespace llvm::PatternMatch;
8788static cl::opt<unsigned > DomConditionsMaxUses (" dom-conditions-max-uses" ,
8889 cl::Hidden, cl::init(20 ));
8990
91+ // Checks whether we will lose information after simplification.
92+ static cl::opt<bool > DetectInformationLoss (" detect-information-loss" ,
93+ cl::Hidden, cl::init(false ));
9094
9195// / Returns the bitwidth of the given scalar or pointer type. For vector types,
9296// / returns the element type's bitwidth.
@@ -9053,3 +9057,101 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned,
90539057
90549058 return CR;
90559059}
9060+
9061+ #ifndef NDEBUG
9062+ llvm::ValueTrackingCache::ValueTrackingCache (Instruction *FromInst,
9063+ const SimplifyQuery &SQ)
9064+ : From(FromInst) {
9065+ if (!DetectInformationLoss)
9066+ return ;
9067+
9068+ NoPoison = isGuaranteedNotToBePoison (From, SQ.AC , From, SQ.DT );
9069+ NoUndef = isGuaranteedNotToBeUndef (From, SQ.AC , From, SQ.DT );
9070+
9071+ Type *Ty = From->getType ();
9072+ if (Ty->isIntOrIntVectorTy () || Ty->isPtrOrPtrVectorTy ()) {
9073+ // KnownBits
9074+ KnownBits Known =
9075+ computeKnownBits (From, /* Depth=*/ 0 , SQ.getWithInstruction (From));
9076+ if (!Known.isUnknown ())
9077+ BeforeKnown = Known;
9078+ } else if (Ty->isFPOrFPVectorTy ()) {
9079+ // KnownFPClass
9080+ // TODO: use FMF flags
9081+ KnownFPClass Known = computeKnownFPClass (From, fcAllFlags, /* Depth=*/ 0 ,
9082+ SQ.getWithInstruction (From));
9083+ if (Known.KnownFPClasses != fcAllFlags || Known.SignBit )
9084+ BeforeKnown = Known;
9085+ }
9086+ }
9087+
9088+ void llvm::ValueTrackingCache::detectInformationLoss (Value *To,
9089+ const SimplifyQuery &SQ) {
9090+ if (!DetectInformationLoss)
9091+ return ;
9092+
9093+ Instruction *ToInst = dyn_cast<Instruction>(To);
9094+ if (!ToInst)
9095+ return ;
9096+
9097+ bool Inserted = false ;
9098+ if (!ToInst->getParent ()) {
9099+ ToInst->insertAfter (From);
9100+ Inserted = true ;
9101+ }
9102+
9103+ auto WarnOnInformationLoss = [&](StringRef Attr) {
9104+ errs () << " Warning: the attribute " << Attr << " got lost when simplifying "
9105+ << *From << " into " << *To << ' \n ' ;
9106+ };
9107+
9108+ // Poison
9109+ if (NoPoison && !isGuaranteedNotToBePoison (To, SQ.AC , ToInst, SQ.DT ))
9110+ WarnOnInformationLoss (" non-poison" );
9111+
9112+ // Undef
9113+ if (NoUndef && !isGuaranteedNotToBeUndef (To, SQ.AC , ToInst, SQ.DT ))
9114+ WarnOnInformationLoss (" non-undef" );
9115+
9116+ Type *Ty = From->getType ();
9117+ if ((Ty->isIntOrIntVectorTy () || Ty->isPtrOrPtrVectorTy ()) &&
9118+ std::holds_alternative<KnownBits>(BeforeKnown)) {
9119+ KnownBits &Before = std::get<KnownBits>(BeforeKnown);
9120+ KnownBits After =
9121+ computeKnownBits (To, /* Depth=*/ 0 , SQ.getWithInstruction (ToInst));
9122+ // KnownBits of From should be a subset of KnownBits of To.
9123+ if (!Before.Zero .isSubsetOf (After.Zero ) ||
9124+ !Before.One .isSubsetOf (After.One )) {
9125+ WarnOnInformationLoss (" knownbits" );
9126+ errs () << " Before: " << Before << ' \n ' ;
9127+ errs () << " After: " << After << ' \n ' ;
9128+ }
9129+ assert ((Before.One & After.Zero ).isZero () && " Possible miscompilation" );
9130+ assert ((Before.Zero & After.One ).isZero () && " Possible miscompilation" );
9131+ } else if (Ty->isFPOrFPVectorTy () &&
9132+ std::holds_alternative<KnownFPClass>(BeforeKnown)) {
9133+ // KnownFPClass
9134+ KnownFPClass &Before = std::get<KnownFPClass>(BeforeKnown);
9135+ // TODO: use FMF flags
9136+ KnownFPClass After = computeKnownFPClass (To, fcAllFlags, /* Depth=*/ 0 ,
9137+ SQ.getWithInstruction (ToInst));
9138+ // KnownFPClass of From should be a subset of KnownFPClass of To.
9139+ if ((Before.KnownFPClasses & After.KnownFPClasses ) !=
9140+ Before.KnownFPClasses ) {
9141+ WarnOnInformationLoss (" fpclasses" );
9142+ errs () << " Before: " << Before.KnownFPClasses << ' \n ' ;
9143+ errs () << " After: " << After.KnownFPClasses << ' \n ' ;
9144+ }
9145+ assert ((Before.KnownFPClasses & After.KnownFPClasses ) != fcNone &&
9146+ " Possible miscompilation" );
9147+ if (Before.SignBit .has_value () && !After.SignBit .has_value ())
9148+ WarnOnInformationLoss (" sign" );
9149+ assert ((!Before.SignBit .has_value () || !After.SignBit .has_value () ||
9150+ Before.SignBit == After.SignBit ) &&
9151+ " Possible miscompilation" );
9152+ }
9153+
9154+ if (Inserted)
9155+ ToInst->removeFromParent ();
9156+ }
9157+ #endif
0 commit comments