diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -63,6 +63,15 @@ STATISTIC(NumAShrs, "Number of ashr converted to lshr"); STATISTIC(NumSRems, "Number of srem converted to urem"); STATISTIC(NumSExt, "Number of sext converted to zext"); +STATISTIC(NumNW, "Number of no-wrap deductions"); +STATISTIC(NumNSW, "Number of no-signed-wrap deductions"); +STATISTIC(NumNUW, "Number of no-unsigned-wrap deductions"); +STATISTIC(NumAddNSW, "Number of add deduced to be nsw"); +STATISTIC(NumAddNUW, "Number of add deduced to be nuw"); +STATISTIC(NumSubNSW, "Number of sub deduced to be nsw"); +STATISTIC(NumSubNUW, "Number of sub deduced to be nuw"); +STATISTIC(NumMulNSW, "Number of mul deduced to be nsw"); +STATISTIC(NumMulNUW, "Number of mul deduced to be nuw"); STATISTIC(NumOverflows, "Number of overflow checks removed"); STATISTIC(NumSaturating, "Number of saturating arithmetics converted to normal arithmetics"); @@ -418,18 +427,55 @@ return NWRegion.contains(LRange); } +static void overflowingBinaryOperatorFlagsDeduced(Value *V, + Instruction::BinaryOps Opcode, + bool NewNSW, bool NewNUW) { + if (auto *Inst = dyn_cast(V)) { + if (NewNSW) { + ++NumNW; + ++NumNSW; + Inst->setHasNoSignedWrap(); + } + if (NewNUW) { + ++NumNW; + ++NumNUW; + Inst->setHasNoUnsignedWrap(); + } + } + switch (Opcode) { + case Instruction::Add: + if (NewNSW) + ++NumAddNSW; + if (NewNUW) + ++NumAddNUW; + break; + case Instruction::Sub: + if (NewNSW) + ++NumSubNSW; + if (NewNUW) + ++NumSubNUW; + break; + case Instruction::Mul: + if (NewNSW) + ++NumMulNSW; + if (NewNUW) + ++NumMulNUW; + break; + default: + llvm_unreachable("Will not be called with other binops"); + } +} + // Rewrite this with.overflow intrinsic as non-overflowing. static void processOverflowIntrinsic(WithOverflowInst *WO) { IRBuilder<> B(WO); - Value *NewOp = B.CreateBinOp( - WO->getBinaryOp(), WO->getLHS(), WO->getRHS(), WO->getName()); - // Constant-folding could have happened. - if (auto *Inst = dyn_cast(NewOp)) { - if (WO->isSigned()) - Inst->setHasNoSignedWrap(); - else - Inst->setHasNoUnsignedWrap(); - } + Instruction::BinaryOps Opcode = WO->getBinaryOp(); + bool NSW = WO->isSigned(); + bool NUW = !WO->isSigned(); + + Value *NewOp = + B.CreateBinOp(Opcode, WO->getLHS(), WO->getRHS(), WO->getName()); + overflowingBinaryOperatorFlagsDeduced(NewOp, Opcode, NSW, NUW); StructType *ST = cast(WO->getType()); Constant *Struct = ConstantStruct::get(ST, @@ -442,13 +488,13 @@ } static void processSaturatingInst(SaturatingInst *SI) { + Instruction::BinaryOps Opcode = SI->getBinaryOp(); + bool NSW = SI->isSigned(); + bool NUW = !SI->isSigned(); BinaryOperator *BinOp = BinaryOperator::Create( - SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI); + Opcode, SI->getLHS(), SI->getRHS(), SI->getName(), SI); BinOp->setDebugLoc(SI->getDebugLoc()); - if (SI->isSigned()) - BinOp->setHasNoSignedWrap(); - else - BinOp->setHasNoUnsignedWrap(); + overflowingBinaryOperatorFlagsDeduced(BinOp, Opcode, NSW, NUW); SI->replaceAllUsesWith(BinOp); SI->eraseFromParent(); @@ -675,6 +721,7 @@ BasicBlock *BB = BinOp->getParent(); + Instruction::BinaryOps Opcode = BinOp->getOpcode(); Value *LHS = BinOp->getOperand(0); Value *RHS = BinOp->getOperand(1); @@ -682,21 +729,22 @@ ConstantRange RRange = LVI->getConstantRange(RHS, BB, BinOp); bool Changed = false; + bool NewNUW = false, NewNSW = false; if (!NUW) { ConstantRange NUWRange = ConstantRange::makeGuaranteedNoWrapRegion( - BinOp->getOpcode(), RRange, OBO::NoUnsignedWrap); - bool NewNUW = NUWRange.contains(LRange); - BinOp->setHasNoUnsignedWrap(NewNUW); + Opcode, RRange, OBO::NoUnsignedWrap); + NewNUW = NUWRange.contains(LRange); Changed |= NewNUW; } if (!NSW) { ConstantRange NSWRange = ConstantRange::makeGuaranteedNoWrapRegion( - BinOp->getOpcode(), RRange, OBO::NoSignedWrap); - bool NewNSW = NSWRange.contains(LRange); - BinOp->setHasNoSignedWrap(NewNSW); + Opcode, RRange, OBO::NoSignedWrap); + NewNSW = NSWRange.contains(LRange); Changed |= NewNSW; } + overflowingBinaryOperatorFlagsDeduced(BinOp, Opcode, NewNSW, NewNUW); + return Changed; }