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