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