STATISTIC(NumAShrs, "Number of ashr converted to lshr");
STATISTIC(NumSRems, "Number of srem converted to urem");
STATISTIC(NumOverflows, "Number of overflow checks removed");
-STATISTIC(NumSaturating,
- "Number of saturating arithmetics converted to normal arithmetics");
static cl::opt<bool> DontAddNoWrapFlags("cvp-dont-add-nowrap-flags", cl::init(true));
IRBuilder<> B(WO);
Value *NewOp = B.CreateBinOp(
WO->getBinaryOp(), WO->getLHS(), WO->getRHS(), WO->getName());
- // Constant-folding could have happened.
+ // Constant-holing could have happened.
if (auto *Inst = dyn_cast<Instruction>(NewOp)) {
if (WO->isSigned())
Inst->setHasNoSignedWrap();
++NumOverflows;
}
-static void processSaturatingInst(SaturatingInst *SI) {
- BinaryOperator *BinOp = BinaryOperator::Create(
- SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI);
- BinOp->setDebugLoc(SI->getDebugLoc());
- if (SI->isSigned())
- BinOp->setHasNoSignedWrap();
- else
- BinOp->setHasNoUnsignedWrap();
-
- SI->replaceAllUsesWith(BinOp);
- SI->eraseFromParent();
- ++NumSaturating;
-}
-
/// Infer nonnull attributes for the arguments at the specified callsite.
static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
SmallVector<unsigned, 4> ArgNos;
}
}
- if (auto *SI = dyn_cast<SaturatingInst>(CS.getInstruction())) {
- if (willNotOverflow(SI, LVI)) {
- processSaturatingInst(SI);
- return true;
- }
- }
-
// Deopt bundle operands are intended to capture state with minimal
// perturbance of the code otherwise. If we can find a constant value for
// any such operand and remove a use of the original value, that's
; CHECK-NEXT: call void @llvm.trap()
; CHECK-NEXT: unreachable
; CHECK: cont:
-; CHECK-NEXT: [[RES1:%.*]] = add nuw i8 [[X]], 100
-; CHECK-NEXT: ret i8 [[RES1]]
+; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X]], i8 100)
+; CHECK-NEXT: ret i8 [[RES]]
;
%cmp = icmp ugt i8 %x, 100
br i1 %cmp, label %trap, label %cont
; CHECK-NEXT: call void @llvm.trap()
; CHECK-NEXT: unreachable
; CHECK: cont:
-; CHECK-NEXT: [[RES1:%.*]] = add nsw i8 [[X]], 20
-; CHECK-NEXT: ret i8 [[RES1]]
+; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X]], i8 20)
+; CHECK-NEXT: ret i8 [[RES]]
;
%cmp = icmp sgt i8 %x, 100
br i1 %cmp, label %trap, label %cont
; CHECK-NEXT: call void @llvm.trap()
; CHECK-NEXT: unreachable
; CHECK: cont:
-; CHECK-NEXT: [[RES1:%.*]] = sub nuw i8 [[X]], 100
-; CHECK-NEXT: ret i8 [[RES1]]
+; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X]], i8 100)
+; CHECK-NEXT: ret i8 [[RES]]
;
%cmp = icmp ult i8 %x, 100
br i1 %cmp, label %trap, label %cont
; CHECK-NEXT: call void @llvm.trap()
; CHECK-NEXT: unreachable
; CHECK: cont:
-; CHECK-NEXT: [[RES1:%.*]] = sub nsw i8 [[X]], 20
-; CHECK-NEXT: ret i8 [[RES1]]
+; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X]], i8 20)
+; CHECK-NEXT: ret i8 [[RES]]
;
%cmp = icmp slt i8 %x, -100
br i1 %cmp, label %trap, label %cont