21
21
#include " llvm/Analysis/ValueTracking.h"
22
22
#include " llvm/IR/Dominators.h"
23
23
#include " llvm/IR/Function.h"
24
+ #include " llvm/IR/IRBuilder.h"
24
25
#include " llvm/IR/Instructions.h"
25
26
#include " llvm/IR/PatternMatch.h"
26
27
#include " llvm/InitializePasses.h"
@@ -517,6 +518,55 @@ void State::addInfoFor(BasicBlock &BB) {
517
518
WorkList.emplace_back (DT.getNode (Br->getSuccessor (1 )), CmpI, true );
518
519
}
519
520
521
+ static void
522
+ tryToSimplifyOverflowMath (IntrinsicInst *II, ConstraintInfo &Info,
523
+ SmallVectorImpl<Instruction *> &ToRemove) {
524
+ auto DoesConditionHold = [](CmpInst::Predicate Pred, Value *A, Value *B,
525
+ ConstraintInfo &Info) {
526
+ DenseMap<Value *, unsigned > NewIndices;
527
+ auto R = getConstraint (
528
+ Pred, A, B, Info.getValue2Index (CmpInst::isSigned (Pred)), NewIndices);
529
+ if (R.size () < 2 || R.needsNewIndices (NewIndices) || !R.isValid (Info))
530
+ return false ;
531
+
532
+ auto &CSToUse = Info.getCS (CmpInst::isSigned (Pred));
533
+ return CSToUse.isConditionImplied (R.Coefficients );
534
+ };
535
+
536
+ if (II->getIntrinsicID () == Intrinsic::ssub_with_overflow) {
537
+ // If A s>= B && B s>= 0, ssub.with.overflow(a, b) should not overflow and
538
+ // can be simplified to a regular sub.
539
+ Value *A = II->getArgOperand (0 );
540
+ Value *B = II->getArgOperand (1 );
541
+ if (!DoesConditionHold (CmpInst::ICMP_SGE, A, B, Info) ||
542
+ !DoesConditionHold (CmpInst::ICMP_SGE, B,
543
+ ConstantInt::get (A->getType (), 0 ), Info))
544
+ return ;
545
+
546
+ IRBuilder<> Builder (II->getParent (), II->getIterator ());
547
+ Value *Sub = nullptr ;
548
+ for (User *U : make_early_inc_range (II->users ())) {
549
+ if (match (U, m_ExtractValue<0 >(m_Value ()))) {
550
+ if (!Sub)
551
+ Sub = Builder.CreateSub (A, B);
552
+ U->replaceAllUsesWith (Sub);
553
+ } else if (match (U, m_ExtractValue<1 >(m_Value ())))
554
+ U->replaceAllUsesWith (Builder.getFalse ());
555
+ else
556
+ continue ;
557
+
558
+ if (U->use_empty ()) {
559
+ auto *I = cast<Instruction>(U);
560
+ ToRemove.push_back (I);
561
+ I->setOperand (0 , PoisonValue::get (II->getType ()));
562
+ }
563
+ }
564
+
565
+ if (II->use_empty ())
566
+ II->eraseFromParent ();
567
+ }
568
+ }
569
+
520
570
static bool eliminateConstraints (Function &F, DominatorTree &DT) {
521
571
bool Changed = false ;
522
572
DT.updateDFSNumbers ();
@@ -540,6 +590,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
540
590
return std::tie (A.NumIn , A.IsBlock ) < std::tie (B.NumIn , B.IsBlock );
541
591
});
542
592
593
+ SmallVector<Instruction *> ToRemove;
594
+
543
595
// Finally, process ordered worklist and eliminate implied conditions.
544
596
SmallVector<StackEntry, 16 > DFSInStack;
545
597
for (ConstraintOrBlock &CB : S.WorkList ) {
@@ -576,7 +628,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
576
628
// For a block, check if any CmpInsts become known based on the current set
577
629
// of constraints.
578
630
if (CB.IsBlock ) {
579
- for (Instruction &I : *CB.BB ) {
631
+ for (Instruction &I : make_early_inc_range (*CB.BB )) {
632
+ if (auto *II = dyn_cast<WithOverflowInst>(&I)) {
633
+ tryToSimplifyOverflowMath (II, Info, ToRemove);
634
+ continue ;
635
+ }
580
636
auto *Cmp = dyn_cast<ICmpInst>(&I);
581
637
if (!Cmp)
582
638
continue ;
@@ -699,6 +755,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
699
755
" updates to CS and DFSInStack are out of sync" );
700
756
#endif
701
757
758
+ for (Instruction *I : ToRemove)
759
+ I->eraseFromParent ();
702
760
return Changed;
703
761
}
704
762
0 commit comments