1*fe6060f1SDimitry Andric //==-- OverflowInstAnalysis.cpp - Utils to fold overflow insts ----*- C++ -*-=//
2*fe6060f1SDimitry Andric //
3*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fe6060f1SDimitry Andric //
7*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8*fe6060f1SDimitry Andric //
9*fe6060f1SDimitry Andric // This file holds routines to help analyse overflow instructions
10*fe6060f1SDimitry Andric // and fold them into constants or other overflow instructions
11*fe6060f1SDimitry Andric //
12*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13*fe6060f1SDimitry Andric 
14*fe6060f1SDimitry Andric #include "llvm/Analysis/OverflowInstAnalysis.h"
15*fe6060f1SDimitry Andric #include "llvm/IR/Instructions.h"
16*fe6060f1SDimitry Andric #include "llvm/IR/PatternMatch.h"
17*fe6060f1SDimitry Andric 
18*fe6060f1SDimitry Andric using namespace llvm;
19*fe6060f1SDimitry Andric using namespace llvm::PatternMatch;
20*fe6060f1SDimitry Andric 
isCheckForZeroAndMulWithOverflow(Value * Op0,Value * Op1,bool IsAnd,Use * & Y)21*fe6060f1SDimitry Andric bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
22*fe6060f1SDimitry Andric                                             Use *&Y) {
23*fe6060f1SDimitry Andric   ICmpInst::Predicate Pred;
24*fe6060f1SDimitry Andric   Value *X, *NotOp1;
25*fe6060f1SDimitry Andric   int XIdx;
26*fe6060f1SDimitry Andric   IntrinsicInst *II;
27*fe6060f1SDimitry Andric 
28*fe6060f1SDimitry Andric   if (!match(Op0, m_ICmp(Pred, m_Value(X), m_Zero())))
29*fe6060f1SDimitry Andric     return false;
30*fe6060f1SDimitry Andric 
31*fe6060f1SDimitry Andric   ///   %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %???)
32*fe6060f1SDimitry Andric   ///   %V = extractvalue { i4, i1 } %Agg, 1
33*fe6060f1SDimitry Andric   auto matchMulOverflowCheck = [X, &II, &XIdx](Value *V) {
34*fe6060f1SDimitry Andric     auto *Extract = dyn_cast<ExtractValueInst>(V);
35*fe6060f1SDimitry Andric     // We should only be extracting the overflow bit.
36*fe6060f1SDimitry Andric     if (!Extract || !Extract->getIndices().equals(1))
37*fe6060f1SDimitry Andric       return false;
38*fe6060f1SDimitry Andric 
39*fe6060f1SDimitry Andric     II = dyn_cast<IntrinsicInst>(Extract->getAggregateOperand());
40*fe6060f1SDimitry Andric     if (!II ||
41*fe6060f1SDimitry Andric         !match(II, m_CombineOr(m_Intrinsic<Intrinsic::umul_with_overflow>(),
42*fe6060f1SDimitry Andric                                m_Intrinsic<Intrinsic::smul_with_overflow>())))
43*fe6060f1SDimitry Andric       return false;
44*fe6060f1SDimitry Andric 
45*fe6060f1SDimitry Andric     if (II->getArgOperand(0) == X)
46*fe6060f1SDimitry Andric       XIdx = 0;
47*fe6060f1SDimitry Andric     else if (II->getArgOperand(1) == X)
48*fe6060f1SDimitry Andric       XIdx = 1;
49*fe6060f1SDimitry Andric     else
50*fe6060f1SDimitry Andric       return false;
51*fe6060f1SDimitry Andric     return true;
52*fe6060f1SDimitry Andric   };
53*fe6060f1SDimitry Andric 
54*fe6060f1SDimitry Andric   bool Matched =
55*fe6060f1SDimitry Andric       (IsAnd && Pred == ICmpInst::Predicate::ICMP_NE &&
56*fe6060f1SDimitry Andric        matchMulOverflowCheck(Op1)) ||
57*fe6060f1SDimitry Andric       (!IsAnd && Pred == ICmpInst::Predicate::ICMP_EQ &&
58*fe6060f1SDimitry Andric        match(Op1, m_Not(m_Value(NotOp1))) && matchMulOverflowCheck(NotOp1));
59*fe6060f1SDimitry Andric 
60*fe6060f1SDimitry Andric   if (!Matched)
61*fe6060f1SDimitry Andric     return false;
62*fe6060f1SDimitry Andric 
63*fe6060f1SDimitry Andric   Y = &II->getArgOperandUse(!XIdx);
64*fe6060f1SDimitry Andric   return true;
65*fe6060f1SDimitry Andric }
66*fe6060f1SDimitry Andric 
isCheckForZeroAndMulWithOverflow(Value * Op0,Value * Op1,bool IsAnd)67*fe6060f1SDimitry Andric bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1,
68*fe6060f1SDimitry Andric                                             bool IsAnd) {
69*fe6060f1SDimitry Andric   Use *Y;
70*fe6060f1SDimitry Andric   return isCheckForZeroAndMulWithOverflow(Op0, Op1, IsAnd, Y);
71*fe6060f1SDimitry Andric }
72