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 }