diff options
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/ConstantFPRange.cpp | 92 | ||||
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/IR/Core.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 2 |
5 files changed, 106 insertions, 22 deletions
diff --git a/llvm/lib/IR/ConstantFPRange.cpp b/llvm/lib/IR/ConstantFPRange.cpp index 070e833..e9c058e 100644 --- a/llvm/lib/IR/ConstantFPRange.cpp +++ b/llvm/lib/IR/ConstantFPRange.cpp @@ -8,6 +8,7 @@ #include "llvm/IR/ConstantFPRange.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/FloatingPointMode.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include <cassert> @@ -414,15 +415,31 @@ ConstantFPRange ConstantFPRange::negate() const { return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN); } +/// Return true if the finite part is not empty after removing infinities. +static bool removeInf(APFloat &Lower, APFloat &Upper, bool &HasPosInf, + bool &HasNegInf) { + assert(strictCompare(Lower, Upper) != APFloat::cmpGreaterThan && + "Non-NaN part is empty."); + auto &Sem = Lower.getSemantics(); + if (Lower.isNegInfinity()) { + Lower = APFloat::getLargest(Sem, /*Negative=*/true); + HasNegInf = true; + } + if (Upper.isPosInfinity()) { + Upper = APFloat::getLargest(Sem, /*Negative=*/false); + HasPosInf = true; + } + return strictCompare(Lower, Upper) != APFloat::cmpGreaterThan; +} + ConstantFPRange ConstantFPRange::getWithoutInf() const { if (isNaNOnly()) return *this; APFloat NewLower = Lower; APFloat NewUpper = Upper; - if (Lower.isNegInfinity()) - NewLower = APFloat::getLargest(getSemantics(), /*Negative=*/true); - if (Upper.isPosInfinity()) - NewUpper = APFloat::getLargest(getSemantics(), /*Negative=*/false); + bool UnusedFlag; + removeInf(NewLower, NewUpper, /*HasPosInf=*/UnusedFlag, + /*HasNegInf=*/UnusedFlag); canonicalizeRange(NewLower, NewUpper); return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN, MayBeSNaN); @@ -444,3 +461,70 @@ ConstantFPRange ConstantFPRange::cast(const fltSemantics &DstSem, /*MayBeQNaNVal=*/MayBeQNaN || MayBeSNaN, /*MayBeSNaNVal=*/false); } + +ConstantFPRange ConstantFPRange::add(const ConstantFPRange &Other) const { + bool ResMayBeQNaN = ((MayBeQNaN || MayBeSNaN) && !Other.isEmptySet()) || + ((Other.MayBeQNaN || Other.MayBeSNaN) && !isEmptySet()); + if (isNaNOnly() || Other.isNaNOnly()) + return getNaNOnly(getSemantics(), /*MayBeQNaN=*/ResMayBeQNaN, + /*MayBeSNaN=*/false); + bool LHSHasNegInf = false, LHSHasPosInf = false; + APFloat LHSLower = Lower, LHSUpper = Upper; + bool LHSFiniteIsNonEmpty = + removeInf(LHSLower, LHSUpper, LHSHasPosInf, LHSHasNegInf); + bool RHSHasNegInf = false, RHSHasPosInf = false; + APFloat RHSLower = Other.Lower, RHSUpper = Other.Upper; + bool RHSFiniteIsNonEmpty = + removeInf(RHSLower, RHSUpper, RHSHasPosInf, RHSHasNegInf); + // -inf + +inf = QNaN + ResMayBeQNaN |= + (LHSHasNegInf && RHSHasPosInf) || (LHSHasPosInf && RHSHasNegInf); + // +inf + finite/+inf = +inf, -inf + finite/-inf = -inf + bool HasNegInf = (LHSHasNegInf && (RHSFiniteIsNonEmpty || RHSHasNegInf)) || + (RHSHasNegInf && (LHSFiniteIsNonEmpty || LHSHasNegInf)); + bool HasPosInf = (LHSHasPosInf && (RHSFiniteIsNonEmpty || RHSHasPosInf)) || + (RHSHasPosInf && (LHSFiniteIsNonEmpty || LHSHasPosInf)); + if (LHSFiniteIsNonEmpty && RHSFiniteIsNonEmpty) { + APFloat NewLower = + HasNegInf ? APFloat::getInf(LHSLower.getSemantics(), /*Negative=*/true) + : LHSLower + RHSLower; + APFloat NewUpper = + HasPosInf ? APFloat::getInf(LHSUpper.getSemantics(), /*Negative=*/false) + : LHSUpper + RHSUpper; + return ConstantFPRange(NewLower, NewUpper, ResMayBeQNaN, + /*MayBeSNaN=*/false); + } + // If both HasNegInf and HasPosInf are false, the non-NaN part is empty. + // We just return the canonical form [+inf, -inf] for the empty non-NaN set. + return ConstantFPRange( + APFloat::getInf(Lower.getSemantics(), /*Negative=*/HasNegInf), + APFloat::getInf(Upper.getSemantics(), /*Negative=*/!HasPosInf), + ResMayBeQNaN, + /*MayBeSNaN=*/false); +} + +ConstantFPRange ConstantFPRange::sub(const ConstantFPRange &Other) const { + // fsub X, Y = fadd X, (fneg Y) + return add(Other.negate()); +} + +void ConstantFPRange::flushDenormals(DenormalMode::DenormalModeKind Mode) { + if (Mode == DenormalMode::IEEE) + return; + FPClassTest Class = classify(); + if (!(Class & fcSubnormal)) + return; + + auto &Sem = getSemantics(); + // PreserveSign: PosSubnormal -> PosZero, NegSubnormal -> NegZero + // PositiveZero: PosSubnormal -> PosZero, NegSubnormal -> PosZero + // Dynamic: PosSubnormal -> PosZero, NegSubnormal -> NegZero/PosZero + bool ZeroLowerNegative = + Mode != DenormalMode::PositiveZero && (Class & fcNegSubnormal); + bool ZeroUpperNegative = + Mode == DenormalMode::PreserveSign && !(Class & fcPosSubnormal); + assert((ZeroLowerNegative || !ZeroUpperNegative) && + "ZeroLower is greater than ZeroUpper."); + Lower = minnum(Lower, APFloat::getZero(Sem, ZeroLowerNegative)); + Upper = maxnum(Upper, APFloat::getZero(Sem, ZeroUpperNegative)); +} diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 2c2950c..cbce8bd 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -667,8 +667,11 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { if (CE->getOpcode() == Instruction::Sub) { ConstantExpr *LHS = dyn_cast<ConstantExpr>(CE->getOperand(0)); ConstantExpr *RHS = dyn_cast<ConstantExpr>(CE->getOperand(1)); - if (LHS && RHS && LHS->getOpcode() == Instruction::PtrToInt && - RHS->getOpcode() == Instruction::PtrToInt) { + if (LHS && RHS && + (LHS->getOpcode() == Instruction::PtrToInt || + LHS->getOpcode() == Instruction::PtrToAddr) && + (RHS->getOpcode() == Instruction::PtrToInt || + RHS->getOpcode() == Instruction::PtrToAddr)) { Constant *LHSOp0 = LHS->getOperand(0); Constant *RHSOp0 = RHS->getOperand(0); diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 3f1cc1e..27d8294 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -4098,15 +4098,8 @@ LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str, return wrap(unwrap(B)->CreateGlobalString(Str, Name)); } -LLVMBool LLVMGetVolatile(LLVMValueRef MemAccessInst) { - Value *P = unwrap(MemAccessInst); - if (LoadInst *LI = dyn_cast<LoadInst>(P)) - return LI->isVolatile(); - if (StoreInst *SI = dyn_cast<StoreInst>(P)) - return SI->isVolatile(); - if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(P)) - return AI->isVolatile(); - return cast<AtomicCmpXchgInst>(P)->isVolatile(); +LLVMBool LLVMGetVolatile(LLVMValueRef Inst) { + return cast<Instruction>(unwrap(Inst))->isVolatile(); } void LLVMSetVolatile(LLVMValueRef MemAccessInst, LLVMBool isVolatile) { diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 88e7c44..9060a89 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2965,8 +2965,7 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp, // zext, sext -> zext, because sext can't sign extend after zext return Instruction::ZExt; case 11: { - // inttoptr, ptrtoint/ptrtoaddr -> bitcast if SrcSize<=PtrSize/AddrSize - // and SrcSize==DstSize + // inttoptr, ptrtoint/ptrtoaddr -> integer cast if (!DL) return 0; unsigned MidSize = secondOp == Instruction::PtrToAddr @@ -2974,10 +2973,15 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp, : DL->getPointerTypeSizeInBits(MidTy); unsigned SrcSize = SrcTy->getScalarSizeInBits(); unsigned DstSize = DstTy->getScalarSizeInBits(); - // TODO: Could also produce zext or trunc here. - if (SrcSize <= MidSize && SrcSize == DstSize) - return Instruction::BitCast; - return 0; + // If the middle size is smaller than both source and destination, + // an additional masking operation would be required. + if (MidSize < SrcSize && MidSize < DstSize) + return 0; + if (DstSize < SrcSize) + return Instruction::Trunc; + if (DstSize > SrcSize) + return Instruction::ZExt; + return Instruction::BitCast; } case 12: // addrspacecast, addrspacecast -> bitcast, if SrcAS == DstAS diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index c9ff86b..c79a950 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -893,7 +893,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { if (GV.hasInitializer()) { const Constant *Init = GV.getInitializer(); const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); - Check(InitArray, "wrong initalizer for intrinsic global variable", + Check(InitArray, "wrong initializer for intrinsic global variable", Init); for (Value *Op : InitArray->operands()) { Value *V = Op->stripPointerCasts(); |