xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/OverflowInstAnalysis.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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/Constants.h"
16*fe6060f1SDimitry Andric #include "llvm/IR/Instructions.h"
17*fe6060f1SDimitry Andric #include "llvm/IR/PatternMatch.h"
18*fe6060f1SDimitry Andric 
19*fe6060f1SDimitry Andric using namespace llvm;
20*fe6060f1SDimitry Andric using namespace llvm::PatternMatch;
21*fe6060f1SDimitry Andric 
22*fe6060f1SDimitry Andric bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
23*fe6060f1SDimitry Andric                                             Use *&Y) {
24*fe6060f1SDimitry Andric   ICmpInst::Predicate Pred;
25*fe6060f1SDimitry Andric   Value *X, *NotOp1;
26*fe6060f1SDimitry Andric   int XIdx;
27*fe6060f1SDimitry Andric   IntrinsicInst *II;
28*fe6060f1SDimitry Andric 
29*fe6060f1SDimitry Andric   if (!match(Op0, m_ICmp(Pred, m_Value(X), m_Zero())))
30*fe6060f1SDimitry Andric     return false;
31*fe6060f1SDimitry Andric 
32*fe6060f1SDimitry Andric   ///   %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %???)
33*fe6060f1SDimitry Andric   ///   %V = extractvalue { i4, i1 } %Agg, 1
34*fe6060f1SDimitry Andric   auto matchMulOverflowCheck = [X, &II, &XIdx](Value *V) {
35*fe6060f1SDimitry Andric     auto *Extract = dyn_cast<ExtractValueInst>(V);
36*fe6060f1SDimitry Andric     // We should only be extracting the overflow bit.
37*fe6060f1SDimitry Andric     if (!Extract || !Extract->getIndices().equals(1))
38*fe6060f1SDimitry Andric       return false;
39*fe6060f1SDimitry Andric 
40*fe6060f1SDimitry Andric     II = dyn_cast<IntrinsicInst>(Extract->getAggregateOperand());
41*fe6060f1SDimitry Andric     if (!II ||
42*fe6060f1SDimitry Andric         !match(II, m_CombineOr(m_Intrinsic<Intrinsic::umul_with_overflow>(),
43*fe6060f1SDimitry Andric                                m_Intrinsic<Intrinsic::smul_with_overflow>())))
44*fe6060f1SDimitry Andric       return false;
45*fe6060f1SDimitry Andric 
46*fe6060f1SDimitry Andric     if (II->getArgOperand(0) == X)
47*fe6060f1SDimitry Andric       XIdx = 0;
48*fe6060f1SDimitry Andric     else if (II->getArgOperand(1) == X)
49*fe6060f1SDimitry Andric       XIdx = 1;
50*fe6060f1SDimitry Andric     else
51*fe6060f1SDimitry Andric       return false;
52*fe6060f1SDimitry Andric     return true;
53*fe6060f1SDimitry Andric   };
54*fe6060f1SDimitry Andric 
55*fe6060f1SDimitry Andric   bool Matched =
56*fe6060f1SDimitry Andric       (IsAnd && Pred == ICmpInst::Predicate::ICMP_NE &&
57*fe6060f1SDimitry Andric        matchMulOverflowCheck(Op1)) ||
58*fe6060f1SDimitry Andric       (!IsAnd && Pred == ICmpInst::Predicate::ICMP_EQ &&
59*fe6060f1SDimitry Andric        match(Op1, m_Not(m_Value(NotOp1))) && matchMulOverflowCheck(NotOp1));
60*fe6060f1SDimitry Andric 
61*fe6060f1SDimitry Andric   if (!Matched)
62*fe6060f1SDimitry Andric     return false;
63*fe6060f1SDimitry Andric 
64*fe6060f1SDimitry Andric   Y = &II->getArgOperandUse(!XIdx);
65*fe6060f1SDimitry Andric   return true;
66*fe6060f1SDimitry Andric }
67*fe6060f1SDimitry Andric 
68*fe6060f1SDimitry Andric bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1,
69*fe6060f1SDimitry Andric                                             bool IsAnd) {
70*fe6060f1SDimitry Andric   Use *Y;
71*fe6060f1SDimitry Andric   return isCheckForZeroAndMulWithOverflow(Op0, Op1, IsAnd, Y);
72*fe6060f1SDimitry Andric }