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