10b57cec5SDimitry Andric //===- InstCombineAddSub.cpp ------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the visit functions for add, fadd, sub, and fsub. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "InstCombineInternal.h" 140b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 150b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 180b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 190b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 200b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 210b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 220b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 230b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 240b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 250b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 260b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h" 270b57cec5SDimitry Andric #include "llvm/IR/Type.h" 280b57cec5SDimitry Andric #include "llvm/IR/Value.h" 290b57cec5SDimitry Andric #include "llvm/Support/AlignOf.h" 300b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 310b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 32e8d8bef9SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombiner.h" 330b57cec5SDimitry Andric #include <cassert> 340b57cec5SDimitry Andric #include <utility> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric using namespace PatternMatch; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #define DEBUG_TYPE "instcombine" 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric namespace { 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// Class representing coefficient of floating-point addend. 440b57cec5SDimitry Andric /// This class needs to be highly efficient, which is especially true for 450b57cec5SDimitry Andric /// the constructor. As of I write this comment, the cost of the default 460b57cec5SDimitry Andric /// constructor is merely 4-byte-store-zero (Assuming compiler is able to 470b57cec5SDimitry Andric /// perform write-merging). 480b57cec5SDimitry Andric /// 490b57cec5SDimitry Andric class FAddendCoef { 500b57cec5SDimitry Andric public: 510b57cec5SDimitry Andric // The constructor has to initialize a APFloat, which is unnecessary for 520b57cec5SDimitry Andric // most addends which have coefficient either 1 or -1. So, the constructor 530b57cec5SDimitry Andric // is expensive. In order to avoid the cost of the constructor, we should 540b57cec5SDimitry Andric // reuse some instances whenever possible. The pre-created instances 550b57cec5SDimitry Andric // FAddCombine::Add[0-5] embodies this idea. 560b57cec5SDimitry Andric FAddendCoef() = default; 570b57cec5SDimitry Andric ~FAddendCoef(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // If possible, don't define operator+/operator- etc because these 600b57cec5SDimitry Andric // operators inevitably call FAddendCoef's constructor which is not cheap. 610b57cec5SDimitry Andric void operator=(const FAddendCoef &A); 620b57cec5SDimitry Andric void operator+=(const FAddendCoef &A); 630b57cec5SDimitry Andric void operator*=(const FAddendCoef &S); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric void set(short C) { 660b57cec5SDimitry Andric assert(!insaneIntVal(C) && "Insane coefficient"); 670b57cec5SDimitry Andric IsFp = false; IntVal = C; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void set(const APFloat& C); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric void negate(); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric bool isZero() const { return isInt() ? !IntVal : getFpVal().isZero(); } 750b57cec5SDimitry Andric Value *getValue(Type *) const; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric bool isOne() const { return isInt() && IntVal == 1; } 780b57cec5SDimitry Andric bool isTwo() const { return isInt() && IntVal == 2; } 790b57cec5SDimitry Andric bool isMinusOne() const { return isInt() && IntVal == -1; } 800b57cec5SDimitry Andric bool isMinusTwo() const { return isInt() && IntVal == -2; } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric private: 830b57cec5SDimitry Andric bool insaneIntVal(int V) { return V > 4 || V < -4; } 840b57cec5SDimitry Andric 85e8d8bef9SDimitry Andric APFloat *getFpValPtr() { return reinterpret_cast<APFloat *>(&FpValBuf); } 860b57cec5SDimitry Andric 87e8d8bef9SDimitry Andric const APFloat *getFpValPtr() const { 88e8d8bef9SDimitry Andric return reinterpret_cast<const APFloat *>(&FpValBuf); 89e8d8bef9SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric const APFloat &getFpVal() const { 920b57cec5SDimitry Andric assert(IsFp && BufHasFpVal && "Incorret state"); 930b57cec5SDimitry Andric return *getFpValPtr(); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric APFloat &getFpVal() { 970b57cec5SDimitry Andric assert(IsFp && BufHasFpVal && "Incorret state"); 980b57cec5SDimitry Andric return *getFpValPtr(); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric bool isInt() const { return !IsFp; } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // If the coefficient is represented by an integer, promote it to a 1040b57cec5SDimitry Andric // floating point. 1050b57cec5SDimitry Andric void convertToFpType(const fltSemantics &Sem); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Construct an APFloat from a signed integer. 1080b57cec5SDimitry Andric // TODO: We should get rid of this function when APFloat can be constructed 1090b57cec5SDimitry Andric // from an *SIGNED* integer. 1100b57cec5SDimitry Andric APFloat createAPFloatFromInt(const fltSemantics &Sem, int Val); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric bool IsFp = false; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // True iff FpValBuf contains an instance of APFloat. 1150b57cec5SDimitry Andric bool BufHasFpVal = false; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // The integer coefficient of an individual addend is either 1 or -1, 1180b57cec5SDimitry Andric // and we try to simplify at most 4 addends from neighboring at most 1190b57cec5SDimitry Andric // two instructions. So the range of <IntVal> falls in [-4, 4]. APInt 1200b57cec5SDimitry Andric // is overkill of this end. 1210b57cec5SDimitry Andric short IntVal = 0; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric AlignedCharArrayUnion<APFloat> FpValBuf; 1240b57cec5SDimitry Andric }; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric /// FAddend is used to represent floating-point addend. An addend is 1270b57cec5SDimitry Andric /// represented as <C, V>, where the V is a symbolic value, and C is a 1280b57cec5SDimitry Andric /// constant coefficient. A constant addend is represented as <C, 0>. 1290b57cec5SDimitry Andric class FAddend { 1300b57cec5SDimitry Andric public: 1310b57cec5SDimitry Andric FAddend() = default; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric void operator+=(const FAddend &T) { 1340b57cec5SDimitry Andric assert((Val == T.Val) && "Symbolic-values disagree"); 1350b57cec5SDimitry Andric Coeff += T.Coeff; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric Value *getSymVal() const { return Val; } 1390b57cec5SDimitry Andric const FAddendCoef &getCoef() const { return Coeff; } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric bool isConstant() const { return Val == nullptr; } 1420b57cec5SDimitry Andric bool isZero() const { return Coeff.isZero(); } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric void set(short Coefficient, Value *V) { 1450b57cec5SDimitry Andric Coeff.set(Coefficient); 1460b57cec5SDimitry Andric Val = V; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric void set(const APFloat &Coefficient, Value *V) { 1490b57cec5SDimitry Andric Coeff.set(Coefficient); 1500b57cec5SDimitry Andric Val = V; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric void set(const ConstantFP *Coefficient, Value *V) { 1530b57cec5SDimitry Andric Coeff.set(Coefficient->getValueAPF()); 1540b57cec5SDimitry Andric Val = V; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric void negate() { Coeff.negate(); } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// Drill down the U-D chain one step to find the definition of V, and 1600b57cec5SDimitry Andric /// try to break the definition into one or two addends. 1610b57cec5SDimitry Andric static unsigned drillValueDownOneStep(Value* V, FAddend &A0, FAddend &A1); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Similar to FAddend::drillDownOneStep() except that the value being 1640b57cec5SDimitry Andric /// splitted is the addend itself. 1650b57cec5SDimitry Andric unsigned drillAddendDownOneStep(FAddend &Addend0, FAddend &Addend1) const; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric private: 1680b57cec5SDimitry Andric void Scale(const FAddendCoef& ScaleAmt) { Coeff *= ScaleAmt; } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // This addend has the value of "Coeff * Val". 1710b57cec5SDimitry Andric Value *Val = nullptr; 1720b57cec5SDimitry Andric FAddendCoef Coeff; 1730b57cec5SDimitry Andric }; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric /// FAddCombine is the class for optimizing an unsafe fadd/fsub along 1760b57cec5SDimitry Andric /// with its neighboring at most two instructions. 1770b57cec5SDimitry Andric /// 1780b57cec5SDimitry Andric class FAddCombine { 1790b57cec5SDimitry Andric public: 1800b57cec5SDimitry Andric FAddCombine(InstCombiner::BuilderTy &B) : Builder(B) {} 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric Value *simplify(Instruction *FAdd); 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric private: 1850b57cec5SDimitry Andric using AddendVect = SmallVector<const FAddend *, 4>; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric Value *simplifyFAdd(AddendVect& V, unsigned InstrQuota); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// Convert given addend to a Value 1900b57cec5SDimitry Andric Value *createAddendVal(const FAddend &A, bool& NeedNeg); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric /// Return the number of instructions needed to emit the N-ary addition. 1930b57cec5SDimitry Andric unsigned calcInstrNumber(const AddendVect& Vect); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric Value *createFSub(Value *Opnd0, Value *Opnd1); 1960b57cec5SDimitry Andric Value *createFAdd(Value *Opnd0, Value *Opnd1); 1970b57cec5SDimitry Andric Value *createFMul(Value *Opnd0, Value *Opnd1); 1980b57cec5SDimitry Andric Value *createFNeg(Value *V); 1990b57cec5SDimitry Andric Value *createNaryFAdd(const AddendVect& Opnds, unsigned InstrQuota); 2000b57cec5SDimitry Andric void createInstPostProc(Instruction *NewInst, bool NoNumber = false); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // Debugging stuff are clustered here. 2030b57cec5SDimitry Andric #ifndef NDEBUG 2040b57cec5SDimitry Andric unsigned CreateInstrNum; 2050b57cec5SDimitry Andric void initCreateInstNum() { CreateInstrNum = 0; } 2060b57cec5SDimitry Andric void incCreateInstNum() { CreateInstrNum++; } 2070b57cec5SDimitry Andric #else 2080b57cec5SDimitry Andric void initCreateInstNum() {} 2090b57cec5SDimitry Andric void incCreateInstNum() {} 2100b57cec5SDimitry Andric #endif 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder; 2130b57cec5SDimitry Andric Instruction *Instr = nullptr; 2140b57cec5SDimitry Andric }; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric } // end anonymous namespace 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2190b57cec5SDimitry Andric // 2200b57cec5SDimitry Andric // Implementation of 2210b57cec5SDimitry Andric // {FAddendCoef, FAddend, FAddition, FAddCombine}. 2220b57cec5SDimitry Andric // 2230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2240b57cec5SDimitry Andric FAddendCoef::~FAddendCoef() { 2250b57cec5SDimitry Andric if (BufHasFpVal) 2260b57cec5SDimitry Andric getFpValPtr()->~APFloat(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void FAddendCoef::set(const APFloat& C) { 2300b57cec5SDimitry Andric APFloat *P = getFpValPtr(); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric if (isInt()) { 2330b57cec5SDimitry Andric // As the buffer is meanless byte stream, we cannot call 2340b57cec5SDimitry Andric // APFloat::operator=(). 2350b57cec5SDimitry Andric new(P) APFloat(C); 2360b57cec5SDimitry Andric } else 2370b57cec5SDimitry Andric *P = C; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric IsFp = BufHasFpVal = true; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric void FAddendCoef::convertToFpType(const fltSemantics &Sem) { 2430b57cec5SDimitry Andric if (!isInt()) 2440b57cec5SDimitry Andric return; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric APFloat *P = getFpValPtr(); 2470b57cec5SDimitry Andric if (IntVal > 0) 2480b57cec5SDimitry Andric new(P) APFloat(Sem, IntVal); 2490b57cec5SDimitry Andric else { 2500b57cec5SDimitry Andric new(P) APFloat(Sem, 0 - IntVal); 2510b57cec5SDimitry Andric P->changeSign(); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric IsFp = BufHasFpVal = true; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric APFloat FAddendCoef::createAPFloatFromInt(const fltSemantics &Sem, int Val) { 2570b57cec5SDimitry Andric if (Val >= 0) 2580b57cec5SDimitry Andric return APFloat(Sem, Val); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric APFloat T(Sem, 0 - Val); 2610b57cec5SDimitry Andric T.changeSign(); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric return T; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric void FAddendCoef::operator=(const FAddendCoef &That) { 2670b57cec5SDimitry Andric if (That.isInt()) 2680b57cec5SDimitry Andric set(That.IntVal); 2690b57cec5SDimitry Andric else 2700b57cec5SDimitry Andric set(That.getFpVal()); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric void FAddendCoef::operator+=(const FAddendCoef &That) { 2745ffd83dbSDimitry Andric RoundingMode RndMode = RoundingMode::NearestTiesToEven; 2750b57cec5SDimitry Andric if (isInt() == That.isInt()) { 2760b57cec5SDimitry Andric if (isInt()) 2770b57cec5SDimitry Andric IntVal += That.IntVal; 2780b57cec5SDimitry Andric else 2790b57cec5SDimitry Andric getFpVal().add(That.getFpVal(), RndMode); 2800b57cec5SDimitry Andric return; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if (isInt()) { 2840b57cec5SDimitry Andric const APFloat &T = That.getFpVal(); 2850b57cec5SDimitry Andric convertToFpType(T.getSemantics()); 2860b57cec5SDimitry Andric getFpVal().add(T, RndMode); 2870b57cec5SDimitry Andric return; 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric APFloat &T = getFpVal(); 2910b57cec5SDimitry Andric T.add(createAPFloatFromInt(T.getSemantics(), That.IntVal), RndMode); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric void FAddendCoef::operator*=(const FAddendCoef &That) { 2950b57cec5SDimitry Andric if (That.isOne()) 2960b57cec5SDimitry Andric return; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric if (That.isMinusOne()) { 2990b57cec5SDimitry Andric negate(); 3000b57cec5SDimitry Andric return; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric if (isInt() && That.isInt()) { 3040b57cec5SDimitry Andric int Res = IntVal * (int)That.IntVal; 3050b57cec5SDimitry Andric assert(!insaneIntVal(Res) && "Insane int value"); 3060b57cec5SDimitry Andric IntVal = Res; 3070b57cec5SDimitry Andric return; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric const fltSemantics &Semantic = 3110b57cec5SDimitry Andric isInt() ? That.getFpVal().getSemantics() : getFpVal().getSemantics(); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric if (isInt()) 3140b57cec5SDimitry Andric convertToFpType(Semantic); 3150b57cec5SDimitry Andric APFloat &F0 = getFpVal(); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric if (That.isInt()) 3180b57cec5SDimitry Andric F0.multiply(createAPFloatFromInt(Semantic, That.IntVal), 3190b57cec5SDimitry Andric APFloat::rmNearestTiesToEven); 3200b57cec5SDimitry Andric else 3210b57cec5SDimitry Andric F0.multiply(That.getFpVal(), APFloat::rmNearestTiesToEven); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric void FAddendCoef::negate() { 3250b57cec5SDimitry Andric if (isInt()) 3260b57cec5SDimitry Andric IntVal = 0 - IntVal; 3270b57cec5SDimitry Andric else 3280b57cec5SDimitry Andric getFpVal().changeSign(); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric Value *FAddendCoef::getValue(Type *Ty) const { 3320b57cec5SDimitry Andric return isInt() ? 3330b57cec5SDimitry Andric ConstantFP::get(Ty, float(IntVal)) : 3340b57cec5SDimitry Andric ConstantFP::get(Ty->getContext(), getFpVal()); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // The definition of <Val> Addends 3380b57cec5SDimitry Andric // ========================================= 3390b57cec5SDimitry Andric // A + B <1, A>, <1,B> 3400b57cec5SDimitry Andric // A - B <1, A>, <1,B> 3410b57cec5SDimitry Andric // 0 - B <-1, B> 3420b57cec5SDimitry Andric // C * A, <C, A> 3430b57cec5SDimitry Andric // A + C <1, A> <C, NULL> 3440b57cec5SDimitry Andric // 0 +/- 0 <0, NULL> (corner case) 3450b57cec5SDimitry Andric // 3460b57cec5SDimitry Andric // Legend: A and B are not constant, C is constant 3470b57cec5SDimitry Andric unsigned FAddend::drillValueDownOneStep 3480b57cec5SDimitry Andric (Value *Val, FAddend &Addend0, FAddend &Addend1) { 3490b57cec5SDimitry Andric Instruction *I = nullptr; 3500b57cec5SDimitry Andric if (!Val || !(I = dyn_cast<Instruction>(Val))) 3510b57cec5SDimitry Andric return 0; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric unsigned Opcode = I->getOpcode(); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric if (Opcode == Instruction::FAdd || Opcode == Instruction::FSub) { 3560b57cec5SDimitry Andric ConstantFP *C0, *C1; 3570b57cec5SDimitry Andric Value *Opnd0 = I->getOperand(0); 3580b57cec5SDimitry Andric Value *Opnd1 = I->getOperand(1); 3590b57cec5SDimitry Andric if ((C0 = dyn_cast<ConstantFP>(Opnd0)) && C0->isZero()) 3600b57cec5SDimitry Andric Opnd0 = nullptr; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric if ((C1 = dyn_cast<ConstantFP>(Opnd1)) && C1->isZero()) 3630b57cec5SDimitry Andric Opnd1 = nullptr; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric if (Opnd0) { 3660b57cec5SDimitry Andric if (!C0) 3670b57cec5SDimitry Andric Addend0.set(1, Opnd0); 3680b57cec5SDimitry Andric else 3690b57cec5SDimitry Andric Addend0.set(C0, nullptr); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric if (Opnd1) { 3730b57cec5SDimitry Andric FAddend &Addend = Opnd0 ? Addend1 : Addend0; 3740b57cec5SDimitry Andric if (!C1) 3750b57cec5SDimitry Andric Addend.set(1, Opnd1); 3760b57cec5SDimitry Andric else 3770b57cec5SDimitry Andric Addend.set(C1, nullptr); 3780b57cec5SDimitry Andric if (Opcode == Instruction::FSub) 3790b57cec5SDimitry Andric Addend.negate(); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric if (Opnd0 || Opnd1) 3830b57cec5SDimitry Andric return Opnd0 && Opnd1 ? 2 : 1; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // Both operands are zero. Weird! 3860b57cec5SDimitry Andric Addend0.set(APFloat(C0->getValueAPF().getSemantics()), nullptr); 3870b57cec5SDimitry Andric return 1; 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric if (I->getOpcode() == Instruction::FMul) { 3910b57cec5SDimitry Andric Value *V0 = I->getOperand(0); 3920b57cec5SDimitry Andric Value *V1 = I->getOperand(1); 3930b57cec5SDimitry Andric if (ConstantFP *C = dyn_cast<ConstantFP>(V0)) { 3940b57cec5SDimitry Andric Addend0.set(C, V1); 3950b57cec5SDimitry Andric return 1; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric if (ConstantFP *C = dyn_cast<ConstantFP>(V1)) { 3990b57cec5SDimitry Andric Addend0.set(C, V0); 4000b57cec5SDimitry Andric return 1; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric return 0; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric // Try to break *this* addend into two addends. e.g. Suppose this addend is 4080b57cec5SDimitry Andric // <2.3, V>, and V = X + Y, by calling this function, we obtain two addends, 4090b57cec5SDimitry Andric // i.e. <2.3, X> and <2.3, Y>. 4100b57cec5SDimitry Andric unsigned FAddend::drillAddendDownOneStep 4110b57cec5SDimitry Andric (FAddend &Addend0, FAddend &Addend1) const { 4120b57cec5SDimitry Andric if (isConstant()) 4130b57cec5SDimitry Andric return 0; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric unsigned BreakNum = FAddend::drillValueDownOneStep(Val, Addend0, Addend1); 4160b57cec5SDimitry Andric if (!BreakNum || Coeff.isOne()) 4170b57cec5SDimitry Andric return BreakNum; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric Addend0.Scale(Coeff); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric if (BreakNum == 2) 4220b57cec5SDimitry Andric Addend1.Scale(Coeff); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric return BreakNum; 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric Value *FAddCombine::simplify(Instruction *I) { 4280b57cec5SDimitry Andric assert(I->hasAllowReassoc() && I->hasNoSignedZeros() && 4290b57cec5SDimitry Andric "Expected 'reassoc'+'nsz' instruction"); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Currently we are not able to handle vector type. 4320b57cec5SDimitry Andric if (I->getType()->isVectorTy()) 4330b57cec5SDimitry Andric return nullptr; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric assert((I->getOpcode() == Instruction::FAdd || 4360b57cec5SDimitry Andric I->getOpcode() == Instruction::FSub) && "Expect add/sub"); 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric // Save the instruction before calling other member-functions. 4390b57cec5SDimitry Andric Instr = I; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric FAddend Opnd0, Opnd1, Opnd0_0, Opnd0_1, Opnd1_0, Opnd1_1; 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric unsigned OpndNum = FAddend::drillValueDownOneStep(I, Opnd0, Opnd1); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric // Step 1: Expand the 1st addend into Opnd0_0 and Opnd0_1. 4460b57cec5SDimitry Andric unsigned Opnd0_ExpNum = 0; 4470b57cec5SDimitry Andric unsigned Opnd1_ExpNum = 0; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric if (!Opnd0.isConstant()) 4500b57cec5SDimitry Andric Opnd0_ExpNum = Opnd0.drillAddendDownOneStep(Opnd0_0, Opnd0_1); 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric // Step 2: Expand the 2nd addend into Opnd1_0 and Opnd1_1. 4530b57cec5SDimitry Andric if (OpndNum == 2 && !Opnd1.isConstant()) 4540b57cec5SDimitry Andric Opnd1_ExpNum = Opnd1.drillAddendDownOneStep(Opnd1_0, Opnd1_1); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric // Step 3: Try to optimize Opnd0_0 + Opnd0_1 + Opnd1_0 + Opnd1_1 4570b57cec5SDimitry Andric if (Opnd0_ExpNum && Opnd1_ExpNum) { 4580b57cec5SDimitry Andric AddendVect AllOpnds; 4590b57cec5SDimitry Andric AllOpnds.push_back(&Opnd0_0); 4600b57cec5SDimitry Andric AllOpnds.push_back(&Opnd1_0); 4610b57cec5SDimitry Andric if (Opnd0_ExpNum == 2) 4620b57cec5SDimitry Andric AllOpnds.push_back(&Opnd0_1); 4630b57cec5SDimitry Andric if (Opnd1_ExpNum == 2) 4640b57cec5SDimitry Andric AllOpnds.push_back(&Opnd1_1); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric // Compute instruction quota. We should save at least one instruction. 4670b57cec5SDimitry Andric unsigned InstQuota = 0; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric Value *V0 = I->getOperand(0); 4700b57cec5SDimitry Andric Value *V1 = I->getOperand(1); 4710b57cec5SDimitry Andric InstQuota = ((!isa<Constant>(V0) && V0->hasOneUse()) && 4720b57cec5SDimitry Andric (!isa<Constant>(V1) && V1->hasOneUse())) ? 2 : 1; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric if (Value *R = simplifyFAdd(AllOpnds, InstQuota)) 4750b57cec5SDimitry Andric return R; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric if (OpndNum != 2) { 4790b57cec5SDimitry Andric // The input instruction is : "I=0.0 +/- V". If the "V" were able to be 4800b57cec5SDimitry Andric // splitted into two addends, say "V = X - Y", the instruction would have 4810b57cec5SDimitry Andric // been optimized into "I = Y - X" in the previous steps. 4820b57cec5SDimitry Andric // 4830b57cec5SDimitry Andric const FAddendCoef &CE = Opnd0.getCoef(); 4840b57cec5SDimitry Andric return CE.isOne() ? Opnd0.getSymVal() : nullptr; 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric // step 4: Try to optimize Opnd0 + Opnd1_0 [+ Opnd1_1] 4880b57cec5SDimitry Andric if (Opnd1_ExpNum) { 4890b57cec5SDimitry Andric AddendVect AllOpnds; 4900b57cec5SDimitry Andric AllOpnds.push_back(&Opnd0); 4910b57cec5SDimitry Andric AllOpnds.push_back(&Opnd1_0); 4920b57cec5SDimitry Andric if (Opnd1_ExpNum == 2) 4930b57cec5SDimitry Andric AllOpnds.push_back(&Opnd1_1); 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric if (Value *R = simplifyFAdd(AllOpnds, 1)) 4960b57cec5SDimitry Andric return R; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // step 5: Try to optimize Opnd1 + Opnd0_0 [+ Opnd0_1] 5000b57cec5SDimitry Andric if (Opnd0_ExpNum) { 5010b57cec5SDimitry Andric AddendVect AllOpnds; 5020b57cec5SDimitry Andric AllOpnds.push_back(&Opnd1); 5030b57cec5SDimitry Andric AllOpnds.push_back(&Opnd0_0); 5040b57cec5SDimitry Andric if (Opnd0_ExpNum == 2) 5050b57cec5SDimitry Andric AllOpnds.push_back(&Opnd0_1); 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric if (Value *R = simplifyFAdd(AllOpnds, 1)) 5080b57cec5SDimitry Andric return R; 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric return nullptr; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) { 5150b57cec5SDimitry Andric unsigned AddendNum = Addends.size(); 5160b57cec5SDimitry Andric assert(AddendNum <= 4 && "Too many addends"); 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric // For saving intermediate results; 5190b57cec5SDimitry Andric unsigned NextTmpIdx = 0; 5200b57cec5SDimitry Andric FAddend TmpResult[3]; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric // Simplified addends are placed <SimpVect>. 5230b57cec5SDimitry Andric AddendVect SimpVect; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // The outer loop works on one symbolic-value at a time. Suppose the input 5260b57cec5SDimitry Andric // addends are : <a1, x>, <b1, y>, <a2, x>, <c1, z>, <b2, y>, ... 5270b57cec5SDimitry Andric // The symbolic-values will be processed in this order: x, y, z. 5280b57cec5SDimitry Andric for (unsigned SymIdx = 0; SymIdx < AddendNum; SymIdx++) { 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric const FAddend *ThisAddend = Addends[SymIdx]; 5310b57cec5SDimitry Andric if (!ThisAddend) { 5320b57cec5SDimitry Andric // This addend was processed before. 5330b57cec5SDimitry Andric continue; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric Value *Val = ThisAddend->getSymVal(); 53704eeddc0SDimitry Andric 53804eeddc0SDimitry Andric // If the resulting expr has constant-addend, this constant-addend is 53904eeddc0SDimitry Andric // desirable to reside at the top of the resulting expression tree. Placing 54004eeddc0SDimitry Andric // constant close to super-expr(s) will potentially reveal some 54104eeddc0SDimitry Andric // optimization opportunities in super-expr(s). Here we do not implement 54204eeddc0SDimitry Andric // this logic intentionally and rely on SimplifyAssociativeOrCommutative 54304eeddc0SDimitry Andric // call later. 54404eeddc0SDimitry Andric 5450b57cec5SDimitry Andric unsigned StartIdx = SimpVect.size(); 5460b57cec5SDimitry Andric SimpVect.push_back(ThisAddend); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric // The inner loop collects addends sharing same symbolic-value, and these 5490b57cec5SDimitry Andric // addends will be later on folded into a single addend. Following above 5500b57cec5SDimitry Andric // example, if the symbolic value "y" is being processed, the inner loop 5510b57cec5SDimitry Andric // will collect two addends "<b1,y>" and "<b2,Y>". These two addends will 5520b57cec5SDimitry Andric // be later on folded into "<b1+b2, y>". 5530b57cec5SDimitry Andric for (unsigned SameSymIdx = SymIdx + 1; 5540b57cec5SDimitry Andric SameSymIdx < AddendNum; SameSymIdx++) { 5550b57cec5SDimitry Andric const FAddend *T = Addends[SameSymIdx]; 5560b57cec5SDimitry Andric if (T && T->getSymVal() == Val) { 5570b57cec5SDimitry Andric // Set null such that next iteration of the outer loop will not process 5580b57cec5SDimitry Andric // this addend again. 5590b57cec5SDimitry Andric Addends[SameSymIdx] = nullptr; 5600b57cec5SDimitry Andric SimpVect.push_back(T); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric // If multiple addends share same symbolic value, fold them together. 5650b57cec5SDimitry Andric if (StartIdx + 1 != SimpVect.size()) { 5660b57cec5SDimitry Andric FAddend &R = TmpResult[NextTmpIdx ++]; 5670b57cec5SDimitry Andric R = *SimpVect[StartIdx]; 5680b57cec5SDimitry Andric for (unsigned Idx = StartIdx + 1; Idx < SimpVect.size(); Idx++) 5690b57cec5SDimitry Andric R += *SimpVect[Idx]; 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric // Pop all addends being folded and push the resulting folded addend. 5720b57cec5SDimitry Andric SimpVect.resize(StartIdx); 5730b57cec5SDimitry Andric if (!R.isZero()) { 5740b57cec5SDimitry Andric SimpVect.push_back(&R); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 579bdd1243dSDimitry Andric assert((NextTmpIdx <= std::size(TmpResult) + 1) && "out-of-bound access"); 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric Value *Result; 5820b57cec5SDimitry Andric if (!SimpVect.empty()) 5830b57cec5SDimitry Andric Result = createNaryFAdd(SimpVect, InstrQuota); 5840b57cec5SDimitry Andric else { 5850b57cec5SDimitry Andric // The addition is folded to 0.0. 5860b57cec5SDimitry Andric Result = ConstantFP::get(Instr->getType(), 0.0); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric return Result; 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric Value *FAddCombine::createNaryFAdd 5930b57cec5SDimitry Andric (const AddendVect &Opnds, unsigned InstrQuota) { 5940b57cec5SDimitry Andric assert(!Opnds.empty() && "Expect at least one addend"); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric // Step 1: Check if the # of instructions needed exceeds the quota. 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric unsigned InstrNeeded = calcInstrNumber(Opnds); 5990b57cec5SDimitry Andric if (InstrNeeded > InstrQuota) 6000b57cec5SDimitry Andric return nullptr; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric initCreateInstNum(); 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric // step 2: Emit the N-ary addition. 6050b57cec5SDimitry Andric // Note that at most three instructions are involved in Fadd-InstCombine: the 6060b57cec5SDimitry Andric // addition in question, and at most two neighboring instructions. 6070b57cec5SDimitry Andric // The resulting optimized addition should have at least one less instruction 6080b57cec5SDimitry Andric // than the original addition expression tree. This implies that the resulting 6090b57cec5SDimitry Andric // N-ary addition has at most two instructions, and we don't need to worry 6100b57cec5SDimitry Andric // about tree-height when constructing the N-ary addition. 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric Value *LastVal = nullptr; 6130b57cec5SDimitry Andric bool LastValNeedNeg = false; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric // Iterate the addends, creating fadd/fsub using adjacent two addends. 6160b57cec5SDimitry Andric for (const FAddend *Opnd : Opnds) { 6170b57cec5SDimitry Andric bool NeedNeg; 6180b57cec5SDimitry Andric Value *V = createAddendVal(*Opnd, NeedNeg); 6190b57cec5SDimitry Andric if (!LastVal) { 6200b57cec5SDimitry Andric LastVal = V; 6210b57cec5SDimitry Andric LastValNeedNeg = NeedNeg; 6220b57cec5SDimitry Andric continue; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric if (LastValNeedNeg == NeedNeg) { 6260b57cec5SDimitry Andric LastVal = createFAdd(LastVal, V); 6270b57cec5SDimitry Andric continue; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric if (LastValNeedNeg) 6310b57cec5SDimitry Andric LastVal = createFSub(V, LastVal); 6320b57cec5SDimitry Andric else 6330b57cec5SDimitry Andric LastVal = createFSub(LastVal, V); 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric LastValNeedNeg = false; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric if (LastValNeedNeg) { 6390b57cec5SDimitry Andric LastVal = createFNeg(LastVal); 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric #ifndef NDEBUG 6430b57cec5SDimitry Andric assert(CreateInstrNum == InstrNeeded && 6440b57cec5SDimitry Andric "Inconsistent in instruction numbers"); 6450b57cec5SDimitry Andric #endif 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric return LastVal; 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric Value *FAddCombine::createFSub(Value *Opnd0, Value *Opnd1) { 6510b57cec5SDimitry Andric Value *V = Builder.CreateFSub(Opnd0, Opnd1); 6520b57cec5SDimitry Andric if (Instruction *I = dyn_cast<Instruction>(V)) 6530b57cec5SDimitry Andric createInstPostProc(I); 6540b57cec5SDimitry Andric return V; 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric Value *FAddCombine::createFNeg(Value *V) { 6585ffd83dbSDimitry Andric Value *NewV = Builder.CreateFNeg(V); 6590b57cec5SDimitry Andric if (Instruction *I = dyn_cast<Instruction>(NewV)) 6600b57cec5SDimitry Andric createInstPostProc(I, true); // fneg's don't receive instruction numbers. 6610b57cec5SDimitry Andric return NewV; 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric Value *FAddCombine::createFAdd(Value *Opnd0, Value *Opnd1) { 6650b57cec5SDimitry Andric Value *V = Builder.CreateFAdd(Opnd0, Opnd1); 6660b57cec5SDimitry Andric if (Instruction *I = dyn_cast<Instruction>(V)) 6670b57cec5SDimitry Andric createInstPostProc(I); 6680b57cec5SDimitry Andric return V; 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric Value *FAddCombine::createFMul(Value *Opnd0, Value *Opnd1) { 6720b57cec5SDimitry Andric Value *V = Builder.CreateFMul(Opnd0, Opnd1); 6730b57cec5SDimitry Andric if (Instruction *I = dyn_cast<Instruction>(V)) 6740b57cec5SDimitry Andric createInstPostProc(I); 6750b57cec5SDimitry Andric return V; 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric void FAddCombine::createInstPostProc(Instruction *NewInstr, bool NoNumber) { 6790b57cec5SDimitry Andric NewInstr->setDebugLoc(Instr->getDebugLoc()); 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric // Keep track of the number of instruction created. 6820b57cec5SDimitry Andric if (!NoNumber) 6830b57cec5SDimitry Andric incCreateInstNum(); 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric // Propagate fast-math flags 6860b57cec5SDimitry Andric NewInstr->setFastMathFlags(Instr->getFastMathFlags()); 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric // Return the number of instruction needed to emit the N-ary addition. 6900b57cec5SDimitry Andric // NOTE: Keep this function in sync with createAddendVal(). 6910b57cec5SDimitry Andric unsigned FAddCombine::calcInstrNumber(const AddendVect &Opnds) { 6920b57cec5SDimitry Andric unsigned OpndNum = Opnds.size(); 6930b57cec5SDimitry Andric unsigned InstrNeeded = OpndNum - 1; 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric // Adjust the number of instructions needed to emit the N-ary add. 6960b57cec5SDimitry Andric for (const FAddend *Opnd : Opnds) { 6970b57cec5SDimitry Andric if (Opnd->isConstant()) 6980b57cec5SDimitry Andric continue; 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric // The constant check above is really for a few special constant 7010b57cec5SDimitry Andric // coefficients. 7020b57cec5SDimitry Andric if (isa<UndefValue>(Opnd->getSymVal())) 7030b57cec5SDimitry Andric continue; 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric const FAddendCoef &CE = Opnd->getCoef(); 7060b57cec5SDimitry Andric // Let the addend be "c * x". If "c == +/-1", the value of the addend 7070b57cec5SDimitry Andric // is immediately available; otherwise, it needs exactly one instruction 7080b57cec5SDimitry Andric // to evaluate the value. 7090b57cec5SDimitry Andric if (!CE.isMinusOne() && !CE.isOne()) 7100b57cec5SDimitry Andric InstrNeeded++; 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric return InstrNeeded; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric // Input Addend Value NeedNeg(output) 7160b57cec5SDimitry Andric // ================================================================ 7170b57cec5SDimitry Andric // Constant C C false 7180b57cec5SDimitry Andric // <+/-1, V> V coefficient is -1 7190b57cec5SDimitry Andric // <2/-2, V> "fadd V, V" coefficient is -2 7200b57cec5SDimitry Andric // <C, V> "fmul V, C" false 7210b57cec5SDimitry Andric // 7220b57cec5SDimitry Andric // NOTE: Keep this function in sync with FAddCombine::calcInstrNumber. 7230b57cec5SDimitry Andric Value *FAddCombine::createAddendVal(const FAddend &Opnd, bool &NeedNeg) { 7240b57cec5SDimitry Andric const FAddendCoef &Coeff = Opnd.getCoef(); 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric if (Opnd.isConstant()) { 7270b57cec5SDimitry Andric NeedNeg = false; 7280b57cec5SDimitry Andric return Coeff.getValue(Instr->getType()); 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric Value *OpndVal = Opnd.getSymVal(); 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric if (Coeff.isMinusOne() || Coeff.isOne()) { 7340b57cec5SDimitry Andric NeedNeg = Coeff.isMinusOne(); 7350b57cec5SDimitry Andric return OpndVal; 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric if (Coeff.isTwo() || Coeff.isMinusTwo()) { 7390b57cec5SDimitry Andric NeedNeg = Coeff.isMinusTwo(); 7400b57cec5SDimitry Andric return createFAdd(OpndVal, OpndVal); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric NeedNeg = false; 7440b57cec5SDimitry Andric return createFMul(OpndVal, Coeff.getValue(Instr->getType())); 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // Checks if any operand is negative and we can convert add to sub. 7480b57cec5SDimitry Andric // This function checks for following negative patterns 7490b57cec5SDimitry Andric // ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C)) 7500b57cec5SDimitry Andric // ADD(XOR(AND(Z, C), C), 1) == NEG(OR(Z, ~C)) 7510b57cec5SDimitry Andric // XOR(AND(Z, C), (C + 1)) == NEG(OR(Z, ~C)) if C is even 7520b57cec5SDimitry Andric static Value *checkForNegativeOperand(BinaryOperator &I, 7530b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 7540b57cec5SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric // This function creates 2 instructions to replace ADD, we need at least one 7570b57cec5SDimitry Andric // of LHS or RHS to have one use to ensure benefit in transform. 7580b57cec5SDimitry Andric if (!LHS->hasOneUse() && !RHS->hasOneUse()) 7590b57cec5SDimitry Andric return nullptr; 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric Value *X = nullptr, *Y = nullptr, *Z = nullptr; 7620b57cec5SDimitry Andric const APInt *C1 = nullptr, *C2 = nullptr; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric // if ONE is on other side, swap 7650b57cec5SDimitry Andric if (match(RHS, m_Add(m_Value(X), m_One()))) 7660b57cec5SDimitry Andric std::swap(LHS, RHS); 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric if (match(LHS, m_Add(m_Value(X), m_One()))) { 7690b57cec5SDimitry Andric // if XOR on other side, swap 7700b57cec5SDimitry Andric if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1)))) 7710b57cec5SDimitry Andric std::swap(X, RHS); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (match(X, m_Xor(m_Value(Y), m_APInt(C1)))) { 7740b57cec5SDimitry Andric // X = XOR(Y, C1), Y = OR(Z, C2), C2 = NOT(C1) ==> X == NOT(AND(Z, C1)) 7750b57cec5SDimitry Andric // ADD(ADD(X, 1), RHS) == ADD(X, ADD(RHS, 1)) == SUB(RHS, AND(Z, C1)) 7760b57cec5SDimitry Andric if (match(Y, m_Or(m_Value(Z), m_APInt(C2))) && (*C2 == ~(*C1))) { 7770b57cec5SDimitry Andric Value *NewAnd = Builder.CreateAnd(Z, *C1); 7780b57cec5SDimitry Andric return Builder.CreateSub(RHS, NewAnd, "sub"); 7790b57cec5SDimitry Andric } else if (match(Y, m_And(m_Value(Z), m_APInt(C2))) && (*C1 == *C2)) { 7800b57cec5SDimitry Andric // X = XOR(Y, C1), Y = AND(Z, C2), C2 == C1 ==> X == NOT(OR(Z, ~C1)) 7810b57cec5SDimitry Andric // ADD(ADD(X, 1), RHS) == ADD(X, ADD(RHS, 1)) == SUB(RHS, OR(Z, ~C1)) 7820b57cec5SDimitry Andric Value *NewOr = Builder.CreateOr(Z, ~(*C1)); 7830b57cec5SDimitry Andric return Builder.CreateSub(RHS, NewOr, "sub"); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric // Restore LHS and RHS 7890b57cec5SDimitry Andric LHS = I.getOperand(0); 7900b57cec5SDimitry Andric RHS = I.getOperand(1); 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric // if XOR is on other side, swap 7930b57cec5SDimitry Andric if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1)))) 7940b57cec5SDimitry Andric std::swap(LHS, RHS); 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric // C2 is ODD 7970b57cec5SDimitry Andric // LHS = XOR(Y, C1), Y = AND(Z, C2), C1 == (C2 + 1) => LHS == NEG(OR(Z, ~C2)) 7980b57cec5SDimitry Andric // ADD(LHS, RHS) == SUB(RHS, OR(Z, ~C2)) 7990b57cec5SDimitry Andric if (match(LHS, m_Xor(m_Value(Y), m_APInt(C1)))) 80006c3fb27SDimitry Andric if (C1->countr_zero() == 0) 8010b57cec5SDimitry Andric if (match(Y, m_And(m_Value(Z), m_APInt(C2))) && *C1 == (*C2 + 1)) { 8020b57cec5SDimitry Andric Value *NewOr = Builder.CreateOr(Z, ~(*C2)); 8030b57cec5SDimitry Andric return Builder.CreateSub(RHS, NewOr, "sub"); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric return nullptr; 8060b57cec5SDimitry Andric } 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric /// Wrapping flags may allow combining constants separated by an extend. 8090b57cec5SDimitry Andric static Instruction *foldNoWrapAdd(BinaryOperator &Add, 8100b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 8110b57cec5SDimitry Andric Value *Op0 = Add.getOperand(0), *Op1 = Add.getOperand(1); 8120b57cec5SDimitry Andric Type *Ty = Add.getType(); 8130b57cec5SDimitry Andric Constant *Op1C; 8140b57cec5SDimitry Andric if (!match(Op1, m_Constant(Op1C))) 8150b57cec5SDimitry Andric return nullptr; 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Try this match first because it results in an add in the narrow type. 8180b57cec5SDimitry Andric // (zext (X +nuw C2)) + C1 --> zext (X + (C2 + trunc(C1))) 8190b57cec5SDimitry Andric Value *X; 8200b57cec5SDimitry Andric const APInt *C1, *C2; 8210b57cec5SDimitry Andric if (match(Op1, m_APInt(C1)) && 822*0fca6ea1SDimitry Andric match(Op0, m_ZExt(m_NUWAddLike(m_Value(X), m_APInt(C2)))) && 8230b57cec5SDimitry Andric C1->isNegative() && C1->sge(-C2->sext(C1->getBitWidth()))) { 824*0fca6ea1SDimitry Andric APInt NewC = *C2 + C1->trunc(C2->getBitWidth()); 825*0fca6ea1SDimitry Andric // If the smaller add will fold to zero, we don't need to check one use. 826*0fca6ea1SDimitry Andric if (NewC.isZero()) 827*0fca6ea1SDimitry Andric return new ZExtInst(X, Ty); 828*0fca6ea1SDimitry Andric // Otherwise only do this if the existing zero extend will be removed. 829*0fca6ea1SDimitry Andric if (Op0->hasOneUse()) 830*0fca6ea1SDimitry Andric return new ZExtInst( 831*0fca6ea1SDimitry Andric Builder.CreateNUWAdd(X, ConstantInt::get(X->getType(), NewC)), Ty); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric // More general combining of constants in the wide type. 8350b57cec5SDimitry Andric // (sext (X +nsw NarrowC)) + C --> (sext X) + (sext(NarrowC) + C) 836*0fca6ea1SDimitry Andric // or (zext nneg (X +nsw NarrowC)) + C --> (sext X) + (sext(NarrowC) + C) 8370b57cec5SDimitry Andric Constant *NarrowC; 838*0fca6ea1SDimitry Andric if (match(Op0, m_OneUse(m_SExtLike( 839*0fca6ea1SDimitry Andric m_NSWAddLike(m_Value(X), m_Constant(NarrowC)))))) { 8405f757f3fSDimitry Andric Value *WideC = Builder.CreateSExt(NarrowC, Ty); 8415f757f3fSDimitry Andric Value *NewC = Builder.CreateAdd(WideC, Op1C); 8420b57cec5SDimitry Andric Value *WideX = Builder.CreateSExt(X, Ty); 8430b57cec5SDimitry Andric return BinaryOperator::CreateAdd(WideX, NewC); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric // (zext (X +nuw NarrowC)) + C --> (zext X) + (zext(NarrowC) + C) 846*0fca6ea1SDimitry Andric if (match(Op0, 847*0fca6ea1SDimitry Andric m_OneUse(m_ZExt(m_NUWAddLike(m_Value(X), m_Constant(NarrowC)))))) { 8485f757f3fSDimitry Andric Value *WideC = Builder.CreateZExt(NarrowC, Ty); 8495f757f3fSDimitry Andric Value *NewC = Builder.CreateAdd(WideC, Op1C); 8500b57cec5SDimitry Andric Value *WideX = Builder.CreateZExt(X, Ty); 8510b57cec5SDimitry Andric return BinaryOperator::CreateAdd(WideX, NewC); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric return nullptr; 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 856e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) { 8570b57cec5SDimitry Andric Value *Op0 = Add.getOperand(0), *Op1 = Add.getOperand(1); 858bdd1243dSDimitry Andric Type *Ty = Add.getType(); 8590b57cec5SDimitry Andric Constant *Op1C; 860fe6060f1SDimitry Andric if (!match(Op1, m_ImmConstant(Op1C))) 8610b57cec5SDimitry Andric return nullptr; 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric if (Instruction *NV = foldBinOpIntoSelectOrPhi(Add)) 8640b57cec5SDimitry Andric return NV; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric Value *X; 8670b57cec5SDimitry Andric Constant *Op00C; 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric // add (sub C1, X), C2 --> sub (add C1, C2), X 8700b57cec5SDimitry Andric if (match(Op0, m_Sub(m_Constant(Op00C), m_Value(X)))) 8710b57cec5SDimitry Andric return BinaryOperator::CreateSub(ConstantExpr::getAdd(Op00C, Op1C), X); 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric Value *Y; 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric // add (sub X, Y), -1 --> add (not Y), X 8760b57cec5SDimitry Andric if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y)))) && 8770b57cec5SDimitry Andric match(Op1, m_AllOnes())) 8780b57cec5SDimitry Andric return BinaryOperator::CreateAdd(Builder.CreateNot(Y), X); 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric // zext(bool) + C -> bool ? C + 1 : C 8810b57cec5SDimitry Andric if (match(Op0, m_ZExt(m_Value(X))) && 8820b57cec5SDimitry Andric X->getType()->getScalarSizeInBits() == 1) 883e8d8bef9SDimitry Andric return SelectInst::Create(X, InstCombiner::AddOne(Op1C), Op1); 884480093f4SDimitry Andric // sext(bool) + C -> bool ? C - 1 : C 885480093f4SDimitry Andric if (match(Op0, m_SExt(m_Value(X))) && 886480093f4SDimitry Andric X->getType()->getScalarSizeInBits() == 1) 887e8d8bef9SDimitry Andric return SelectInst::Create(X, InstCombiner::SubOne(Op1C), Op1); 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric // ~X + C --> (C-1) - X 89006c3fb27SDimitry Andric if (match(Op0, m_Not(m_Value(X)))) { 89106c3fb27SDimitry Andric // ~X + C has NSW and (C-1) won't oveflow => (C-1)-X can have NSW 89206c3fb27SDimitry Andric auto *COne = ConstantInt::get(Op1C->getType(), 1); 89306c3fb27SDimitry Andric bool WillNotSOV = willNotOverflowSignedSub(Op1C, COne, Add); 89406c3fb27SDimitry Andric BinaryOperator *Res = 89506c3fb27SDimitry Andric BinaryOperator::CreateSub(ConstantExpr::getSub(Op1C, COne), X); 89606c3fb27SDimitry Andric Res->setHasNoSignedWrap(Add.hasNoSignedWrap() && WillNotSOV); 89706c3fb27SDimitry Andric return Res; 89806c3fb27SDimitry Andric } 8990b57cec5SDimitry Andric 900bdd1243dSDimitry Andric // (iN X s>> (N - 1)) + 1 --> zext (X > -1) 9010b57cec5SDimitry Andric const APInt *C; 902bdd1243dSDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 903bdd1243dSDimitry Andric if (match(Op0, m_OneUse(m_AShr(m_Value(X), 904*0fca6ea1SDimitry Andric m_SpecificIntAllowPoison(BitWidth - 1)))) && 905bdd1243dSDimitry Andric match(Op1, m_One())) 906bdd1243dSDimitry Andric return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty); 907bdd1243dSDimitry Andric 9080b57cec5SDimitry Andric if (!match(Op1, m_APInt(C))) 9090b57cec5SDimitry Andric return nullptr; 9100b57cec5SDimitry Andric 911fe6060f1SDimitry Andric // (X | Op01C) + Op1C --> X + (Op01C + Op1C) iff the `or` is actually an `add` 912fe6060f1SDimitry Andric Constant *Op01C; 913*0fca6ea1SDimitry Andric if (match(Op0, m_DisjointOr(m_Value(X), m_ImmConstant(Op01C)))) { 914*0fca6ea1SDimitry Andric BinaryOperator *NewAdd = 915*0fca6ea1SDimitry Andric BinaryOperator::CreateAdd(X, ConstantExpr::getAdd(Op01C, Op1C)); 916*0fca6ea1SDimitry Andric NewAdd->setHasNoSignedWrap(Add.hasNoSignedWrap() && 917*0fca6ea1SDimitry Andric willNotOverflowSignedAdd(Op01C, Op1C, Add)); 918*0fca6ea1SDimitry Andric NewAdd->setHasNoUnsignedWrap(Add.hasNoUnsignedWrap()); 919*0fca6ea1SDimitry Andric return NewAdd; 920*0fca6ea1SDimitry Andric } 921fe6060f1SDimitry Andric 9220b57cec5SDimitry Andric // (X | C2) + C --> (X | C2) ^ C2 iff (C2 == -C) 9230b57cec5SDimitry Andric const APInt *C2; 9240b57cec5SDimitry Andric if (match(Op0, m_Or(m_Value(), m_APInt(C2))) && *C2 == -*C) 9250b57cec5SDimitry Andric return BinaryOperator::CreateXor(Op0, ConstantInt::get(Add.getType(), *C2)); 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric if (C->isSignMask()) { 9280b57cec5SDimitry Andric // If wrapping is not allowed, then the addition must set the sign bit: 9290b57cec5SDimitry Andric // X + (signmask) --> X | signmask 9300b57cec5SDimitry Andric if (Add.hasNoSignedWrap() || Add.hasNoUnsignedWrap()) 9310b57cec5SDimitry Andric return BinaryOperator::CreateOr(Op0, Op1); 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric // If wrapping is allowed, then the addition flips the sign bit of LHS: 9340b57cec5SDimitry Andric // X + (signmask) --> X ^ signmask 9350b57cec5SDimitry Andric return BinaryOperator::CreateXor(Op0, Op1); 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric // Is this add the last step in a convoluted sext? 9390b57cec5SDimitry Andric // add(zext(xor i16 X, -32768), -32768) --> sext X 9400b57cec5SDimitry Andric if (match(Op0, m_ZExt(m_Xor(m_Value(X), m_APInt(C2)))) && 9410b57cec5SDimitry Andric C2->isMinSignedValue() && C2->sext(Ty->getScalarSizeInBits()) == *C) 9420b57cec5SDimitry Andric return CastInst::Create(Instruction::SExt, X, Ty); 9430b57cec5SDimitry Andric 944e8d8bef9SDimitry Andric if (match(Op0, m_Xor(m_Value(X), m_APInt(C2)))) { 945e8d8bef9SDimitry Andric // (X ^ signmask) + C --> (X + (signmask ^ C)) 946e8d8bef9SDimitry Andric if (C2->isSignMask()) 947e8d8bef9SDimitry Andric return BinaryOperator::CreateAdd(X, ConstantInt::get(Ty, *C2 ^ *C)); 948e8d8bef9SDimitry Andric 949e8d8bef9SDimitry Andric // If X has no high-bits set above an xor mask: 950e8d8bef9SDimitry Andric // add (xor X, LowMaskC), C --> sub (LowMaskC + C), X 951e8d8bef9SDimitry Andric if (C2->isMask()) { 952e8d8bef9SDimitry Andric KnownBits LHSKnown = computeKnownBits(X, 0, &Add); 953349cc55cSDimitry Andric if ((*C2 | LHSKnown.Zero).isAllOnes()) 954e8d8bef9SDimitry Andric return BinaryOperator::CreateSub(ConstantInt::get(Ty, *C2 + *C), X); 955e8d8bef9SDimitry Andric } 956e8d8bef9SDimitry Andric 957e8d8bef9SDimitry Andric // Look for a math+logic pattern that corresponds to sext-in-register of a 958e8d8bef9SDimitry Andric // value with cleared high bits. Convert that into a pair of shifts: 959e8d8bef9SDimitry Andric // add (xor X, 0x80), 0xF..F80 --> (X << ShAmtC) >>s ShAmtC 960e8d8bef9SDimitry Andric // add (xor X, 0xF..F80), 0x80 --> (X << ShAmtC) >>s ShAmtC 961e8d8bef9SDimitry Andric if (Op0->hasOneUse() && *C2 == -(*C)) { 962e8d8bef9SDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 963e8d8bef9SDimitry Andric unsigned ShAmt = 0; 964e8d8bef9SDimitry Andric if (C->isPowerOf2()) 965e8d8bef9SDimitry Andric ShAmt = BitWidth - C->logBase2() - 1; 966e8d8bef9SDimitry Andric else if (C2->isPowerOf2()) 967e8d8bef9SDimitry Andric ShAmt = BitWidth - C2->logBase2() - 1; 968e8d8bef9SDimitry Andric if (ShAmt && MaskedValueIsZero(X, APInt::getHighBitsSet(BitWidth, ShAmt), 969e8d8bef9SDimitry Andric 0, &Add)) { 970e8d8bef9SDimitry Andric Constant *ShAmtC = ConstantInt::get(Ty, ShAmt); 971e8d8bef9SDimitry Andric Value *NewShl = Builder.CreateShl(X, ShAmtC, "sext"); 972e8d8bef9SDimitry Andric return BinaryOperator::CreateAShr(NewShl, ShAmtC); 973e8d8bef9SDimitry Andric } 974e8d8bef9SDimitry Andric } 975e8d8bef9SDimitry Andric } 976e8d8bef9SDimitry Andric 977349cc55cSDimitry Andric if (C->isOne() && Op0->hasOneUse()) { 9780b57cec5SDimitry Andric // add (sext i1 X), 1 --> zext (not X) 9790b57cec5SDimitry Andric // TODO: The smallest IR representation is (select X, 0, 1), and that would 9800b57cec5SDimitry Andric // not require the one-use check. But we need to remove a transform in 9810b57cec5SDimitry Andric // visitSelect and make sure that IR value tracking for select is equal or 9820b57cec5SDimitry Andric // better than for these ops. 9830b57cec5SDimitry Andric if (match(Op0, m_SExt(m_Value(X))) && 9840b57cec5SDimitry Andric X->getType()->getScalarSizeInBits() == 1) 9850b57cec5SDimitry Andric return new ZExtInst(Builder.CreateNot(X), Ty); 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric // Shifts and add used to flip and mask off the low bit: 9880b57cec5SDimitry Andric // add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1 9890b57cec5SDimitry Andric const APInt *C3; 9900b57cec5SDimitry Andric if (match(Op0, m_AShr(m_Shl(m_Value(X), m_APInt(C2)), m_APInt(C3))) && 9910b57cec5SDimitry Andric C2 == C3 && *C2 == Ty->getScalarSizeInBits() - 1) { 9920b57cec5SDimitry Andric Value *NotX = Builder.CreateNot(X); 9930b57cec5SDimitry Andric return BinaryOperator::CreateAnd(NotX, ConstantInt::get(Ty, 1)); 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 99706c3fb27SDimitry Andric // Fold (add (zext (add X, -1)), 1) -> (zext X) if X is non-zero. 99806c3fb27SDimitry Andric // TODO: There's a general form for any constant on the outer add. 99906c3fb27SDimitry Andric if (C->isOne()) { 100006c3fb27SDimitry Andric if (match(Op0, m_ZExt(m_Add(m_Value(X), m_AllOnes())))) { 100106c3fb27SDimitry Andric const SimplifyQuery Q = SQ.getWithInstruction(&Add); 1002*0fca6ea1SDimitry Andric if (llvm::isKnownNonZero(X, Q)) 100306c3fb27SDimitry Andric return new ZExtInst(X, Ty); 100406c3fb27SDimitry Andric } 100506c3fb27SDimitry Andric } 100606c3fb27SDimitry Andric 10070b57cec5SDimitry Andric return nullptr; 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric 10105f757f3fSDimitry Andric // match variations of a^2 + 2*a*b + b^2 10115f757f3fSDimitry Andric // 10125f757f3fSDimitry Andric // to reuse the code between the FP and Int versions, the instruction OpCodes 10135f757f3fSDimitry Andric // and constant types have been turned into template parameters. 10145f757f3fSDimitry Andric // 10155f757f3fSDimitry Andric // Mul2Rhs: The constant to perform the multiplicative equivalent of X*2 with; 10165f757f3fSDimitry Andric // should be `m_SpecificFP(2.0)` for FP and `m_SpecificInt(1)` for Int 10175f757f3fSDimitry Andric // (we're matching `X<<1` instead of `X*2` for Int) 10185f757f3fSDimitry Andric template <bool FP, typename Mul2Rhs> 10195f757f3fSDimitry Andric static bool matchesSquareSum(BinaryOperator &I, Mul2Rhs M2Rhs, Value *&A, 10205f757f3fSDimitry Andric Value *&B) { 10215f757f3fSDimitry Andric constexpr unsigned MulOp = FP ? Instruction::FMul : Instruction::Mul; 10225f757f3fSDimitry Andric constexpr unsigned AddOp = FP ? Instruction::FAdd : Instruction::Add; 10235f757f3fSDimitry Andric constexpr unsigned Mul2Op = FP ? Instruction::FMul : Instruction::Shl; 10245f757f3fSDimitry Andric 10255f757f3fSDimitry Andric // (a * a) + (((a * 2) + b) * b) 10265f757f3fSDimitry Andric if (match(&I, m_c_BinOp( 10275f757f3fSDimitry Andric AddOp, m_OneUse(m_BinOp(MulOp, m_Value(A), m_Deferred(A))), 1028*0fca6ea1SDimitry Andric m_OneUse(m_c_BinOp( 10295f757f3fSDimitry Andric MulOp, 10305f757f3fSDimitry Andric m_c_BinOp(AddOp, m_BinOp(Mul2Op, m_Deferred(A), M2Rhs), 10315f757f3fSDimitry Andric m_Value(B)), 10325f757f3fSDimitry Andric m_Deferred(B)))))) 10335f757f3fSDimitry Andric return true; 10345f757f3fSDimitry Andric 10355f757f3fSDimitry Andric // ((a * b) * 2) or ((a * 2) * b) 10365f757f3fSDimitry Andric // + 10375f757f3fSDimitry Andric // (a * a + b * b) or (b * b + a * a) 10385f757f3fSDimitry Andric return match( 1039*0fca6ea1SDimitry Andric &I, m_c_BinOp( 1040*0fca6ea1SDimitry Andric AddOp, 10415f757f3fSDimitry Andric m_CombineOr( 10425f757f3fSDimitry Andric m_OneUse(m_BinOp( 10435f757f3fSDimitry Andric Mul2Op, m_BinOp(MulOp, m_Value(A), m_Value(B)), M2Rhs)), 1044*0fca6ea1SDimitry Andric m_OneUse(m_c_BinOp(MulOp, m_BinOp(Mul2Op, m_Value(A), M2Rhs), 10455f757f3fSDimitry Andric m_Value(B)))), 1046*0fca6ea1SDimitry Andric m_OneUse( 1047*0fca6ea1SDimitry Andric m_c_BinOp(AddOp, m_BinOp(MulOp, m_Deferred(A), m_Deferred(A)), 10485f757f3fSDimitry Andric m_BinOp(MulOp, m_Deferred(B), m_Deferred(B)))))); 10495f757f3fSDimitry Andric } 10505f757f3fSDimitry Andric 10515f757f3fSDimitry Andric // Fold integer variations of a^2 + 2*a*b + b^2 -> (a + b)^2 10525f757f3fSDimitry Andric Instruction *InstCombinerImpl::foldSquareSumInt(BinaryOperator &I) { 10535f757f3fSDimitry Andric Value *A, *B; 10545f757f3fSDimitry Andric if (matchesSquareSum</*FP*/ false>(I, m_SpecificInt(1), A, B)) { 10555f757f3fSDimitry Andric Value *AB = Builder.CreateAdd(A, B); 10565f757f3fSDimitry Andric return BinaryOperator::CreateMul(AB, AB); 10575f757f3fSDimitry Andric } 10585f757f3fSDimitry Andric return nullptr; 10595f757f3fSDimitry Andric } 10605f757f3fSDimitry Andric 10615f757f3fSDimitry Andric // Fold floating point variations of a^2 + 2*a*b + b^2 -> (a + b)^2 10625f757f3fSDimitry Andric // Requires `nsz` and `reassoc`. 10635f757f3fSDimitry Andric Instruction *InstCombinerImpl::foldSquareSumFP(BinaryOperator &I) { 10645f757f3fSDimitry Andric assert(I.hasAllowReassoc() && I.hasNoSignedZeros() && "Assumption mismatch"); 10655f757f3fSDimitry Andric Value *A, *B; 10665f757f3fSDimitry Andric if (matchesSquareSum</*FP*/ true>(I, m_SpecificFP(2.0), A, B)) { 10675f757f3fSDimitry Andric Value *AB = Builder.CreateFAddFMF(A, B, &I); 10685f757f3fSDimitry Andric return BinaryOperator::CreateFMulFMF(AB, AB, &I); 10695f757f3fSDimitry Andric } 10705f757f3fSDimitry Andric return nullptr; 10715f757f3fSDimitry Andric } 10725f757f3fSDimitry Andric 10730b57cec5SDimitry Andric // Matches multiplication expression Op * C where C is a constant. Returns the 10740b57cec5SDimitry Andric // constant value in C and the other operand in Op. Returns true if such a 10750b57cec5SDimitry Andric // match is found. 10760b57cec5SDimitry Andric static bool MatchMul(Value *E, Value *&Op, APInt &C) { 10770b57cec5SDimitry Andric const APInt *AI; 10780b57cec5SDimitry Andric if (match(E, m_Mul(m_Value(Op), m_APInt(AI)))) { 10790b57cec5SDimitry Andric C = *AI; 10800b57cec5SDimitry Andric return true; 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric if (match(E, m_Shl(m_Value(Op), m_APInt(AI)))) { 10830b57cec5SDimitry Andric C = APInt(AI->getBitWidth(), 1); 10840b57cec5SDimitry Andric C <<= *AI; 10850b57cec5SDimitry Andric return true; 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric return false; 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric // Matches remainder expression Op % C where C is a constant. Returns the 10910b57cec5SDimitry Andric // constant value in C and the other operand in Op. Returns the signedness of 10920b57cec5SDimitry Andric // the remainder operation in IsSigned. Returns true if such a match is 10930b57cec5SDimitry Andric // found. 10940b57cec5SDimitry Andric static bool MatchRem(Value *E, Value *&Op, APInt &C, bool &IsSigned) { 10950b57cec5SDimitry Andric const APInt *AI; 10960b57cec5SDimitry Andric IsSigned = false; 10970b57cec5SDimitry Andric if (match(E, m_SRem(m_Value(Op), m_APInt(AI)))) { 10980b57cec5SDimitry Andric IsSigned = true; 10990b57cec5SDimitry Andric C = *AI; 11000b57cec5SDimitry Andric return true; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric if (match(E, m_URem(m_Value(Op), m_APInt(AI)))) { 11030b57cec5SDimitry Andric C = *AI; 11040b57cec5SDimitry Andric return true; 11050b57cec5SDimitry Andric } 11060b57cec5SDimitry Andric if (match(E, m_And(m_Value(Op), m_APInt(AI))) && (*AI + 1).isPowerOf2()) { 11070b57cec5SDimitry Andric C = *AI + 1; 11080b57cec5SDimitry Andric return true; 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric return false; 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric // Matches division expression Op / C with the given signedness as indicated 11140b57cec5SDimitry Andric // by IsSigned, where C is a constant. Returns the constant value in C and the 11150b57cec5SDimitry Andric // other operand in Op. Returns true if such a match is found. 11160b57cec5SDimitry Andric static bool MatchDiv(Value *E, Value *&Op, APInt &C, bool IsSigned) { 11170b57cec5SDimitry Andric const APInt *AI; 11180b57cec5SDimitry Andric if (IsSigned && match(E, m_SDiv(m_Value(Op), m_APInt(AI)))) { 11190b57cec5SDimitry Andric C = *AI; 11200b57cec5SDimitry Andric return true; 11210b57cec5SDimitry Andric } 11220b57cec5SDimitry Andric if (!IsSigned) { 11230b57cec5SDimitry Andric if (match(E, m_UDiv(m_Value(Op), m_APInt(AI)))) { 11240b57cec5SDimitry Andric C = *AI; 11250b57cec5SDimitry Andric return true; 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric if (match(E, m_LShr(m_Value(Op), m_APInt(AI)))) { 11280b57cec5SDimitry Andric C = APInt(AI->getBitWidth(), 1); 11290b57cec5SDimitry Andric C <<= *AI; 11300b57cec5SDimitry Andric return true; 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric return false; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // Returns whether C0 * C1 with the given signedness overflows. 11370b57cec5SDimitry Andric static bool MulWillOverflow(APInt &C0, APInt &C1, bool IsSigned) { 11380b57cec5SDimitry Andric bool overflow; 11390b57cec5SDimitry Andric if (IsSigned) 11400b57cec5SDimitry Andric (void)C0.smul_ov(C1, overflow); 11410b57cec5SDimitry Andric else 11420b57cec5SDimitry Andric (void)C0.umul_ov(C1, overflow); 11430b57cec5SDimitry Andric return overflow; 11440b57cec5SDimitry Andric } 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric // Simplifies X % C0 + (( X / C0 ) % C1) * C0 to X % (C0 * C1), where (C0 * C1) 11470b57cec5SDimitry Andric // does not overflow. 1148*0fca6ea1SDimitry Andric // Simplifies (X / C0) * C1 + (X % C0) * C2 to 1149*0fca6ea1SDimitry Andric // (X / C0) * (C1 - C2 * C0) + X * C2 1150e8d8bef9SDimitry Andric Value *InstCombinerImpl::SimplifyAddWithRemainder(BinaryOperator &I) { 11510b57cec5SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 11520b57cec5SDimitry Andric Value *X, *MulOpV; 11530b57cec5SDimitry Andric APInt C0, MulOpC; 11540b57cec5SDimitry Andric bool IsSigned; 11550b57cec5SDimitry Andric // Match I = X % C0 + MulOpV * C0 11560b57cec5SDimitry Andric if (((MatchRem(LHS, X, C0, IsSigned) && MatchMul(RHS, MulOpV, MulOpC)) || 11570b57cec5SDimitry Andric (MatchRem(RHS, X, C0, IsSigned) && MatchMul(LHS, MulOpV, MulOpC))) && 11580b57cec5SDimitry Andric C0 == MulOpC) { 11590b57cec5SDimitry Andric Value *RemOpV; 11600b57cec5SDimitry Andric APInt C1; 11610b57cec5SDimitry Andric bool Rem2IsSigned; 11620b57cec5SDimitry Andric // Match MulOpC = RemOpV % C1 11630b57cec5SDimitry Andric if (MatchRem(MulOpV, RemOpV, C1, Rem2IsSigned) && 11640b57cec5SDimitry Andric IsSigned == Rem2IsSigned) { 11650b57cec5SDimitry Andric Value *DivOpV; 11660b57cec5SDimitry Andric APInt DivOpC; 11670b57cec5SDimitry Andric // Match RemOpV = X / C0 11680b57cec5SDimitry Andric if (MatchDiv(RemOpV, DivOpV, DivOpC, IsSigned) && X == DivOpV && 11690b57cec5SDimitry Andric C0 == DivOpC && !MulWillOverflow(C0, C1, IsSigned)) { 11705ffd83dbSDimitry Andric Value *NewDivisor = ConstantInt::get(X->getType(), C0 * C1); 11710b57cec5SDimitry Andric return IsSigned ? Builder.CreateSRem(X, NewDivisor, "srem") 11720b57cec5SDimitry Andric : Builder.CreateURem(X, NewDivisor, "urem"); 11730b57cec5SDimitry Andric } 11740b57cec5SDimitry Andric } 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric 1177*0fca6ea1SDimitry Andric // Match I = (X / C0) * C1 + (X % C0) * C2 1178*0fca6ea1SDimitry Andric Value *Div, *Rem; 1179*0fca6ea1SDimitry Andric APInt C1, C2; 1180*0fca6ea1SDimitry Andric if (!LHS->hasOneUse() || !MatchMul(LHS, Div, C1)) 1181*0fca6ea1SDimitry Andric Div = LHS, C1 = APInt(I.getType()->getScalarSizeInBits(), 1); 1182*0fca6ea1SDimitry Andric if (!RHS->hasOneUse() || !MatchMul(RHS, Rem, C2)) 1183*0fca6ea1SDimitry Andric Rem = RHS, C2 = APInt(I.getType()->getScalarSizeInBits(), 1); 1184*0fca6ea1SDimitry Andric if (match(Div, m_IRem(m_Value(), m_Value()))) { 1185*0fca6ea1SDimitry Andric std::swap(Div, Rem); 1186*0fca6ea1SDimitry Andric std::swap(C1, C2); 1187*0fca6ea1SDimitry Andric } 1188*0fca6ea1SDimitry Andric Value *DivOpV; 1189*0fca6ea1SDimitry Andric APInt DivOpC; 1190*0fca6ea1SDimitry Andric if (MatchRem(Rem, X, C0, IsSigned) && 1191*0fca6ea1SDimitry Andric MatchDiv(Div, DivOpV, DivOpC, IsSigned) && X == DivOpV && C0 == DivOpC) { 1192*0fca6ea1SDimitry Andric APInt NewC = C1 - C2 * C0; 1193*0fca6ea1SDimitry Andric if (!NewC.isZero() && !Rem->hasOneUse()) 1194*0fca6ea1SDimitry Andric return nullptr; 1195*0fca6ea1SDimitry Andric if (!isGuaranteedNotToBeUndef(X, &AC, &I, &DT)) 1196*0fca6ea1SDimitry Andric return nullptr; 1197*0fca6ea1SDimitry Andric Value *MulXC2 = Builder.CreateMul(X, ConstantInt::get(X->getType(), C2)); 1198*0fca6ea1SDimitry Andric if (NewC.isZero()) 1199*0fca6ea1SDimitry Andric return MulXC2; 1200*0fca6ea1SDimitry Andric return Builder.CreateAdd( 1201*0fca6ea1SDimitry Andric Builder.CreateMul(Div, ConstantInt::get(X->getType(), NewC)), MulXC2); 1202*0fca6ea1SDimitry Andric } 1203*0fca6ea1SDimitry Andric 12040b57cec5SDimitry Andric return nullptr; 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric /// Fold 12080b57cec5SDimitry Andric /// (1 << NBits) - 1 12090b57cec5SDimitry Andric /// Into: 12100b57cec5SDimitry Andric /// ~(-(1 << NBits)) 12110b57cec5SDimitry Andric /// Because a 'not' is better for bit-tracking analysis and other transforms 12120b57cec5SDimitry Andric /// than an 'add'. The new shl is always nsw, and is nuw if old `and` was. 12130b57cec5SDimitry Andric static Instruction *canonicalizeLowbitMask(BinaryOperator &I, 12140b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 12150b57cec5SDimitry Andric Value *NBits; 12160b57cec5SDimitry Andric if (!match(&I, m_Add(m_OneUse(m_Shl(m_One(), m_Value(NBits))), m_AllOnes()))) 12170b57cec5SDimitry Andric return nullptr; 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric Constant *MinusOne = Constant::getAllOnesValue(NBits->getType()); 12200b57cec5SDimitry Andric Value *NotMask = Builder.CreateShl(MinusOne, NBits, "notmask"); 12210b57cec5SDimitry Andric // Be wary of constant folding. 12220b57cec5SDimitry Andric if (auto *BOp = dyn_cast<BinaryOperator>(NotMask)) { 12230b57cec5SDimitry Andric // Always NSW. But NUW propagates from `add`. 12240b57cec5SDimitry Andric BOp->setHasNoSignedWrap(); 12250b57cec5SDimitry Andric BOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); 12260b57cec5SDimitry Andric } 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric return BinaryOperator::CreateNot(NotMask, I.getName()); 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric static Instruction *foldToUnsignedSaturatedAdd(BinaryOperator &I) { 12320b57cec5SDimitry Andric assert(I.getOpcode() == Instruction::Add && "Expecting add instruction"); 12330b57cec5SDimitry Andric Type *Ty = I.getType(); 12340b57cec5SDimitry Andric auto getUAddSat = [&]() { 12350b57cec5SDimitry Andric return Intrinsic::getDeclaration(I.getModule(), Intrinsic::uadd_sat, Ty); 12360b57cec5SDimitry Andric }; 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric // add (umin X, ~Y), Y --> uaddsat X, Y 12390b57cec5SDimitry Andric Value *X, *Y; 12400b57cec5SDimitry Andric if (match(&I, m_c_Add(m_c_UMin(m_Value(X), m_Not(m_Value(Y))), 12410b57cec5SDimitry Andric m_Deferred(Y)))) 12420b57cec5SDimitry Andric return CallInst::Create(getUAddSat(), { X, Y }); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric // add (umin X, ~C), C --> uaddsat X, C 12450b57cec5SDimitry Andric const APInt *C, *NotC; 12460b57cec5SDimitry Andric if (match(&I, m_Add(m_UMin(m_Value(X), m_APInt(NotC)), m_APInt(C))) && 12470b57cec5SDimitry Andric *C == ~*NotC) 12480b57cec5SDimitry Andric return CallInst::Create(getUAddSat(), { X, ConstantInt::get(Ty, *C) }); 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric return nullptr; 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric 12535f757f3fSDimitry Andric // Transform: 12545f757f3fSDimitry Andric // (add A, (shl (neg B), Y)) 12555f757f3fSDimitry Andric // -> (sub A, (shl B, Y)) 12565f757f3fSDimitry Andric static Instruction *combineAddSubWithShlAddSub(InstCombiner::BuilderTy &Builder, 12575f757f3fSDimitry Andric const BinaryOperator &I) { 12585f757f3fSDimitry Andric Value *A, *B, *Cnt; 12595f757f3fSDimitry Andric if (match(&I, 12605f757f3fSDimitry Andric m_c_Add(m_OneUse(m_Shl(m_OneUse(m_Neg(m_Value(B))), m_Value(Cnt))), 12615f757f3fSDimitry Andric m_Value(A)))) { 12625f757f3fSDimitry Andric Value *NewShl = Builder.CreateShl(B, Cnt); 12635f757f3fSDimitry Andric return BinaryOperator::CreateSub(A, NewShl); 12645f757f3fSDimitry Andric } 12655f757f3fSDimitry Andric return nullptr; 12665f757f3fSDimitry Andric } 12675f757f3fSDimitry Andric 1268bdd1243dSDimitry Andric /// Try to reduce signed division by power-of-2 to an arithmetic shift right. 1269bdd1243dSDimitry Andric static Instruction *foldAddToAshr(BinaryOperator &Add) { 1270bdd1243dSDimitry Andric // Division must be by power-of-2, but not the minimum signed value. 1271bdd1243dSDimitry Andric Value *X; 1272bdd1243dSDimitry Andric const APInt *DivC; 1273bdd1243dSDimitry Andric if (!match(Add.getOperand(0), m_SDiv(m_Value(X), m_Power2(DivC))) || 1274bdd1243dSDimitry Andric DivC->isNegative()) 1275bdd1243dSDimitry Andric return nullptr; 1276bdd1243dSDimitry Andric 1277bdd1243dSDimitry Andric // Rounding is done by adding -1 if the dividend (X) is negative and has any 12785f757f3fSDimitry Andric // low bits set. It recognizes two canonical patterns: 12795f757f3fSDimitry Andric // 1. For an 'ugt' cmp with the signed minimum value (SMIN), the 12805f757f3fSDimitry Andric // pattern is: sext (icmp ugt (X & (DivC - 1)), SMIN). 12815f757f3fSDimitry Andric // 2. For an 'eq' cmp, the pattern's: sext (icmp eq X & (SMIN + 1), SMIN + 1). 12825f757f3fSDimitry Andric // Note that, by the time we end up here, if possible, ugt has been 12835f757f3fSDimitry Andric // canonicalized into eq. 12845f757f3fSDimitry Andric const APInt *MaskC, *MaskCCmp; 1285bdd1243dSDimitry Andric ICmpInst::Predicate Pred; 1286bdd1243dSDimitry Andric if (!match(Add.getOperand(1), 1287bdd1243dSDimitry Andric m_SExt(m_ICmp(Pred, m_And(m_Specific(X), m_APInt(MaskC)), 12885f757f3fSDimitry Andric m_APInt(MaskCCmp))))) 12895f757f3fSDimitry Andric return nullptr; 12905f757f3fSDimitry Andric 12915f757f3fSDimitry Andric if ((Pred != ICmpInst::ICMP_UGT || !MaskCCmp->isSignMask()) && 12925f757f3fSDimitry Andric (Pred != ICmpInst::ICMP_EQ || *MaskCCmp != *MaskC)) 1293bdd1243dSDimitry Andric return nullptr; 1294bdd1243dSDimitry Andric 1295bdd1243dSDimitry Andric APInt SMin = APInt::getSignedMinValue(Add.getType()->getScalarSizeInBits()); 12965f757f3fSDimitry Andric bool IsMaskValid = Pred == ICmpInst::ICMP_UGT 12975f757f3fSDimitry Andric ? (*MaskC == (SMin | (*DivC - 1))) 12985f757f3fSDimitry Andric : (*DivC == 2 && *MaskC == SMin + 1); 12995f757f3fSDimitry Andric if (!IsMaskValid) 1300bdd1243dSDimitry Andric return nullptr; 1301bdd1243dSDimitry Andric 1302bdd1243dSDimitry Andric // (X / DivC) + sext ((X & (SMin | (DivC - 1)) >u SMin) --> X >>s log2(DivC) 1303bdd1243dSDimitry Andric return BinaryOperator::CreateAShr( 1304bdd1243dSDimitry Andric X, ConstantInt::get(Add.getType(), DivC->exactLogBase2())); 1305bdd1243dSDimitry Andric } 1306bdd1243dSDimitry Andric 1307e8d8bef9SDimitry Andric Instruction *InstCombinerImpl:: 1308e8d8bef9SDimitry Andric canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract( 13098bcb0991SDimitry Andric BinaryOperator &I) { 13108bcb0991SDimitry Andric assert((I.getOpcode() == Instruction::Add || 13118bcb0991SDimitry Andric I.getOpcode() == Instruction::Or || 13128bcb0991SDimitry Andric I.getOpcode() == Instruction::Sub) && 13138bcb0991SDimitry Andric "Expecting add/or/sub instruction"); 13148bcb0991SDimitry Andric 13158bcb0991SDimitry Andric // We have a subtraction/addition between a (potentially truncated) *logical* 13168bcb0991SDimitry Andric // right-shift of X and a "select". 13178bcb0991SDimitry Andric Value *X, *Select; 13188bcb0991SDimitry Andric Instruction *LowBitsToSkip, *Extract; 13198bcb0991SDimitry Andric if (!match(&I, m_c_BinOp(m_TruncOrSelf(m_CombineAnd( 13208bcb0991SDimitry Andric m_LShr(m_Value(X), m_Instruction(LowBitsToSkip)), 13218bcb0991SDimitry Andric m_Instruction(Extract))), 13228bcb0991SDimitry Andric m_Value(Select)))) 13238bcb0991SDimitry Andric return nullptr; 13248bcb0991SDimitry Andric 13258bcb0991SDimitry Andric // `add`/`or` is commutative; but for `sub`, "select" *must* be on RHS. 13268bcb0991SDimitry Andric if (I.getOpcode() == Instruction::Sub && I.getOperand(1) != Select) 13278bcb0991SDimitry Andric return nullptr; 13288bcb0991SDimitry Andric 13298bcb0991SDimitry Andric Type *XTy = X->getType(); 13308bcb0991SDimitry Andric bool HadTrunc = I.getType() != XTy; 13318bcb0991SDimitry Andric 13328bcb0991SDimitry Andric // If there was a truncation of extracted value, then we'll need to produce 13338bcb0991SDimitry Andric // one extra instruction, so we need to ensure one instruction will go away. 13348bcb0991SDimitry Andric if (HadTrunc && !match(&I, m_c_BinOp(m_OneUse(m_Value()), m_Value()))) 13358bcb0991SDimitry Andric return nullptr; 13368bcb0991SDimitry Andric 13378bcb0991SDimitry Andric // Extraction should extract high NBits bits, with shift amount calculated as: 13388bcb0991SDimitry Andric // low bits to skip = shift bitwidth - high bits to extract 13398bcb0991SDimitry Andric // The shift amount itself may be extended, and we need to look past zero-ext 13408bcb0991SDimitry Andric // when matching NBits, that will matter for matching later. 13418bcb0991SDimitry Andric Constant *C; 13428bcb0991SDimitry Andric Value *NBits; 13438bcb0991SDimitry Andric if (!match( 13448bcb0991SDimitry Andric LowBitsToSkip, 13458bcb0991SDimitry Andric m_ZExtOrSelf(m_Sub(m_Constant(C), m_ZExtOrSelf(m_Value(NBits))))) || 13468bcb0991SDimitry Andric !match(C, m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, 13478bcb0991SDimitry Andric APInt(C->getType()->getScalarSizeInBits(), 13488bcb0991SDimitry Andric X->getType()->getScalarSizeInBits())))) 13498bcb0991SDimitry Andric return nullptr; 13508bcb0991SDimitry Andric 13518bcb0991SDimitry Andric // Sign-extending value can be zero-extended if we `sub`tract it, 13528bcb0991SDimitry Andric // or sign-extended otherwise. 13538bcb0991SDimitry Andric auto SkipExtInMagic = [&I](Value *&V) { 13548bcb0991SDimitry Andric if (I.getOpcode() == Instruction::Sub) 13558bcb0991SDimitry Andric match(V, m_ZExtOrSelf(m_Value(V))); 13568bcb0991SDimitry Andric else 13578bcb0991SDimitry Andric match(V, m_SExtOrSelf(m_Value(V))); 13588bcb0991SDimitry Andric }; 13598bcb0991SDimitry Andric 13608bcb0991SDimitry Andric // Now, finally validate the sign-extending magic. 13618bcb0991SDimitry Andric // `select` itself may be appropriately extended, look past that. 13628bcb0991SDimitry Andric SkipExtInMagic(Select); 13638bcb0991SDimitry Andric 13648bcb0991SDimitry Andric ICmpInst::Predicate Pred; 13658bcb0991SDimitry Andric const APInt *Thr; 13668bcb0991SDimitry Andric Value *SignExtendingValue, *Zero; 13678bcb0991SDimitry Andric bool ShouldSignext; 13688bcb0991SDimitry Andric // It must be a select between two values we will later establish to be a 13698bcb0991SDimitry Andric // sign-extending value and a zero constant. The condition guarding the 13708bcb0991SDimitry Andric // sign-extension must be based on a sign bit of the same X we had in `lshr`. 13718bcb0991SDimitry Andric if (!match(Select, m_Select(m_ICmp(Pred, m_Specific(X), m_APInt(Thr)), 13728bcb0991SDimitry Andric m_Value(SignExtendingValue), m_Value(Zero))) || 13738bcb0991SDimitry Andric !isSignBitCheck(Pred, *Thr, ShouldSignext)) 13748bcb0991SDimitry Andric return nullptr; 13758bcb0991SDimitry Andric 13768bcb0991SDimitry Andric // icmp-select pair is commutative. 13778bcb0991SDimitry Andric if (!ShouldSignext) 13788bcb0991SDimitry Andric std::swap(SignExtendingValue, Zero); 13798bcb0991SDimitry Andric 13808bcb0991SDimitry Andric // If we should not perform sign-extension then we must add/or/subtract zero. 13818bcb0991SDimitry Andric if (!match(Zero, m_Zero())) 13828bcb0991SDimitry Andric return nullptr; 13838bcb0991SDimitry Andric // Otherwise, it should be some constant, left-shifted by the same NBits we 13848bcb0991SDimitry Andric // had in `lshr`. Said left-shift can also be appropriately extended. 13858bcb0991SDimitry Andric // Again, we must look past zero-ext when looking for NBits. 13868bcb0991SDimitry Andric SkipExtInMagic(SignExtendingValue); 13878bcb0991SDimitry Andric Constant *SignExtendingValueBaseConstant; 13888bcb0991SDimitry Andric if (!match(SignExtendingValue, 13898bcb0991SDimitry Andric m_Shl(m_Constant(SignExtendingValueBaseConstant), 13908bcb0991SDimitry Andric m_ZExtOrSelf(m_Specific(NBits))))) 13918bcb0991SDimitry Andric return nullptr; 13928bcb0991SDimitry Andric // If we `sub`, then the constant should be one, else it should be all-ones. 13938bcb0991SDimitry Andric if (I.getOpcode() == Instruction::Sub 13948bcb0991SDimitry Andric ? !match(SignExtendingValueBaseConstant, m_One()) 13958bcb0991SDimitry Andric : !match(SignExtendingValueBaseConstant, m_AllOnes())) 13968bcb0991SDimitry Andric return nullptr; 13978bcb0991SDimitry Andric 13988bcb0991SDimitry Andric auto *NewAShr = BinaryOperator::CreateAShr(X, LowBitsToSkip, 13998bcb0991SDimitry Andric Extract->getName() + ".sext"); 14008bcb0991SDimitry Andric NewAShr->copyIRFlags(Extract); // Preserve `exact`-ness. 14018bcb0991SDimitry Andric if (!HadTrunc) 14028bcb0991SDimitry Andric return NewAShr; 14038bcb0991SDimitry Andric 14048bcb0991SDimitry Andric Builder.Insert(NewAShr); 14058bcb0991SDimitry Andric return TruncInst::CreateTruncOrBitCast(NewAShr, I.getType()); 14068bcb0991SDimitry Andric } 14078bcb0991SDimitry Andric 1408e8d8bef9SDimitry Andric /// This is a specialization of a more general transform from 1409bdd1243dSDimitry Andric /// foldUsingDistributiveLaws. If that code can be made to work optimally 1410e8d8bef9SDimitry Andric /// for multi-use cases or propagating nsw/nuw, then we would not need this. 1411e8d8bef9SDimitry Andric static Instruction *factorizeMathWithShlOps(BinaryOperator &I, 1412e8d8bef9SDimitry Andric InstCombiner::BuilderTy &Builder) { 1413e8d8bef9SDimitry Andric // TODO: Also handle mul by doubling the shift amount? 1414e8d8bef9SDimitry Andric assert((I.getOpcode() == Instruction::Add || 1415e8d8bef9SDimitry Andric I.getOpcode() == Instruction::Sub) && 1416e8d8bef9SDimitry Andric "Expected add/sub"); 1417e8d8bef9SDimitry Andric auto *Op0 = dyn_cast<BinaryOperator>(I.getOperand(0)); 1418e8d8bef9SDimitry Andric auto *Op1 = dyn_cast<BinaryOperator>(I.getOperand(1)); 1419e8d8bef9SDimitry Andric if (!Op0 || !Op1 || !(Op0->hasOneUse() || Op1->hasOneUse())) 1420e8d8bef9SDimitry Andric return nullptr; 1421e8d8bef9SDimitry Andric 1422e8d8bef9SDimitry Andric Value *X, *Y, *ShAmt; 1423e8d8bef9SDimitry Andric if (!match(Op0, m_Shl(m_Value(X), m_Value(ShAmt))) || 1424e8d8bef9SDimitry Andric !match(Op1, m_Shl(m_Value(Y), m_Specific(ShAmt)))) 1425e8d8bef9SDimitry Andric return nullptr; 1426e8d8bef9SDimitry Andric 1427e8d8bef9SDimitry Andric // No-wrap propagates only when all ops have no-wrap. 1428e8d8bef9SDimitry Andric bool HasNSW = I.hasNoSignedWrap() && Op0->hasNoSignedWrap() && 1429e8d8bef9SDimitry Andric Op1->hasNoSignedWrap(); 1430e8d8bef9SDimitry Andric bool HasNUW = I.hasNoUnsignedWrap() && Op0->hasNoUnsignedWrap() && 1431e8d8bef9SDimitry Andric Op1->hasNoUnsignedWrap(); 1432e8d8bef9SDimitry Andric 1433e8d8bef9SDimitry Andric // add/sub (X << ShAmt), (Y << ShAmt) --> (add/sub X, Y) << ShAmt 1434e8d8bef9SDimitry Andric Value *NewMath = Builder.CreateBinOp(I.getOpcode(), X, Y); 1435e8d8bef9SDimitry Andric if (auto *NewI = dyn_cast<BinaryOperator>(NewMath)) { 1436e8d8bef9SDimitry Andric NewI->setHasNoSignedWrap(HasNSW); 1437e8d8bef9SDimitry Andric NewI->setHasNoUnsignedWrap(HasNUW); 1438e8d8bef9SDimitry Andric } 1439e8d8bef9SDimitry Andric auto *NewShl = BinaryOperator::CreateShl(NewMath, ShAmt); 1440e8d8bef9SDimitry Andric NewShl->setHasNoSignedWrap(HasNSW); 1441e8d8bef9SDimitry Andric NewShl->setHasNoUnsignedWrap(HasNUW); 1442e8d8bef9SDimitry Andric return NewShl; 1443e8d8bef9SDimitry Andric } 1444e8d8bef9SDimitry Andric 1445bdd1243dSDimitry Andric /// Reduce a sequence of masked half-width multiplies to a single multiply. 1446bdd1243dSDimitry Andric /// ((XLow * YHigh) + (YLow * XHigh)) << HalfBits) + (XLow * YLow) --> X * Y 1447bdd1243dSDimitry Andric static Instruction *foldBoxMultiply(BinaryOperator &I) { 1448bdd1243dSDimitry Andric unsigned BitWidth = I.getType()->getScalarSizeInBits(); 1449bdd1243dSDimitry Andric // Skip the odd bitwidth types. 1450bdd1243dSDimitry Andric if ((BitWidth & 0x1)) 1451bdd1243dSDimitry Andric return nullptr; 1452bdd1243dSDimitry Andric 1453bdd1243dSDimitry Andric unsigned HalfBits = BitWidth >> 1; 1454bdd1243dSDimitry Andric APInt HalfMask = APInt::getMaxValue(HalfBits); 1455bdd1243dSDimitry Andric 1456bdd1243dSDimitry Andric // ResLo = (CrossSum << HalfBits) + (YLo * XLo) 1457bdd1243dSDimitry Andric Value *XLo, *YLo; 1458bdd1243dSDimitry Andric Value *CrossSum; 14595f757f3fSDimitry Andric // Require one-use on the multiply to avoid increasing the number of 14605f757f3fSDimitry Andric // multiplications. 1461bdd1243dSDimitry Andric if (!match(&I, m_c_Add(m_Shl(m_Value(CrossSum), m_SpecificInt(HalfBits)), 14625f757f3fSDimitry Andric m_OneUse(m_Mul(m_Value(YLo), m_Value(XLo)))))) 1463bdd1243dSDimitry Andric return nullptr; 1464bdd1243dSDimitry Andric 1465bdd1243dSDimitry Andric // XLo = X & HalfMask 1466bdd1243dSDimitry Andric // YLo = Y & HalfMask 1467bdd1243dSDimitry Andric // TODO: Refactor with SimplifyDemandedBits or KnownBits known leading zeros 1468bdd1243dSDimitry Andric // to enhance robustness 1469bdd1243dSDimitry Andric Value *X, *Y; 1470bdd1243dSDimitry Andric if (!match(XLo, m_And(m_Value(X), m_SpecificInt(HalfMask))) || 1471bdd1243dSDimitry Andric !match(YLo, m_And(m_Value(Y), m_SpecificInt(HalfMask)))) 1472bdd1243dSDimitry Andric return nullptr; 1473bdd1243dSDimitry Andric 1474bdd1243dSDimitry Andric // CrossSum = (X' * (Y >> Halfbits)) + (Y' * (X >> HalfBits)) 1475bdd1243dSDimitry Andric // X' can be either X or XLo in the pattern (and the same for Y') 1476bdd1243dSDimitry Andric if (match(CrossSum, 1477bdd1243dSDimitry Andric m_c_Add(m_c_Mul(m_LShr(m_Specific(Y), m_SpecificInt(HalfBits)), 1478bdd1243dSDimitry Andric m_CombineOr(m_Specific(X), m_Specific(XLo))), 1479bdd1243dSDimitry Andric m_c_Mul(m_LShr(m_Specific(X), m_SpecificInt(HalfBits)), 1480bdd1243dSDimitry Andric m_CombineOr(m_Specific(Y), m_Specific(YLo)))))) 1481bdd1243dSDimitry Andric return BinaryOperator::CreateMul(X, Y); 1482bdd1243dSDimitry Andric 1483bdd1243dSDimitry Andric return nullptr; 1484bdd1243dSDimitry Andric } 1485bdd1243dSDimitry Andric 1486e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { 148781ad6265SDimitry Andric if (Value *V = simplifyAddInst(I.getOperand(0), I.getOperand(1), 14880b57cec5SDimitry Andric I.hasNoSignedWrap(), I.hasNoUnsignedWrap(), 14890b57cec5SDimitry Andric SQ.getWithInstruction(&I))) 14900b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric if (SimplifyAssociativeOrCommutative(I)) 14930b57cec5SDimitry Andric return &I; 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric if (Instruction *X = foldVectorBinop(I)) 14960b57cec5SDimitry Andric return X; 14970b57cec5SDimitry Andric 149804eeddc0SDimitry Andric if (Instruction *Phi = foldBinopWithPhiOperands(I)) 149904eeddc0SDimitry Andric return Phi; 150004eeddc0SDimitry Andric 15010b57cec5SDimitry Andric // (A*B)+(A*C) -> A*(B+C) etc 1502bdd1243dSDimitry Andric if (Value *V = foldUsingDistributiveLaws(I)) 15030b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 15040b57cec5SDimitry Andric 1505bdd1243dSDimitry Andric if (Instruction *R = foldBoxMultiply(I)) 1506bdd1243dSDimitry Andric return R; 1507bdd1243dSDimitry Andric 1508e8d8bef9SDimitry Andric if (Instruction *R = factorizeMathWithShlOps(I, Builder)) 1509e8d8bef9SDimitry Andric return R; 1510e8d8bef9SDimitry Andric 15110b57cec5SDimitry Andric if (Instruction *X = foldAddWithConstant(I)) 15120b57cec5SDimitry Andric return X; 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric if (Instruction *X = foldNoWrapAdd(I, Builder)) 15150b57cec5SDimitry Andric return X; 15160b57cec5SDimitry Andric 151706c3fb27SDimitry Andric if (Instruction *R = foldBinOpShiftWithShift(I)) 151806c3fb27SDimitry Andric return R; 151906c3fb27SDimitry Andric 15205f757f3fSDimitry Andric if (Instruction *R = combineAddSubWithShlAddSub(Builder, I)) 15215f757f3fSDimitry Andric return R; 15225f757f3fSDimitry Andric 15230b57cec5SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 15240b57cec5SDimitry Andric Type *Ty = I.getType(); 15250b57cec5SDimitry Andric if (Ty->isIntOrIntVectorTy(1)) 15260b57cec5SDimitry Andric return BinaryOperator::CreateXor(LHS, RHS); 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric // X + X --> X << 1 15290b57cec5SDimitry Andric if (LHS == RHS) { 15300b57cec5SDimitry Andric auto *Shl = BinaryOperator::CreateShl(LHS, ConstantInt::get(Ty, 1)); 15310b57cec5SDimitry Andric Shl->setHasNoSignedWrap(I.hasNoSignedWrap()); 15320b57cec5SDimitry Andric Shl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); 15330b57cec5SDimitry Andric return Shl; 15340b57cec5SDimitry Andric } 15350b57cec5SDimitry Andric 15360b57cec5SDimitry Andric Value *A, *B; 15370b57cec5SDimitry Andric if (match(LHS, m_Neg(m_Value(A)))) { 15380b57cec5SDimitry Andric // -A + -B --> -(A + B) 15390b57cec5SDimitry Andric if (match(RHS, m_Neg(m_Value(B)))) 15400b57cec5SDimitry Andric return BinaryOperator::CreateNeg(Builder.CreateAdd(A, B)); 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andric // -A + B --> B - A 15435f757f3fSDimitry Andric auto *Sub = BinaryOperator::CreateSub(RHS, A); 15445f757f3fSDimitry Andric auto *OB0 = cast<OverflowingBinaryOperator>(LHS); 15455f757f3fSDimitry Andric Sub->setHasNoSignedWrap(I.hasNoSignedWrap() && OB0->hasNoSignedWrap()); 15465f757f3fSDimitry Andric 15475f757f3fSDimitry Andric return Sub; 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric // A + -B --> A - B 15510b57cec5SDimitry Andric if (match(RHS, m_Neg(m_Value(B)))) 15520b57cec5SDimitry Andric return BinaryOperator::CreateSub(LHS, B); 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric if (Value *V = checkForNegativeOperand(I, Builder)) 15550b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric // (A + 1) + ~B --> A - B 15580b57cec5SDimitry Andric // ~B + (A + 1) --> A - B 15590b57cec5SDimitry Andric // (~B + A) + 1 --> A - B 15600b57cec5SDimitry Andric // (A + ~B) + 1 --> A - B 15610b57cec5SDimitry Andric if (match(&I, m_c_BinOp(m_Add(m_Value(A), m_One()), m_Not(m_Value(B)))) || 15620b57cec5SDimitry Andric match(&I, m_BinOp(m_c_Add(m_Not(m_Value(B)), m_Value(A)), m_One()))) 15630b57cec5SDimitry Andric return BinaryOperator::CreateSub(A, B); 15640b57cec5SDimitry Andric 15655ffd83dbSDimitry Andric // (A + RHS) + RHS --> A + (RHS << 1) 15665ffd83dbSDimitry Andric if (match(LHS, m_OneUse(m_c_Add(m_Value(A), m_Specific(RHS))))) 15675ffd83dbSDimitry Andric return BinaryOperator::CreateAdd(A, Builder.CreateShl(RHS, 1, "reass.add")); 15685ffd83dbSDimitry Andric 15695ffd83dbSDimitry Andric // LHS + (A + LHS) --> A + (LHS << 1) 15705ffd83dbSDimitry Andric if (match(RHS, m_OneUse(m_c_Add(m_Value(A), m_Specific(LHS))))) 15715ffd83dbSDimitry Andric return BinaryOperator::CreateAdd(A, Builder.CreateShl(LHS, 1, "reass.add")); 15725ffd83dbSDimitry Andric 1573349cc55cSDimitry Andric { 1574349cc55cSDimitry Andric // (A + C1) + (C2 - B) --> (A - B) + (C1 + C2) 1575349cc55cSDimitry Andric Constant *C1, *C2; 1576349cc55cSDimitry Andric if (match(&I, m_c_Add(m_Add(m_Value(A), m_ImmConstant(C1)), 1577349cc55cSDimitry Andric m_Sub(m_ImmConstant(C2), m_Value(B)))) && 1578349cc55cSDimitry Andric (LHS->hasOneUse() || RHS->hasOneUse())) { 1579349cc55cSDimitry Andric Value *Sub = Builder.CreateSub(A, B); 1580349cc55cSDimitry Andric return BinaryOperator::CreateAdd(Sub, ConstantExpr::getAdd(C1, C2)); 1581349cc55cSDimitry Andric } 158206c3fb27SDimitry Andric 158306c3fb27SDimitry Andric // Canonicalize a constant sub operand as an add operand for better folding: 158406c3fb27SDimitry Andric // (C1 - A) + B --> (B - A) + C1 158506c3fb27SDimitry Andric if (match(&I, m_c_Add(m_OneUse(m_Sub(m_ImmConstant(C1), m_Value(A))), 158606c3fb27SDimitry Andric m_Value(B)))) { 158706c3fb27SDimitry Andric Value *Sub = Builder.CreateSub(B, A, "reass.sub"); 158806c3fb27SDimitry Andric return BinaryOperator::CreateAdd(Sub, C1); 158906c3fb27SDimitry Andric } 1590349cc55cSDimitry Andric } 1591349cc55cSDimitry Andric 15920b57cec5SDimitry Andric // X % C0 + (( X / C0 ) % C1) * C0 => X % (C0 * C1) 15930b57cec5SDimitry Andric if (Value *V = SimplifyAddWithRemainder(I)) return replaceInstUsesWith(I, V); 15940b57cec5SDimitry Andric 15955ffd83dbSDimitry Andric // ((X s/ C1) << C2) + X => X s% -C1 where -C1 is 1 << C2 15965ffd83dbSDimitry Andric const APInt *C1, *C2; 15975ffd83dbSDimitry Andric if (match(LHS, m_Shl(m_SDiv(m_Specific(RHS), m_APInt(C1)), m_APInt(C2)))) { 15985ffd83dbSDimitry Andric APInt one(C2->getBitWidth(), 1); 15995ffd83dbSDimitry Andric APInt minusC1 = -(*C1); 16005ffd83dbSDimitry Andric if (minusC1 == (one << *C2)) { 16015ffd83dbSDimitry Andric Constant *NewRHS = ConstantInt::get(RHS->getType(), minusC1); 16025ffd83dbSDimitry Andric return BinaryOperator::CreateSRem(RHS, NewRHS); 16035ffd83dbSDimitry Andric } 16045ffd83dbSDimitry Andric } 16055ffd83dbSDimitry Andric 160681ad6265SDimitry Andric // (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit 160781ad6265SDimitry Andric if (match(&I, m_c_Add(m_And(m_Value(A), m_APInt(C1)), m_Deferred(A))) && 160806c3fb27SDimitry Andric C1->isPowerOf2() && (ComputeNumSignBits(A) > C1->countl_zero())) { 160981ad6265SDimitry Andric Constant *NewMask = ConstantInt::get(RHS->getType(), *C1 - 1); 161081ad6265SDimitry Andric return BinaryOperator::CreateAnd(A, NewMask); 161181ad6265SDimitry Andric } 161281ad6265SDimitry Andric 1613bdd1243dSDimitry Andric // ZExt (B - A) + ZExt(A) --> ZExt(B) 1614bdd1243dSDimitry Andric if ((match(RHS, m_ZExt(m_Value(A))) && 1615bdd1243dSDimitry Andric match(LHS, m_ZExt(m_NUWSub(m_Value(B), m_Specific(A))))) || 1616bdd1243dSDimitry Andric (match(LHS, m_ZExt(m_Value(A))) && 1617bdd1243dSDimitry Andric match(RHS, m_ZExt(m_NUWSub(m_Value(B), m_Specific(A)))))) 1618bdd1243dSDimitry Andric return new ZExtInst(B, LHS->getType()); 1619bdd1243dSDimitry Andric 162006c3fb27SDimitry Andric // zext(A) + sext(A) --> 0 if A is i1 162106c3fb27SDimitry Andric if (match(&I, m_c_BinOp(m_ZExt(m_Value(A)), m_SExt(m_Deferred(A)))) && 162206c3fb27SDimitry Andric A->getType()->isIntOrIntVectorTy(1)) 162306c3fb27SDimitry Andric return replaceInstUsesWith(I, Constant::getNullValue(I.getType())); 162406c3fb27SDimitry Andric 16250b57cec5SDimitry Andric // A+B --> A|B iff A and B have no bits set in common. 16265f757f3fSDimitry Andric WithCache<const Value *> LHSCache(LHS), RHSCache(RHS); 16275f757f3fSDimitry Andric if (haveNoCommonBitsSet(LHSCache, RHSCache, SQ.getWithInstruction(&I))) 16285f757f3fSDimitry Andric return BinaryOperator::CreateDisjointOr(LHS, RHS); 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric if (Instruction *Ext = narrowMathIfNoOverflow(I)) 16310b57cec5SDimitry Andric return Ext; 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andric // (add (xor A, B) (and A, B)) --> (or A, B) 16340b57cec5SDimitry Andric // (add (and A, B) (xor A, B)) --> (or A, B) 16350b57cec5SDimitry Andric if (match(&I, m_c_BinOp(m_Xor(m_Value(A), m_Value(B)), 16360b57cec5SDimitry Andric m_c_And(m_Deferred(A), m_Deferred(B))))) 16370b57cec5SDimitry Andric return BinaryOperator::CreateOr(A, B); 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric // (add (or A, B) (and A, B)) --> (add A, B) 16400b57cec5SDimitry Andric // (add (and A, B) (or A, B)) --> (add A, B) 16410b57cec5SDimitry Andric if (match(&I, m_c_BinOp(m_Or(m_Value(A), m_Value(B)), 16420b57cec5SDimitry Andric m_c_And(m_Deferred(A), m_Deferred(B))))) { 16435ffd83dbSDimitry Andric // Replacing operands in-place to preserve nuw/nsw flags. 16445ffd83dbSDimitry Andric replaceOperand(I, 0, A); 16455ffd83dbSDimitry Andric replaceOperand(I, 1, B); 16460b57cec5SDimitry Andric return &I; 16470b57cec5SDimitry Andric } 16480b57cec5SDimitry Andric 1649bdd1243dSDimitry Andric // (add A (or A, -A)) --> (and (add A, -1) A) 1650bdd1243dSDimitry Andric // (add A (or -A, A)) --> (and (add A, -1) A) 1651bdd1243dSDimitry Andric // (add (or A, -A) A) --> (and (add A, -1) A) 1652bdd1243dSDimitry Andric // (add (or -A, A) A) --> (and (add A, -1) A) 1653bdd1243dSDimitry Andric if (match(&I, m_c_BinOp(m_Value(A), m_OneUse(m_c_Or(m_Neg(m_Deferred(A)), 1654bdd1243dSDimitry Andric m_Deferred(A)))))) { 1655bdd1243dSDimitry Andric Value *Add = 1656bdd1243dSDimitry Andric Builder.CreateAdd(A, Constant::getAllOnesValue(A->getType()), "", 1657bdd1243dSDimitry Andric I.hasNoUnsignedWrap(), I.hasNoSignedWrap()); 1658bdd1243dSDimitry Andric return BinaryOperator::CreateAnd(Add, A); 1659bdd1243dSDimitry Andric } 1660bdd1243dSDimitry Andric 1661bdd1243dSDimitry Andric // Canonicalize ((A & -A) - 1) --> ((A - 1) & ~A) 1662bdd1243dSDimitry Andric // Forms all commutable operations, and simplifies ctpop -> cttz folds. 1663bdd1243dSDimitry Andric if (match(&I, 1664bdd1243dSDimitry Andric m_Add(m_OneUse(m_c_And(m_Value(A), m_OneUse(m_Neg(m_Deferred(A))))), 1665bdd1243dSDimitry Andric m_AllOnes()))) { 1666bdd1243dSDimitry Andric Constant *AllOnes = ConstantInt::getAllOnesValue(RHS->getType()); 1667bdd1243dSDimitry Andric Value *Dec = Builder.CreateAdd(A, AllOnes); 1668bdd1243dSDimitry Andric Value *Not = Builder.CreateXor(A, AllOnes); 1669bdd1243dSDimitry Andric return BinaryOperator::CreateAnd(Dec, Not); 1670bdd1243dSDimitry Andric } 1671bdd1243dSDimitry Andric 1672bdd1243dSDimitry Andric // Disguised reassociation/factorization: 1673bdd1243dSDimitry Andric // ~(A * C1) + A 1674bdd1243dSDimitry Andric // ((A * -C1) - 1) + A 1675bdd1243dSDimitry Andric // ((A * -C1) + A) - 1 1676bdd1243dSDimitry Andric // (A * (1 - C1)) - 1 1677bdd1243dSDimitry Andric if (match(&I, 1678bdd1243dSDimitry Andric m_c_Add(m_OneUse(m_Not(m_OneUse(m_Mul(m_Value(A), m_APInt(C1))))), 1679bdd1243dSDimitry Andric m_Deferred(A)))) { 1680bdd1243dSDimitry Andric Type *Ty = I.getType(); 1681bdd1243dSDimitry Andric Constant *NewMulC = ConstantInt::get(Ty, 1 - *C1); 1682bdd1243dSDimitry Andric Value *NewMul = Builder.CreateMul(A, NewMulC); 1683bdd1243dSDimitry Andric return BinaryOperator::CreateAdd(NewMul, ConstantInt::getAllOnesValue(Ty)); 1684bdd1243dSDimitry Andric } 1685bdd1243dSDimitry Andric 1686bdd1243dSDimitry Andric // (A * -2**C) + B --> B - (A << C) 1687bdd1243dSDimitry Andric const APInt *NegPow2C; 1688bdd1243dSDimitry Andric if (match(&I, m_c_Add(m_OneUse(m_Mul(m_Value(A), m_NegatedPower2(NegPow2C))), 1689bdd1243dSDimitry Andric m_Value(B)))) { 169006c3fb27SDimitry Andric Constant *ShiftAmtC = ConstantInt::get(Ty, NegPow2C->countr_zero()); 1691bdd1243dSDimitry Andric Value *Shl = Builder.CreateShl(A, ShiftAmtC); 1692bdd1243dSDimitry Andric return BinaryOperator::CreateSub(B, Shl); 1693bdd1243dSDimitry Andric } 1694bdd1243dSDimitry Andric 1695bdd1243dSDimitry Andric // Canonicalize signum variant that ends in add: 1696bdd1243dSDimitry Andric // (A s>> (BW - 1)) + (zext (A s> 0)) --> (A s>> (BW - 1)) | (zext (A != 0)) 1697bdd1243dSDimitry Andric ICmpInst::Predicate Pred; 1698bdd1243dSDimitry Andric uint64_t BitWidth = Ty->getScalarSizeInBits(); 1699*0fca6ea1SDimitry Andric if (match(LHS, m_AShr(m_Value(A), m_SpecificIntAllowPoison(BitWidth - 1))) && 1700bdd1243dSDimitry Andric match(RHS, m_OneUse(m_ZExt( 1701bdd1243dSDimitry Andric m_OneUse(m_ICmp(Pred, m_Specific(A), m_ZeroInt()))))) && 1702bdd1243dSDimitry Andric Pred == CmpInst::ICMP_SGT) { 1703bdd1243dSDimitry Andric Value *NotZero = Builder.CreateIsNotNull(A, "isnotnull"); 1704bdd1243dSDimitry Andric Value *Zext = Builder.CreateZExt(NotZero, Ty, "isnotnull.zext"); 1705bdd1243dSDimitry Andric return BinaryOperator::CreateOr(LHS, Zext); 1706bdd1243dSDimitry Andric } 1707bdd1243dSDimitry Andric 1708*0fca6ea1SDimitry Andric { 1709*0fca6ea1SDimitry Andric Value *Cond, *Ext; 1710*0fca6ea1SDimitry Andric Constant *C; 1711*0fca6ea1SDimitry Andric // (add X, (sext/zext (icmp eq X, C))) 1712*0fca6ea1SDimitry Andric // -> (select (icmp eq X, C), (add C, (sext/zext 1)), X) 1713*0fca6ea1SDimitry Andric auto CondMatcher = m_CombineAnd( 1714*0fca6ea1SDimitry Andric m_Value(Cond), m_ICmp(Pred, m_Deferred(A), m_ImmConstant(C))); 1715*0fca6ea1SDimitry Andric 1716*0fca6ea1SDimitry Andric if (match(&I, 1717*0fca6ea1SDimitry Andric m_c_Add(m_Value(A), 1718*0fca6ea1SDimitry Andric m_CombineAnd(m_Value(Ext), m_ZExtOrSExt(CondMatcher)))) && 1719*0fca6ea1SDimitry Andric Pred == ICmpInst::ICMP_EQ && Ext->hasOneUse()) { 1720*0fca6ea1SDimitry Andric Value *Add = isa<ZExtInst>(Ext) ? InstCombiner::AddOne(C) 1721*0fca6ea1SDimitry Andric : InstCombiner::SubOne(C); 1722*0fca6ea1SDimitry Andric return replaceInstUsesWith(I, Builder.CreateSelect(Cond, Add, A)); 1723*0fca6ea1SDimitry Andric } 1724*0fca6ea1SDimitry Andric } 1725*0fca6ea1SDimitry Andric 1726bdd1243dSDimitry Andric if (Instruction *Ashr = foldAddToAshr(I)) 1727bdd1243dSDimitry Andric return Ashr; 1728bdd1243dSDimitry Andric 17295f757f3fSDimitry Andric // (~X) + (~Y) --> -2 - (X + Y) 17305f757f3fSDimitry Andric { 17315f757f3fSDimitry Andric // To ensure we can save instructions we need to ensure that we consume both 17325f757f3fSDimitry Andric // LHS/RHS (i.e they have a `not`). 17335f757f3fSDimitry Andric bool ConsumesLHS, ConsumesRHS; 17345f757f3fSDimitry Andric if (isFreeToInvert(LHS, LHS->hasOneUse(), ConsumesLHS) && ConsumesLHS && 17355f757f3fSDimitry Andric isFreeToInvert(RHS, RHS->hasOneUse(), ConsumesRHS) && ConsumesRHS) { 17365f757f3fSDimitry Andric Value *NotLHS = getFreelyInverted(LHS, LHS->hasOneUse(), &Builder); 17375f757f3fSDimitry Andric Value *NotRHS = getFreelyInverted(RHS, RHS->hasOneUse(), &Builder); 17385f757f3fSDimitry Andric assert(NotLHS != nullptr && NotRHS != nullptr && 17395f757f3fSDimitry Andric "isFreeToInvert desynced with getFreelyInverted"); 17405f757f3fSDimitry Andric Value *LHSPlusRHS = Builder.CreateAdd(NotLHS, NotRHS); 1741647cbc5dSDimitry Andric return BinaryOperator::CreateSub( 1742647cbc5dSDimitry Andric ConstantInt::getSigned(RHS->getType(), -2), LHSPlusRHS); 17435f757f3fSDimitry Andric } 17445f757f3fSDimitry Andric } 17455f757f3fSDimitry Andric 17467a6dacacSDimitry Andric if (Instruction *R = tryFoldInstWithCtpopWithNot(&I)) 17477a6dacacSDimitry Andric return R; 17487a6dacacSDimitry Andric 17490b57cec5SDimitry Andric // TODO(jingyue): Consider willNotOverflowSignedAdd and 17500b57cec5SDimitry Andric // willNotOverflowUnsignedAdd to reduce the number of invocations of 17510b57cec5SDimitry Andric // computeKnownBits. 17520b57cec5SDimitry Andric bool Changed = false; 17535f757f3fSDimitry Andric if (!I.hasNoSignedWrap() && willNotOverflowSignedAdd(LHSCache, RHSCache, I)) { 17540b57cec5SDimitry Andric Changed = true; 17550b57cec5SDimitry Andric I.setHasNoSignedWrap(true); 17560b57cec5SDimitry Andric } 17575f757f3fSDimitry Andric if (!I.hasNoUnsignedWrap() && 17585f757f3fSDimitry Andric willNotOverflowUnsignedAdd(LHSCache, RHSCache, I)) { 17590b57cec5SDimitry Andric Changed = true; 17600b57cec5SDimitry Andric I.setHasNoUnsignedWrap(true); 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric 17630b57cec5SDimitry Andric if (Instruction *V = canonicalizeLowbitMask(I, Builder)) 17640b57cec5SDimitry Andric return V; 17650b57cec5SDimitry Andric 17668bcb0991SDimitry Andric if (Instruction *V = 17678bcb0991SDimitry Andric canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I)) 17688bcb0991SDimitry Andric return V; 17698bcb0991SDimitry Andric 17700b57cec5SDimitry Andric if (Instruction *SatAdd = foldToUnsignedSaturatedAdd(I)) 17710b57cec5SDimitry Andric return SatAdd; 17720b57cec5SDimitry Andric 1773e8d8bef9SDimitry Andric // usub.sat(A, B) + B => umax(A, B) 1774e8d8bef9SDimitry Andric if (match(&I, m_c_BinOp( 1775e8d8bef9SDimitry Andric m_OneUse(m_Intrinsic<Intrinsic::usub_sat>(m_Value(A), m_Value(B))), 1776e8d8bef9SDimitry Andric m_Deferred(B)))) { 1777e8d8bef9SDimitry Andric return replaceInstUsesWith(I, 1778e8d8bef9SDimitry Andric Builder.CreateIntrinsic(Intrinsic::umax, {I.getType()}, {A, B})); 1779e8d8bef9SDimitry Andric } 1780e8d8bef9SDimitry Andric 1781fe6060f1SDimitry Andric // ctpop(A) + ctpop(B) => ctpop(A | B) if A and B have no bits set in common. 1782fe6060f1SDimitry Andric if (match(LHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(A)))) && 1783fe6060f1SDimitry Andric match(RHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(B)))) && 17845f757f3fSDimitry Andric haveNoCommonBitsSet(A, B, SQ.getWithInstruction(&I))) 1785fe6060f1SDimitry Andric return replaceInstUsesWith( 1786fe6060f1SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::ctpop, {I.getType()}, 1787fe6060f1SDimitry Andric {Builder.CreateOr(A, B)})); 1788fe6060f1SDimitry Andric 1789297eecfbSDimitry Andric // Fold the log2_ceil idiom: 1790297eecfbSDimitry Andric // zext(ctpop(A) >u/!= 1) + (ctlz(A, true) ^ (BW - 1)) 1791297eecfbSDimitry Andric // --> 1792297eecfbSDimitry Andric // BW - ctlz(A - 1, false) 1793297eecfbSDimitry Andric const APInt *XorC; 1794297eecfbSDimitry Andric if (match(&I, 1795297eecfbSDimitry Andric m_c_Add( 1796297eecfbSDimitry Andric m_ZExt(m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value(A)), 1797297eecfbSDimitry Andric m_One())), 1798297eecfbSDimitry Andric m_OneUse(m_ZExtOrSelf(m_OneUse(m_Xor( 1799297eecfbSDimitry Andric m_OneUse(m_TruncOrSelf(m_OneUse( 1800297eecfbSDimitry Andric m_Intrinsic<Intrinsic::ctlz>(m_Deferred(A), m_One())))), 1801297eecfbSDimitry Andric m_APInt(XorC))))))) && 1802297eecfbSDimitry Andric (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_NE) && 1803297eecfbSDimitry Andric *XorC == A->getType()->getScalarSizeInBits() - 1) { 1804297eecfbSDimitry Andric Value *Sub = Builder.CreateAdd(A, Constant::getAllOnesValue(A->getType())); 1805297eecfbSDimitry Andric Value *Ctlz = Builder.CreateIntrinsic(Intrinsic::ctlz, {A->getType()}, 1806297eecfbSDimitry Andric {Sub, Builder.getFalse()}); 1807297eecfbSDimitry Andric Value *Ret = Builder.CreateSub( 1808297eecfbSDimitry Andric ConstantInt::get(A->getType(), A->getType()->getScalarSizeInBits()), 1809297eecfbSDimitry Andric Ctlz, "", /*HasNUW*/ true, /*HasNSW*/ true); 1810297eecfbSDimitry Andric return replaceInstUsesWith(I, Builder.CreateZExtOrTrunc(Ret, I.getType())); 1811297eecfbSDimitry Andric } 1812297eecfbSDimitry Andric 18135f757f3fSDimitry Andric if (Instruction *Res = foldSquareSumInt(I)) 18145f757f3fSDimitry Andric return Res; 18155f757f3fSDimitry Andric 181606c3fb27SDimitry Andric if (Instruction *Res = foldBinOpOfDisplacedShifts(I)) 181706c3fb27SDimitry Andric return Res; 181806c3fb27SDimitry Andric 181906c3fb27SDimitry Andric if (Instruction *Res = foldBinOpOfSelectAndCastOfSelectCondition(I)) 182006c3fb27SDimitry Andric return Res; 182106c3fb27SDimitry Andric 18220b57cec5SDimitry Andric return Changed ? &I : nullptr; 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric 18258bcb0991SDimitry Andric /// Eliminate an op from a linear interpolation (lerp) pattern. 18268bcb0991SDimitry Andric static Instruction *factorizeLerp(BinaryOperator &I, 18278bcb0991SDimitry Andric InstCombiner::BuilderTy &Builder) { 18288bcb0991SDimitry Andric Value *X, *Y, *Z; 18298bcb0991SDimitry Andric if (!match(&I, m_c_FAdd(m_OneUse(m_c_FMul(m_Value(Y), 18308bcb0991SDimitry Andric m_OneUse(m_FSub(m_FPOne(), 18318bcb0991SDimitry Andric m_Value(Z))))), 18328bcb0991SDimitry Andric m_OneUse(m_c_FMul(m_Value(X), m_Deferred(Z)))))) 18338bcb0991SDimitry Andric return nullptr; 18348bcb0991SDimitry Andric 18358bcb0991SDimitry Andric // (Y * (1.0 - Z)) + (X * Z) --> Y + Z * (X - Y) [8 commuted variants] 18368bcb0991SDimitry Andric Value *XY = Builder.CreateFSubFMF(X, Y, &I); 18378bcb0991SDimitry Andric Value *MulZ = Builder.CreateFMulFMF(Z, XY, &I); 18388bcb0991SDimitry Andric return BinaryOperator::CreateFAddFMF(Y, MulZ, &I); 18398bcb0991SDimitry Andric } 18408bcb0991SDimitry Andric 18410b57cec5SDimitry Andric /// Factor a common operand out of fadd/fsub of fmul/fdiv. 18420b57cec5SDimitry Andric static Instruction *factorizeFAddFSub(BinaryOperator &I, 18430b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 18440b57cec5SDimitry Andric assert((I.getOpcode() == Instruction::FAdd || 18450b57cec5SDimitry Andric I.getOpcode() == Instruction::FSub) && "Expecting fadd/fsub"); 18460b57cec5SDimitry Andric assert(I.hasAllowReassoc() && I.hasNoSignedZeros() && 18470b57cec5SDimitry Andric "FP factorization requires FMF"); 18488bcb0991SDimitry Andric 18498bcb0991SDimitry Andric if (Instruction *Lerp = factorizeLerp(I, Builder)) 18508bcb0991SDimitry Andric return Lerp; 18518bcb0991SDimitry Andric 18520b57cec5SDimitry Andric Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); 185304eeddc0SDimitry Andric if (!Op0->hasOneUse() || !Op1->hasOneUse()) 185404eeddc0SDimitry Andric return nullptr; 185504eeddc0SDimitry Andric 18560b57cec5SDimitry Andric Value *X, *Y, *Z; 18570b57cec5SDimitry Andric bool IsFMul; 185804eeddc0SDimitry Andric if ((match(Op0, m_FMul(m_Value(X), m_Value(Z))) && 185904eeddc0SDimitry Andric match(Op1, m_c_FMul(m_Value(Y), m_Specific(Z)))) || 186004eeddc0SDimitry Andric (match(Op0, m_FMul(m_Value(Z), m_Value(X))) && 186104eeddc0SDimitry Andric match(Op1, m_c_FMul(m_Value(Y), m_Specific(Z))))) 18620b57cec5SDimitry Andric IsFMul = true; 186304eeddc0SDimitry Andric else if (match(Op0, m_FDiv(m_Value(X), m_Value(Z))) && 186404eeddc0SDimitry Andric match(Op1, m_FDiv(m_Value(Y), m_Specific(Z)))) 18650b57cec5SDimitry Andric IsFMul = false; 18660b57cec5SDimitry Andric else 18670b57cec5SDimitry Andric return nullptr; 18680b57cec5SDimitry Andric 18690b57cec5SDimitry Andric // (X * Z) + (Y * Z) --> (X + Y) * Z 18700b57cec5SDimitry Andric // (X * Z) - (Y * Z) --> (X - Y) * Z 18710b57cec5SDimitry Andric // (X / Z) + (Y / Z) --> (X + Y) / Z 18720b57cec5SDimitry Andric // (X / Z) - (Y / Z) --> (X - Y) / Z 18730b57cec5SDimitry Andric bool IsFAdd = I.getOpcode() == Instruction::FAdd; 18740b57cec5SDimitry Andric Value *XY = IsFAdd ? Builder.CreateFAddFMF(X, Y, &I) 18750b57cec5SDimitry Andric : Builder.CreateFSubFMF(X, Y, &I); 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric // Bail out if we just created a denormal constant. 18780b57cec5SDimitry Andric // TODO: This is copied from a previous implementation. Is it necessary? 18790b57cec5SDimitry Andric const APFloat *C; 18800b57cec5SDimitry Andric if (match(XY, m_APFloat(C)) && !C->isNormal()) 18810b57cec5SDimitry Andric return nullptr; 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric return IsFMul ? BinaryOperator::CreateFMulFMF(XY, Z, &I) 18840b57cec5SDimitry Andric : BinaryOperator::CreateFDivFMF(XY, Z, &I); 18850b57cec5SDimitry Andric } 18860b57cec5SDimitry Andric 1887e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) { 188881ad6265SDimitry Andric if (Value *V = simplifyFAddInst(I.getOperand(0), I.getOperand(1), 18890b57cec5SDimitry Andric I.getFastMathFlags(), 18900b57cec5SDimitry Andric SQ.getWithInstruction(&I))) 18910b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 18920b57cec5SDimitry Andric 18930b57cec5SDimitry Andric if (SimplifyAssociativeOrCommutative(I)) 18940b57cec5SDimitry Andric return &I; 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric if (Instruction *X = foldVectorBinop(I)) 18970b57cec5SDimitry Andric return X; 18980b57cec5SDimitry Andric 189904eeddc0SDimitry Andric if (Instruction *Phi = foldBinopWithPhiOperands(I)) 190004eeddc0SDimitry Andric return Phi; 190104eeddc0SDimitry Andric 19020b57cec5SDimitry Andric if (Instruction *FoldedFAdd = foldBinOpIntoSelectOrPhi(I)) 19030b57cec5SDimitry Andric return FoldedFAdd; 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric // (-X) + Y --> Y - X 19068bcb0991SDimitry Andric Value *X, *Y; 19078bcb0991SDimitry Andric if (match(&I, m_c_FAdd(m_FNeg(m_Value(X)), m_Value(Y)))) 19088bcb0991SDimitry Andric return BinaryOperator::CreateFSubFMF(Y, X, &I); 19098bcb0991SDimitry Andric 19108bcb0991SDimitry Andric // Similar to above, but look through fmul/fdiv for the negated term. 19118bcb0991SDimitry Andric // (-X * Y) + Z --> Z - (X * Y) [4 commuted variants] 19128bcb0991SDimitry Andric Value *Z; 19138bcb0991SDimitry Andric if (match(&I, m_c_FAdd(m_OneUse(m_c_FMul(m_FNeg(m_Value(X)), m_Value(Y))), 19148bcb0991SDimitry Andric m_Value(Z)))) { 19158bcb0991SDimitry Andric Value *XY = Builder.CreateFMulFMF(X, Y, &I); 19168bcb0991SDimitry Andric return BinaryOperator::CreateFSubFMF(Z, XY, &I); 19178bcb0991SDimitry Andric } 19188bcb0991SDimitry Andric // (-X / Y) + Z --> Z - (X / Y) [2 commuted variants] 19198bcb0991SDimitry Andric // (X / -Y) + Z --> Z - (X / Y) [2 commuted variants] 19208bcb0991SDimitry Andric if (match(&I, m_c_FAdd(m_OneUse(m_FDiv(m_FNeg(m_Value(X)), m_Value(Y))), 19218bcb0991SDimitry Andric m_Value(Z))) || 19228bcb0991SDimitry Andric match(&I, m_c_FAdd(m_OneUse(m_FDiv(m_Value(X), m_FNeg(m_Value(Y)))), 19238bcb0991SDimitry Andric m_Value(Z)))) { 19248bcb0991SDimitry Andric Value *XY = Builder.CreateFDivFMF(X, Y, &I); 19258bcb0991SDimitry Andric return BinaryOperator::CreateFSubFMF(Z, XY, &I); 19268bcb0991SDimitry Andric } 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric // Check for (fadd double (sitofp x), y), see if we can merge this into an 19290b57cec5SDimitry Andric // integer add followed by a promotion. 1930*0fca6ea1SDimitry Andric if (Instruction *R = foldFBinOpOfIntCasts(I)) 1931*0fca6ea1SDimitry Andric return R; 1932*0fca6ea1SDimitry Andric 19338bcb0991SDimitry Andric Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); 19340b57cec5SDimitry Andric // Handle specials cases for FAdd with selects feeding the operation 19350b57cec5SDimitry Andric if (Value *V = SimplifySelectsFeedingBinaryOp(I, LHS, RHS)) 19360b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { 19390b57cec5SDimitry Andric if (Instruction *F = factorizeFAddFSub(I, Builder)) 19400b57cec5SDimitry Andric return F; 1941fe6060f1SDimitry Andric 19425f757f3fSDimitry Andric if (Instruction *F = foldSquareSumFP(I)) 19435f757f3fSDimitry Andric return F; 19445f757f3fSDimitry Andric 1945fe6060f1SDimitry Andric // Try to fold fadd into start value of reduction intrinsic. 1946fe6060f1SDimitry Andric if (match(&I, m_c_FAdd(m_OneUse(m_Intrinsic<Intrinsic::vector_reduce_fadd>( 1947fe6060f1SDimitry Andric m_AnyZeroFP(), m_Value(X))), 1948fe6060f1SDimitry Andric m_Value(Y)))) { 1949fe6060f1SDimitry Andric // fadd (rdx 0.0, X), Y --> rdx Y, X 1950fe6060f1SDimitry Andric return replaceInstUsesWith( 1951fe6060f1SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::vector_reduce_fadd, 1952fe6060f1SDimitry Andric {X->getType()}, {Y, X}, &I)); 1953fe6060f1SDimitry Andric } 1954fe6060f1SDimitry Andric const APFloat *StartC, *C; 1955fe6060f1SDimitry Andric if (match(LHS, m_OneUse(m_Intrinsic<Intrinsic::vector_reduce_fadd>( 1956fe6060f1SDimitry Andric m_APFloat(StartC), m_Value(X)))) && 1957fe6060f1SDimitry Andric match(RHS, m_APFloat(C))) { 1958fe6060f1SDimitry Andric // fadd (rdx StartC, X), C --> rdx (C + StartC), X 1959fe6060f1SDimitry Andric Constant *NewStartC = ConstantFP::get(I.getType(), *C + *StartC); 1960fe6060f1SDimitry Andric return replaceInstUsesWith( 1961fe6060f1SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::vector_reduce_fadd, 1962fe6060f1SDimitry Andric {X->getType()}, {NewStartC, X}, &I)); 1963fe6060f1SDimitry Andric } 1964fe6060f1SDimitry Andric 196504eeddc0SDimitry Andric // (X * MulC) + X --> X * (MulC + 1.0) 196604eeddc0SDimitry Andric Constant *MulC; 196704eeddc0SDimitry Andric if (match(&I, m_c_FAdd(m_FMul(m_Value(X), m_ImmConstant(MulC)), 196804eeddc0SDimitry Andric m_Deferred(X)))) { 1969753f127fSDimitry Andric if (Constant *NewMulC = ConstantFoldBinaryOpOperands( 1970753f127fSDimitry Andric Instruction::FAdd, MulC, ConstantFP::get(I.getType(), 1.0), DL)) 1971753f127fSDimitry Andric return BinaryOperator::CreateFMulFMF(X, NewMulC, &I); 197204eeddc0SDimitry Andric } 197304eeddc0SDimitry Andric 1974bdd1243dSDimitry Andric // (-X - Y) + (X + Z) --> Z - Y 1975bdd1243dSDimitry Andric if (match(&I, m_c_FAdd(m_FSub(m_FNeg(m_Value(X)), m_Value(Y)), 1976bdd1243dSDimitry Andric m_c_FAdd(m_Deferred(X), m_Value(Z))))) 1977bdd1243dSDimitry Andric return BinaryOperator::CreateFSubFMF(Z, Y, &I); 1978bdd1243dSDimitry Andric 19790b57cec5SDimitry Andric if (Value *V = FAddCombine(Builder).simplify(&I)) 19800b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 19810b57cec5SDimitry Andric } 19820b57cec5SDimitry Andric 198306c3fb27SDimitry Andric // minumum(X, Y) + maximum(X, Y) => X + Y. 198406c3fb27SDimitry Andric if (match(&I, 198506c3fb27SDimitry Andric m_c_FAdd(m_Intrinsic<Intrinsic::maximum>(m_Value(X), m_Value(Y)), 198606c3fb27SDimitry Andric m_c_Intrinsic<Intrinsic::minimum>(m_Deferred(X), 198706c3fb27SDimitry Andric m_Deferred(Y))))) { 198806c3fb27SDimitry Andric BinaryOperator *Result = BinaryOperator::CreateFAddFMF(X, Y, &I); 198906c3fb27SDimitry Andric // We cannot preserve ninf if nnan flag is not set. 199006c3fb27SDimitry Andric // If X is NaN and Y is Inf then in original program we had NaN + NaN, 199106c3fb27SDimitry Andric // while in optimized version NaN + Inf and this is a poison with ninf flag. 199206c3fb27SDimitry Andric if (!Result->hasNoNaNs()) 199306c3fb27SDimitry Andric Result->setHasNoInfs(false); 199406c3fb27SDimitry Andric return Result; 199506c3fb27SDimitry Andric } 199606c3fb27SDimitry Andric 19970b57cec5SDimitry Andric return nullptr; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric /// Optimize pointer differences into the same array into a size. Consider: 20010b57cec5SDimitry Andric /// &A[10] - &A[0]: we should compile this to "10". LHS/RHS are the pointer 20020b57cec5SDimitry Andric /// operands to the ptrtoint instructions for the LHS/RHS of the subtract. 2003e8d8bef9SDimitry Andric Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS, 2004480093f4SDimitry Andric Type *Ty, bool IsNUW) { 20050b57cec5SDimitry Andric // If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize 20060b57cec5SDimitry Andric // this. 20070b57cec5SDimitry Andric bool Swapped = false; 20080b57cec5SDimitry Andric GEPOperator *GEP1 = nullptr, *GEP2 = nullptr; 2009e8d8bef9SDimitry Andric if (!isa<GEPOperator>(LHS) && isa<GEPOperator>(RHS)) { 2010e8d8bef9SDimitry Andric std::swap(LHS, RHS); 2011e8d8bef9SDimitry Andric Swapped = true; 2012e8d8bef9SDimitry Andric } 20130b57cec5SDimitry Andric 2014e8d8bef9SDimitry Andric // Require at least one GEP with a common base pointer on both sides. 2015e8d8bef9SDimitry Andric if (auto *LHSGEP = dyn_cast<GEPOperator>(LHS)) { 20160b57cec5SDimitry Andric // (gep X, ...) - X 201781ad6265SDimitry Andric if (LHSGEP->getOperand(0)->stripPointerCasts() == 201881ad6265SDimitry Andric RHS->stripPointerCasts()) { 20190b57cec5SDimitry Andric GEP1 = LHSGEP; 2020e8d8bef9SDimitry Andric } else if (auto *RHSGEP = dyn_cast<GEPOperator>(RHS)) { 20210b57cec5SDimitry Andric // (gep X, ...) - (gep X, ...) 20220b57cec5SDimitry Andric if (LHSGEP->getOperand(0)->stripPointerCasts() == 20230b57cec5SDimitry Andric RHSGEP->getOperand(0)->stripPointerCasts()) { 20240b57cec5SDimitry Andric GEP1 = LHSGEP; 2025e8d8bef9SDimitry Andric GEP2 = RHSGEP; 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric } 20280b57cec5SDimitry Andric } 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric if (!GEP1) 20310b57cec5SDimitry Andric return nullptr; 20320b57cec5SDimitry Andric 2033*0fca6ea1SDimitry Andric // To avoid duplicating the offset arithmetic, rewrite the GEP to use the 2034*0fca6ea1SDimitry Andric // computed offset. This may erase the original GEP, so be sure to cache the 2035*0fca6ea1SDimitry Andric // inbounds flag before emitting the offset. 2036*0fca6ea1SDimitry Andric // TODO: We should probably do this even if there is only one GEP. 2037*0fca6ea1SDimitry Andric bool RewriteGEPs = GEP2 != nullptr; 20380b57cec5SDimitry Andric 20390b57cec5SDimitry Andric // Emit the offset of the GEP and an intptr_t. 2040*0fca6ea1SDimitry Andric bool GEP1IsInBounds = GEP1->isInBounds(); 2041*0fca6ea1SDimitry Andric Value *Result = EmitGEPOffset(GEP1, RewriteGEPs); 20420b57cec5SDimitry Andric 2043480093f4SDimitry Andric // If this is a single inbounds GEP and the original sub was nuw, 2044e8d8bef9SDimitry Andric // then the final multiplication is also nuw. 2045e8d8bef9SDimitry Andric if (auto *I = dyn_cast<Instruction>(Result)) 2046*0fca6ea1SDimitry Andric if (IsNUW && !GEP2 && !Swapped && GEP1IsInBounds && 2047480093f4SDimitry Andric I->getOpcode() == Instruction::Mul) 2048480093f4SDimitry Andric I->setHasNoUnsignedWrap(); 2049480093f4SDimitry Andric 2050e8d8bef9SDimitry Andric // If we have a 2nd GEP of the same base pointer, subtract the offsets. 2051e8d8bef9SDimitry Andric // If both GEPs are inbounds, then the subtract does not have signed overflow. 20520b57cec5SDimitry Andric if (GEP2) { 2053*0fca6ea1SDimitry Andric bool GEP2IsInBounds = GEP2->isInBounds(); 2054*0fca6ea1SDimitry Andric Value *Offset = EmitGEPOffset(GEP2, RewriteGEPs); 2055e8d8bef9SDimitry Andric Result = Builder.CreateSub(Result, Offset, "gepdiff", /* NUW */ false, 2056*0fca6ea1SDimitry Andric GEP1IsInBounds && GEP2IsInBounds); 20570b57cec5SDimitry Andric } 20580b57cec5SDimitry Andric 20590b57cec5SDimitry Andric // If we have p - gep(p, ...) then we have to negate the result. 20600b57cec5SDimitry Andric if (Swapped) 20610b57cec5SDimitry Andric Result = Builder.CreateNeg(Result, "diff.neg"); 20620b57cec5SDimitry Andric 20630b57cec5SDimitry Andric return Builder.CreateIntCast(Result, Ty, true); 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 2066753f127fSDimitry Andric static Instruction *foldSubOfMinMax(BinaryOperator &I, 2067753f127fSDimitry Andric InstCombiner::BuilderTy &Builder) { 2068753f127fSDimitry Andric Value *Op0 = I.getOperand(0); 2069753f127fSDimitry Andric Value *Op1 = I.getOperand(1); 2070753f127fSDimitry Andric Type *Ty = I.getType(); 2071753f127fSDimitry Andric auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op1); 2072753f127fSDimitry Andric if (!MinMax) 2073753f127fSDimitry Andric return nullptr; 2074753f127fSDimitry Andric 2075753f127fSDimitry Andric // sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y) 2076753f127fSDimitry Andric // sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y) 2077753f127fSDimitry Andric Value *X = MinMax->getLHS(); 2078753f127fSDimitry Andric Value *Y = MinMax->getRHS(); 2079753f127fSDimitry Andric if (match(Op0, m_c_Add(m_Specific(X), m_Specific(Y))) && 2080753f127fSDimitry Andric (Op0->hasOneUse() || Op1->hasOneUse())) { 2081753f127fSDimitry Andric Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID()); 2082753f127fSDimitry Andric Function *F = Intrinsic::getDeclaration(I.getModule(), InvID, Ty); 2083753f127fSDimitry Andric return CallInst::Create(F, {X, Y}); 2084753f127fSDimitry Andric } 2085753f127fSDimitry Andric 2086753f127fSDimitry Andric // sub(add(X,Y),umin(Y,Z)) --> add(X,usub.sat(Y,Z)) 2087753f127fSDimitry Andric // sub(add(X,Z),umin(Y,Z)) --> add(X,usub.sat(Z,Y)) 2088753f127fSDimitry Andric Value *Z; 2089753f127fSDimitry Andric if (match(Op1, m_OneUse(m_UMin(m_Value(Y), m_Value(Z))))) { 2090753f127fSDimitry Andric if (match(Op0, m_OneUse(m_c_Add(m_Specific(Y), m_Value(X))))) { 2091753f127fSDimitry Andric Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, Ty, {Y, Z}); 2092753f127fSDimitry Andric return BinaryOperator::CreateAdd(X, USub); 2093753f127fSDimitry Andric } 2094753f127fSDimitry Andric if (match(Op0, m_OneUse(m_c_Add(m_Specific(Z), m_Value(X))))) { 2095753f127fSDimitry Andric Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, Ty, {Z, Y}); 2096753f127fSDimitry Andric return BinaryOperator::CreateAdd(X, USub); 2097753f127fSDimitry Andric } 2098753f127fSDimitry Andric } 2099753f127fSDimitry Andric 2100753f127fSDimitry Andric // sub Op0, smin((sub nsw Op0, Z), 0) --> smax Op0, Z 2101753f127fSDimitry Andric // sub Op0, smax((sub nsw Op0, Z), 0) --> smin Op0, Z 2102753f127fSDimitry Andric if (MinMax->isSigned() && match(Y, m_ZeroInt()) && 2103753f127fSDimitry Andric match(X, m_NSWSub(m_Specific(Op0), m_Value(Z)))) { 2104753f127fSDimitry Andric Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID()); 2105753f127fSDimitry Andric Function *F = Intrinsic::getDeclaration(I.getModule(), InvID, Ty); 2106753f127fSDimitry Andric return CallInst::Create(F, {Op0, Z}); 2107753f127fSDimitry Andric } 2108753f127fSDimitry Andric 2109753f127fSDimitry Andric return nullptr; 2110753f127fSDimitry Andric } 2111753f127fSDimitry Andric 2112e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) { 211381ad6265SDimitry Andric if (Value *V = simplifySubInst(I.getOperand(0), I.getOperand(1), 21140b57cec5SDimitry Andric I.hasNoSignedWrap(), I.hasNoUnsignedWrap(), 21150b57cec5SDimitry Andric SQ.getWithInstruction(&I))) 21160b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric if (Instruction *X = foldVectorBinop(I)) 21190b57cec5SDimitry Andric return X; 21200b57cec5SDimitry Andric 212104eeddc0SDimitry Andric if (Instruction *Phi = foldBinopWithPhiOperands(I)) 212204eeddc0SDimitry Andric return Phi; 212304eeddc0SDimitry Andric 21245ffd83dbSDimitry Andric Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); 21250b57cec5SDimitry Andric 21260b57cec5SDimitry Andric // If this is a 'B = x-(-A)', change to B = x+A. 21275ffd83dbSDimitry Andric // We deal with this without involving Negator to preserve NSW flag. 21280b57cec5SDimitry Andric if (Value *V = dyn_castNegVal(Op1)) { 21290b57cec5SDimitry Andric BinaryOperator *Res = BinaryOperator::CreateAdd(Op0, V); 21300b57cec5SDimitry Andric 21310b57cec5SDimitry Andric if (const auto *BO = dyn_cast<BinaryOperator>(Op1)) { 21320b57cec5SDimitry Andric assert(BO->getOpcode() == Instruction::Sub && 21330b57cec5SDimitry Andric "Expected a subtraction operator!"); 21340b57cec5SDimitry Andric if (BO->hasNoSignedWrap() && I.hasNoSignedWrap()) 21350b57cec5SDimitry Andric Res->setHasNoSignedWrap(true); 21360b57cec5SDimitry Andric } else { 21370b57cec5SDimitry Andric if (cast<Constant>(Op1)->isNotMinSignedValue() && I.hasNoSignedWrap()) 21380b57cec5SDimitry Andric Res->setHasNoSignedWrap(true); 21390b57cec5SDimitry Andric } 21400b57cec5SDimitry Andric 21410b57cec5SDimitry Andric return Res; 21420b57cec5SDimitry Andric } 21430b57cec5SDimitry Andric 2144e8d8bef9SDimitry Andric // Try this before Negator to preserve NSW flag. 2145e8d8bef9SDimitry Andric if (Instruction *R = factorizeMathWithShlOps(I, Builder)) 2146e8d8bef9SDimitry Andric return R; 2147e8d8bef9SDimitry Andric 2148fe6060f1SDimitry Andric Constant *C; 2149fe6060f1SDimitry Andric if (match(Op0, m_ImmConstant(C))) { 2150e8d8bef9SDimitry Andric Value *X; 2151e8d8bef9SDimitry Andric Constant *C2; 2152e8d8bef9SDimitry Andric 2153e8d8bef9SDimitry Andric // C-(X+C2) --> (C-C2)-X 215406c3fb27SDimitry Andric if (match(Op1, m_Add(m_Value(X), m_ImmConstant(C2)))) { 21555f757f3fSDimitry Andric // C-C2 never overflow, and C-(X+C2), (X+C2) has NSW/NUW 21565f757f3fSDimitry Andric // => (C-C2)-X can have NSW/NUW 215706c3fb27SDimitry Andric bool WillNotSOV = willNotOverflowSignedSub(C, C2, I); 215806c3fb27SDimitry Andric BinaryOperator *Res = 215906c3fb27SDimitry Andric BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X); 216006c3fb27SDimitry Andric auto *OBO1 = cast<OverflowingBinaryOperator>(Op1); 216106c3fb27SDimitry Andric Res->setHasNoSignedWrap(I.hasNoSignedWrap() && OBO1->hasNoSignedWrap() && 216206c3fb27SDimitry Andric WillNotSOV); 21635f757f3fSDimitry Andric Res->setHasNoUnsignedWrap(I.hasNoUnsignedWrap() && 21645f757f3fSDimitry Andric OBO1->hasNoUnsignedWrap()); 216506c3fb27SDimitry Andric return Res; 216606c3fb27SDimitry Andric } 2167e8d8bef9SDimitry Andric } 2168e8d8bef9SDimitry Andric 21695ffd83dbSDimitry Andric auto TryToNarrowDeduceFlags = [this, &I, &Op0, &Op1]() -> Instruction * { 21705ffd83dbSDimitry Andric if (Instruction *Ext = narrowMathIfNoOverflow(I)) 21715ffd83dbSDimitry Andric return Ext; 21725ffd83dbSDimitry Andric 21735ffd83dbSDimitry Andric bool Changed = false; 21745ffd83dbSDimitry Andric if (!I.hasNoSignedWrap() && willNotOverflowSignedSub(Op0, Op1, I)) { 21755ffd83dbSDimitry Andric Changed = true; 21765ffd83dbSDimitry Andric I.setHasNoSignedWrap(true); 21775ffd83dbSDimitry Andric } 21785ffd83dbSDimitry Andric if (!I.hasNoUnsignedWrap() && willNotOverflowUnsignedSub(Op0, Op1, I)) { 21795ffd83dbSDimitry Andric Changed = true; 21805ffd83dbSDimitry Andric I.setHasNoUnsignedWrap(true); 21815ffd83dbSDimitry Andric } 21825ffd83dbSDimitry Andric 21835ffd83dbSDimitry Andric return Changed ? &I : nullptr; 21845ffd83dbSDimitry Andric }; 21855ffd83dbSDimitry Andric 21865ffd83dbSDimitry Andric // First, let's try to interpret `sub a, b` as `add a, (sub 0, b)`, 21875ffd83dbSDimitry Andric // and let's try to sink `(sub 0, b)` into `b` itself. But only if this isn't 21885ffd83dbSDimitry Andric // a pure negation used by a select that looks like abs/nabs. 21895ffd83dbSDimitry Andric bool IsNegation = match(Op0, m_ZeroInt()); 21905ffd83dbSDimitry Andric if (!IsNegation || none_of(I.users(), [&I, Op1](const User *U) { 21915ffd83dbSDimitry Andric const Instruction *UI = dyn_cast<Instruction>(U); 21925ffd83dbSDimitry Andric if (!UI) 21935ffd83dbSDimitry Andric return false; 21945ffd83dbSDimitry Andric return match(UI, 21955ffd83dbSDimitry Andric m_Select(m_Value(), m_Specific(Op1), m_Specific(&I))) || 21965ffd83dbSDimitry Andric match(UI, m_Select(m_Value(), m_Specific(&I), m_Specific(Op1))); 21975ffd83dbSDimitry Andric })) { 21985f757f3fSDimitry Andric if (Value *NegOp1 = Negator::Negate(IsNegation, /* IsNSW */ IsNegation && 21995f757f3fSDimitry Andric I.hasNoSignedWrap(), 22005f757f3fSDimitry Andric Op1, *this)) 22015ffd83dbSDimitry Andric return BinaryOperator::CreateAdd(NegOp1, Op0); 22025ffd83dbSDimitry Andric } 22035ffd83dbSDimitry Andric if (IsNegation) 22045ffd83dbSDimitry Andric return TryToNarrowDeduceFlags(); // Should have been handled in Negator! 22055ffd83dbSDimitry Andric 22065ffd83dbSDimitry Andric // (A*B)-(A*C) -> A*(B-C) etc 2207bdd1243dSDimitry Andric if (Value *V = foldUsingDistributiveLaws(I)) 22085ffd83dbSDimitry Andric return replaceInstUsesWith(I, V); 22095ffd83dbSDimitry Andric 22100b57cec5SDimitry Andric if (I.getType()->isIntOrIntVectorTy(1)) 22110b57cec5SDimitry Andric return BinaryOperator::CreateXor(Op0, Op1); 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric // Replace (-1 - A) with (~A). 22140b57cec5SDimitry Andric if (match(Op0, m_AllOnes())) 22150b57cec5SDimitry Andric return BinaryOperator::CreateNot(Op1); 22160b57cec5SDimitry Andric 22170b57cec5SDimitry Andric // (X + -1) - Y --> ~Y + X 2218349cc55cSDimitry Andric Value *X, *Y; 22190b57cec5SDimitry Andric if (match(Op0, m_OneUse(m_Add(m_Value(X), m_AllOnes())))) 22200b57cec5SDimitry Andric return BinaryOperator::CreateAdd(Builder.CreateNot(Op1), X); 22210b57cec5SDimitry Andric 22225ffd83dbSDimitry Andric // Reassociate sub/add sequences to create more add instructions and 22235ffd83dbSDimitry Andric // reduce dependency chains: 22245ffd83dbSDimitry Andric // ((X - Y) + Z) - Op1 --> (X + Z) - (Y + Op1) 22255ffd83dbSDimitry Andric Value *Z; 22265ffd83dbSDimitry Andric if (match(Op0, m_OneUse(m_c_Add(m_OneUse(m_Sub(m_Value(X), m_Value(Y))), 22275ffd83dbSDimitry Andric m_Value(Z))))) { 22285ffd83dbSDimitry Andric Value *XZ = Builder.CreateAdd(X, Z); 22295ffd83dbSDimitry Andric Value *YW = Builder.CreateAdd(Y, Op1); 22305ffd83dbSDimitry Andric return BinaryOperator::CreateSub(XZ, YW); 22315ffd83dbSDimitry Andric } 22320b57cec5SDimitry Andric 2233fe6060f1SDimitry Andric // ((X - Y) - Op1) --> X - (Y + Op1) 2234fe6060f1SDimitry Andric if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y))))) { 22355f757f3fSDimitry Andric OverflowingBinaryOperator *LHSSub = cast<OverflowingBinaryOperator>(Op0); 22365f757f3fSDimitry Andric bool HasNUW = I.hasNoUnsignedWrap() && LHSSub->hasNoUnsignedWrap(); 22375f757f3fSDimitry Andric bool HasNSW = HasNUW && I.hasNoSignedWrap() && LHSSub->hasNoSignedWrap(); 22385f757f3fSDimitry Andric Value *Add = Builder.CreateAdd(Y, Op1, "", /* HasNUW */ HasNUW, 22395f757f3fSDimitry Andric /* HasNSW */ HasNSW); 22405f757f3fSDimitry Andric BinaryOperator *Sub = BinaryOperator::CreateSub(X, Add); 22415f757f3fSDimitry Andric Sub->setHasNoUnsignedWrap(HasNUW); 22425f757f3fSDimitry Andric Sub->setHasNoSignedWrap(HasNSW); 22435f757f3fSDimitry Andric return Sub; 22445f757f3fSDimitry Andric } 22455f757f3fSDimitry Andric 22465f757f3fSDimitry Andric { 22475f757f3fSDimitry Andric // (X + Z) - (Y + Z) --> (X - Y) 22485f757f3fSDimitry Andric // This is done in other passes, but we want to be able to consume this 22495f757f3fSDimitry Andric // pattern in InstCombine so we can generate it without creating infinite 22505f757f3fSDimitry Andric // loops. 22515f757f3fSDimitry Andric if (match(Op0, m_Add(m_Value(X), m_Value(Z))) && 22525f757f3fSDimitry Andric match(Op1, m_c_Add(m_Value(Y), m_Specific(Z)))) 22535f757f3fSDimitry Andric return BinaryOperator::CreateSub(X, Y); 22545f757f3fSDimitry Andric 22555f757f3fSDimitry Andric // (X + C0) - (Y + C1) --> (X - Y) + (C0 - C1) 22565f757f3fSDimitry Andric Constant *CX, *CY; 22575f757f3fSDimitry Andric if (match(Op0, m_OneUse(m_Add(m_Value(X), m_ImmConstant(CX)))) && 22585f757f3fSDimitry Andric match(Op1, m_OneUse(m_Add(m_Value(Y), m_ImmConstant(CY))))) { 22595f757f3fSDimitry Andric Value *OpsSub = Builder.CreateSub(X, Y); 22605f757f3fSDimitry Andric Constant *ConstsSub = ConstantExpr::getSub(CX, CY); 22615f757f3fSDimitry Andric return BinaryOperator::CreateAdd(OpsSub, ConstsSub); 22625f757f3fSDimitry Andric } 2263fe6060f1SDimitry Andric } 2264fe6060f1SDimitry Andric 2265349cc55cSDimitry Andric // (~X) - (~Y) --> Y - X 22665f757f3fSDimitry Andric { 22675f757f3fSDimitry Andric // Need to ensure we can consume at least one of the `not` instructions, 22685f757f3fSDimitry Andric // otherwise this can inf loop. 22695f757f3fSDimitry Andric bool ConsumesOp0, ConsumesOp1; 22705f757f3fSDimitry Andric if (isFreeToInvert(Op0, Op0->hasOneUse(), ConsumesOp0) && 22715f757f3fSDimitry Andric isFreeToInvert(Op1, Op1->hasOneUse(), ConsumesOp1) && 22725f757f3fSDimitry Andric (ConsumesOp0 || ConsumesOp1)) { 22735f757f3fSDimitry Andric Value *NotOp0 = getFreelyInverted(Op0, Op0->hasOneUse(), &Builder); 22745f757f3fSDimitry Andric Value *NotOp1 = getFreelyInverted(Op1, Op1->hasOneUse(), &Builder); 22755f757f3fSDimitry Andric assert(NotOp0 != nullptr && NotOp1 != nullptr && 22765f757f3fSDimitry Andric "isFreeToInvert desynced with getFreelyInverted"); 2277349cc55cSDimitry Andric return BinaryOperator::CreateSub(NotOp1, NotOp0); 2278349cc55cSDimitry Andric } 22795f757f3fSDimitry Andric } 2280349cc55cSDimitry Andric 22815ffd83dbSDimitry Andric auto m_AddRdx = [](Value *&Vec) { 2282e8d8bef9SDimitry Andric return m_OneUse(m_Intrinsic<Intrinsic::vector_reduce_add>(m_Value(Vec))); 22835ffd83dbSDimitry Andric }; 22845ffd83dbSDimitry Andric Value *V0, *V1; 22855ffd83dbSDimitry Andric if (match(Op0, m_AddRdx(V0)) && match(Op1, m_AddRdx(V1)) && 22865ffd83dbSDimitry Andric V0->getType() == V1->getType()) { 22875ffd83dbSDimitry Andric // Difference of sums is sum of differences: 22885ffd83dbSDimitry Andric // add_rdx(V0) - add_rdx(V1) --> add_rdx(V0 - V1) 22895ffd83dbSDimitry Andric Value *Sub = Builder.CreateSub(V0, V1); 2290e8d8bef9SDimitry Andric Value *Rdx = Builder.CreateIntrinsic(Intrinsic::vector_reduce_add, 2291e8d8bef9SDimitry Andric {Sub->getType()}, {Sub}); 22925ffd83dbSDimitry Andric return replaceInstUsesWith(I, Rdx); 22930b57cec5SDimitry Andric } 22940b57cec5SDimitry Andric 22950b57cec5SDimitry Andric if (Constant *C = dyn_cast<Constant>(Op0)) { 22960b57cec5SDimitry Andric Value *X; 22975ffd83dbSDimitry Andric if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) 22980b57cec5SDimitry Andric // C - (zext bool) --> bool ? C - 1 : C 2299e8d8bef9SDimitry Andric return SelectInst::Create(X, InstCombiner::SubOne(C), C); 23005ffd83dbSDimitry Andric if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) 23010b57cec5SDimitry Andric // C - (sext bool) --> bool ? C + 1 : C 2302e8d8bef9SDimitry Andric return SelectInst::Create(X, InstCombiner::AddOne(C), C); 23030b57cec5SDimitry Andric 23040b57cec5SDimitry Andric // C - ~X == X + (1+C) 23050b57cec5SDimitry Andric if (match(Op1, m_Not(m_Value(X)))) 2306e8d8bef9SDimitry Andric return BinaryOperator::CreateAdd(X, InstCombiner::AddOne(C)); 23070b57cec5SDimitry Andric 23080b57cec5SDimitry Andric // Try to fold constant sub into select arguments. 23090b57cec5SDimitry Andric if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) 23100b57cec5SDimitry Andric if (Instruction *R = FoldOpIntoSelect(I, SI)) 23110b57cec5SDimitry Andric return R; 23120b57cec5SDimitry Andric 23130b57cec5SDimitry Andric // Try to fold constant sub into PHI values. 23140b57cec5SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(Op1)) 23150b57cec5SDimitry Andric if (Instruction *R = foldOpIntoPhi(I, PN)) 23160b57cec5SDimitry Andric return R; 23170b57cec5SDimitry Andric 23180b57cec5SDimitry Andric Constant *C2; 23190b57cec5SDimitry Andric 23200b57cec5SDimitry Andric // C-(C2-X) --> X+(C-C2) 2321e8d8bef9SDimitry Andric if (match(Op1, m_Sub(m_ImmConstant(C2), m_Value(X)))) 23220b57cec5SDimitry Andric return BinaryOperator::CreateAdd(X, ConstantExpr::getSub(C, C2)); 23230b57cec5SDimitry Andric } 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric const APInt *Op0C; 2326bdd1243dSDimitry Andric if (match(Op0, m_APInt(Op0C))) { 2327bdd1243dSDimitry Andric if (Op0C->isMask()) { 2328fcaf7f86SDimitry Andric // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known 2329*0fca6ea1SDimitry Andric // zero. We don't use information from dominating conditions so this 2330*0fca6ea1SDimitry Andric // transform is easier to reverse if necessary. 2331*0fca6ea1SDimitry Andric KnownBits RHSKnown = llvm::computeKnownBits( 2332*0fca6ea1SDimitry Andric Op1, 0, SQ.getWithInstruction(&I).getWithoutDomCondCache()); 2333fcaf7f86SDimitry Andric if ((*Op0C | RHSKnown.Zero).isAllOnes()) 23340b57cec5SDimitry Andric return BinaryOperator::CreateXor(Op1, Op0); 2335fcaf7f86SDimitry Andric } 23360b57cec5SDimitry Andric 2337bdd1243dSDimitry Andric // C - ((C3 -nuw X) & C2) --> (C - (C2 & C3)) + (X & C2) when: 2338bdd1243dSDimitry Andric // (C3 - ((C2 & C3) - 1)) is pow2 2339bdd1243dSDimitry Andric // ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1) 2340bdd1243dSDimitry Andric // C2 is negative pow2 || sub nuw 2341bdd1243dSDimitry Andric const APInt *C2, *C3; 2342bdd1243dSDimitry Andric BinaryOperator *InnerSub; 2343bdd1243dSDimitry Andric if (match(Op1, m_OneUse(m_And(m_BinOp(InnerSub), m_APInt(C2)))) && 2344bdd1243dSDimitry Andric match(InnerSub, m_Sub(m_APInt(C3), m_Value(X))) && 2345bdd1243dSDimitry Andric (InnerSub->hasNoUnsignedWrap() || C2->isNegatedPowerOf2())) { 2346bdd1243dSDimitry Andric APInt C2AndC3 = *C2 & *C3; 2347bdd1243dSDimitry Andric APInt C2AndC3Minus1 = C2AndC3 - 1; 2348bdd1243dSDimitry Andric APInt C2AddC3 = *C2 + *C3; 2349bdd1243dSDimitry Andric if ((*C3 - C2AndC3Minus1).isPowerOf2() && 2350bdd1243dSDimitry Andric C2AndC3Minus1.isSubsetOf(C2AddC3)) { 2351bdd1243dSDimitry Andric Value *And = Builder.CreateAnd(X, ConstantInt::get(I.getType(), *C2)); 2352bdd1243dSDimitry Andric return BinaryOperator::CreateAdd( 2353bdd1243dSDimitry Andric And, ConstantInt::get(I.getType(), *Op0C - C2AndC3)); 2354bdd1243dSDimitry Andric } 2355bdd1243dSDimitry Andric } 2356bdd1243dSDimitry Andric } 2357bdd1243dSDimitry Andric 23580b57cec5SDimitry Andric { 23590b57cec5SDimitry Andric Value *Y; 23600b57cec5SDimitry Andric // X-(X+Y) == -Y X-(Y+X) == -Y 23610b57cec5SDimitry Andric if (match(Op1, m_c_Add(m_Specific(Op0), m_Value(Y)))) 23620b57cec5SDimitry Andric return BinaryOperator::CreateNeg(Y); 23630b57cec5SDimitry Andric 23640b57cec5SDimitry Andric // (X-Y)-X == -Y 23650b57cec5SDimitry Andric if (match(Op0, m_Sub(m_Specific(Op1), m_Value(Y)))) 23660b57cec5SDimitry Andric return BinaryOperator::CreateNeg(Y); 23670b57cec5SDimitry Andric } 23680b57cec5SDimitry Andric 23698bcb0991SDimitry Andric // (sub (or A, B) (and A, B)) --> (xor A, B) 23708bcb0991SDimitry Andric { 23718bcb0991SDimitry Andric Value *A, *B; 23728bcb0991SDimitry Andric if (match(Op1, m_And(m_Value(A), m_Value(B))) && 23738bcb0991SDimitry Andric match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) 23748bcb0991SDimitry Andric return BinaryOperator::CreateXor(A, B); 23758bcb0991SDimitry Andric } 23768bcb0991SDimitry Andric 2377e8d8bef9SDimitry Andric // (sub (add A, B) (or A, B)) --> (and A, B) 2378e8d8bef9SDimitry Andric { 2379e8d8bef9SDimitry Andric Value *A, *B; 2380e8d8bef9SDimitry Andric if (match(Op0, m_Add(m_Value(A), m_Value(B))) && 2381e8d8bef9SDimitry Andric match(Op1, m_c_Or(m_Specific(A), m_Specific(B)))) 2382e8d8bef9SDimitry Andric return BinaryOperator::CreateAnd(A, B); 2383e8d8bef9SDimitry Andric } 2384e8d8bef9SDimitry Andric 2385e8d8bef9SDimitry Andric // (sub (add A, B) (and A, B)) --> (or A, B) 2386e8d8bef9SDimitry Andric { 2387e8d8bef9SDimitry Andric Value *A, *B; 2388e8d8bef9SDimitry Andric if (match(Op0, m_Add(m_Value(A), m_Value(B))) && 2389e8d8bef9SDimitry Andric match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) 2390e8d8bef9SDimitry Andric return BinaryOperator::CreateOr(A, B); 2391e8d8bef9SDimitry Andric } 2392e8d8bef9SDimitry Andric 23938bcb0991SDimitry Andric // (sub (and A, B) (or A, B)) --> neg (xor A, B) 23948bcb0991SDimitry Andric { 23958bcb0991SDimitry Andric Value *A, *B; 23968bcb0991SDimitry Andric if (match(Op0, m_And(m_Value(A), m_Value(B))) && 23978bcb0991SDimitry Andric match(Op1, m_c_Or(m_Specific(A), m_Specific(B))) && 23988bcb0991SDimitry Andric (Op0->hasOneUse() || Op1->hasOneUse())) 23998bcb0991SDimitry Andric return BinaryOperator::CreateNeg(Builder.CreateXor(A, B)); 24008bcb0991SDimitry Andric } 24018bcb0991SDimitry Andric 24020b57cec5SDimitry Andric // (sub (or A, B), (xor A, B)) --> (and A, B) 24030b57cec5SDimitry Andric { 24040b57cec5SDimitry Andric Value *A, *B; 24050b57cec5SDimitry Andric if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && 24060b57cec5SDimitry Andric match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) 24070b57cec5SDimitry Andric return BinaryOperator::CreateAnd(A, B); 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric 24108bcb0991SDimitry Andric // (sub (xor A, B) (or A, B)) --> neg (and A, B) 24118bcb0991SDimitry Andric { 24128bcb0991SDimitry Andric Value *A, *B; 24138bcb0991SDimitry Andric if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && 24148bcb0991SDimitry Andric match(Op1, m_c_Or(m_Specific(A), m_Specific(B))) && 24158bcb0991SDimitry Andric (Op0->hasOneUse() || Op1->hasOneUse())) 24168bcb0991SDimitry Andric return BinaryOperator::CreateNeg(Builder.CreateAnd(A, B)); 24178bcb0991SDimitry Andric } 24188bcb0991SDimitry Andric 24190b57cec5SDimitry Andric { 24200b57cec5SDimitry Andric Value *Y; 24210b57cec5SDimitry Andric // ((X | Y) - X) --> (~X & Y) 24220b57cec5SDimitry Andric if (match(Op0, m_OneUse(m_c_Or(m_Value(Y), m_Specific(Op1))))) 24230b57cec5SDimitry Andric return BinaryOperator::CreateAnd( 24240b57cec5SDimitry Andric Y, Builder.CreateNot(Op1, Op1->getName() + ".not")); 24250b57cec5SDimitry Andric } 24260b57cec5SDimitry Andric 2427480093f4SDimitry Andric { 2428480093f4SDimitry Andric // (sub (and Op1, (neg X)), Op1) --> neg (and Op1, (add X, -1)) 2429480093f4SDimitry Andric Value *X; 2430480093f4SDimitry Andric if (match(Op0, m_OneUse(m_c_And(m_Specific(Op1), 2431480093f4SDimitry Andric m_OneUse(m_Neg(m_Value(X))))))) { 2432480093f4SDimitry Andric return BinaryOperator::CreateNeg(Builder.CreateAnd( 2433480093f4SDimitry Andric Op1, Builder.CreateAdd(X, Constant::getAllOnesValue(I.getType())))); 2434480093f4SDimitry Andric } 2435480093f4SDimitry Andric } 2436480093f4SDimitry Andric 2437480093f4SDimitry Andric { 2438480093f4SDimitry Andric // (sub (and Op1, C), Op1) --> neg (and Op1, ~C) 2439480093f4SDimitry Andric Constant *C; 2440480093f4SDimitry Andric if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_Constant(C))))) { 2441480093f4SDimitry Andric return BinaryOperator::CreateNeg( 2442480093f4SDimitry Andric Builder.CreateAnd(Op1, Builder.CreateNot(C))); 2443480093f4SDimitry Andric } 2444480093f4SDimitry Andric } 2445480093f4SDimitry Andric 2446*0fca6ea1SDimitry Andric { 2447*0fca6ea1SDimitry Andric // (sub (xor X, (sext C)), (sext C)) => (select C, (neg X), X) 2448*0fca6ea1SDimitry Andric // (sub (sext C), (xor X, (sext C))) => (select C, X, (neg X)) 2449*0fca6ea1SDimitry Andric Value *C, *X; 2450*0fca6ea1SDimitry Andric auto m_SubXorCmp = [&C, &X](Value *LHS, Value *RHS) { 2451*0fca6ea1SDimitry Andric return match(LHS, m_OneUse(m_c_Xor(m_Value(X), m_Specific(RHS)))) && 2452*0fca6ea1SDimitry Andric match(RHS, m_SExt(m_Value(C))) && 2453*0fca6ea1SDimitry Andric (C->getType()->getScalarSizeInBits() == 1); 2454*0fca6ea1SDimitry Andric }; 2455*0fca6ea1SDimitry Andric if (m_SubXorCmp(Op0, Op1)) 2456*0fca6ea1SDimitry Andric return SelectInst::Create(C, Builder.CreateNeg(X), X); 2457*0fca6ea1SDimitry Andric if (m_SubXorCmp(Op1, Op0)) 2458*0fca6ea1SDimitry Andric return SelectInst::Create(C, X, Builder.CreateNeg(X)); 2459*0fca6ea1SDimitry Andric } 2460*0fca6ea1SDimitry Andric 24617a6dacacSDimitry Andric if (Instruction *R = tryFoldInstWithCtpopWithNot(&I)) 24627a6dacacSDimitry Andric return R; 24637a6dacacSDimitry Andric 2464753f127fSDimitry Andric if (Instruction *R = foldSubOfMinMax(I, Builder)) 2465753f127fSDimitry Andric return R; 246681ad6265SDimitry Andric 2467480093f4SDimitry Andric { 2468480093f4SDimitry Andric // If we have a subtraction between some value and a select between 2469480093f4SDimitry Andric // said value and something else, sink subtraction into select hands, i.e.: 2470480093f4SDimitry Andric // sub (select %Cond, %TrueVal, %FalseVal), %Op1 2471480093f4SDimitry Andric // -> 2472480093f4SDimitry Andric // select %Cond, (sub %TrueVal, %Op1), (sub %FalseVal, %Op1) 2473480093f4SDimitry Andric // or 2474480093f4SDimitry Andric // sub %Op0, (select %Cond, %TrueVal, %FalseVal) 2475480093f4SDimitry Andric // -> 2476480093f4SDimitry Andric // select %Cond, (sub %Op0, %TrueVal), (sub %Op0, %FalseVal) 2477480093f4SDimitry Andric // This will result in select between new subtraction and 0. 2478480093f4SDimitry Andric auto SinkSubIntoSelect = 2479480093f4SDimitry Andric [Ty = I.getType()](Value *Select, Value *OtherHandOfSub, 2480480093f4SDimitry Andric auto SubBuilder) -> Instruction * { 2481480093f4SDimitry Andric Value *Cond, *TrueVal, *FalseVal; 2482480093f4SDimitry Andric if (!match(Select, m_OneUse(m_Select(m_Value(Cond), m_Value(TrueVal), 2483480093f4SDimitry Andric m_Value(FalseVal))))) 2484480093f4SDimitry Andric return nullptr; 2485480093f4SDimitry Andric if (OtherHandOfSub != TrueVal && OtherHandOfSub != FalseVal) 2486480093f4SDimitry Andric return nullptr; 2487480093f4SDimitry Andric // While it is really tempting to just create two subtractions and let 2488480093f4SDimitry Andric // InstCombine fold one of those to 0, it isn't possible to do so 2489480093f4SDimitry Andric // because of worklist visitation order. So ugly it is. 2490480093f4SDimitry Andric bool OtherHandOfSubIsTrueVal = OtherHandOfSub == TrueVal; 2491480093f4SDimitry Andric Value *NewSub = SubBuilder(OtherHandOfSubIsTrueVal ? FalseVal : TrueVal); 2492480093f4SDimitry Andric Constant *Zero = Constant::getNullValue(Ty); 2493480093f4SDimitry Andric SelectInst *NewSel = 2494480093f4SDimitry Andric SelectInst::Create(Cond, OtherHandOfSubIsTrueVal ? Zero : NewSub, 2495480093f4SDimitry Andric OtherHandOfSubIsTrueVal ? NewSub : Zero); 2496480093f4SDimitry Andric // Preserve prof metadata if any. 2497480093f4SDimitry Andric NewSel->copyMetadata(cast<Instruction>(*Select)); 2498480093f4SDimitry Andric return NewSel; 2499480093f4SDimitry Andric }; 2500480093f4SDimitry Andric if (Instruction *NewSel = SinkSubIntoSelect( 2501480093f4SDimitry Andric /*Select=*/Op0, /*OtherHandOfSub=*/Op1, 2502480093f4SDimitry Andric [Builder = &Builder, Op1](Value *OtherHandOfSelect) { 2503480093f4SDimitry Andric return Builder->CreateSub(OtherHandOfSelect, 2504480093f4SDimitry Andric /*OtherHandOfSub=*/Op1); 2505480093f4SDimitry Andric })) 2506480093f4SDimitry Andric return NewSel; 2507480093f4SDimitry Andric if (Instruction *NewSel = SinkSubIntoSelect( 2508480093f4SDimitry Andric /*Select=*/Op1, /*OtherHandOfSub=*/Op0, 2509480093f4SDimitry Andric [Builder = &Builder, Op0](Value *OtherHandOfSelect) { 2510480093f4SDimitry Andric return Builder->CreateSub(/*OtherHandOfSub=*/Op0, 2511480093f4SDimitry Andric OtherHandOfSelect); 2512480093f4SDimitry Andric })) 2513480093f4SDimitry Andric return NewSel; 2514480093f4SDimitry Andric } 2515480093f4SDimitry Andric 25160b57cec5SDimitry Andric // (X - (X & Y)) --> (X & ~Y) 25175ffd83dbSDimitry Andric if (match(Op1, m_c_And(m_Specific(Op0), m_Value(Y))) && 25185ffd83dbSDimitry Andric (Op1->hasOneUse() || isa<Constant>(Y))) 25195ffd83dbSDimitry Andric return BinaryOperator::CreateAnd( 25205ffd83dbSDimitry Andric Op0, Builder.CreateNot(Y, Y->getName() + ".not")); 25210b57cec5SDimitry Andric 2522349cc55cSDimitry Andric // ~X - Min/Max(~X, Y) -> ~Min/Max(X, ~Y) - X 2523349cc55cSDimitry Andric // ~X - Min/Max(Y, ~X) -> ~Min/Max(X, ~Y) - X 2524349cc55cSDimitry Andric // Min/Max(~X, Y) - ~X -> X - ~Min/Max(X, ~Y) 2525349cc55cSDimitry Andric // Min/Max(Y, ~X) - ~X -> X - ~Min/Max(X, ~Y) 2526349cc55cSDimitry Andric // As long as Y is freely invertible, this will be neutral or a win. 2527349cc55cSDimitry Andric // Note: We don't generate the inverse max/min, just create the 'not' of 2528349cc55cSDimitry Andric // it and let other folds do the rest. 2529349cc55cSDimitry Andric if (match(Op0, m_Not(m_Value(X))) && 2530349cc55cSDimitry Andric match(Op1, m_c_MaxOrMin(m_Specific(Op0), m_Value(Y))) && 2531349cc55cSDimitry Andric !Op0->hasNUsesOrMore(3) && isFreeToInvert(Y, Y->hasOneUse())) { 2532349cc55cSDimitry Andric Value *Not = Builder.CreateNot(Op1); 2533349cc55cSDimitry Andric return BinaryOperator::CreateSub(Not, X); 2534349cc55cSDimitry Andric } 2535349cc55cSDimitry Andric if (match(Op1, m_Not(m_Value(X))) && 2536349cc55cSDimitry Andric match(Op0, m_c_MaxOrMin(m_Specific(Op1), m_Value(Y))) && 2537349cc55cSDimitry Andric !Op1->hasNUsesOrMore(3) && isFreeToInvert(Y, Y->hasOneUse())) { 2538349cc55cSDimitry Andric Value *Not = Builder.CreateNot(Op0); 2539349cc55cSDimitry Andric return BinaryOperator::CreateSub(X, Not); 2540349cc55cSDimitry Andric } 2541349cc55cSDimitry Andric 25420b57cec5SDimitry Andric // Optimize pointer differences into the same array into a size. Consider: 25430b57cec5SDimitry Andric // &A[10] - &A[0]: we should compile this to "10". 25440b57cec5SDimitry Andric Value *LHSOp, *RHSOp; 25450b57cec5SDimitry Andric if (match(Op0, m_PtrToInt(m_Value(LHSOp))) && 25460b57cec5SDimitry Andric match(Op1, m_PtrToInt(m_Value(RHSOp)))) 2547480093f4SDimitry Andric if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(), 2548480093f4SDimitry Andric I.hasNoUnsignedWrap())) 25490b57cec5SDimitry Andric return replaceInstUsesWith(I, Res); 25500b57cec5SDimitry Andric 25510b57cec5SDimitry Andric // trunc(p)-trunc(q) -> trunc(p-q) 25520b57cec5SDimitry Andric if (match(Op0, m_Trunc(m_PtrToInt(m_Value(LHSOp)))) && 25530b57cec5SDimitry Andric match(Op1, m_Trunc(m_PtrToInt(m_Value(RHSOp))))) 2554480093f4SDimitry Andric if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(), 2555480093f4SDimitry Andric /* IsNUW */ false)) 25560b57cec5SDimitry Andric return replaceInstUsesWith(I, Res); 25570b57cec5SDimitry Andric 25580b57cec5SDimitry Andric // Canonicalize a shifty way to code absolute value to the common pattern. 25590b57cec5SDimitry Andric // There are 2 potential commuted variants. 25600b57cec5SDimitry Andric // We're relying on the fact that we only do this transform when the shift has 25610b57cec5SDimitry Andric // exactly 2 uses and the xor has exactly 1 use (otherwise, we might increase 25620b57cec5SDimitry Andric // instructions). 25630b57cec5SDimitry Andric Value *A; 25640b57cec5SDimitry Andric const APInt *ShAmt; 25650b57cec5SDimitry Andric Type *Ty = I.getType(); 2566bdd1243dSDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 25670b57cec5SDimitry Andric if (match(Op1, m_AShr(m_Value(A), m_APInt(ShAmt))) && 2568bdd1243dSDimitry Andric Op1->hasNUses(2) && *ShAmt == BitWidth - 1 && 25690b57cec5SDimitry Andric match(Op0, m_OneUse(m_c_Xor(m_Specific(A), m_Specific(Op1))))) { 25700b57cec5SDimitry Andric // B = ashr i32 A, 31 ; smear the sign bit 25710b57cec5SDimitry Andric // sub (xor A, B), B ; flip bits if negative and subtract -1 (add 1) 25720b57cec5SDimitry Andric // --> (A < 0) ? -A : A 257381ad6265SDimitry Andric Value *IsNeg = Builder.CreateIsNeg(A); 2574*0fca6ea1SDimitry Andric // Copy the nsw flags from the sub to the negate. 2575*0fca6ea1SDimitry Andric Value *NegA = I.hasNoUnsignedWrap() 2576*0fca6ea1SDimitry Andric ? Constant::getNullValue(A->getType()) 2577*0fca6ea1SDimitry Andric : Builder.CreateNeg(A, "", I.hasNoSignedWrap()); 257881ad6265SDimitry Andric return SelectInst::Create(IsNeg, NegA, A); 25790b57cec5SDimitry Andric } 25800b57cec5SDimitry Andric 2581e8d8bef9SDimitry Andric // If we are subtracting a low-bit masked subset of some value from an add 2582e8d8bef9SDimitry Andric // of that same value with no low bits changed, that is clearing some low bits 2583e8d8bef9SDimitry Andric // of the sum: 2584e8d8bef9SDimitry Andric // sub (X + AddC), (X & AndC) --> and (X + AddC), ~AndC 2585e8d8bef9SDimitry Andric const APInt *AddC, *AndC; 2586e8d8bef9SDimitry Andric if (match(Op0, m_Add(m_Value(X), m_APInt(AddC))) && 2587e8d8bef9SDimitry Andric match(Op1, m_And(m_Specific(X), m_APInt(AndC)))) { 258806c3fb27SDimitry Andric unsigned Cttz = AddC->countr_zero(); 2589e8d8bef9SDimitry Andric APInt HighMask(APInt::getHighBitsSet(BitWidth, BitWidth - Cttz)); 2590349cc55cSDimitry Andric if ((HighMask & *AndC).isZero()) 2591e8d8bef9SDimitry Andric return BinaryOperator::CreateAnd(Op0, ConstantInt::get(Ty, ~(*AndC))); 2592e8d8bef9SDimitry Andric } 2593e8d8bef9SDimitry Andric 25948bcb0991SDimitry Andric if (Instruction *V = 25958bcb0991SDimitry Andric canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I)) 25968bcb0991SDimitry Andric return V; 25978bcb0991SDimitry Andric 2598fe6060f1SDimitry Andric // X - usub.sat(X, Y) => umin(X, Y) 2599fe6060f1SDimitry Andric if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::usub_sat>(m_Specific(Op0), 2600fe6060f1SDimitry Andric m_Value(Y))))) 2601fe6060f1SDimitry Andric return replaceInstUsesWith( 2602fe6060f1SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::umin, {I.getType()}, {Op0, Y})); 2603fe6060f1SDimitry Andric 2604349cc55cSDimitry Andric // umax(X, Op1) - Op1 --> usub.sat(X, Op1) 2605349cc55cSDimitry Andric // TODO: The one-use restriction is not strictly necessary, but it may 2606349cc55cSDimitry Andric // require improving other pattern matching and/or codegen. 2607349cc55cSDimitry Andric if (match(Op0, m_OneUse(m_c_UMax(m_Value(X), m_Specific(Op1))))) 2608349cc55cSDimitry Andric return replaceInstUsesWith( 2609349cc55cSDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op1})); 2610349cc55cSDimitry Andric 261181ad6265SDimitry Andric // Op0 - umin(X, Op0) --> usub.sat(Op0, X) 261281ad6265SDimitry Andric if (match(Op1, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op0))))) 261381ad6265SDimitry Andric return replaceInstUsesWith( 261481ad6265SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op0, X})); 261581ad6265SDimitry Andric 2616349cc55cSDimitry Andric // Op0 - umax(X, Op0) --> 0 - usub.sat(X, Op0) 2617349cc55cSDimitry Andric if (match(Op1, m_OneUse(m_c_UMax(m_Value(X), m_Specific(Op0))))) { 2618349cc55cSDimitry Andric Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op0}); 2619349cc55cSDimitry Andric return BinaryOperator::CreateNeg(USub); 2620349cc55cSDimitry Andric } 2621349cc55cSDimitry Andric 262281ad6265SDimitry Andric // umin(X, Op1) - Op1 --> 0 - usub.sat(Op1, X) 262381ad6265SDimitry Andric if (match(Op0, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op1))))) { 262481ad6265SDimitry Andric Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op1, X}); 262581ad6265SDimitry Andric return BinaryOperator::CreateNeg(USub); 262681ad6265SDimitry Andric } 262781ad6265SDimitry Andric 2628fe6060f1SDimitry Andric // C - ctpop(X) => ctpop(~X) if C is bitwidth 2629bdd1243dSDimitry Andric if (match(Op0, m_SpecificInt(BitWidth)) && 2630fe6060f1SDimitry Andric match(Op1, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(X))))) 2631fe6060f1SDimitry Andric return replaceInstUsesWith( 2632fe6060f1SDimitry Andric I, Builder.CreateIntrinsic(Intrinsic::ctpop, {I.getType()}, 2633fe6060f1SDimitry Andric {Builder.CreateNot(X)})); 2634fe6060f1SDimitry Andric 2635bdd1243dSDimitry Andric // Reduce multiplies for difference-of-squares by factoring: 2636bdd1243dSDimitry Andric // (X * X) - (Y * Y) --> (X + Y) * (X - Y) 2637bdd1243dSDimitry Andric if (match(Op0, m_OneUse(m_Mul(m_Value(X), m_Deferred(X)))) && 2638bdd1243dSDimitry Andric match(Op1, m_OneUse(m_Mul(m_Value(Y), m_Deferred(Y))))) { 2639bdd1243dSDimitry Andric auto *OBO0 = cast<OverflowingBinaryOperator>(Op0); 2640bdd1243dSDimitry Andric auto *OBO1 = cast<OverflowingBinaryOperator>(Op1); 2641bdd1243dSDimitry Andric bool PropagateNSW = I.hasNoSignedWrap() && OBO0->hasNoSignedWrap() && 2642bdd1243dSDimitry Andric OBO1->hasNoSignedWrap() && BitWidth > 2; 2643bdd1243dSDimitry Andric bool PropagateNUW = I.hasNoUnsignedWrap() && OBO0->hasNoUnsignedWrap() && 2644bdd1243dSDimitry Andric OBO1->hasNoUnsignedWrap() && BitWidth > 1; 2645bdd1243dSDimitry Andric Value *Add = Builder.CreateAdd(X, Y, "add", PropagateNUW, PropagateNSW); 2646bdd1243dSDimitry Andric Value *Sub = Builder.CreateSub(X, Y, "sub", PropagateNUW, PropagateNSW); 2647bdd1243dSDimitry Andric Value *Mul = Builder.CreateMul(Add, Sub, "", PropagateNUW, PropagateNSW); 2648bdd1243dSDimitry Andric return replaceInstUsesWith(I, Mul); 2649bdd1243dSDimitry Andric } 2650bdd1243dSDimitry Andric 265106c3fb27SDimitry Andric // max(X,Y) nsw/nuw - min(X,Y) --> abs(X nsw - Y) 265206c3fb27SDimitry Andric if (match(Op0, m_OneUse(m_c_SMax(m_Value(X), m_Value(Y)))) && 265306c3fb27SDimitry Andric match(Op1, m_OneUse(m_c_SMin(m_Specific(X), m_Specific(Y))))) { 265406c3fb27SDimitry Andric if (I.hasNoUnsignedWrap() || I.hasNoSignedWrap()) { 265506c3fb27SDimitry Andric Value *Sub = 265606c3fb27SDimitry Andric Builder.CreateSub(X, Y, "sub", /*HasNUW=*/false, /*HasNSW=*/true); 265706c3fb27SDimitry Andric Value *Call = 265806c3fb27SDimitry Andric Builder.CreateBinaryIntrinsic(Intrinsic::abs, Sub, Builder.getTrue()); 265906c3fb27SDimitry Andric return replaceInstUsesWith(I, Call); 266006c3fb27SDimitry Andric } 266106c3fb27SDimitry Andric } 266206c3fb27SDimitry Andric 266306c3fb27SDimitry Andric if (Instruction *Res = foldBinOpOfSelectAndCastOfSelectCondition(I)) 266406c3fb27SDimitry Andric return Res; 266506c3fb27SDimitry Andric 26665ffd83dbSDimitry Andric return TryToNarrowDeduceFlags(); 26670b57cec5SDimitry Andric } 26680b57cec5SDimitry Andric 26690b57cec5SDimitry Andric /// This eliminates floating-point negation in either 'fneg(X)' or 26700b57cec5SDimitry Andric /// 'fsub(-0.0, X)' form by combining into a constant operand. 2671bdd1243dSDimitry Andric static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) { 2672fe6060f1SDimitry Andric // This is limited with one-use because fneg is assumed better for 2673fe6060f1SDimitry Andric // reassociation and cheaper in codegen than fmul/fdiv. 2674fe6060f1SDimitry Andric // TODO: Should the m_OneUse restriction be removed? 2675fe6060f1SDimitry Andric Instruction *FNegOp; 2676fe6060f1SDimitry Andric if (!match(&I, m_FNeg(m_OneUse(m_Instruction(FNegOp))))) 2677fe6060f1SDimitry Andric return nullptr; 2678fe6060f1SDimitry Andric 26790b57cec5SDimitry Andric Value *X; 26800b57cec5SDimitry Andric Constant *C; 26810b57cec5SDimitry Andric 2682fe6060f1SDimitry Andric // Fold negation into constant operand. 26830b57cec5SDimitry Andric // -(X * C) --> X * (-C) 2684fe6060f1SDimitry Andric if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C)))) 2685bdd1243dSDimitry Andric if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) 2686bdd1243dSDimitry Andric return BinaryOperator::CreateFMulFMF(X, NegC, &I); 26870b57cec5SDimitry Andric // -(X / C) --> X / (-C) 2688fe6060f1SDimitry Andric if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C)))) 2689bdd1243dSDimitry Andric if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) 2690bdd1243dSDimitry Andric return BinaryOperator::CreateFDivFMF(X, NegC, &I); 26910b57cec5SDimitry Andric // -(C / X) --> (-C) / X 2692bdd1243dSDimitry Andric if (match(FNegOp, m_FDiv(m_Constant(C), m_Value(X)))) 2693bdd1243dSDimitry Andric if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) { 2694bdd1243dSDimitry Andric Instruction *FDiv = BinaryOperator::CreateFDivFMF(NegC, X, &I); 26950b57cec5SDimitry Andric 2696bdd1243dSDimitry Andric // Intersect 'nsz' and 'ninf' because those special value exceptions may 2697bdd1243dSDimitry Andric // not apply to the fdiv. Everything else propagates from the fneg. 2698fe6060f1SDimitry Andric // TODO: We could propagate nsz/ninf from fdiv alone? 2699fe6060f1SDimitry Andric FastMathFlags FMF = I.getFastMathFlags(); 2700fe6060f1SDimitry Andric FastMathFlags OpFMF = FNegOp->getFastMathFlags(); 2701349cc55cSDimitry Andric FDiv->setHasNoSignedZeros(FMF.noSignedZeros() && OpFMF.noSignedZeros()); 2702349cc55cSDimitry Andric FDiv->setHasNoInfs(FMF.noInfs() && OpFMF.noInfs()); 2703fe6060f1SDimitry Andric return FDiv; 2704fe6060f1SDimitry Andric } 27055ffd83dbSDimitry Andric // With NSZ [ counter-example with -0.0: -(-0.0 + 0.0) != 0.0 + -0.0 ]: 27065ffd83dbSDimitry Andric // -(X + C) --> -X + -C --> -C - X 2707fe6060f1SDimitry Andric if (I.hasNoSignedZeros() && match(FNegOp, m_FAdd(m_Value(X), m_Constant(C)))) 2708bdd1243dSDimitry Andric if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) 2709bdd1243dSDimitry Andric return BinaryOperator::CreateFSubFMF(NegC, X, &I); 27105ffd83dbSDimitry Andric 27110b57cec5SDimitry Andric return nullptr; 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric 27145f757f3fSDimitry Andric Instruction *InstCombinerImpl::hoistFNegAboveFMulFDiv(Value *FNegOp, 27155f757f3fSDimitry Andric Instruction &FMFSource) { 27168bcb0991SDimitry Andric Value *X, *Y; 27175f757f3fSDimitry Andric if (match(FNegOp, m_FMul(m_Value(X), m_Value(Y)))) { 27185f757f3fSDimitry Andric return cast<Instruction>(Builder.CreateFMulFMF( 27195f757f3fSDimitry Andric Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource)); 27205f757f3fSDimitry Andric } 27218bcb0991SDimitry Andric 27225f757f3fSDimitry Andric if (match(FNegOp, m_FDiv(m_Value(X), m_Value(Y)))) { 27235f757f3fSDimitry Andric return cast<Instruction>(Builder.CreateFDivFMF( 27245f757f3fSDimitry Andric Builder.CreateFNegFMF(X, &FMFSource), Y, &FMFSource)); 27255f757f3fSDimitry Andric } 27265f757f3fSDimitry Andric 27275f757f3fSDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(FNegOp)) { 27285f757f3fSDimitry Andric // Make sure to preserve flags and metadata on the call. 27295f757f3fSDimitry Andric if (II->getIntrinsicID() == Intrinsic::ldexp) { 27305f757f3fSDimitry Andric FastMathFlags FMF = FMFSource.getFastMathFlags() | II->getFastMathFlags(); 27315f757f3fSDimitry Andric IRBuilder<>::FastMathFlagGuard FMFGuard(Builder); 27325f757f3fSDimitry Andric Builder.setFastMathFlags(FMF); 27335f757f3fSDimitry Andric 27345f757f3fSDimitry Andric CallInst *New = Builder.CreateCall( 27355f757f3fSDimitry Andric II->getCalledFunction(), 27365f757f3fSDimitry Andric {Builder.CreateFNeg(II->getArgOperand(0)), II->getArgOperand(1)}); 27375f757f3fSDimitry Andric New->copyMetadata(*II); 27385f757f3fSDimitry Andric return New; 27395f757f3fSDimitry Andric } 27405f757f3fSDimitry Andric } 27418bcb0991SDimitry Andric 27428bcb0991SDimitry Andric return nullptr; 27438bcb0991SDimitry Andric } 27448bcb0991SDimitry Andric 2745e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) { 27460b57cec5SDimitry Andric Value *Op = I.getOperand(0); 27470b57cec5SDimitry Andric 274881ad6265SDimitry Andric if (Value *V = simplifyFNegInst(Op, I.getFastMathFlags(), 2749e8d8bef9SDimitry Andric getSimplifyQuery().getWithInstruction(&I))) 27500b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 27510b57cec5SDimitry Andric 2752bdd1243dSDimitry Andric if (Instruction *X = foldFNegIntoConstant(I, DL)) 27530b57cec5SDimitry Andric return X; 27540b57cec5SDimitry Andric 27550b57cec5SDimitry Andric Value *X, *Y; 27560b57cec5SDimitry Andric 27570b57cec5SDimitry Andric // If we can ignore the sign of zeros: -(X - Y) --> (Y - X) 27580b57cec5SDimitry Andric if (I.hasNoSignedZeros() && 27590b57cec5SDimitry Andric match(Op, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) 27600b57cec5SDimitry Andric return BinaryOperator::CreateFSubFMF(Y, X, &I); 27610b57cec5SDimitry Andric 2762bdd1243dSDimitry Andric Value *OneUse; 2763bdd1243dSDimitry Andric if (!match(Op, m_OneUse(m_Value(OneUse)))) 2764bdd1243dSDimitry Andric return nullptr; 2765bdd1243dSDimitry Andric 27665f757f3fSDimitry Andric if (Instruction *R = hoistFNegAboveFMulFDiv(OneUse, I)) 27675f757f3fSDimitry Andric return replaceInstUsesWith(I, R); 27685f757f3fSDimitry Andric 2769fe6060f1SDimitry Andric // Try to eliminate fneg if at least 1 arm of the select is negated. 2770fe6060f1SDimitry Andric Value *Cond; 2771bdd1243dSDimitry Andric if (match(OneUse, m_Select(m_Value(Cond), m_Value(X), m_Value(Y)))) { 2772fe6060f1SDimitry Andric // Unlike most transforms, this one is not safe to propagate nsz unless 2773bdd1243dSDimitry Andric // it is present on the original select. We union the flags from the select 2774bdd1243dSDimitry Andric // and fneg and then remove nsz if needed. 277581ad6265SDimitry Andric auto propagateSelectFMF = [&](SelectInst *S, bool CommonOperand) { 2776fe6060f1SDimitry Andric S->copyFastMathFlags(&I); 2777bdd1243dSDimitry Andric if (auto *OldSel = dyn_cast<SelectInst>(Op)) { 27785f757f3fSDimitry Andric FastMathFlags FMF = I.getFastMathFlags() | OldSel->getFastMathFlags(); 2779bdd1243dSDimitry Andric S->setFastMathFlags(FMF); 278081ad6265SDimitry Andric if (!OldSel->hasNoSignedZeros() && !CommonOperand && 278181ad6265SDimitry Andric !isGuaranteedNotToBeUndefOrPoison(OldSel->getCondition())) 2782fe6060f1SDimitry Andric S->setHasNoSignedZeros(false); 2783bdd1243dSDimitry Andric } 2784fe6060f1SDimitry Andric }; 2785fe6060f1SDimitry Andric // -(Cond ? -P : Y) --> Cond ? P : -Y 2786fe6060f1SDimitry Andric Value *P; 2787fe6060f1SDimitry Andric if (match(X, m_FNeg(m_Value(P)))) { 2788fe6060f1SDimitry Andric Value *NegY = Builder.CreateFNegFMF(Y, &I, Y->getName() + ".neg"); 2789fe6060f1SDimitry Andric SelectInst *NewSel = SelectInst::Create(Cond, P, NegY); 279081ad6265SDimitry Andric propagateSelectFMF(NewSel, P == Y); 2791fe6060f1SDimitry Andric return NewSel; 2792fe6060f1SDimitry Andric } 2793fe6060f1SDimitry Andric // -(Cond ? X : -P) --> Cond ? -X : P 2794fe6060f1SDimitry Andric if (match(Y, m_FNeg(m_Value(P)))) { 2795fe6060f1SDimitry Andric Value *NegX = Builder.CreateFNegFMF(X, &I, X->getName() + ".neg"); 2796fe6060f1SDimitry Andric SelectInst *NewSel = SelectInst::Create(Cond, NegX, P); 279781ad6265SDimitry Andric propagateSelectFMF(NewSel, P == X); 2798fe6060f1SDimitry Andric return NewSel; 2799fe6060f1SDimitry Andric } 2800*0fca6ea1SDimitry Andric 2801*0fca6ea1SDimitry Andric // -(Cond ? X : C) --> Cond ? -X : -C 2802*0fca6ea1SDimitry Andric // -(Cond ? C : Y) --> Cond ? -C : -Y 2803*0fca6ea1SDimitry Andric if (match(X, m_ImmConstant()) || match(Y, m_ImmConstant())) { 2804*0fca6ea1SDimitry Andric Value *NegX = Builder.CreateFNegFMF(X, &I, X->getName() + ".neg"); 2805*0fca6ea1SDimitry Andric Value *NegY = Builder.CreateFNegFMF(Y, &I, Y->getName() + ".neg"); 2806*0fca6ea1SDimitry Andric SelectInst *NewSel = SelectInst::Create(Cond, NegX, NegY); 2807*0fca6ea1SDimitry Andric propagateSelectFMF(NewSel, /*CommonOperand=*/true); 2808*0fca6ea1SDimitry Andric return NewSel; 2809*0fca6ea1SDimitry Andric } 2810fe6060f1SDimitry Andric } 2811fe6060f1SDimitry Andric 2812bdd1243dSDimitry Andric // fneg (copysign x, y) -> copysign x, (fneg y) 2813bdd1243dSDimitry Andric if (match(OneUse, m_CopySign(m_Value(X), m_Value(Y)))) { 2814bdd1243dSDimitry Andric // The source copysign has an additional value input, so we can't propagate 2815bdd1243dSDimitry Andric // flags the copysign doesn't also have. 2816bdd1243dSDimitry Andric FastMathFlags FMF = I.getFastMathFlags(); 2817bdd1243dSDimitry Andric FMF &= cast<FPMathOperator>(OneUse)->getFastMathFlags(); 2818bdd1243dSDimitry Andric 2819bdd1243dSDimitry Andric IRBuilder<>::FastMathFlagGuard FMFGuard(Builder); 2820bdd1243dSDimitry Andric Builder.setFastMathFlags(FMF); 2821bdd1243dSDimitry Andric 2822bdd1243dSDimitry Andric Value *NegY = Builder.CreateFNeg(Y); 2823bdd1243dSDimitry Andric Value *NewCopySign = Builder.CreateCopySign(X, NegY); 2824bdd1243dSDimitry Andric return replaceInstUsesWith(I, NewCopySign); 2825bdd1243dSDimitry Andric } 2826bdd1243dSDimitry Andric 28270b57cec5SDimitry Andric return nullptr; 28280b57cec5SDimitry Andric } 28290b57cec5SDimitry Andric 2830e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) { 283181ad6265SDimitry Andric if (Value *V = simplifyFSubInst(I.getOperand(0), I.getOperand(1), 28320b57cec5SDimitry Andric I.getFastMathFlags(), 2833e8d8bef9SDimitry Andric getSimplifyQuery().getWithInstruction(&I))) 28340b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric if (Instruction *X = foldVectorBinop(I)) 28370b57cec5SDimitry Andric return X; 28380b57cec5SDimitry Andric 283904eeddc0SDimitry Andric if (Instruction *Phi = foldBinopWithPhiOperands(I)) 284004eeddc0SDimitry Andric return Phi; 284104eeddc0SDimitry Andric 28420b57cec5SDimitry Andric // Subtraction from -0.0 is the canonical form of fneg. 28435ffd83dbSDimitry Andric // fsub -0.0, X ==> fneg X 28445ffd83dbSDimitry Andric // fsub nsz 0.0, X ==> fneg nsz X 28455ffd83dbSDimitry Andric // 28465ffd83dbSDimitry Andric // FIXME This matcher does not respect FTZ or DAZ yet: 28475ffd83dbSDimitry Andric // fsub -0.0, Denorm ==> +-0 28485ffd83dbSDimitry Andric // fneg Denorm ==> -Denorm 28495ffd83dbSDimitry Andric Value *Op; 28505ffd83dbSDimitry Andric if (match(&I, m_FNeg(m_Value(Op)))) 28515ffd83dbSDimitry Andric return UnaryOperator::CreateFNegFMF(Op, &I); 28520b57cec5SDimitry Andric 2853bdd1243dSDimitry Andric if (Instruction *X = foldFNegIntoConstant(I, DL)) 28540b57cec5SDimitry Andric return X; 28550b57cec5SDimitry Andric 2856*0fca6ea1SDimitry Andric if (Instruction *R = foldFBinOpOfIntCasts(I)) 2857*0fca6ea1SDimitry Andric return R; 2858*0fca6ea1SDimitry Andric 28590b57cec5SDimitry Andric Value *X, *Y; 28600b57cec5SDimitry Andric Constant *C; 28610b57cec5SDimitry Andric 28625ffd83dbSDimitry Andric Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); 28630b57cec5SDimitry Andric // If Op0 is not -0.0 or we can ignore -0.0: Z - (X - Y) --> Z + (Y - X) 28640b57cec5SDimitry Andric // Canonicalize to fadd to make analysis easier. 28650b57cec5SDimitry Andric // This can also help codegen because fadd is commutative. 28660b57cec5SDimitry Andric // Note that if this fsub was really an fneg, the fadd with -0.0 will get 28670b57cec5SDimitry Andric // killed later. We still limit that particular transform with 'hasOneUse' 28680b57cec5SDimitry Andric // because an fneg is assumed better/cheaper than a generic fsub. 2869*0fca6ea1SDimitry Andric if (I.hasNoSignedZeros() || 2870*0fca6ea1SDimitry Andric cannotBeNegativeZero(Op0, 0, getSimplifyQuery().getWithInstruction(&I))) { 28710b57cec5SDimitry Andric if (match(Op1, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) { 28720b57cec5SDimitry Andric Value *NewSub = Builder.CreateFSubFMF(Y, X, &I); 28730b57cec5SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, NewSub, &I); 28740b57cec5SDimitry Andric } 28750b57cec5SDimitry Andric } 28760b57cec5SDimitry Andric 28775ffd83dbSDimitry Andric // (-X) - Op1 --> -(X + Op1) 28785ffd83dbSDimitry Andric if (I.hasNoSignedZeros() && !isa<ConstantExpr>(Op0) && 28795ffd83dbSDimitry Andric match(Op0, m_OneUse(m_FNeg(m_Value(X))))) { 28805ffd83dbSDimitry Andric Value *FAdd = Builder.CreateFAddFMF(X, Op1, &I); 28815ffd83dbSDimitry Andric return UnaryOperator::CreateFNegFMF(FAdd, &I); 28825ffd83dbSDimitry Andric } 28835ffd83dbSDimitry Andric 28840b57cec5SDimitry Andric if (isa<Constant>(Op0)) 28850b57cec5SDimitry Andric if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) 28860b57cec5SDimitry Andric if (Instruction *NV = FoldOpIntoSelect(I, SI)) 28870b57cec5SDimitry Andric return NV; 28880b57cec5SDimitry Andric 28890b57cec5SDimitry Andric // X - C --> X + (-C) 28900b57cec5SDimitry Andric // But don't transform constant expressions because there's an inverse fold 28910b57cec5SDimitry Andric // for X + (-Y) --> X - Y. 2892e8d8bef9SDimitry Andric if (match(Op1, m_ImmConstant(C))) 2893bdd1243dSDimitry Andric if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) 2894bdd1243dSDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, NegC, &I); 28950b57cec5SDimitry Andric 28960b57cec5SDimitry Andric // X - (-Y) --> X + Y 28970b57cec5SDimitry Andric if (match(Op1, m_FNeg(m_Value(Y)))) 28980b57cec5SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, Y, &I); 28990b57cec5SDimitry Andric 29000b57cec5SDimitry Andric // Similar to above, but look through a cast of the negated value: 29010b57cec5SDimitry Andric // X - (fptrunc(-Y)) --> X + fptrunc(Y) 29020b57cec5SDimitry Andric Type *Ty = I.getType(); 29030b57cec5SDimitry Andric if (match(Op1, m_OneUse(m_FPTrunc(m_FNeg(m_Value(Y)))))) 29040b57cec5SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPTrunc(Y, Ty), &I); 29050b57cec5SDimitry Andric 29060b57cec5SDimitry Andric // X - (fpext(-Y)) --> X + fpext(Y) 29070b57cec5SDimitry Andric if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y)))))) 29080b57cec5SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPExt(Y, Ty), &I); 29090b57cec5SDimitry Andric 29108bcb0991SDimitry Andric // Similar to above, but look through fmul/fdiv of the negated value: 29118bcb0991SDimitry Andric // Op0 - (-X * Y) --> Op0 + (X * Y) 29128bcb0991SDimitry Andric // Op0 - (Y * -X) --> Op0 + (X * Y) 29138bcb0991SDimitry Andric if (match(Op1, m_OneUse(m_c_FMul(m_FNeg(m_Value(X)), m_Value(Y))))) { 29148bcb0991SDimitry Andric Value *FMul = Builder.CreateFMulFMF(X, Y, &I); 29158bcb0991SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, FMul, &I); 29168bcb0991SDimitry Andric } 29178bcb0991SDimitry Andric // Op0 - (-X / Y) --> Op0 + (X / Y) 29188bcb0991SDimitry Andric // Op0 - (X / -Y) --> Op0 + (X / Y) 29198bcb0991SDimitry Andric if (match(Op1, m_OneUse(m_FDiv(m_FNeg(m_Value(X)), m_Value(Y)))) || 29208bcb0991SDimitry Andric match(Op1, m_OneUse(m_FDiv(m_Value(X), m_FNeg(m_Value(Y)))))) { 29218bcb0991SDimitry Andric Value *FDiv = Builder.CreateFDivFMF(X, Y, &I); 29228bcb0991SDimitry Andric return BinaryOperator::CreateFAddFMF(Op0, FDiv, &I); 29238bcb0991SDimitry Andric } 29248bcb0991SDimitry Andric 29250b57cec5SDimitry Andric // Handle special cases for FSub with selects feeding the operation 29260b57cec5SDimitry Andric if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) 29270b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 29280b57cec5SDimitry Andric 29290b57cec5SDimitry Andric if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { 29300b57cec5SDimitry Andric // (Y - X) - Y --> -X 29310b57cec5SDimitry Andric if (match(Op0, m_FSub(m_Specific(Op1), m_Value(X)))) 29325ffd83dbSDimitry Andric return UnaryOperator::CreateFNegFMF(X, &I); 29330b57cec5SDimitry Andric 29340b57cec5SDimitry Andric // Y - (X + Y) --> -X 29350b57cec5SDimitry Andric // Y - (Y + X) --> -X 29360b57cec5SDimitry Andric if (match(Op1, m_c_FAdd(m_Specific(Op0), m_Value(X)))) 29375ffd83dbSDimitry Andric return UnaryOperator::CreateFNegFMF(X, &I); 29380b57cec5SDimitry Andric 29390b57cec5SDimitry Andric // (X * C) - X --> X * (C - 1.0) 29400b57cec5SDimitry Andric if (match(Op0, m_FMul(m_Specific(Op1), m_Constant(C)))) { 2941753f127fSDimitry Andric if (Constant *CSubOne = ConstantFoldBinaryOpOperands( 2942753f127fSDimitry Andric Instruction::FSub, C, ConstantFP::get(Ty, 1.0), DL)) 29430b57cec5SDimitry Andric return BinaryOperator::CreateFMulFMF(Op1, CSubOne, &I); 29440b57cec5SDimitry Andric } 29450b57cec5SDimitry Andric // X - (X * C) --> X * (1.0 - C) 29460b57cec5SDimitry Andric if (match(Op1, m_FMul(m_Specific(Op0), m_Constant(C)))) { 2947753f127fSDimitry Andric if (Constant *OneSubC = ConstantFoldBinaryOpOperands( 2948753f127fSDimitry Andric Instruction::FSub, ConstantFP::get(Ty, 1.0), C, DL)) 29490b57cec5SDimitry Andric return BinaryOperator::CreateFMulFMF(Op0, OneSubC, &I); 29500b57cec5SDimitry Andric } 29510b57cec5SDimitry Andric 29525ffd83dbSDimitry Andric // Reassociate fsub/fadd sequences to create more fadd instructions and 29535ffd83dbSDimitry Andric // reduce dependency chains: 29545ffd83dbSDimitry Andric // ((X - Y) + Z) - Op1 --> (X + Z) - (Y + Op1) 29555ffd83dbSDimitry Andric Value *Z; 29565ffd83dbSDimitry Andric if (match(Op0, m_OneUse(m_c_FAdd(m_OneUse(m_FSub(m_Value(X), m_Value(Y))), 29575ffd83dbSDimitry Andric m_Value(Z))))) { 29585ffd83dbSDimitry Andric Value *XZ = Builder.CreateFAddFMF(X, Z, &I); 29595ffd83dbSDimitry Andric Value *YW = Builder.CreateFAddFMF(Y, Op1, &I); 29605ffd83dbSDimitry Andric return BinaryOperator::CreateFSubFMF(XZ, YW, &I); 29615ffd83dbSDimitry Andric } 29625ffd83dbSDimitry Andric 29635ffd83dbSDimitry Andric auto m_FaddRdx = [](Value *&Sum, Value *&Vec) { 2964e8d8bef9SDimitry Andric return m_OneUse(m_Intrinsic<Intrinsic::vector_reduce_fadd>(m_Value(Sum), 2965e8d8bef9SDimitry Andric m_Value(Vec))); 29665ffd83dbSDimitry Andric }; 29675ffd83dbSDimitry Andric Value *A0, *A1, *V0, *V1; 29685ffd83dbSDimitry Andric if (match(Op0, m_FaddRdx(A0, V0)) && match(Op1, m_FaddRdx(A1, V1)) && 29695ffd83dbSDimitry Andric V0->getType() == V1->getType()) { 29705ffd83dbSDimitry Andric // Difference of sums is sum of differences: 29715ffd83dbSDimitry Andric // add_rdx(A0, V0) - add_rdx(A1, V1) --> add_rdx(A0, V0 - V1) - A1 29725ffd83dbSDimitry Andric Value *Sub = Builder.CreateFSubFMF(V0, V1, &I); 2973e8d8bef9SDimitry Andric Value *Rdx = Builder.CreateIntrinsic(Intrinsic::vector_reduce_fadd, 2974e8d8bef9SDimitry Andric {Sub->getType()}, {A0, Sub}, &I); 29755ffd83dbSDimitry Andric return BinaryOperator::CreateFSubFMF(Rdx, A1, &I); 29765ffd83dbSDimitry Andric } 29775ffd83dbSDimitry Andric 29780b57cec5SDimitry Andric if (Instruction *F = factorizeFAddFSub(I, Builder)) 29790b57cec5SDimitry Andric return F; 29800b57cec5SDimitry Andric 29810b57cec5SDimitry Andric // TODO: This performs reassociative folds for FP ops. Some fraction of the 29820b57cec5SDimitry Andric // functionality has been subsumed by simple pattern matching here and in 29830b57cec5SDimitry Andric // InstSimplify. We should let a dedicated reassociation pass handle more 29840b57cec5SDimitry Andric // complex pattern matching and remove this from InstCombine. 29850b57cec5SDimitry Andric if (Value *V = FAddCombine(Builder).simplify(&I)) 29860b57cec5SDimitry Andric return replaceInstUsesWith(I, V); 29875ffd83dbSDimitry Andric 29885ffd83dbSDimitry Andric // (X - Y) - Op1 --> X - (Y + Op1) 29895ffd83dbSDimitry Andric if (match(Op0, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) { 29905ffd83dbSDimitry Andric Value *FAdd = Builder.CreateFAddFMF(Y, Op1, &I); 29915ffd83dbSDimitry Andric return BinaryOperator::CreateFSubFMF(X, FAdd, &I); 29925ffd83dbSDimitry Andric } 29930b57cec5SDimitry Andric } 29940b57cec5SDimitry Andric 29950b57cec5SDimitry Andric return nullptr; 29960b57cec5SDimitry Andric } 2997