10b57cec5SDimitry Andric //===- InstCombineCalls.cpp -----------------------------------------------===// 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 visitCall, visitInvoke, and visitCallBr functions. 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/APSInt.h" 170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 1881ad6265SDimitry Andric #include "llvm/ADT/STLFunctionalExtras.h" 19fe6060f1SDimitry Andric #include "llvm/ADT/SmallBitVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 210b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 225ffd83dbSDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 235ffd83dbSDimitry Andric #include "llvm/Analysis/AssumeBundleQueries.h" 240b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 260b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h" 270b57cec5SDimitry Andric #include "llvm/Analysis/MemoryBuiltins.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/VectorUtils.h" 3006c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h" 310b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 320b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 330b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 340b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 350b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 36bdd1243dSDimitry Andric #include "llvm/IR/DebugInfo.h" 370b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 380b57cec5SDimitry Andric #include "llvm/IR/Function.h" 390b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 40fe6060f1SDimitry Andric #include "llvm/IR/InlineAsm.h" 410b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 420b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 430b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 440b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 450b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 46480093f4SDimitry Andric #include "llvm/IR/IntrinsicsAArch64.h" 47480093f4SDimitry Andric #include "llvm/IR/IntrinsicsAMDGPU.h" 485ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicsARM.h" 495ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicsHexagon.h" 500b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 510b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 520b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h" 530b57cec5SDimitry Andric #include "llvm/IR/Statepoint.h" 540b57cec5SDimitry Andric #include "llvm/IR/Type.h" 550b57cec5SDimitry Andric #include "llvm/IR/User.h" 560b57cec5SDimitry Andric #include "llvm/IR/Value.h" 570b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h" 580b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h" 590b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 600b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 610b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 620b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 630b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 640b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 650b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 660b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 67e8d8bef9SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombiner.h" 68fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" 690b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 700b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SimplifyLibCalls.h" 710b57cec5SDimitry Andric #include <algorithm> 720b57cec5SDimitry Andric #include <cassert> 730b57cec5SDimitry Andric #include <cstdint> 74bdd1243dSDimitry Andric #include <optional> 750b57cec5SDimitry Andric #include <utility> 760b57cec5SDimitry Andric #include <vector> 770b57cec5SDimitry Andric 78349cc55cSDimitry Andric #define DEBUG_TYPE "instcombine" 79349cc55cSDimitry Andric #include "llvm/Transforms/Utils/InstructionWorklist.h" 80349cc55cSDimitry Andric 810b57cec5SDimitry Andric using namespace llvm; 820b57cec5SDimitry Andric using namespace PatternMatch; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric STATISTIC(NumSimplified, "Number of library calls simplified"); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric static cl::opt<unsigned> GuardWideningWindow( 870b57cec5SDimitry Andric "instcombine-guard-widening-window", 880b57cec5SDimitry Andric cl::init(3), 890b57cec5SDimitry Andric cl::desc("How wide an instruction window to bypass looking for " 900b57cec5SDimitry Andric "another guard")); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Return the specified type promoted as it would be to pass though a va_arg 930b57cec5SDimitry Andric /// area. 940b57cec5SDimitry Andric static Type *getPromotedType(Type *Ty) { 950b57cec5SDimitry Andric if (IntegerType* ITy = dyn_cast<IntegerType>(Ty)) { 960b57cec5SDimitry Andric if (ITy->getBitWidth() < 32) 970b57cec5SDimitry Andric return Type::getInt32Ty(Ty->getContext()); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric return Ty; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 10281ad6265SDimitry Andric /// Recognize a memcpy/memmove from a trivially otherwise unused alloca. 10381ad6265SDimitry Andric /// TODO: This should probably be integrated with visitAllocSites, but that 10481ad6265SDimitry Andric /// requires a deeper change to allow either unread or unwritten objects. 10581ad6265SDimitry Andric static bool hasUndefSource(AnyMemTransferInst *MI) { 10681ad6265SDimitry Andric auto *Src = MI->getRawSource(); 10781ad6265SDimitry Andric while (isa<GetElementPtrInst>(Src) || isa<BitCastInst>(Src)) { 10881ad6265SDimitry Andric if (!Src->hasOneUse()) 10981ad6265SDimitry Andric return false; 11081ad6265SDimitry Andric Src = cast<Instruction>(Src)->getOperand(0); 11181ad6265SDimitry Andric } 11281ad6265SDimitry Andric return isa<AllocaInst>(Src) && Src->hasOneUse(); 11381ad6265SDimitry Andric } 11481ad6265SDimitry Andric 115e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) { 1165ffd83dbSDimitry Andric Align DstAlign = getKnownAlignment(MI->getRawDest(), DL, MI, &AC, &DT); 1175ffd83dbSDimitry Andric MaybeAlign CopyDstAlign = MI->getDestAlign(); 1185ffd83dbSDimitry Andric if (!CopyDstAlign || *CopyDstAlign < DstAlign) { 1190b57cec5SDimitry Andric MI->setDestAlignment(DstAlign); 1200b57cec5SDimitry Andric return MI; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1235ffd83dbSDimitry Andric Align SrcAlign = getKnownAlignment(MI->getRawSource(), DL, MI, &AC, &DT); 1245ffd83dbSDimitry Andric MaybeAlign CopySrcAlign = MI->getSourceAlign(); 1255ffd83dbSDimitry Andric if (!CopySrcAlign || *CopySrcAlign < SrcAlign) { 1260b57cec5SDimitry Andric MI->setSourceAlignment(SrcAlign); 1270b57cec5SDimitry Andric return MI; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // If we have a store to a location which is known constant, we can conclude 1310b57cec5SDimitry Andric // that the store must be storing the constant value (else the memory 1320b57cec5SDimitry Andric // wouldn't be constant), and this must be a noop. 133bdd1243dSDimitry Andric if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) { 1340b57cec5SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 1350b57cec5SDimitry Andric MI->setLength(Constant::getNullValue(MI->getLength()->getType())); 1360b57cec5SDimitry Andric return MI; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 13981ad6265SDimitry Andric // If the source is provably undef, the memcpy/memmove doesn't do anything 14081ad6265SDimitry Andric // (unless the transfer is volatile). 14181ad6265SDimitry Andric if (hasUndefSource(MI) && !MI->isVolatile()) { 14281ad6265SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 14381ad6265SDimitry Andric MI->setLength(Constant::getNullValue(MI->getLength()->getType())); 14481ad6265SDimitry Andric return MI; 14581ad6265SDimitry Andric } 14681ad6265SDimitry Andric 1470b57cec5SDimitry Andric // If MemCpyInst length is 1/2/4/8 bytes then replace memcpy with 1480b57cec5SDimitry Andric // load/store. 1490b57cec5SDimitry Andric ConstantInt *MemOpLength = dyn_cast<ConstantInt>(MI->getLength()); 1500b57cec5SDimitry Andric if (!MemOpLength) return nullptr; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Source and destination pointer types are always "i8*" for intrinsic. See 1530b57cec5SDimitry Andric // if the size is something we can handle with a single primitive load/store. 1540b57cec5SDimitry Andric // A single load+store correctly handles overlapping memory in the memmove 1550b57cec5SDimitry Andric // case. 1560b57cec5SDimitry Andric uint64_t Size = MemOpLength->getLimitedValue(); 1570b57cec5SDimitry Andric assert(Size && "0-sized memory transferring should be removed already."); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric if (Size > 8 || (Size&(Size-1))) 1600b57cec5SDimitry Andric return nullptr; // If not 1/2/4/8 bytes, exit. 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // If it is an atomic and alignment is less than the size then we will 1630b57cec5SDimitry Andric // introduce the unaligned memory access which will be later transformed 1640b57cec5SDimitry Andric // into libcall in CodeGen. This is not evident performance gain so disable 1650b57cec5SDimitry Andric // it now. 1660b57cec5SDimitry Andric if (isa<AtomicMemTransferInst>(MI)) 1675ffd83dbSDimitry Andric if (*CopyDstAlign < Size || *CopySrcAlign < Size) 1680b57cec5SDimitry Andric return nullptr; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Use an integer load+store unless we can find something better. 1710b57cec5SDimitry Andric IntegerType* IntType = IntegerType::get(MI->getContext(), Size<<3); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // If the memcpy has metadata describing the members, see if we can get the 17462987288SDimitry Andric // TBAA, scope and noalias tags describing our copy. 1750fca6ea1SDimitry Andric AAMDNodes AACopyMD = MI->getAAMetadata().adjustForAccess(Size); 1760b57cec5SDimitry Andric 1775f757f3fSDimitry Andric Value *Src = MI->getArgOperand(1); 1785f757f3fSDimitry Andric Value *Dest = MI->getArgOperand(0); 1790b57cec5SDimitry Andric LoadInst *L = Builder.CreateLoad(IntType, Src); 1800b57cec5SDimitry Andric // Alignment from the mem intrinsic will be better, so use it. 1815ffd83dbSDimitry Andric L->setAlignment(*CopySrcAlign); 1821db9f3b2SDimitry Andric L->setAAMetadata(AACopyMD); 1830b57cec5SDimitry Andric MDNode *LoopMemParallelMD = 1840b57cec5SDimitry Andric MI->getMetadata(LLVMContext::MD_mem_parallel_loop_access); 1850b57cec5SDimitry Andric if (LoopMemParallelMD) 1860b57cec5SDimitry Andric L->setMetadata(LLVMContext::MD_mem_parallel_loop_access, LoopMemParallelMD); 1870b57cec5SDimitry Andric MDNode *AccessGroupMD = MI->getMetadata(LLVMContext::MD_access_group); 1880b57cec5SDimitry Andric if (AccessGroupMD) 1890b57cec5SDimitry Andric L->setMetadata(LLVMContext::MD_access_group, AccessGroupMD); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric StoreInst *S = Builder.CreateStore(L, Dest); 1920b57cec5SDimitry Andric // Alignment from the mem intrinsic will be better, so use it. 1935ffd83dbSDimitry Andric S->setAlignment(*CopyDstAlign); 1941db9f3b2SDimitry Andric S->setAAMetadata(AACopyMD); 1950b57cec5SDimitry Andric if (LoopMemParallelMD) 1960b57cec5SDimitry Andric S->setMetadata(LLVMContext::MD_mem_parallel_loop_access, LoopMemParallelMD); 1970b57cec5SDimitry Andric if (AccessGroupMD) 1980b57cec5SDimitry Andric S->setMetadata(LLVMContext::MD_access_group, AccessGroupMD); 199bdd1243dSDimitry Andric S->copyMetadata(*MI, LLVMContext::MD_DIAssignID); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric if (auto *MT = dyn_cast<MemTransferInst>(MI)) { 2020b57cec5SDimitry Andric // non-atomics can be volatile 2030b57cec5SDimitry Andric L->setVolatile(MT->isVolatile()); 2040b57cec5SDimitry Andric S->setVolatile(MT->isVolatile()); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric if (isa<AtomicMemTransferInst>(MI)) { 2070b57cec5SDimitry Andric // atomics have to be unordered 2080b57cec5SDimitry Andric L->setOrdering(AtomicOrdering::Unordered); 2090b57cec5SDimitry Andric S->setOrdering(AtomicOrdering::Unordered); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 2130b57cec5SDimitry Andric MI->setLength(Constant::getNullValue(MemOpLength->getType())); 2140b57cec5SDimitry Andric return MI; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 217e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) { 2185ffd83dbSDimitry Andric const Align KnownAlignment = 2198bcb0991SDimitry Andric getKnownAlignment(MI->getDest(), DL, MI, &AC, &DT); 2205ffd83dbSDimitry Andric MaybeAlign MemSetAlign = MI->getDestAlign(); 2215ffd83dbSDimitry Andric if (!MemSetAlign || *MemSetAlign < KnownAlignment) { 2228bcb0991SDimitry Andric MI->setDestAlignment(KnownAlignment); 2230b57cec5SDimitry Andric return MI; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // If we have a store to a location which is known constant, we can conclude 2270b57cec5SDimitry Andric // that the store must be storing the constant value (else the memory 2280b57cec5SDimitry Andric // wouldn't be constant), and this must be a noop. 229bdd1243dSDimitry Andric if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) { 2300b57cec5SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 2310b57cec5SDimitry Andric MI->setLength(Constant::getNullValue(MI->getLength()->getType())); 2320b57cec5SDimitry Andric return MI; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 23581ad6265SDimitry Andric // Remove memset with an undef value. 23681ad6265SDimitry Andric // FIXME: This is technically incorrect because it might overwrite a poison 23781ad6265SDimitry Andric // value. Change to PoisonValue once #52930 is resolved. 23881ad6265SDimitry Andric if (isa<UndefValue>(MI->getValue())) { 23981ad6265SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 24081ad6265SDimitry Andric MI->setLength(Constant::getNullValue(MI->getLength()->getType())); 24181ad6265SDimitry Andric return MI; 24281ad6265SDimitry Andric } 24381ad6265SDimitry Andric 2440b57cec5SDimitry Andric // Extract the length and alignment and fill if they are constant. 2450b57cec5SDimitry Andric ConstantInt *LenC = dyn_cast<ConstantInt>(MI->getLength()); 2460b57cec5SDimitry Andric ConstantInt *FillC = dyn_cast<ConstantInt>(MI->getValue()); 2470b57cec5SDimitry Andric if (!LenC || !FillC || !FillC->getType()->isIntegerTy(8)) 2480b57cec5SDimitry Andric return nullptr; 2498bcb0991SDimitry Andric const uint64_t Len = LenC->getLimitedValue(); 2500b57cec5SDimitry Andric assert(Len && "0-sized memory setting should be removed already."); 25181ad6265SDimitry Andric const Align Alignment = MI->getDestAlign().valueOrOne(); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric // If it is an atomic and alignment is less than the size then we will 2540b57cec5SDimitry Andric // introduce the unaligned memory access which will be later transformed 2550b57cec5SDimitry Andric // into libcall in CodeGen. This is not evident performance gain so disable 2560b57cec5SDimitry Andric // it now. 2570b57cec5SDimitry Andric if (isa<AtomicMemSetInst>(MI)) 2580b57cec5SDimitry Andric if (Alignment < Len) 2590b57cec5SDimitry Andric return nullptr; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric // memset(s,c,n) -> store s, c (for n=1,2,4,8) 2620b57cec5SDimitry Andric if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) { 2630b57cec5SDimitry Andric Type *ITy = IntegerType::get(MI->getContext(), Len*8); // n=1 -> i8. 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric Value *Dest = MI->getDest(); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // Extract the fill value and store. 268bdd1243dSDimitry Andric const uint64_t Fill = FillC->getZExtValue()*0x0101010101010101ULL; 269bdd1243dSDimitry Andric Constant *FillVal = ConstantInt::get(ITy, Fill); 270bdd1243dSDimitry Andric StoreInst *S = Builder.CreateStore(FillVal, Dest, MI->isVolatile()); 271bdd1243dSDimitry Andric S->copyMetadata(*MI, LLVMContext::MD_DIAssignID); 2727a6dacacSDimitry Andric auto replaceOpForAssignmentMarkers = [FillC, FillVal](auto *DbgAssign) { 2737a6dacacSDimitry Andric if (llvm::is_contained(DbgAssign->location_ops(), FillC)) 2747a6dacacSDimitry Andric DbgAssign->replaceVariableLocationOp(FillC, FillVal); 2757a6dacacSDimitry Andric }; 2767a6dacacSDimitry Andric for_each(at::getAssignmentMarkers(S), replaceOpForAssignmentMarkers); 2770fca6ea1SDimitry Andric for_each(at::getDVRAssignmentMarkers(S), replaceOpForAssignmentMarkers); 278bdd1243dSDimitry Andric 2790b57cec5SDimitry Andric S->setAlignment(Alignment); 2800b57cec5SDimitry Andric if (isa<AtomicMemSetInst>(MI)) 2810b57cec5SDimitry Andric S->setOrdering(AtomicOrdering::Unordered); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric // Set the size of the copy to 0, it will be deleted on the next iteration. 2840b57cec5SDimitry Andric MI->setLength(Constant::getNullValue(LenC->getType())); 2850b57cec5SDimitry Andric return MI; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric return nullptr; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // TODO, Obvious Missing Transforms: 2920b57cec5SDimitry Andric // * Narrow width by halfs excluding zero/undef lanes 293e8d8bef9SDimitry Andric Value *InstCombinerImpl::simplifyMaskedLoad(IntrinsicInst &II) { 2940b57cec5SDimitry Andric Value *LoadPtr = II.getArgOperand(0); 2955ffd83dbSDimitry Andric const Align Alignment = 2965ffd83dbSDimitry Andric cast<ConstantInt>(II.getArgOperand(1))->getAlignValue(); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // If the mask is all ones or undefs, this is a plain vector load of the 1st 2990b57cec5SDimitry Andric // argument. 300fe6060f1SDimitry Andric if (maskIsAllOneOrUndef(II.getArgOperand(2))) { 301fe6060f1SDimitry Andric LoadInst *L = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment, 3020b57cec5SDimitry Andric "unmaskedload"); 303fe6060f1SDimitry Andric L->copyMetadata(II); 304fe6060f1SDimitry Andric return L; 305fe6060f1SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // If we can unconditionally load from this address, replace with a 3080b57cec5SDimitry Andric // load/select idiom. TODO: use DT for context sensitive query 309e8d8bef9SDimitry Andric if (isDereferenceablePointer(LoadPtr, II.getType(), 3100fca6ea1SDimitry Andric II.getDataLayout(), &II, &AC)) { 311fe6060f1SDimitry Andric LoadInst *LI = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment, 3120b57cec5SDimitry Andric "unmaskedload"); 313fe6060f1SDimitry Andric LI->copyMetadata(II); 3140b57cec5SDimitry Andric return Builder.CreateSelect(II.getArgOperand(2), LI, II.getArgOperand(3)); 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric return nullptr; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric // TODO, Obvious Missing Transforms: 3210b57cec5SDimitry Andric // * Single constant active lane -> store 3220b57cec5SDimitry Andric // * Narrow width by halfs excluding zero/undef lanes 323e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) { 3240b57cec5SDimitry Andric auto *ConstMask = dyn_cast<Constant>(II.getArgOperand(3)); 3250b57cec5SDimitry Andric if (!ConstMask) 3260b57cec5SDimitry Andric return nullptr; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // If the mask is all zeros, this instruction does nothing. 3290b57cec5SDimitry Andric if (ConstMask->isNullValue()) 3300b57cec5SDimitry Andric return eraseInstFromFunction(II); 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric // If the mask is all ones, this is a plain vector store of the 1st argument. 3330b57cec5SDimitry Andric if (ConstMask->isAllOnesValue()) { 3340b57cec5SDimitry Andric Value *StorePtr = II.getArgOperand(1); 3355ffd83dbSDimitry Andric Align Alignment = cast<ConstantInt>(II.getArgOperand(2))->getAlignValue(); 336fe6060f1SDimitry Andric StoreInst *S = 337fe6060f1SDimitry Andric new StoreInst(II.getArgOperand(0), StorePtr, false, Alignment); 338fe6060f1SDimitry Andric S->copyMetadata(II); 339fe6060f1SDimitry Andric return S; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 342e8d8bef9SDimitry Andric if (isa<ScalableVectorType>(ConstMask->getType())) 343e8d8bef9SDimitry Andric return nullptr; 344e8d8bef9SDimitry Andric 3450b57cec5SDimitry Andric // Use masked off lanes to simplify operands via SimplifyDemandedVectorElts 3460b57cec5SDimitry Andric APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask); 347cb14a3feSDimitry Andric APInt PoisonElts(DemandedElts.getBitWidth(), 0); 348cb14a3feSDimitry Andric if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, 349cb14a3feSDimitry Andric PoisonElts)) 3505ffd83dbSDimitry Andric return replaceOperand(II, 0, V); 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric return nullptr; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric // TODO, Obvious Missing Transforms: 3560b57cec5SDimitry Andric // * Single constant active lane load -> load 3570b57cec5SDimitry Andric // * Dereferenceable address & few lanes -> scalarize speculative load/selects 3580b57cec5SDimitry Andric // * Adjacent vector addresses -> masked.load 3590b57cec5SDimitry Andric // * Narrow width by halfs excluding zero/undef lanes 3600b57cec5SDimitry Andric // * Vector incrementing address -> vector masked load 361e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::simplifyMaskedGather(IntrinsicInst &II) { 36204eeddc0SDimitry Andric auto *ConstMask = dyn_cast<Constant>(II.getArgOperand(2)); 36304eeddc0SDimitry Andric if (!ConstMask) 36404eeddc0SDimitry Andric return nullptr; 36504eeddc0SDimitry Andric 36604eeddc0SDimitry Andric // Vector splat address w/known mask -> scalar load 36704eeddc0SDimitry Andric // Fold the gather to load the source vector first lane 36804eeddc0SDimitry Andric // because it is reloading the same value each time 36904eeddc0SDimitry Andric if (ConstMask->isAllOnesValue()) 37004eeddc0SDimitry Andric if (auto *SplatPtr = getSplatValue(II.getArgOperand(0))) { 37104eeddc0SDimitry Andric auto *VecTy = cast<VectorType>(II.getType()); 37204eeddc0SDimitry Andric const Align Alignment = 37304eeddc0SDimitry Andric cast<ConstantInt>(II.getArgOperand(1))->getAlignValue(); 37404eeddc0SDimitry Andric LoadInst *L = Builder.CreateAlignedLoad(VecTy->getElementType(), SplatPtr, 37504eeddc0SDimitry Andric Alignment, "load.scalar"); 37604eeddc0SDimitry Andric Value *Shuf = 37704eeddc0SDimitry Andric Builder.CreateVectorSplat(VecTy->getElementCount(), L, "broadcast"); 37804eeddc0SDimitry Andric return replaceInstUsesWith(II, cast<Instruction>(Shuf)); 37904eeddc0SDimitry Andric } 38004eeddc0SDimitry Andric 3810b57cec5SDimitry Andric return nullptr; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // TODO, Obvious Missing Transforms: 3850b57cec5SDimitry Andric // * Single constant active lane -> store 3860b57cec5SDimitry Andric // * Adjacent vector addresses -> masked.store 3870b57cec5SDimitry Andric // * Narrow store width by halfs excluding zero/undef lanes 3880b57cec5SDimitry Andric // * Vector incrementing address -> vector masked store 389e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) { 3900b57cec5SDimitry Andric auto *ConstMask = dyn_cast<Constant>(II.getArgOperand(3)); 3910b57cec5SDimitry Andric if (!ConstMask) 3920b57cec5SDimitry Andric return nullptr; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric // If the mask is all zeros, a scatter does nothing. 3950b57cec5SDimitry Andric if (ConstMask->isNullValue()) 3960b57cec5SDimitry Andric return eraseInstFromFunction(II); 3970b57cec5SDimitry Andric 39804eeddc0SDimitry Andric // Vector splat address -> scalar store 39904eeddc0SDimitry Andric if (auto *SplatPtr = getSplatValue(II.getArgOperand(1))) { 40004eeddc0SDimitry Andric // scatter(splat(value), splat(ptr), non-zero-mask) -> store value, ptr 40104eeddc0SDimitry Andric if (auto *SplatValue = getSplatValue(II.getArgOperand(0))) { 402439352acSDimitry Andric if (maskContainsAllOneOrUndef(ConstMask)) { 403439352acSDimitry Andric Align Alignment = 404439352acSDimitry Andric cast<ConstantInt>(II.getArgOperand(2))->getAlignValue(); 405439352acSDimitry Andric StoreInst *S = new StoreInst(SplatValue, SplatPtr, /*IsVolatile=*/false, 406439352acSDimitry Andric Alignment); 40704eeddc0SDimitry Andric S->copyMetadata(II); 40804eeddc0SDimitry Andric return S; 40904eeddc0SDimitry Andric } 410439352acSDimitry Andric } 41104eeddc0SDimitry Andric // scatter(vector, splat(ptr), splat(true)) -> store extract(vector, 41204eeddc0SDimitry Andric // lastlane), ptr 41304eeddc0SDimitry Andric if (ConstMask->isAllOnesValue()) { 41404eeddc0SDimitry Andric Align Alignment = cast<ConstantInt>(II.getArgOperand(2))->getAlignValue(); 41504eeddc0SDimitry Andric VectorType *WideLoadTy = cast<VectorType>(II.getArgOperand(1)->getType()); 41604eeddc0SDimitry Andric ElementCount VF = WideLoadTy->getElementCount(); 41706c3fb27SDimitry Andric Value *RunTimeVF = Builder.CreateElementCount(Builder.getInt32Ty(), VF); 41804eeddc0SDimitry Andric Value *LastLane = Builder.CreateSub(RunTimeVF, Builder.getInt32(1)); 41904eeddc0SDimitry Andric Value *Extract = 42004eeddc0SDimitry Andric Builder.CreateExtractElement(II.getArgOperand(0), LastLane); 42104eeddc0SDimitry Andric StoreInst *S = 42204eeddc0SDimitry Andric new StoreInst(Extract, SplatPtr, /*IsVolatile=*/false, Alignment); 42304eeddc0SDimitry Andric S->copyMetadata(II); 42404eeddc0SDimitry Andric return S; 42504eeddc0SDimitry Andric } 42604eeddc0SDimitry Andric } 427e8d8bef9SDimitry Andric if (isa<ScalableVectorType>(ConstMask->getType())) 428e8d8bef9SDimitry Andric return nullptr; 429e8d8bef9SDimitry Andric 4300b57cec5SDimitry Andric // Use masked off lanes to simplify operands via SimplifyDemandedVectorElts 4310b57cec5SDimitry Andric APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask); 432cb14a3feSDimitry Andric APInt PoisonElts(DemandedElts.getBitWidth(), 0); 433cb14a3feSDimitry Andric if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, 434cb14a3feSDimitry Andric PoisonElts)) 4355ffd83dbSDimitry Andric return replaceOperand(II, 0, V); 436cb14a3feSDimitry Andric if (Value *V = SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts, 437cb14a3feSDimitry Andric PoisonElts)) 4385ffd83dbSDimitry Andric return replaceOperand(II, 1, V); 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric return nullptr; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric /// This function transforms launder.invariant.group and strip.invariant.group 4440b57cec5SDimitry Andric /// like: 4450b57cec5SDimitry Andric /// launder(launder(%x)) -> launder(%x) (the result is not the argument) 4460b57cec5SDimitry Andric /// launder(strip(%x)) -> launder(%x) 4470b57cec5SDimitry Andric /// strip(strip(%x)) -> strip(%x) (the result is not the argument) 4480b57cec5SDimitry Andric /// strip(launder(%x)) -> strip(%x) 4490b57cec5SDimitry Andric /// This is legal because it preserves the most recent information about 4500b57cec5SDimitry Andric /// the presence or absence of invariant.group. 4510b57cec5SDimitry Andric static Instruction *simplifyInvariantGroupIntrinsic(IntrinsicInst &II, 452e8d8bef9SDimitry Andric InstCombinerImpl &IC) { 4530b57cec5SDimitry Andric auto *Arg = II.getArgOperand(0); 4540b57cec5SDimitry Andric auto *StrippedArg = Arg->stripPointerCasts(); 455fe6060f1SDimitry Andric auto *StrippedInvariantGroupsArg = StrippedArg; 456fe6060f1SDimitry Andric while (auto *Intr = dyn_cast<IntrinsicInst>(StrippedInvariantGroupsArg)) { 457fe6060f1SDimitry Andric if (Intr->getIntrinsicID() != Intrinsic::launder_invariant_group && 458fe6060f1SDimitry Andric Intr->getIntrinsicID() != Intrinsic::strip_invariant_group) 459fe6060f1SDimitry Andric break; 460fe6060f1SDimitry Andric StrippedInvariantGroupsArg = Intr->getArgOperand(0)->stripPointerCasts(); 461fe6060f1SDimitry Andric } 4620b57cec5SDimitry Andric if (StrippedArg == StrippedInvariantGroupsArg) 4630b57cec5SDimitry Andric return nullptr; // No launders/strips to remove. 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric Value *Result = nullptr; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric if (II.getIntrinsicID() == Intrinsic::launder_invariant_group) 4680b57cec5SDimitry Andric Result = IC.Builder.CreateLaunderInvariantGroup(StrippedInvariantGroupsArg); 4690b57cec5SDimitry Andric else if (II.getIntrinsicID() == Intrinsic::strip_invariant_group) 4700b57cec5SDimitry Andric Result = IC.Builder.CreateStripInvariantGroup(StrippedInvariantGroupsArg); 4710b57cec5SDimitry Andric else 4720b57cec5SDimitry Andric llvm_unreachable( 4730b57cec5SDimitry Andric "simplifyInvariantGroupIntrinsic only handles launder and strip"); 4740b57cec5SDimitry Andric if (Result->getType()->getPointerAddressSpace() != 4750b57cec5SDimitry Andric II.getType()->getPointerAddressSpace()) 4760b57cec5SDimitry Andric Result = IC.Builder.CreateAddrSpaceCast(Result, II.getType()); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric return cast<Instruction>(Result); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 481e8d8bef9SDimitry Andric static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) { 4820b57cec5SDimitry Andric assert((II.getIntrinsicID() == Intrinsic::cttz || 4830b57cec5SDimitry Andric II.getIntrinsicID() == Intrinsic::ctlz) && 4840b57cec5SDimitry Andric "Expected cttz or ctlz intrinsic"); 4850b57cec5SDimitry Andric bool IsTZ = II.getIntrinsicID() == Intrinsic::cttz; 4860b57cec5SDimitry Andric Value *Op0 = II.getArgOperand(0); 487fe6060f1SDimitry Andric Value *Op1 = II.getArgOperand(1); 4880b57cec5SDimitry Andric Value *X; 4890b57cec5SDimitry Andric // ctlz(bitreverse(x)) -> cttz(x) 4900b57cec5SDimitry Andric // cttz(bitreverse(x)) -> ctlz(x) 4910b57cec5SDimitry Andric if (match(Op0, m_BitReverse(m_Value(X)))) { 4920b57cec5SDimitry Andric Intrinsic::ID ID = IsTZ ? Intrinsic::ctlz : Intrinsic::cttz; 4930b57cec5SDimitry Andric Function *F = Intrinsic::getDeclaration(II.getModule(), ID, II.getType()); 4940b57cec5SDimitry Andric return CallInst::Create(F, {X, II.getArgOperand(1)}); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 497fe6060f1SDimitry Andric if (II.getType()->isIntOrIntVectorTy(1)) { 498fe6060f1SDimitry Andric // ctlz/cttz i1 Op0 --> not Op0 499fe6060f1SDimitry Andric if (match(Op1, m_Zero())) 500fe6060f1SDimitry Andric return BinaryOperator::CreateNot(Op0); 50104eeddc0SDimitry Andric // If zero is poison, then the input can be assumed to be "true", so the 502fe6060f1SDimitry Andric // instruction simplifies to "false". 503fe6060f1SDimitry Andric assert(match(Op1, m_One()) && "Expected ctlz/cttz operand to be 0 or 1"); 504fe6060f1SDimitry Andric return IC.replaceInstUsesWith(II, ConstantInt::getNullValue(II.getType())); 505fe6060f1SDimitry Andric } 506fe6060f1SDimitry Andric 5070fca6ea1SDimitry Andric // If ctlz/cttz is only used as a shift amount, set is_zero_poison to true. 5080fca6ea1SDimitry Andric if (II.hasOneUse() && match(Op1, m_Zero()) && 509*71ac745dSDimitry Andric match(II.user_back(), m_Shift(m_Value(), m_Specific(&II)))) { 510*71ac745dSDimitry Andric II.dropUBImplyingAttrsAndMetadata(); 5110fca6ea1SDimitry Andric return IC.replaceOperand(II, 1, IC.Builder.getTrue()); 512*71ac745dSDimitry Andric } 5130fca6ea1SDimitry Andric 5145f757f3fSDimitry Andric Constant *C; 5155f757f3fSDimitry Andric 5160b57cec5SDimitry Andric if (IsTZ) { 5170b57cec5SDimitry Andric // cttz(-x) -> cttz(x) 5185ffd83dbSDimitry Andric if (match(Op0, m_Neg(m_Value(X)))) 5195ffd83dbSDimitry Andric return IC.replaceOperand(II, 0, X); 5200b57cec5SDimitry Andric 52106c3fb27SDimitry Andric // cttz(-x & x) -> cttz(x) 52206c3fb27SDimitry Andric if (match(Op0, m_c_And(m_Neg(m_Value(X)), m_Deferred(X)))) 52306c3fb27SDimitry Andric return IC.replaceOperand(II, 0, X); 52406c3fb27SDimitry Andric 525fe6060f1SDimitry Andric // cttz(sext(x)) -> cttz(zext(x)) 526fe6060f1SDimitry Andric if (match(Op0, m_OneUse(m_SExt(m_Value(X))))) { 527fe6060f1SDimitry Andric auto *Zext = IC.Builder.CreateZExt(X, II.getType()); 528fe6060f1SDimitry Andric auto *CttzZext = 529fe6060f1SDimitry Andric IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, Zext, Op1); 530fe6060f1SDimitry Andric return IC.replaceInstUsesWith(II, CttzZext); 531fe6060f1SDimitry Andric } 532fe6060f1SDimitry Andric 533fe6060f1SDimitry Andric // Zext doesn't change the number of trailing zeros, so narrow: 53404eeddc0SDimitry Andric // cttz(zext(x)) -> zext(cttz(x)) if the 'ZeroIsPoison' parameter is 'true'. 535fe6060f1SDimitry Andric if (match(Op0, m_OneUse(m_ZExt(m_Value(X)))) && match(Op1, m_One())) { 536fe6060f1SDimitry Andric auto *Cttz = IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, X, 537fe6060f1SDimitry Andric IC.Builder.getTrue()); 538fe6060f1SDimitry Andric auto *ZextCttz = IC.Builder.CreateZExt(Cttz, II.getType()); 539fe6060f1SDimitry Andric return IC.replaceInstUsesWith(II, ZextCttz); 540fe6060f1SDimitry Andric } 541fe6060f1SDimitry Andric 5420b57cec5SDimitry Andric // cttz(abs(x)) -> cttz(x) 5430b57cec5SDimitry Andric // cttz(nabs(x)) -> cttz(x) 5440b57cec5SDimitry Andric Value *Y; 5450b57cec5SDimitry Andric SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor; 5465ffd83dbSDimitry Andric if (SPF == SPF_ABS || SPF == SPF_NABS) 5475ffd83dbSDimitry Andric return IC.replaceOperand(II, 0, X); 548e8d8bef9SDimitry Andric 549e8d8bef9SDimitry Andric if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X)))) 550e8d8bef9SDimitry Andric return IC.replaceOperand(II, 0, X); 5515f757f3fSDimitry Andric 5525f757f3fSDimitry Andric // cttz(shl(%const, %val), 1) --> add(cttz(%const, 1), %val) 5535f757f3fSDimitry Andric if (match(Op0, m_Shl(m_ImmConstant(C), m_Value(X))) && 5545f757f3fSDimitry Andric match(Op1, m_One())) { 5555f757f3fSDimitry Andric Value *ConstCttz = 5565f757f3fSDimitry Andric IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, C, Op1); 5575f757f3fSDimitry Andric return BinaryOperator::CreateAdd(ConstCttz, X); 5585f757f3fSDimitry Andric } 5595f757f3fSDimitry Andric 5605f757f3fSDimitry Andric // cttz(lshr exact (%const, %val), 1) --> sub(cttz(%const, 1), %val) 5615f757f3fSDimitry Andric if (match(Op0, m_Exact(m_LShr(m_ImmConstant(C), m_Value(X)))) && 5625f757f3fSDimitry Andric match(Op1, m_One())) { 5635f757f3fSDimitry Andric Value *ConstCttz = 5645f757f3fSDimitry Andric IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, C, Op1); 5655f757f3fSDimitry Andric return BinaryOperator::CreateSub(ConstCttz, X); 5665f757f3fSDimitry Andric } 5670fca6ea1SDimitry Andric 5680fca6ea1SDimitry Andric // cttz(add(lshr(UINT_MAX, %val), 1)) --> sub(width, %val) 5690fca6ea1SDimitry Andric if (match(Op0, m_Add(m_LShr(m_AllOnes(), m_Value(X)), m_One()))) { 5700fca6ea1SDimitry Andric Value *Width = 5710fca6ea1SDimitry Andric ConstantInt::get(II.getType(), II.getType()->getScalarSizeInBits()); 5720fca6ea1SDimitry Andric return BinaryOperator::CreateSub(Width, X); 5730fca6ea1SDimitry Andric } 5745f757f3fSDimitry Andric } else { 5755f757f3fSDimitry Andric // ctlz(lshr(%const, %val), 1) --> add(ctlz(%const, 1), %val) 5765f757f3fSDimitry Andric if (match(Op0, m_LShr(m_ImmConstant(C), m_Value(X))) && 5775f757f3fSDimitry Andric match(Op1, m_One())) { 5785f757f3fSDimitry Andric Value *ConstCtlz = 5795f757f3fSDimitry Andric IC.Builder.CreateBinaryIntrinsic(Intrinsic::ctlz, C, Op1); 5805f757f3fSDimitry Andric return BinaryOperator::CreateAdd(ConstCtlz, X); 5815f757f3fSDimitry Andric } 5825f757f3fSDimitry Andric 5835f757f3fSDimitry Andric // ctlz(shl nuw (%const, %val), 1) --> sub(ctlz(%const, 1), %val) 5845f757f3fSDimitry Andric if (match(Op0, m_NUWShl(m_ImmConstant(C), m_Value(X))) && 5855f757f3fSDimitry Andric match(Op1, m_One())) { 5865f757f3fSDimitry Andric Value *ConstCtlz = 5875f757f3fSDimitry Andric IC.Builder.CreateBinaryIntrinsic(Intrinsic::ctlz, C, Op1); 5885f757f3fSDimitry Andric return BinaryOperator::CreateSub(ConstCtlz, X); 5895f757f3fSDimitry Andric } 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric KnownBits Known = IC.computeKnownBits(Op0, 0, &II); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric // Create a mask for bits above (ctlz) or below (cttz) the first known one. 5950b57cec5SDimitry Andric unsigned PossibleZeros = IsTZ ? Known.countMaxTrailingZeros() 5960b57cec5SDimitry Andric : Known.countMaxLeadingZeros(); 5970b57cec5SDimitry Andric unsigned DefiniteZeros = IsTZ ? Known.countMinTrailingZeros() 5980b57cec5SDimitry Andric : Known.countMinLeadingZeros(); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // If all bits above (ctlz) or below (cttz) the first known one are known 6010b57cec5SDimitry Andric // zero, this value is constant. 6020b57cec5SDimitry Andric // FIXME: This should be in InstSimplify because we're replacing an 6030b57cec5SDimitry Andric // instruction with a constant. 6040b57cec5SDimitry Andric if (PossibleZeros == DefiniteZeros) { 6050b57cec5SDimitry Andric auto *C = ConstantInt::get(Op0->getType(), DefiniteZeros); 6060b57cec5SDimitry Andric return IC.replaceInstUsesWith(II, C); 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric // If the input to cttz/ctlz is known to be non-zero, 61004eeddc0SDimitry Andric // then change the 'ZeroIsPoison' parameter to 'true' 6110b57cec5SDimitry Andric // because we know the zero behavior can't affect the result. 612349cc55cSDimitry Andric if (!Known.One.isZero() || 6130fca6ea1SDimitry Andric isKnownNonZero(Op0, IC.getSimplifyQuery().getWithInstruction(&II))) { 6145ffd83dbSDimitry Andric if (!match(II.getArgOperand(1), m_One())) 6155ffd83dbSDimitry Andric return IC.replaceOperand(II, 1, IC.Builder.getTrue()); 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180fca6ea1SDimitry Andric // Add range attribute since known bits can't completely reflect what we know. 6190fca6ea1SDimitry Andric unsigned BitWidth = Op0->getType()->getScalarSizeInBits(); 6200fca6ea1SDimitry Andric if (BitWidth != 1 && !II.hasRetAttr(Attribute::Range) && 6210fca6ea1SDimitry Andric !II.getMetadata(LLVMContext::MD_range)) { 6220fca6ea1SDimitry Andric ConstantRange Range(APInt(BitWidth, DefiniteZeros), 6230fca6ea1SDimitry Andric APInt(BitWidth, PossibleZeros + 1)); 6240fca6ea1SDimitry Andric II.addRangeRetAttr(Range); 6250b57cec5SDimitry Andric return &II; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric return nullptr; 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 631e8d8bef9SDimitry Andric static Instruction *foldCtpop(IntrinsicInst &II, InstCombinerImpl &IC) { 6320b57cec5SDimitry Andric assert(II.getIntrinsicID() == Intrinsic::ctpop && 6330b57cec5SDimitry Andric "Expected ctpop intrinsic"); 6345ffd83dbSDimitry Andric Type *Ty = II.getType(); 6355ffd83dbSDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 6360b57cec5SDimitry Andric Value *Op0 = II.getArgOperand(0); 637fe6060f1SDimitry Andric Value *X, *Y; 6385ffd83dbSDimitry Andric 6390b57cec5SDimitry Andric // ctpop(bitreverse(x)) -> ctpop(x) 6400b57cec5SDimitry Andric // ctpop(bswap(x)) -> ctpop(x) 6415ffd83dbSDimitry Andric if (match(Op0, m_BitReverse(m_Value(X))) || match(Op0, m_BSwap(m_Value(X)))) 6425ffd83dbSDimitry Andric return IC.replaceOperand(II, 0, X); 6435ffd83dbSDimitry Andric 644fe6060f1SDimitry Andric // ctpop(rot(x)) -> ctpop(x) 645fe6060f1SDimitry Andric if ((match(Op0, m_FShl(m_Value(X), m_Value(Y), m_Value())) || 646fe6060f1SDimitry Andric match(Op0, m_FShr(m_Value(X), m_Value(Y), m_Value()))) && 647fe6060f1SDimitry Andric X == Y) 648fe6060f1SDimitry Andric return IC.replaceOperand(II, 0, X); 649fe6060f1SDimitry Andric 6505ffd83dbSDimitry Andric // ctpop(x | -x) -> bitwidth - cttz(x, false) 6515ffd83dbSDimitry Andric if (Op0->hasOneUse() && 6525ffd83dbSDimitry Andric match(Op0, m_c_Or(m_Value(X), m_Neg(m_Deferred(X))))) { 6535ffd83dbSDimitry Andric Function *F = 6545ffd83dbSDimitry Andric Intrinsic::getDeclaration(II.getModule(), Intrinsic::cttz, Ty); 6555ffd83dbSDimitry Andric auto *Cttz = IC.Builder.CreateCall(F, {X, IC.Builder.getFalse()}); 6565ffd83dbSDimitry Andric auto *Bw = ConstantInt::get(Ty, APInt(BitWidth, BitWidth)); 6575ffd83dbSDimitry Andric return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(Bw, Cttz)); 6585ffd83dbSDimitry Andric } 6595ffd83dbSDimitry Andric 6605ffd83dbSDimitry Andric // ctpop(~x & (x - 1)) -> cttz(x, false) 6615ffd83dbSDimitry Andric if (match(Op0, 6625ffd83dbSDimitry Andric m_c_And(m_Not(m_Value(X)), m_Add(m_Deferred(X), m_AllOnes())))) { 6635ffd83dbSDimitry Andric Function *F = 6645ffd83dbSDimitry Andric Intrinsic::getDeclaration(II.getModule(), Intrinsic::cttz, Ty); 6655ffd83dbSDimitry Andric return CallInst::Create(F, {X, IC.Builder.getFalse()}); 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 668fe6060f1SDimitry Andric // Zext doesn't change the number of set bits, so narrow: 669fe6060f1SDimitry Andric // ctpop (zext X) --> zext (ctpop X) 670fe6060f1SDimitry Andric if (match(Op0, m_OneUse(m_ZExt(m_Value(X))))) { 671fe6060f1SDimitry Andric Value *NarrowPop = IC.Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, X); 672fe6060f1SDimitry Andric return CastInst::Create(Instruction::ZExt, NarrowPop, Ty); 673fe6060f1SDimitry Andric } 674fe6060f1SDimitry Andric 675fe6060f1SDimitry Andric KnownBits Known(BitWidth); 676fe6060f1SDimitry Andric IC.computeKnownBits(Op0, Known, 0, &II); 677fe6060f1SDimitry Andric 678fe6060f1SDimitry Andric // If all bits are zero except for exactly one fixed bit, then the result 679fe6060f1SDimitry Andric // must be 0 or 1, and we can get that answer by shifting to LSB: 680fe6060f1SDimitry Andric // ctpop (X & 32) --> (X & 32) >> 5 681bdd1243dSDimitry Andric // TODO: Investigate removing this as its likely unnecessary given the below 682bdd1243dSDimitry Andric // `isKnownToBeAPowerOfTwo` check. 683fe6060f1SDimitry Andric if ((~Known.Zero).isPowerOf2()) 684fe6060f1SDimitry Andric return BinaryOperator::CreateLShr( 685fe6060f1SDimitry Andric Op0, ConstantInt::get(Ty, (~Known.Zero).exactLogBase2())); 686fe6060f1SDimitry Andric 687bdd1243dSDimitry Andric // More generally we can also handle non-constant power of 2 patterns such as 688bdd1243dSDimitry Andric // shl/shr(Pow2, X), (X & -X), etc... by transforming: 689bdd1243dSDimitry Andric // ctpop(Pow2OrZero) --> icmp ne X, 0 690bdd1243dSDimitry Andric if (IC.isKnownToBeAPowerOfTwo(Op0, /* OrZero */ true)) 691bdd1243dSDimitry Andric return CastInst::Create(Instruction::ZExt, 692bdd1243dSDimitry Andric IC.Builder.CreateICmp(ICmpInst::ICMP_NE, Op0, 693bdd1243dSDimitry Andric Constant::getNullValue(Ty)), 694bdd1243dSDimitry Andric Ty); 695bdd1243dSDimitry Andric 6960fca6ea1SDimitry Andric // Add range attribute since known bits can't completely reflect what we know. 6970fca6ea1SDimitry Andric if (BitWidth != 1 && !II.hasRetAttr(Attribute::Range) && 6980fca6ea1SDimitry Andric !II.getMetadata(LLVMContext::MD_range)) { 6990fca6ea1SDimitry Andric ConstantRange Range(APInt(BitWidth, Known.countMinPopulation()), 7000fca6ea1SDimitry Andric APInt(BitWidth, Known.countMaxPopulation() + 1)); 7010fca6ea1SDimitry Andric II.addRangeRetAttr(Range); 7020b57cec5SDimitry Andric return &II; 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric return nullptr; 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric /// Convert a table lookup to shufflevector if the mask is constant. 7090b57cec5SDimitry Andric /// This could benefit tbl1 if the mask is { 7,6,5,4,3,2,1,0 }, in 7100b57cec5SDimitry Andric /// which case we could lower the shufflevector with rev64 instructions 7110b57cec5SDimitry Andric /// as it's actually a byte reverse. 7120b57cec5SDimitry Andric static Value *simplifyNeonTbl1(const IntrinsicInst &II, 7130b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 7140b57cec5SDimitry Andric // Bail out if the mask is not a constant. 7150b57cec5SDimitry Andric auto *C = dyn_cast<Constant>(II.getArgOperand(1)); 7160b57cec5SDimitry Andric if (!C) 7170b57cec5SDimitry Andric return nullptr; 7180b57cec5SDimitry Andric 719e8d8bef9SDimitry Andric auto *VecTy = cast<FixedVectorType>(II.getType()); 7200b57cec5SDimitry Andric unsigned NumElts = VecTy->getNumElements(); 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric // Only perform this transformation for <8 x i8> vector types. 7230b57cec5SDimitry Andric if (!VecTy->getElementType()->isIntegerTy(8) || NumElts != 8) 7240b57cec5SDimitry Andric return nullptr; 7250b57cec5SDimitry Andric 7265ffd83dbSDimitry Andric int Indexes[8]; 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric for (unsigned I = 0; I < NumElts; ++I) { 7290b57cec5SDimitry Andric Constant *COp = C->getAggregateElement(I); 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric if (!COp || !isa<ConstantInt>(COp)) 7320b57cec5SDimitry Andric return nullptr; 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric Indexes[I] = cast<ConstantInt>(COp)->getLimitedValue(); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric // Make sure the mask indices are in range. 7375ffd83dbSDimitry Andric if ((unsigned)Indexes[I] >= NumElts) 7380b57cec5SDimitry Andric return nullptr; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric auto *V1 = II.getArgOperand(0); 7420b57cec5SDimitry Andric auto *V2 = Constant::getNullValue(V1->getType()); 743bdd1243dSDimitry Andric return Builder.CreateShuffleVector(V1, V2, ArrayRef(Indexes)); 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric // Returns true iff the 2 intrinsics have the same operands, limiting the 7470b57cec5SDimitry Andric // comparison to the first NumOperands. 7480b57cec5SDimitry Andric static bool haveSameOperands(const IntrinsicInst &I, const IntrinsicInst &E, 7490b57cec5SDimitry Andric unsigned NumOperands) { 750349cc55cSDimitry Andric assert(I.arg_size() >= NumOperands && "Not enough operands"); 751349cc55cSDimitry Andric assert(E.arg_size() >= NumOperands && "Not enough operands"); 7520b57cec5SDimitry Andric for (unsigned i = 0; i < NumOperands; i++) 7530b57cec5SDimitry Andric if (I.getArgOperand(i) != E.getArgOperand(i)) 7540b57cec5SDimitry Andric return false; 7550b57cec5SDimitry Andric return true; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric // Remove trivially empty start/end intrinsic ranges, i.e. a start 7590b57cec5SDimitry Andric // immediately followed by an end (ignoring debuginfo or other 7600b57cec5SDimitry Andric // start/end intrinsics in between). As this handles only the most trivial 7610b57cec5SDimitry Andric // cases, tracking the nesting level is not needed: 7620b57cec5SDimitry Andric // 7630b57cec5SDimitry Andric // call @llvm.foo.start(i1 0) 7645ffd83dbSDimitry Andric // call @llvm.foo.start(i1 0) ; This one won't be skipped: it will be removed 7650b57cec5SDimitry Andric // call @llvm.foo.end(i1 0) 7665ffd83dbSDimitry Andric // call @llvm.foo.end(i1 0) ; &I 767e8d8bef9SDimitry Andric static bool 768e8d8bef9SDimitry Andric removeTriviallyEmptyRange(IntrinsicInst &EndI, InstCombinerImpl &IC, 7695ffd83dbSDimitry Andric std::function<bool(const IntrinsicInst &)> IsStart) { 7705ffd83dbSDimitry Andric // We start from the end intrinsic and scan backwards, so that InstCombine 7715ffd83dbSDimitry Andric // has already processed (and potentially removed) all the instructions 7725ffd83dbSDimitry Andric // before the end intrinsic. 7735ffd83dbSDimitry Andric BasicBlock::reverse_iterator BI(EndI), BE(EndI.getParent()->rend()); 7745ffd83dbSDimitry Andric for (; BI != BE; ++BI) { 7755ffd83dbSDimitry Andric if (auto *I = dyn_cast<IntrinsicInst>(&*BI)) { 776349cc55cSDimitry Andric if (I->isDebugOrPseudoInst() || 7775ffd83dbSDimitry Andric I->getIntrinsicID() == EndI.getIntrinsicID()) 7780b57cec5SDimitry Andric continue; 7795ffd83dbSDimitry Andric if (IsStart(*I)) { 780349cc55cSDimitry Andric if (haveSameOperands(EndI, *I, EndI.arg_size())) { 7815ffd83dbSDimitry Andric IC.eraseInstFromFunction(*I); 7825ffd83dbSDimitry Andric IC.eraseInstFromFunction(EndI); 7830b57cec5SDimitry Andric return true; 7840b57cec5SDimitry Andric } 7855ffd83dbSDimitry Andric // Skip start intrinsics that don't pair with this end intrinsic. 7865ffd83dbSDimitry Andric continue; 7875ffd83dbSDimitry Andric } 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric break; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric return false; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 795e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitVAEndInst(VAEndInst &I) { 7965ffd83dbSDimitry Andric removeTriviallyEmptyRange(I, *this, [](const IntrinsicInst &I) { 7975ffd83dbSDimitry Andric return I.getIntrinsicID() == Intrinsic::vastart || 7985ffd83dbSDimitry Andric I.getIntrinsicID() == Intrinsic::vacopy; 7995ffd83dbSDimitry Andric }); 8000b57cec5SDimitry Andric return nullptr; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 803e8d8bef9SDimitry Andric static CallInst *canonicalizeConstantArg0ToArg1(CallInst &Call) { 804349cc55cSDimitry Andric assert(Call.arg_size() > 1 && "Need at least 2 args to swap"); 8050b57cec5SDimitry Andric Value *Arg0 = Call.getArgOperand(0), *Arg1 = Call.getArgOperand(1); 8060b57cec5SDimitry Andric if (isa<Constant>(Arg0) && !isa<Constant>(Arg1)) { 8070b57cec5SDimitry Andric Call.setArgOperand(0, Arg1); 8080b57cec5SDimitry Andric Call.setArgOperand(1, Arg0); 8090b57cec5SDimitry Andric return &Call; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric return nullptr; 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814e8d8bef9SDimitry Andric /// Creates a result tuple for an overflow intrinsic \p II with a given 815e8d8bef9SDimitry Andric /// \p Result and a constant \p Overflow value. 816e8d8bef9SDimitry Andric static Instruction *createOverflowTuple(IntrinsicInst *II, Value *Result, 817e8d8bef9SDimitry Andric Constant *Overflow) { 81881ad6265SDimitry Andric Constant *V[] = {PoisonValue::get(Result->getType()), Overflow}; 819e8d8bef9SDimitry Andric StructType *ST = cast<StructType>(II->getType()); 820e8d8bef9SDimitry Andric Constant *Struct = ConstantStruct::get(ST, V); 821e8d8bef9SDimitry Andric return InsertValueInst::Create(Struct, Result, 0); 822e8d8bef9SDimitry Andric } 823e8d8bef9SDimitry Andric 824e8d8bef9SDimitry Andric Instruction * 825e8d8bef9SDimitry Andric InstCombinerImpl::foldIntrinsicWithOverflowCommon(IntrinsicInst *II) { 8260b57cec5SDimitry Andric WithOverflowInst *WO = cast<WithOverflowInst>(II); 8270b57cec5SDimitry Andric Value *OperationResult = nullptr; 8280b57cec5SDimitry Andric Constant *OverflowResult = nullptr; 8290b57cec5SDimitry Andric if (OptimizeOverflowCheck(WO->getBinaryOp(), WO->isSigned(), WO->getLHS(), 8300b57cec5SDimitry Andric WO->getRHS(), *WO, OperationResult, OverflowResult)) 831e8d8bef9SDimitry Andric return createOverflowTuple(WO, OperationResult, OverflowResult); 8320b57cec5SDimitry Andric return nullptr; 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 83506c3fb27SDimitry Andric static bool inputDenormalIsIEEE(const Function &F, const Type *Ty) { 83606c3fb27SDimitry Andric Ty = Ty->getScalarType(); 83706c3fb27SDimitry Andric return F.getDenormalMode(Ty->getFltSemantics()).Input == DenormalMode::IEEE; 83806c3fb27SDimitry Andric } 83906c3fb27SDimitry Andric 84006c3fb27SDimitry Andric static bool inputDenormalIsDAZ(const Function &F, const Type *Ty) { 84106c3fb27SDimitry Andric Ty = Ty->getScalarType(); 84206c3fb27SDimitry Andric return F.getDenormalMode(Ty->getFltSemantics()).inputsAreZero(); 84306c3fb27SDimitry Andric } 84406c3fb27SDimitry Andric 84506c3fb27SDimitry Andric /// \returns the compare predicate type if the test performed by 84606c3fb27SDimitry Andric /// llvm.is.fpclass(x, \p Mask) is equivalent to fcmp o__ x, 0.0 with the 84706c3fb27SDimitry Andric /// floating-point environment assumed for \p F for type \p Ty 84806c3fb27SDimitry Andric static FCmpInst::Predicate fpclassTestIsFCmp0(FPClassTest Mask, 84906c3fb27SDimitry Andric const Function &F, Type *Ty) { 85006c3fb27SDimitry Andric switch (static_cast<unsigned>(Mask)) { 85106c3fb27SDimitry Andric case fcZero: 85206c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 85306c3fb27SDimitry Andric return FCmpInst::FCMP_OEQ; 85406c3fb27SDimitry Andric break; 85506c3fb27SDimitry Andric case fcZero | fcSubnormal: 85606c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 85706c3fb27SDimitry Andric return FCmpInst::FCMP_OEQ; 85806c3fb27SDimitry Andric break; 85906c3fb27SDimitry Andric case fcPositive | fcNegZero: 86006c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 86106c3fb27SDimitry Andric return FCmpInst::FCMP_OGE; 86206c3fb27SDimitry Andric break; 86306c3fb27SDimitry Andric case fcPositive | fcNegZero | fcNegSubnormal: 86406c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 86506c3fb27SDimitry Andric return FCmpInst::FCMP_OGE; 86606c3fb27SDimitry Andric break; 86706c3fb27SDimitry Andric case fcPosSubnormal | fcPosNormal | fcPosInf: 86806c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 86906c3fb27SDimitry Andric return FCmpInst::FCMP_OGT; 87006c3fb27SDimitry Andric break; 87106c3fb27SDimitry Andric case fcNegative | fcPosZero: 87206c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 87306c3fb27SDimitry Andric return FCmpInst::FCMP_OLE; 87406c3fb27SDimitry Andric break; 87506c3fb27SDimitry Andric case fcNegative | fcPosZero | fcPosSubnormal: 87606c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 87706c3fb27SDimitry Andric return FCmpInst::FCMP_OLE; 87806c3fb27SDimitry Andric break; 87906c3fb27SDimitry Andric case fcNegSubnormal | fcNegNormal | fcNegInf: 88006c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 88106c3fb27SDimitry Andric return FCmpInst::FCMP_OLT; 88206c3fb27SDimitry Andric break; 88306c3fb27SDimitry Andric case fcPosNormal | fcPosInf: 88406c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 88506c3fb27SDimitry Andric return FCmpInst::FCMP_OGT; 88606c3fb27SDimitry Andric break; 88706c3fb27SDimitry Andric case fcNegNormal | fcNegInf: 88806c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 88906c3fb27SDimitry Andric return FCmpInst::FCMP_OLT; 89006c3fb27SDimitry Andric break; 89106c3fb27SDimitry Andric case ~fcZero & ~fcNan: 89206c3fb27SDimitry Andric if (inputDenormalIsIEEE(F, Ty)) 89306c3fb27SDimitry Andric return FCmpInst::FCMP_ONE; 89406c3fb27SDimitry Andric break; 89506c3fb27SDimitry Andric case ~(fcZero | fcSubnormal) & ~fcNan: 89606c3fb27SDimitry Andric if (inputDenormalIsDAZ(F, Ty)) 89706c3fb27SDimitry Andric return FCmpInst::FCMP_ONE; 89806c3fb27SDimitry Andric break; 89906c3fb27SDimitry Andric default: 90006c3fb27SDimitry Andric break; 90106c3fb27SDimitry Andric } 90206c3fb27SDimitry Andric 90306c3fb27SDimitry Andric return FCmpInst::BAD_FCMP_PREDICATE; 90406c3fb27SDimitry Andric } 90506c3fb27SDimitry Andric 90606c3fb27SDimitry Andric Instruction *InstCombinerImpl::foldIntrinsicIsFPClass(IntrinsicInst &II) { 90706c3fb27SDimitry Andric Value *Src0 = II.getArgOperand(0); 90806c3fb27SDimitry Andric Value *Src1 = II.getArgOperand(1); 90906c3fb27SDimitry Andric const ConstantInt *CMask = cast<ConstantInt>(Src1); 91006c3fb27SDimitry Andric FPClassTest Mask = static_cast<FPClassTest>(CMask->getZExtValue()); 91106c3fb27SDimitry Andric const bool IsUnordered = (Mask & fcNan) == fcNan; 91206c3fb27SDimitry Andric const bool IsOrdered = (Mask & fcNan) == fcNone; 91306c3fb27SDimitry Andric const FPClassTest OrderedMask = Mask & ~fcNan; 91406c3fb27SDimitry Andric const FPClassTest OrderedInvertedMask = ~OrderedMask & ~fcNan; 91506c3fb27SDimitry Andric 9160fca6ea1SDimitry Andric const bool IsStrict = 9170fca6ea1SDimitry Andric II.getFunction()->getAttributes().hasFnAttr(Attribute::StrictFP); 91806c3fb27SDimitry Andric 91906c3fb27SDimitry Andric Value *FNegSrc; 92006c3fb27SDimitry Andric if (match(Src0, m_FNeg(m_Value(FNegSrc)))) { 92106c3fb27SDimitry Andric // is.fpclass (fneg x), mask -> is.fpclass x, (fneg mask) 92206c3fb27SDimitry Andric 92306c3fb27SDimitry Andric II.setArgOperand(1, ConstantInt::get(Src1->getType(), fneg(Mask))); 92406c3fb27SDimitry Andric return replaceOperand(II, 0, FNegSrc); 92506c3fb27SDimitry Andric } 92606c3fb27SDimitry Andric 92706c3fb27SDimitry Andric Value *FAbsSrc; 92806c3fb27SDimitry Andric if (match(Src0, m_FAbs(m_Value(FAbsSrc)))) { 9295f757f3fSDimitry Andric II.setArgOperand(1, ConstantInt::get(Src1->getType(), inverse_fabs(Mask))); 93006c3fb27SDimitry Andric return replaceOperand(II, 0, FAbsSrc); 93106c3fb27SDimitry Andric } 93206c3fb27SDimitry Andric 9335f757f3fSDimitry Andric if ((OrderedMask == fcInf || OrderedInvertedMask == fcInf) && 9345f757f3fSDimitry Andric (IsOrdered || IsUnordered) && !IsStrict) { 9355f757f3fSDimitry Andric // is.fpclass(x, fcInf) -> fcmp oeq fabs(x), +inf 9365f757f3fSDimitry Andric // is.fpclass(x, ~fcInf) -> fcmp one fabs(x), +inf 9375f757f3fSDimitry Andric // is.fpclass(x, fcInf|fcNan) -> fcmp ueq fabs(x), +inf 9385f757f3fSDimitry Andric // is.fpclass(x, ~(fcInf|fcNan)) -> fcmp une fabs(x), +inf 9395f757f3fSDimitry Andric Constant *Inf = ConstantFP::getInfinity(Src0->getType()); 9405f757f3fSDimitry Andric FCmpInst::Predicate Pred = 9415f757f3fSDimitry Andric IsUnordered ? FCmpInst::FCMP_UEQ : FCmpInst::FCMP_OEQ; 9425f757f3fSDimitry Andric if (OrderedInvertedMask == fcInf) 9435f757f3fSDimitry Andric Pred = IsUnordered ? FCmpInst::FCMP_UNE : FCmpInst::FCMP_ONE; 9445f757f3fSDimitry Andric 9455f757f3fSDimitry Andric Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, Src0); 9465f757f3fSDimitry Andric Value *CmpInf = Builder.CreateFCmp(Pred, Fabs, Inf); 9475f757f3fSDimitry Andric CmpInf->takeName(&II); 9485f757f3fSDimitry Andric return replaceInstUsesWith(II, CmpInf); 9495f757f3fSDimitry Andric } 95006c3fb27SDimitry Andric 95106c3fb27SDimitry Andric if ((OrderedMask == fcPosInf || OrderedMask == fcNegInf) && 95206c3fb27SDimitry Andric (IsOrdered || IsUnordered) && !IsStrict) { 95306c3fb27SDimitry Andric // is.fpclass(x, fcPosInf) -> fcmp oeq x, +inf 95406c3fb27SDimitry Andric // is.fpclass(x, fcNegInf) -> fcmp oeq x, -inf 95506c3fb27SDimitry Andric // is.fpclass(x, fcPosInf|fcNan) -> fcmp ueq x, +inf 95606c3fb27SDimitry Andric // is.fpclass(x, fcNegInf|fcNan) -> fcmp ueq x, -inf 95706c3fb27SDimitry Andric Constant *Inf = 95806c3fb27SDimitry Andric ConstantFP::getInfinity(Src0->getType(), OrderedMask == fcNegInf); 95906c3fb27SDimitry Andric Value *EqInf = IsUnordered ? Builder.CreateFCmpUEQ(Src0, Inf) 96006c3fb27SDimitry Andric : Builder.CreateFCmpOEQ(Src0, Inf); 96106c3fb27SDimitry Andric 96206c3fb27SDimitry Andric EqInf->takeName(&II); 96306c3fb27SDimitry Andric return replaceInstUsesWith(II, EqInf); 96406c3fb27SDimitry Andric } 96506c3fb27SDimitry Andric 96606c3fb27SDimitry Andric if ((OrderedInvertedMask == fcPosInf || OrderedInvertedMask == fcNegInf) && 96706c3fb27SDimitry Andric (IsOrdered || IsUnordered) && !IsStrict) { 96806c3fb27SDimitry Andric // is.fpclass(x, ~fcPosInf) -> fcmp one x, +inf 96906c3fb27SDimitry Andric // is.fpclass(x, ~fcNegInf) -> fcmp one x, -inf 97006c3fb27SDimitry Andric // is.fpclass(x, ~fcPosInf|fcNan) -> fcmp une x, +inf 97106c3fb27SDimitry Andric // is.fpclass(x, ~fcNegInf|fcNan) -> fcmp une x, -inf 97206c3fb27SDimitry Andric Constant *Inf = ConstantFP::getInfinity(Src0->getType(), 97306c3fb27SDimitry Andric OrderedInvertedMask == fcNegInf); 97406c3fb27SDimitry Andric Value *NeInf = IsUnordered ? Builder.CreateFCmpUNE(Src0, Inf) 97506c3fb27SDimitry Andric : Builder.CreateFCmpONE(Src0, Inf); 97606c3fb27SDimitry Andric NeInf->takeName(&II); 97706c3fb27SDimitry Andric return replaceInstUsesWith(II, NeInf); 97806c3fb27SDimitry Andric } 97906c3fb27SDimitry Andric 98006c3fb27SDimitry Andric if (Mask == fcNan && !IsStrict) { 98106c3fb27SDimitry Andric // Equivalent of isnan. Replace with standard fcmp if we don't care about FP 98206c3fb27SDimitry Andric // exceptions. 98306c3fb27SDimitry Andric Value *IsNan = 98406c3fb27SDimitry Andric Builder.CreateFCmpUNO(Src0, ConstantFP::getZero(Src0->getType())); 98506c3fb27SDimitry Andric IsNan->takeName(&II); 98606c3fb27SDimitry Andric return replaceInstUsesWith(II, IsNan); 98706c3fb27SDimitry Andric } 98806c3fb27SDimitry Andric 98906c3fb27SDimitry Andric if (Mask == (~fcNan & fcAllFlags) && !IsStrict) { 99006c3fb27SDimitry Andric // Equivalent of !isnan. Replace with standard fcmp. 99106c3fb27SDimitry Andric Value *FCmp = 99206c3fb27SDimitry Andric Builder.CreateFCmpORD(Src0, ConstantFP::getZero(Src0->getType())); 99306c3fb27SDimitry Andric FCmp->takeName(&II); 99406c3fb27SDimitry Andric return replaceInstUsesWith(II, FCmp); 99506c3fb27SDimitry Andric } 99606c3fb27SDimitry Andric 99706c3fb27SDimitry Andric FCmpInst::Predicate PredType = FCmpInst::BAD_FCMP_PREDICATE; 99806c3fb27SDimitry Andric 99906c3fb27SDimitry Andric // Try to replace with an fcmp with 0 100006c3fb27SDimitry Andric // 100106c3fb27SDimitry Andric // is.fpclass(x, fcZero) -> fcmp oeq x, 0.0 100206c3fb27SDimitry Andric // is.fpclass(x, fcZero | fcNan) -> fcmp ueq x, 0.0 100306c3fb27SDimitry Andric // is.fpclass(x, ~fcZero & ~fcNan) -> fcmp one x, 0.0 100406c3fb27SDimitry Andric // is.fpclass(x, ~fcZero) -> fcmp une x, 0.0 100506c3fb27SDimitry Andric // 100606c3fb27SDimitry Andric // is.fpclass(x, fcPosSubnormal | fcPosNormal | fcPosInf) -> fcmp ogt x, 0.0 100706c3fb27SDimitry Andric // is.fpclass(x, fcPositive | fcNegZero) -> fcmp oge x, 0.0 100806c3fb27SDimitry Andric // 100906c3fb27SDimitry Andric // is.fpclass(x, fcNegSubnormal | fcNegNormal | fcNegInf) -> fcmp olt x, 0.0 101006c3fb27SDimitry Andric // is.fpclass(x, fcNegative | fcPosZero) -> fcmp ole x, 0.0 101106c3fb27SDimitry Andric // 101206c3fb27SDimitry Andric if (!IsStrict && (IsOrdered || IsUnordered) && 101306c3fb27SDimitry Andric (PredType = fpclassTestIsFCmp0(OrderedMask, *II.getFunction(), 101406c3fb27SDimitry Andric Src0->getType())) != 101506c3fb27SDimitry Andric FCmpInst::BAD_FCMP_PREDICATE) { 101606c3fb27SDimitry Andric Constant *Zero = ConstantFP::getZero(Src0->getType()); 101706c3fb27SDimitry Andric // Equivalent of == 0. 101806c3fb27SDimitry Andric Value *FCmp = Builder.CreateFCmp( 101906c3fb27SDimitry Andric IsUnordered ? FCmpInst::getUnorderedPredicate(PredType) : PredType, 102006c3fb27SDimitry Andric Src0, Zero); 102106c3fb27SDimitry Andric 102206c3fb27SDimitry Andric FCmp->takeName(&II); 102306c3fb27SDimitry Andric return replaceInstUsesWith(II, FCmp); 102406c3fb27SDimitry Andric } 102506c3fb27SDimitry Andric 10265f757f3fSDimitry Andric KnownFPClass Known = computeKnownFPClass(Src0, Mask, &II); 102706c3fb27SDimitry Andric 102806c3fb27SDimitry Andric // Clear test bits we know must be false from the source value. 102906c3fb27SDimitry Andric // fp_class (nnan x), qnan|snan|other -> fp_class (nnan x), other 103006c3fb27SDimitry Andric // fp_class (ninf x), ninf|pinf|other -> fp_class (ninf x), other 103106c3fb27SDimitry Andric if ((Mask & Known.KnownFPClasses) != Mask) { 103206c3fb27SDimitry Andric II.setArgOperand( 103306c3fb27SDimitry Andric 1, ConstantInt::get(Src1->getType(), Mask & Known.KnownFPClasses)); 103406c3fb27SDimitry Andric return &II; 103506c3fb27SDimitry Andric } 103606c3fb27SDimitry Andric 103706c3fb27SDimitry Andric // If none of the tests which can return false are possible, fold to true. 103806c3fb27SDimitry Andric // fp_class (nnan x), ~(qnan|snan) -> true 103906c3fb27SDimitry Andric // fp_class (ninf x), ~(ninf|pinf) -> true 104006c3fb27SDimitry Andric if (Mask == Known.KnownFPClasses) 104106c3fb27SDimitry Andric return replaceInstUsesWith(II, ConstantInt::get(II.getType(), true)); 104206c3fb27SDimitry Andric 104306c3fb27SDimitry Andric return nullptr; 104406c3fb27SDimitry Andric } 104506c3fb27SDimitry Andric 10460fca6ea1SDimitry Andric static std::optional<bool> getKnownSign(Value *Op, const SimplifyQuery &SQ) { 10470fca6ea1SDimitry Andric KnownBits Known = computeKnownBits(Op, /*Depth=*/0, SQ); 1048e8d8bef9SDimitry Andric if (Known.isNonNegative()) 1049e8d8bef9SDimitry Andric return false; 1050e8d8bef9SDimitry Andric if (Known.isNegative()) 1051e8d8bef9SDimitry Andric return true; 1052e8d8bef9SDimitry Andric 105381ad6265SDimitry Andric Value *X, *Y; 105481ad6265SDimitry Andric if (match(Op, m_NSWSub(m_Value(X), m_Value(Y)))) 10550fca6ea1SDimitry Andric return isImpliedByDomCondition(ICmpInst::ICMP_SLT, X, Y, SQ.CxtI, SQ.DL); 105681ad6265SDimitry Andric 10570fca6ea1SDimitry Andric return std::nullopt; 1058e8d8bef9SDimitry Andric } 1059e8d8bef9SDimitry Andric 10600fca6ea1SDimitry Andric static std::optional<bool> getKnownSignOrZero(Value *Op, 10610fca6ea1SDimitry Andric const SimplifyQuery &SQ) { 10620fca6ea1SDimitry Andric if (std::optional<bool> Sign = getKnownSign(Op, SQ)) 10635f757f3fSDimitry Andric return Sign; 10645f757f3fSDimitry Andric 10655f757f3fSDimitry Andric Value *X, *Y; 10665f757f3fSDimitry Andric if (match(Op, m_NSWSub(m_Value(X), m_Value(Y)))) 10670fca6ea1SDimitry Andric return isImpliedByDomCondition(ICmpInst::ICMP_SLE, X, Y, SQ.CxtI, SQ.DL); 10685f757f3fSDimitry Andric 10695f757f3fSDimitry Andric return std::nullopt; 10705f757f3fSDimitry Andric } 10715f757f3fSDimitry Andric 107206c3fb27SDimitry Andric /// Return true if two values \p Op0 and \p Op1 are known to have the same sign. 10730fca6ea1SDimitry Andric static bool signBitMustBeTheSame(Value *Op0, Value *Op1, 10740fca6ea1SDimitry Andric const SimplifyQuery &SQ) { 10750fca6ea1SDimitry Andric std::optional<bool> Known1 = getKnownSign(Op1, SQ); 107606c3fb27SDimitry Andric if (!Known1) 107706c3fb27SDimitry Andric return false; 10780fca6ea1SDimitry Andric std::optional<bool> Known0 = getKnownSign(Op0, SQ); 107906c3fb27SDimitry Andric if (!Known0) 108006c3fb27SDimitry Andric return false; 108106c3fb27SDimitry Andric return *Known0 == *Known1; 108206c3fb27SDimitry Andric } 108306c3fb27SDimitry Andric 1084349cc55cSDimitry Andric /// Try to canonicalize min/max(X + C0, C1) as min/max(X, C1 - C0) + C0. This 1085349cc55cSDimitry Andric /// can trigger other combines. 1086349cc55cSDimitry Andric static Instruction *moveAddAfterMinMax(IntrinsicInst *II, 1087349cc55cSDimitry Andric InstCombiner::BuilderTy &Builder) { 1088349cc55cSDimitry Andric Intrinsic::ID MinMaxID = II->getIntrinsicID(); 1089349cc55cSDimitry Andric assert((MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin || 1090349cc55cSDimitry Andric MinMaxID == Intrinsic::umax || MinMaxID == Intrinsic::umin) && 1091349cc55cSDimitry Andric "Expected a min or max intrinsic"); 1092349cc55cSDimitry Andric 1093349cc55cSDimitry Andric // TODO: Match vectors with undef elements, but undef may not propagate. 1094349cc55cSDimitry Andric Value *Op0 = II->getArgOperand(0), *Op1 = II->getArgOperand(1); 1095349cc55cSDimitry Andric Value *X; 1096349cc55cSDimitry Andric const APInt *C0, *C1; 1097349cc55cSDimitry Andric if (!match(Op0, m_OneUse(m_Add(m_Value(X), m_APInt(C0)))) || 1098349cc55cSDimitry Andric !match(Op1, m_APInt(C1))) 1099349cc55cSDimitry Andric return nullptr; 1100349cc55cSDimitry Andric 1101349cc55cSDimitry Andric // Check for necessary no-wrap and overflow constraints. 1102349cc55cSDimitry Andric bool IsSigned = MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin; 1103349cc55cSDimitry Andric auto *Add = cast<BinaryOperator>(Op0); 1104349cc55cSDimitry Andric if ((IsSigned && !Add->hasNoSignedWrap()) || 1105349cc55cSDimitry Andric (!IsSigned && !Add->hasNoUnsignedWrap())) 1106349cc55cSDimitry Andric return nullptr; 1107349cc55cSDimitry Andric 1108349cc55cSDimitry Andric // If the constant difference overflows, then instsimplify should reduce the 1109349cc55cSDimitry Andric // min/max to the add or C1. 1110349cc55cSDimitry Andric bool Overflow; 1111349cc55cSDimitry Andric APInt CDiff = 1112349cc55cSDimitry Andric IsSigned ? C1->ssub_ov(*C0, Overflow) : C1->usub_ov(*C0, Overflow); 1113349cc55cSDimitry Andric assert(!Overflow && "Expected simplify of min/max"); 1114349cc55cSDimitry Andric 1115349cc55cSDimitry Andric // min/max (add X, C0), C1 --> add (min/max X, C1 - C0), C0 1116349cc55cSDimitry Andric // Note: the "mismatched" no-overflow setting does not propagate. 1117349cc55cSDimitry Andric Constant *NewMinMaxC = ConstantInt::get(II->getType(), CDiff); 1118349cc55cSDimitry Andric Value *NewMinMax = Builder.CreateBinaryIntrinsic(MinMaxID, X, NewMinMaxC); 1119349cc55cSDimitry Andric return IsSigned ? BinaryOperator::CreateNSWAdd(NewMinMax, Add->getOperand(1)) 1120349cc55cSDimitry Andric : BinaryOperator::CreateNUWAdd(NewMinMax, Add->getOperand(1)); 1121349cc55cSDimitry Andric } 112281ad6265SDimitry Andric /// Match a sadd_sat or ssub_sat which is using min/max to clamp the value. 112381ad6265SDimitry Andric Instruction *InstCombinerImpl::matchSAddSubSat(IntrinsicInst &MinMax1) { 112481ad6265SDimitry Andric Type *Ty = MinMax1.getType(); 112581ad6265SDimitry Andric 112681ad6265SDimitry Andric // We are looking for a tree of: 112781ad6265SDimitry Andric // max(INT_MIN, min(INT_MAX, add(sext(A), sext(B)))) 112881ad6265SDimitry Andric // Where the min and max could be reversed 112981ad6265SDimitry Andric Instruction *MinMax2; 113081ad6265SDimitry Andric BinaryOperator *AddSub; 113181ad6265SDimitry Andric const APInt *MinValue, *MaxValue; 113281ad6265SDimitry Andric if (match(&MinMax1, m_SMin(m_Instruction(MinMax2), m_APInt(MaxValue)))) { 113381ad6265SDimitry Andric if (!match(MinMax2, m_SMax(m_BinOp(AddSub), m_APInt(MinValue)))) 113481ad6265SDimitry Andric return nullptr; 113581ad6265SDimitry Andric } else if (match(&MinMax1, 113681ad6265SDimitry Andric m_SMax(m_Instruction(MinMax2), m_APInt(MinValue)))) { 113781ad6265SDimitry Andric if (!match(MinMax2, m_SMin(m_BinOp(AddSub), m_APInt(MaxValue)))) 113881ad6265SDimitry Andric return nullptr; 113981ad6265SDimitry Andric } else 114081ad6265SDimitry Andric return nullptr; 114181ad6265SDimitry Andric 114281ad6265SDimitry Andric // Check that the constants clamp a saturate, and that the new type would be 114381ad6265SDimitry Andric // sensible to convert to. 114481ad6265SDimitry Andric if (!(*MaxValue + 1).isPowerOf2() || -*MinValue != *MaxValue + 1) 114581ad6265SDimitry Andric return nullptr; 114681ad6265SDimitry Andric // In what bitwidth can this be treated as saturating arithmetics? 114781ad6265SDimitry Andric unsigned NewBitWidth = (*MaxValue + 1).logBase2() + 1; 114881ad6265SDimitry Andric // FIXME: This isn't quite right for vectors, but using the scalar type is a 114981ad6265SDimitry Andric // good first approximation for what should be done there. 115081ad6265SDimitry Andric if (!shouldChangeType(Ty->getScalarType()->getIntegerBitWidth(), NewBitWidth)) 115181ad6265SDimitry Andric return nullptr; 115281ad6265SDimitry Andric 115381ad6265SDimitry Andric // Also make sure that the inner min/max and the add/sub have one use. 115481ad6265SDimitry Andric if (!MinMax2->hasOneUse() || !AddSub->hasOneUse()) 115581ad6265SDimitry Andric return nullptr; 115681ad6265SDimitry Andric 115781ad6265SDimitry Andric // Create the new type (which can be a vector type) 115881ad6265SDimitry Andric Type *NewTy = Ty->getWithNewBitWidth(NewBitWidth); 115981ad6265SDimitry Andric 116081ad6265SDimitry Andric Intrinsic::ID IntrinsicID; 116181ad6265SDimitry Andric if (AddSub->getOpcode() == Instruction::Add) 116281ad6265SDimitry Andric IntrinsicID = Intrinsic::sadd_sat; 116381ad6265SDimitry Andric else if (AddSub->getOpcode() == Instruction::Sub) 116481ad6265SDimitry Andric IntrinsicID = Intrinsic::ssub_sat; 116581ad6265SDimitry Andric else 116681ad6265SDimitry Andric return nullptr; 116781ad6265SDimitry Andric 116881ad6265SDimitry Andric // The two operands of the add/sub must be nsw-truncatable to the NewTy. This 116981ad6265SDimitry Andric // is usually achieved via a sext from a smaller type. 117081ad6265SDimitry Andric if (ComputeMaxSignificantBits(AddSub->getOperand(0), 0, AddSub) > 117181ad6265SDimitry Andric NewBitWidth || 117281ad6265SDimitry Andric ComputeMaxSignificantBits(AddSub->getOperand(1), 0, AddSub) > NewBitWidth) 117381ad6265SDimitry Andric return nullptr; 117481ad6265SDimitry Andric 117581ad6265SDimitry Andric // Finally create and return the sat intrinsic, truncated to the new type 117681ad6265SDimitry Andric Function *F = Intrinsic::getDeclaration(MinMax1.getModule(), IntrinsicID, NewTy); 117781ad6265SDimitry Andric Value *AT = Builder.CreateTrunc(AddSub->getOperand(0), NewTy); 117881ad6265SDimitry Andric Value *BT = Builder.CreateTrunc(AddSub->getOperand(1), NewTy); 117981ad6265SDimitry Andric Value *Sat = Builder.CreateCall(F, {AT, BT}); 118081ad6265SDimitry Andric return CastInst::Create(Instruction::SExt, Sat, Ty); 118181ad6265SDimitry Andric } 118281ad6265SDimitry Andric 1183349cc55cSDimitry Andric 1184fe6060f1SDimitry Andric /// If we have a clamp pattern like max (min X, 42), 41 -- where the output 1185fe6060f1SDimitry Andric /// can only be one of two possible constant values -- turn that into a select 1186fe6060f1SDimitry Andric /// of constants. 1187fe6060f1SDimitry Andric static Instruction *foldClampRangeOfTwo(IntrinsicInst *II, 1188fe6060f1SDimitry Andric InstCombiner::BuilderTy &Builder) { 1189fe6060f1SDimitry Andric Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1); 1190fe6060f1SDimitry Andric Value *X; 1191fe6060f1SDimitry Andric const APInt *C0, *C1; 1192fe6060f1SDimitry Andric if (!match(I1, m_APInt(C1)) || !I0->hasOneUse()) 1193fe6060f1SDimitry Andric return nullptr; 1194fe6060f1SDimitry Andric 1195fe6060f1SDimitry Andric CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; 1196fe6060f1SDimitry Andric switch (II->getIntrinsicID()) { 1197fe6060f1SDimitry Andric case Intrinsic::smax: 1198fe6060f1SDimitry Andric if (match(I0, m_SMin(m_Value(X), m_APInt(C0))) && *C0 == *C1 + 1) 1199fe6060f1SDimitry Andric Pred = ICmpInst::ICMP_SGT; 1200fe6060f1SDimitry Andric break; 1201fe6060f1SDimitry Andric case Intrinsic::smin: 1202fe6060f1SDimitry Andric if (match(I0, m_SMax(m_Value(X), m_APInt(C0))) && *C1 == *C0 + 1) 1203fe6060f1SDimitry Andric Pred = ICmpInst::ICMP_SLT; 1204fe6060f1SDimitry Andric break; 1205fe6060f1SDimitry Andric case Intrinsic::umax: 1206fe6060f1SDimitry Andric if (match(I0, m_UMin(m_Value(X), m_APInt(C0))) && *C0 == *C1 + 1) 1207fe6060f1SDimitry Andric Pred = ICmpInst::ICMP_UGT; 1208fe6060f1SDimitry Andric break; 1209fe6060f1SDimitry Andric case Intrinsic::umin: 1210fe6060f1SDimitry Andric if (match(I0, m_UMax(m_Value(X), m_APInt(C0))) && *C1 == *C0 + 1) 1211fe6060f1SDimitry Andric Pred = ICmpInst::ICMP_ULT; 1212fe6060f1SDimitry Andric break; 1213fe6060f1SDimitry Andric default: 1214fe6060f1SDimitry Andric llvm_unreachable("Expected min/max intrinsic"); 1215fe6060f1SDimitry Andric } 1216fe6060f1SDimitry Andric if (Pred == CmpInst::BAD_ICMP_PREDICATE) 1217fe6060f1SDimitry Andric return nullptr; 1218fe6060f1SDimitry Andric 1219fe6060f1SDimitry Andric // max (min X, 42), 41 --> X > 41 ? 42 : 41 1220fe6060f1SDimitry Andric // min (max X, 42), 43 --> X < 43 ? 42 : 43 1221fe6060f1SDimitry Andric Value *Cmp = Builder.CreateICmp(Pred, X, I1); 1222fe6060f1SDimitry Andric return SelectInst::Create(Cmp, ConstantInt::get(II->getType(), *C0), I1); 1223fe6060f1SDimitry Andric } 1224fe6060f1SDimitry Andric 122581ad6265SDimitry Andric /// If this min/max has a constant operand and an operand that is a matching 122681ad6265SDimitry Andric /// min/max with a constant operand, constant-fold the 2 constant operands. 122706c3fb27SDimitry Andric static Value *reassociateMinMaxWithConstants(IntrinsicInst *II, 12280fca6ea1SDimitry Andric IRBuilderBase &Builder, 12290fca6ea1SDimitry Andric const SimplifyQuery &SQ) { 123081ad6265SDimitry Andric Intrinsic::ID MinMaxID = II->getIntrinsicID(); 12310fca6ea1SDimitry Andric auto *LHS = dyn_cast<MinMaxIntrinsic>(II->getArgOperand(0)); 12320fca6ea1SDimitry Andric if (!LHS) 123381ad6265SDimitry Andric return nullptr; 123481ad6265SDimitry Andric 123581ad6265SDimitry Andric Constant *C0, *C1; 123681ad6265SDimitry Andric if (!match(LHS->getArgOperand(1), m_ImmConstant(C0)) || 123781ad6265SDimitry Andric !match(II->getArgOperand(1), m_ImmConstant(C1))) 123881ad6265SDimitry Andric return nullptr; 123981ad6265SDimitry Andric 12400fca6ea1SDimitry Andric // max (max X, C0), C1 --> max X, (max C0, C1) 12410fca6ea1SDimitry Andric // min (min X, C0), C1 --> min X, (min C0, C1) 12420fca6ea1SDimitry Andric // umax (smax X, nneg C0), nneg C1 --> smax X, (umax C0, C1) 12430fca6ea1SDimitry Andric // smin (umin X, nneg C0), nneg C1 --> umin X, (smin C0, C1) 12440fca6ea1SDimitry Andric Intrinsic::ID InnerMinMaxID = LHS->getIntrinsicID(); 12450fca6ea1SDimitry Andric if (InnerMinMaxID != MinMaxID && 12460fca6ea1SDimitry Andric !(((MinMaxID == Intrinsic::umax && InnerMinMaxID == Intrinsic::smax) || 12470fca6ea1SDimitry Andric (MinMaxID == Intrinsic::smin && InnerMinMaxID == Intrinsic::umin)) && 12480fca6ea1SDimitry Andric isKnownNonNegative(C0, SQ) && isKnownNonNegative(C1, SQ))) 12490fca6ea1SDimitry Andric return nullptr; 12500fca6ea1SDimitry Andric 125181ad6265SDimitry Andric ICmpInst::Predicate Pred = MinMaxIntrinsic::getPredicate(MinMaxID); 125206c3fb27SDimitry Andric Value *CondC = Builder.CreateICmp(Pred, C0, C1); 125306c3fb27SDimitry Andric Value *NewC = Builder.CreateSelect(CondC, C0, C1); 12540fca6ea1SDimitry Andric return Builder.CreateIntrinsic(InnerMinMaxID, II->getType(), 125506c3fb27SDimitry Andric {LHS->getArgOperand(0), NewC}); 125681ad6265SDimitry Andric } 125781ad6265SDimitry Andric 125881ad6265SDimitry Andric /// If this min/max has a matching min/max operand with a constant, try to push 125981ad6265SDimitry Andric /// the constant operand into this instruction. This can enable more folds. 126081ad6265SDimitry Andric static Instruction * 126181ad6265SDimitry Andric reassociateMinMaxWithConstantInOperand(IntrinsicInst *II, 126281ad6265SDimitry Andric InstCombiner::BuilderTy &Builder) { 126381ad6265SDimitry Andric // Match and capture a min/max operand candidate. 126481ad6265SDimitry Andric Value *X, *Y; 126581ad6265SDimitry Andric Constant *C; 126681ad6265SDimitry Andric Instruction *Inner; 126781ad6265SDimitry Andric if (!match(II, m_c_MaxOrMin(m_OneUse(m_CombineAnd( 126881ad6265SDimitry Andric m_Instruction(Inner), 126981ad6265SDimitry Andric m_MaxOrMin(m_Value(X), m_ImmConstant(C)))), 127081ad6265SDimitry Andric m_Value(Y)))) 127181ad6265SDimitry Andric return nullptr; 127281ad6265SDimitry Andric 127381ad6265SDimitry Andric // The inner op must match. Check for constants to avoid infinite loops. 127481ad6265SDimitry Andric Intrinsic::ID MinMaxID = II->getIntrinsicID(); 127581ad6265SDimitry Andric auto *InnerMM = dyn_cast<IntrinsicInst>(Inner); 127681ad6265SDimitry Andric if (!InnerMM || InnerMM->getIntrinsicID() != MinMaxID || 127781ad6265SDimitry Andric match(X, m_ImmConstant()) || match(Y, m_ImmConstant())) 127881ad6265SDimitry Andric return nullptr; 127981ad6265SDimitry Andric 128081ad6265SDimitry Andric // max (max X, C), Y --> max (max X, Y), C 128181ad6265SDimitry Andric Function *MinMax = 128281ad6265SDimitry Andric Intrinsic::getDeclaration(II->getModule(), MinMaxID, II->getType()); 128381ad6265SDimitry Andric Value *NewInner = Builder.CreateBinaryIntrinsic(MinMaxID, X, Y); 128481ad6265SDimitry Andric NewInner->takeName(Inner); 128581ad6265SDimitry Andric return CallInst::Create(MinMax, {NewInner, C}); 128681ad6265SDimitry Andric } 128781ad6265SDimitry Andric 1288349cc55cSDimitry Andric /// Reduce a sequence of min/max intrinsics with a common operand. 1289349cc55cSDimitry Andric static Instruction *factorizeMinMaxTree(IntrinsicInst *II) { 1290349cc55cSDimitry Andric // Match 3 of the same min/max ops. Example: umin(umin(), umin()). 1291349cc55cSDimitry Andric auto *LHS = dyn_cast<IntrinsicInst>(II->getArgOperand(0)); 1292349cc55cSDimitry Andric auto *RHS = dyn_cast<IntrinsicInst>(II->getArgOperand(1)); 1293349cc55cSDimitry Andric Intrinsic::ID MinMaxID = II->getIntrinsicID(); 1294349cc55cSDimitry Andric if (!LHS || !RHS || LHS->getIntrinsicID() != MinMaxID || 1295349cc55cSDimitry Andric RHS->getIntrinsicID() != MinMaxID || 1296349cc55cSDimitry Andric (!LHS->hasOneUse() && !RHS->hasOneUse())) 1297349cc55cSDimitry Andric return nullptr; 1298349cc55cSDimitry Andric 1299349cc55cSDimitry Andric Value *A = LHS->getArgOperand(0); 1300349cc55cSDimitry Andric Value *B = LHS->getArgOperand(1); 1301349cc55cSDimitry Andric Value *C = RHS->getArgOperand(0); 1302349cc55cSDimitry Andric Value *D = RHS->getArgOperand(1); 1303349cc55cSDimitry Andric 1304349cc55cSDimitry Andric // Look for a common operand. 1305349cc55cSDimitry Andric Value *MinMaxOp = nullptr; 1306349cc55cSDimitry Andric Value *ThirdOp = nullptr; 1307349cc55cSDimitry Andric if (LHS->hasOneUse()) { 1308349cc55cSDimitry Andric // If the LHS is only used in this chain and the RHS is used outside of it, 1309349cc55cSDimitry Andric // reuse the RHS min/max because that will eliminate the LHS. 1310349cc55cSDimitry Andric if (D == A || C == A) { 1311349cc55cSDimitry Andric // min(min(a, b), min(c, a)) --> min(min(c, a), b) 1312349cc55cSDimitry Andric // min(min(a, b), min(a, d)) --> min(min(a, d), b) 1313349cc55cSDimitry Andric MinMaxOp = RHS; 1314349cc55cSDimitry Andric ThirdOp = B; 1315349cc55cSDimitry Andric } else if (D == B || C == B) { 1316349cc55cSDimitry Andric // min(min(a, b), min(c, b)) --> min(min(c, b), a) 1317349cc55cSDimitry Andric // min(min(a, b), min(b, d)) --> min(min(b, d), a) 1318349cc55cSDimitry Andric MinMaxOp = RHS; 1319349cc55cSDimitry Andric ThirdOp = A; 1320349cc55cSDimitry Andric } 1321349cc55cSDimitry Andric } else { 1322349cc55cSDimitry Andric assert(RHS->hasOneUse() && "Expected one-use operand"); 1323349cc55cSDimitry Andric // Reuse the LHS. This will eliminate the RHS. 1324349cc55cSDimitry Andric if (D == A || D == B) { 1325349cc55cSDimitry Andric // min(min(a, b), min(c, a)) --> min(min(a, b), c) 1326349cc55cSDimitry Andric // min(min(a, b), min(c, b)) --> min(min(a, b), c) 1327349cc55cSDimitry Andric MinMaxOp = LHS; 1328349cc55cSDimitry Andric ThirdOp = C; 1329349cc55cSDimitry Andric } else if (C == A || C == B) { 1330349cc55cSDimitry Andric // min(min(a, b), min(b, d)) --> min(min(a, b), d) 1331349cc55cSDimitry Andric // min(min(a, b), min(c, b)) --> min(min(a, b), d) 1332349cc55cSDimitry Andric MinMaxOp = LHS; 1333349cc55cSDimitry Andric ThirdOp = D; 1334349cc55cSDimitry Andric } 1335349cc55cSDimitry Andric } 1336349cc55cSDimitry Andric 1337349cc55cSDimitry Andric if (!MinMaxOp || !ThirdOp) 1338349cc55cSDimitry Andric return nullptr; 1339349cc55cSDimitry Andric 1340349cc55cSDimitry Andric Module *Mod = II->getModule(); 1341349cc55cSDimitry Andric Function *MinMax = Intrinsic::getDeclaration(Mod, MinMaxID, II->getType()); 1342349cc55cSDimitry Andric return CallInst::Create(MinMax, { MinMaxOp, ThirdOp }); 1343349cc55cSDimitry Andric } 1344349cc55cSDimitry Andric 134581ad6265SDimitry Andric /// If all arguments of the intrinsic are unary shuffles with the same mask, 134681ad6265SDimitry Andric /// try to shuffle after the intrinsic. 134781ad6265SDimitry Andric static Instruction * 134881ad6265SDimitry Andric foldShuffledIntrinsicOperands(IntrinsicInst *II, 134981ad6265SDimitry Andric InstCombiner::BuilderTy &Builder) { 135081ad6265SDimitry Andric // TODO: This should be extended to handle other intrinsics like fshl, ctpop, 135181ad6265SDimitry Andric // etc. Use llvm::isTriviallyVectorizable() and related to determine 135281ad6265SDimitry Andric // which intrinsics are safe to shuffle? 135381ad6265SDimitry Andric switch (II->getIntrinsicID()) { 135481ad6265SDimitry Andric case Intrinsic::smax: 135581ad6265SDimitry Andric case Intrinsic::smin: 135681ad6265SDimitry Andric case Intrinsic::umax: 135781ad6265SDimitry Andric case Intrinsic::umin: 135881ad6265SDimitry Andric case Intrinsic::fma: 135981ad6265SDimitry Andric case Intrinsic::fshl: 136081ad6265SDimitry Andric case Intrinsic::fshr: 136181ad6265SDimitry Andric break; 136281ad6265SDimitry Andric default: 136381ad6265SDimitry Andric return nullptr; 136481ad6265SDimitry Andric } 136581ad6265SDimitry Andric 136681ad6265SDimitry Andric Value *X; 136781ad6265SDimitry Andric ArrayRef<int> Mask; 136881ad6265SDimitry Andric if (!match(II->getArgOperand(0), 136981ad6265SDimitry Andric m_Shuffle(m_Value(X), m_Undef(), m_Mask(Mask)))) 137081ad6265SDimitry Andric return nullptr; 137181ad6265SDimitry Andric 137281ad6265SDimitry Andric // At least 1 operand must have 1 use because we are creating 2 instructions. 137381ad6265SDimitry Andric if (none_of(II->args(), [](Value *V) { return V->hasOneUse(); })) 137481ad6265SDimitry Andric return nullptr; 137581ad6265SDimitry Andric 137681ad6265SDimitry Andric // See if all arguments are shuffled with the same mask. 137781ad6265SDimitry Andric SmallVector<Value *, 4> NewArgs(II->arg_size()); 137881ad6265SDimitry Andric NewArgs[0] = X; 137981ad6265SDimitry Andric Type *SrcTy = X->getType(); 138081ad6265SDimitry Andric for (unsigned i = 1, e = II->arg_size(); i != e; ++i) { 138181ad6265SDimitry Andric if (!match(II->getArgOperand(i), 138281ad6265SDimitry Andric m_Shuffle(m_Value(X), m_Undef(), m_SpecificMask(Mask))) || 138381ad6265SDimitry Andric X->getType() != SrcTy) 138481ad6265SDimitry Andric return nullptr; 138581ad6265SDimitry Andric NewArgs[i] = X; 138681ad6265SDimitry Andric } 138781ad6265SDimitry Andric 138881ad6265SDimitry Andric // intrinsic (shuf X, M), (shuf Y, M), ... --> shuf (intrinsic X, Y, ...), M 138981ad6265SDimitry Andric Instruction *FPI = isa<FPMathOperator>(II) ? II : nullptr; 139081ad6265SDimitry Andric Value *NewIntrinsic = 139181ad6265SDimitry Andric Builder.CreateIntrinsic(II->getIntrinsicID(), SrcTy, NewArgs, FPI); 139281ad6265SDimitry Andric return new ShuffleVectorInst(NewIntrinsic, Mask); 139381ad6265SDimitry Andric } 139481ad6265SDimitry Andric 139506c3fb27SDimitry Andric /// Fold the following cases and accepts bswap and bitreverse intrinsics: 139606c3fb27SDimitry Andric /// bswap(logic_op(bswap(x), y)) --> logic_op(x, bswap(y)) 139706c3fb27SDimitry Andric /// bswap(logic_op(bswap(x), bswap(y))) --> logic_op(x, y) (ignores multiuse) 139806c3fb27SDimitry Andric template <Intrinsic::ID IntrID> 139906c3fb27SDimitry Andric static Instruction *foldBitOrderCrossLogicOp(Value *V, 140006c3fb27SDimitry Andric InstCombiner::BuilderTy &Builder) { 140106c3fb27SDimitry Andric static_assert(IntrID == Intrinsic::bswap || IntrID == Intrinsic::bitreverse, 140206c3fb27SDimitry Andric "This helper only supports BSWAP and BITREVERSE intrinsics"); 140306c3fb27SDimitry Andric 140406c3fb27SDimitry Andric Value *X, *Y; 140506c3fb27SDimitry Andric // Find bitwise logic op. Check that it is a BinaryOperator explicitly so we 140606c3fb27SDimitry Andric // don't match ConstantExpr that aren't meaningful for this transform. 140706c3fb27SDimitry Andric if (match(V, m_OneUse(m_BitwiseLogic(m_Value(X), m_Value(Y)))) && 140806c3fb27SDimitry Andric isa<BinaryOperator>(V)) { 140906c3fb27SDimitry Andric Value *OldReorderX, *OldReorderY; 141006c3fb27SDimitry Andric BinaryOperator::BinaryOps Op = cast<BinaryOperator>(V)->getOpcode(); 141106c3fb27SDimitry Andric 141206c3fb27SDimitry Andric // If both X and Y are bswap/bitreverse, the transform reduces the number 141306c3fb27SDimitry Andric // of instructions even if there's multiuse. 141406c3fb27SDimitry Andric // If only one operand is bswap/bitreverse, we need to ensure the operand 141506c3fb27SDimitry Andric // have only one use. 141606c3fb27SDimitry Andric if (match(X, m_Intrinsic<IntrID>(m_Value(OldReorderX))) && 141706c3fb27SDimitry Andric match(Y, m_Intrinsic<IntrID>(m_Value(OldReorderY)))) { 141806c3fb27SDimitry Andric return BinaryOperator::Create(Op, OldReorderX, OldReorderY); 141906c3fb27SDimitry Andric } 142006c3fb27SDimitry Andric 142106c3fb27SDimitry Andric if (match(X, m_OneUse(m_Intrinsic<IntrID>(m_Value(OldReorderX))))) { 142206c3fb27SDimitry Andric Value *NewReorder = Builder.CreateUnaryIntrinsic(IntrID, Y); 142306c3fb27SDimitry Andric return BinaryOperator::Create(Op, OldReorderX, NewReorder); 142406c3fb27SDimitry Andric } 142506c3fb27SDimitry Andric 142606c3fb27SDimitry Andric if (match(Y, m_OneUse(m_Intrinsic<IntrID>(m_Value(OldReorderY))))) { 142706c3fb27SDimitry Andric Value *NewReorder = Builder.CreateUnaryIntrinsic(IntrID, X); 142806c3fb27SDimitry Andric return BinaryOperator::Create(Op, NewReorder, OldReorderY); 142906c3fb27SDimitry Andric } 143006c3fb27SDimitry Andric } 143106c3fb27SDimitry Andric return nullptr; 143206c3fb27SDimitry Andric } 143306c3fb27SDimitry Andric 14340fca6ea1SDimitry Andric static Value *simplifyReductionOperand(Value *Arg, bool CanReorderLanes) { 14350fca6ea1SDimitry Andric if (!CanReorderLanes) 14360fca6ea1SDimitry Andric return nullptr; 14370fca6ea1SDimitry Andric 14380fca6ea1SDimitry Andric Value *V; 14390fca6ea1SDimitry Andric if (match(Arg, m_VecReverse(m_Value(V)))) 14400fca6ea1SDimitry Andric return V; 14410fca6ea1SDimitry Andric 14420fca6ea1SDimitry Andric ArrayRef<int> Mask; 14430fca6ea1SDimitry Andric if (!isa<FixedVectorType>(Arg->getType()) || 14440fca6ea1SDimitry Andric !match(Arg, m_Shuffle(m_Value(V), m_Undef(), m_Mask(Mask))) || 14450fca6ea1SDimitry Andric !cast<ShuffleVectorInst>(Arg)->isSingleSource()) 14460fca6ea1SDimitry Andric return nullptr; 14470fca6ea1SDimitry Andric 14480fca6ea1SDimitry Andric int Sz = Mask.size(); 14490fca6ea1SDimitry Andric SmallBitVector UsedIndices(Sz); 14500fca6ea1SDimitry Andric for (int Idx : Mask) { 14510fca6ea1SDimitry Andric if (Idx == PoisonMaskElem || UsedIndices.test(Idx)) 14520fca6ea1SDimitry Andric return nullptr; 14530fca6ea1SDimitry Andric UsedIndices.set(Idx); 14540fca6ea1SDimitry Andric } 14550fca6ea1SDimitry Andric 14560fca6ea1SDimitry Andric // Can remove shuffle iff just shuffled elements, no repeats, undefs, or 14570fca6ea1SDimitry Andric // other changes. 14580fca6ea1SDimitry Andric return UsedIndices.all() ? V : nullptr; 14590fca6ea1SDimitry Andric } 14600fca6ea1SDimitry Andric 14610fca6ea1SDimitry Andric /// Fold an unsigned minimum of trailing or leading zero bits counts: 14620fca6ea1SDimitry Andric /// umin(cttz(CtOp, ZeroUndef), ConstOp) --> cttz(CtOp | (1 << ConstOp)) 14630fca6ea1SDimitry Andric /// umin(ctlz(CtOp, ZeroUndef), ConstOp) --> ctlz(CtOp | (SignedMin 14640fca6ea1SDimitry Andric /// >> ConstOp)) 14650fca6ea1SDimitry Andric template <Intrinsic::ID IntrID> 14660fca6ea1SDimitry Andric static Value * 14670fca6ea1SDimitry Andric foldMinimumOverTrailingOrLeadingZeroCount(Value *I0, Value *I1, 14680fca6ea1SDimitry Andric const DataLayout &DL, 14690fca6ea1SDimitry Andric InstCombiner::BuilderTy &Builder) { 14700fca6ea1SDimitry Andric static_assert(IntrID == Intrinsic::cttz || IntrID == Intrinsic::ctlz, 14710fca6ea1SDimitry Andric "This helper only supports cttz and ctlz intrinsics"); 14720fca6ea1SDimitry Andric 14730fca6ea1SDimitry Andric Value *CtOp; 14740fca6ea1SDimitry Andric Value *ZeroUndef; 14750fca6ea1SDimitry Andric if (!match(I0, 14760fca6ea1SDimitry Andric m_OneUse(m_Intrinsic<IntrID>(m_Value(CtOp), m_Value(ZeroUndef))))) 14770fca6ea1SDimitry Andric return nullptr; 14780fca6ea1SDimitry Andric 14790fca6ea1SDimitry Andric unsigned BitWidth = I1->getType()->getScalarSizeInBits(); 14800fca6ea1SDimitry Andric auto LessBitWidth = [BitWidth](auto &C) { return C.ult(BitWidth); }; 14810fca6ea1SDimitry Andric if (!match(I1, m_CheckedInt(LessBitWidth))) 14820fca6ea1SDimitry Andric // We have a constant >= BitWidth (which can be handled by CVP) 14830fca6ea1SDimitry Andric // or a non-splat vector with elements < and >= BitWidth 14840fca6ea1SDimitry Andric return nullptr; 14850fca6ea1SDimitry Andric 14860fca6ea1SDimitry Andric Type *Ty = I1->getType(); 14870fca6ea1SDimitry Andric Constant *NewConst = ConstantFoldBinaryOpOperands( 14880fca6ea1SDimitry Andric IntrID == Intrinsic::cttz ? Instruction::Shl : Instruction::LShr, 14890fca6ea1SDimitry Andric IntrID == Intrinsic::cttz 14900fca6ea1SDimitry Andric ? ConstantInt::get(Ty, 1) 14910fca6ea1SDimitry Andric : ConstantInt::get(Ty, APInt::getSignedMinValue(BitWidth)), 14920fca6ea1SDimitry Andric cast<Constant>(I1), DL); 14930fca6ea1SDimitry Andric return Builder.CreateBinaryIntrinsic( 14940fca6ea1SDimitry Andric IntrID, Builder.CreateOr(CtOp, NewConst), 14950fca6ea1SDimitry Andric ConstantInt::getTrue(ZeroUndef->getType())); 14960fca6ea1SDimitry Andric } 14970fca6ea1SDimitry Andric 14980b57cec5SDimitry Andric /// CallInst simplification. This mostly only handles folding of intrinsic 14990b57cec5SDimitry Andric /// instructions. For normal calls, it allows visitCallBase to do the heavy 15000b57cec5SDimitry Andric /// lifting. 1501e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { 15025ffd83dbSDimitry Andric // Don't try to simplify calls without uses. It will not do anything useful, 15035ffd83dbSDimitry Andric // but will result in the following folds being skipped. 150406c3fb27SDimitry Andric if (!CI.use_empty()) { 150506c3fb27SDimitry Andric SmallVector<Value *, 4> Args; 150606c3fb27SDimitry Andric Args.reserve(CI.arg_size()); 150706c3fb27SDimitry Andric for (Value *Op : CI.args()) 150806c3fb27SDimitry Andric Args.push_back(Op); 150906c3fb27SDimitry Andric if (Value *V = simplifyCall(&CI, CI.getCalledOperand(), Args, 151006c3fb27SDimitry Andric SQ.getWithInstruction(&CI))) 15110b57cec5SDimitry Andric return replaceInstUsesWith(CI, V); 151206c3fb27SDimitry Andric } 15130b57cec5SDimitry Andric 1514fcaf7f86SDimitry Andric if (Value *FreedOp = getFreedOperand(&CI, &TLI)) 1515fcaf7f86SDimitry Andric return visitFree(CI, FreedOp); 15160b57cec5SDimitry Andric 151781ad6265SDimitry Andric // If the caller function (i.e. us, the function that contains this CallInst) 151881ad6265SDimitry Andric // is nounwind, mark the call as nounwind, even if the callee isn't. 15190b57cec5SDimitry Andric if (CI.getFunction()->doesNotThrow() && !CI.doesNotThrow()) { 15200b57cec5SDimitry Andric CI.setDoesNotThrow(); 15210b57cec5SDimitry Andric return &CI; 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric IntrinsicInst *II = dyn_cast<IntrinsicInst>(&CI); 15250b57cec5SDimitry Andric if (!II) return visitCallBase(CI); 15260b57cec5SDimitry Andric 15275ffd83dbSDimitry Andric // For atomic unordered mem intrinsics if len is not a positive or 15285ffd83dbSDimitry Andric // not a multiple of element size then behavior is undefined. 15295ffd83dbSDimitry Andric if (auto *AMI = dyn_cast<AtomicMemIntrinsic>(II)) 15305ffd83dbSDimitry Andric if (ConstantInt *NumBytes = dyn_cast<ConstantInt>(AMI->getLength())) 153106c3fb27SDimitry Andric if (NumBytes->isNegative() || 15325ffd83dbSDimitry Andric (NumBytes->getZExtValue() % AMI->getElementSizeInBytes() != 0)) { 15335ffd83dbSDimitry Andric CreateNonTerminatorUnreachable(AMI); 15345ffd83dbSDimitry Andric assert(AMI->getType()->isVoidTy() && 15355ffd83dbSDimitry Andric "non void atomic unordered mem intrinsic"); 15365ffd83dbSDimitry Andric return eraseInstFromFunction(*AMI); 15375ffd83dbSDimitry Andric } 15385ffd83dbSDimitry Andric 15390b57cec5SDimitry Andric // Intrinsics cannot occur in an invoke or a callbr, so handle them here 15400b57cec5SDimitry Andric // instead of in visitCallBase. 15410b57cec5SDimitry Andric if (auto *MI = dyn_cast<AnyMemIntrinsic>(II)) { 15420b57cec5SDimitry Andric bool Changed = false; 15430b57cec5SDimitry Andric 15440b57cec5SDimitry Andric // memmove/cpy/set of zero bytes is a noop. 15450b57cec5SDimitry Andric if (Constant *NumBytes = dyn_cast<Constant>(MI->getLength())) { 15460b57cec5SDimitry Andric if (NumBytes->isNullValue()) 15470b57cec5SDimitry Andric return eraseInstFromFunction(CI); 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric // No other transformations apply to volatile transfers. 15510b57cec5SDimitry Andric if (auto *M = dyn_cast<MemIntrinsic>(MI)) 15520b57cec5SDimitry Andric if (M->isVolatile()) 15530b57cec5SDimitry Andric return nullptr; 15540b57cec5SDimitry Andric 15550b57cec5SDimitry Andric // If we have a memmove and the source operation is a constant global, 15560b57cec5SDimitry Andric // then the source and dest pointers can't alias, so we can change this 15570b57cec5SDimitry Andric // into a call to memcpy. 15580b57cec5SDimitry Andric if (auto *MMI = dyn_cast<AnyMemMoveInst>(MI)) { 15590b57cec5SDimitry Andric if (GlobalVariable *GVSrc = dyn_cast<GlobalVariable>(MMI->getSource())) 15600b57cec5SDimitry Andric if (GVSrc->isConstant()) { 15610b57cec5SDimitry Andric Module *M = CI.getModule(); 15620b57cec5SDimitry Andric Intrinsic::ID MemCpyID = 15630b57cec5SDimitry Andric isa<AtomicMemMoveInst>(MMI) 15640b57cec5SDimitry Andric ? Intrinsic::memcpy_element_unordered_atomic 15650b57cec5SDimitry Andric : Intrinsic::memcpy; 15660b57cec5SDimitry Andric Type *Tys[3] = { CI.getArgOperand(0)->getType(), 15670b57cec5SDimitry Andric CI.getArgOperand(1)->getType(), 15680b57cec5SDimitry Andric CI.getArgOperand(2)->getType() }; 15690b57cec5SDimitry Andric CI.setCalledFunction(Intrinsic::getDeclaration(M, MemCpyID, Tys)); 15700b57cec5SDimitry Andric Changed = true; 15710b57cec5SDimitry Andric } 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric if (AnyMemTransferInst *MTI = dyn_cast<AnyMemTransferInst>(MI)) { 15750b57cec5SDimitry Andric // memmove(x,x,size) -> noop. 15760b57cec5SDimitry Andric if (MTI->getSource() == MTI->getDest()) 15770b57cec5SDimitry Andric return eraseInstFromFunction(CI); 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric // If we can determine a pointer alignment that is bigger than currently 15810b57cec5SDimitry Andric // set, update the alignment. 15820b57cec5SDimitry Andric if (auto *MTI = dyn_cast<AnyMemTransferInst>(MI)) { 15830b57cec5SDimitry Andric if (Instruction *I = SimplifyAnyMemTransfer(MTI)) 15840b57cec5SDimitry Andric return I; 15850b57cec5SDimitry Andric } else if (auto *MSI = dyn_cast<AnyMemSetInst>(MI)) { 15860b57cec5SDimitry Andric if (Instruction *I = SimplifyAnyMemSet(MSI)) 15870b57cec5SDimitry Andric return I; 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric 15900b57cec5SDimitry Andric if (Changed) return II; 15910b57cec5SDimitry Andric } 15920b57cec5SDimitry Andric 15935ffd83dbSDimitry Andric // For fixed width vector result intrinsics, use the generic demanded vector 15945ffd83dbSDimitry Andric // support. 15955ffd83dbSDimitry Andric if (auto *IIFVTy = dyn_cast<FixedVectorType>(II->getType())) { 15965ffd83dbSDimitry Andric auto VWidth = IIFVTy->getNumElements(); 1597cb14a3feSDimitry Andric APInt PoisonElts(VWidth, 0); 1598349cc55cSDimitry Andric APInt AllOnesEltMask(APInt::getAllOnes(VWidth)); 1599cb14a3feSDimitry Andric if (Value *V = SimplifyDemandedVectorElts(II, AllOnesEltMask, PoisonElts)) { 16000b57cec5SDimitry Andric if (V != II) 16010b57cec5SDimitry Andric return replaceInstUsesWith(*II, V); 16020b57cec5SDimitry Andric return II; 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric } 16050b57cec5SDimitry Andric 1606e8d8bef9SDimitry Andric if (II->isCommutative()) { 16071db9f3b2SDimitry Andric if (auto Pair = matchSymmetricPair(II->getOperand(0), II->getOperand(1))) { 16081db9f3b2SDimitry Andric replaceOperand(*II, 0, Pair->first); 16091db9f3b2SDimitry Andric replaceOperand(*II, 1, Pair->second); 16101db9f3b2SDimitry Andric return II; 16111db9f3b2SDimitry Andric } 1612cb14a3feSDimitry Andric 1613e8d8bef9SDimitry Andric if (CallInst *NewCall = canonicalizeConstantArg0ToArg1(CI)) 1614e8d8bef9SDimitry Andric return NewCall; 1615e8d8bef9SDimitry Andric } 16160b57cec5SDimitry Andric 161781ad6265SDimitry Andric // Unused constrained FP intrinsic calls may have declared side effect, which 161881ad6265SDimitry Andric // prevents it from being removed. In some cases however the side effect is 161981ad6265SDimitry Andric // actually absent. To detect this case, call SimplifyConstrainedFPCall. If it 162081ad6265SDimitry Andric // returns a replacement, the call may be removed. 162181ad6265SDimitry Andric if (CI.use_empty() && isa<ConstrainedFPIntrinsic>(CI)) { 162281ad6265SDimitry Andric if (simplifyConstrainedFPCall(&CI, SQ.getWithInstruction(&CI))) 162381ad6265SDimitry Andric return eraseInstFromFunction(CI); 162481ad6265SDimitry Andric } 162581ad6265SDimitry Andric 16260b57cec5SDimitry Andric Intrinsic::ID IID = II->getIntrinsicID(); 16270b57cec5SDimitry Andric switch (IID) { 162806c3fb27SDimitry Andric case Intrinsic::objectsize: { 162906c3fb27SDimitry Andric SmallVector<Instruction *> InsertedInstructions; 163006c3fb27SDimitry Andric if (Value *V = lowerObjectSizeCall(II, DL, &TLI, AA, /*MustSucceed=*/false, 163106c3fb27SDimitry Andric &InsertedInstructions)) { 163206c3fb27SDimitry Andric for (Instruction *Inserted : InsertedInstructions) 163306c3fb27SDimitry Andric Worklist.add(Inserted); 16340b57cec5SDimitry Andric return replaceInstUsesWith(CI, V); 163506c3fb27SDimitry Andric } 16360b57cec5SDimitry Andric return nullptr; 163706c3fb27SDimitry Andric } 1638e8d8bef9SDimitry Andric case Intrinsic::abs: { 1639e8d8bef9SDimitry Andric Value *IIOperand = II->getArgOperand(0); 1640e8d8bef9SDimitry Andric bool IntMinIsPoison = cast<Constant>(II->getArgOperand(1))->isOneValue(); 1641e8d8bef9SDimitry Andric 1642e8d8bef9SDimitry Andric // abs(-x) -> abs(x) 1643e8d8bef9SDimitry Andric // TODO: Copy nsw if it was present on the neg? 1644e8d8bef9SDimitry Andric Value *X; 1645e8d8bef9SDimitry Andric if (match(IIOperand, m_Neg(m_Value(X)))) 1646e8d8bef9SDimitry Andric return replaceOperand(*II, 0, X); 1647e8d8bef9SDimitry Andric if (match(IIOperand, m_Select(m_Value(), m_Value(X), m_Neg(m_Deferred(X))))) 1648e8d8bef9SDimitry Andric return replaceOperand(*II, 0, X); 1649e8d8bef9SDimitry Andric if (match(IIOperand, m_Select(m_Value(), m_Neg(m_Value(X)), m_Deferred(X)))) 1650e8d8bef9SDimitry Andric return replaceOperand(*II, 0, X); 1651e8d8bef9SDimitry Andric 16520fca6ea1SDimitry Andric Value *Y; 16530fca6ea1SDimitry Andric // abs(a * abs(b)) -> abs(a * b) 16540fca6ea1SDimitry Andric if (match(IIOperand, 16550fca6ea1SDimitry Andric m_OneUse(m_c_Mul(m_Value(X), 16560fca6ea1SDimitry Andric m_Intrinsic<Intrinsic::abs>(m_Value(Y)))))) { 16570fca6ea1SDimitry Andric bool NSW = 16580fca6ea1SDimitry Andric cast<Instruction>(IIOperand)->hasNoSignedWrap() && IntMinIsPoison; 16590fca6ea1SDimitry Andric auto *XY = NSW ? Builder.CreateNSWMul(X, Y) : Builder.CreateMul(X, Y); 16600fca6ea1SDimitry Andric return replaceOperand(*II, 0, XY); 16610fca6ea1SDimitry Andric } 16620fca6ea1SDimitry Andric 16635f757f3fSDimitry Andric if (std::optional<bool> Known = 16640fca6ea1SDimitry Andric getKnownSignOrZero(IIOperand, SQ.getWithInstruction(II))) { 16655f757f3fSDimitry Andric // abs(x) -> x if x >= 0 (include abs(x-y) --> x - y where x >= y) 16665f757f3fSDimitry Andric // abs(x) -> x if x > 0 (include abs(x-y) --> x - y where x > y) 16675f757f3fSDimitry Andric if (!*Known) 1668e8d8bef9SDimitry Andric return replaceInstUsesWith(*II, IIOperand); 1669e8d8bef9SDimitry Andric 1670e8d8bef9SDimitry Andric // abs(x) -> -x if x < 0 16715f757f3fSDimitry Andric // abs(x) -> -x if x < = 0 (include abs(x-y) --> y - x where x <= y) 1672e8d8bef9SDimitry Andric if (IntMinIsPoison) 1673e8d8bef9SDimitry Andric return BinaryOperator::CreateNSWNeg(IIOperand); 1674e8d8bef9SDimitry Andric return BinaryOperator::CreateNeg(IIOperand); 1675e8d8bef9SDimitry Andric } 1676e8d8bef9SDimitry Andric 1677e8d8bef9SDimitry Andric // abs (sext X) --> zext (abs X*) 1678e8d8bef9SDimitry Andric // Clear the IsIntMin (nsw) bit on the abs to allow narrowing. 1679e8d8bef9SDimitry Andric if (match(IIOperand, m_OneUse(m_SExt(m_Value(X))))) { 1680e8d8bef9SDimitry Andric Value *NarrowAbs = 1681e8d8bef9SDimitry Andric Builder.CreateBinaryIntrinsic(Intrinsic::abs, X, Builder.getFalse()); 1682e8d8bef9SDimitry Andric return CastInst::Create(Instruction::ZExt, NarrowAbs, II->getType()); 1683e8d8bef9SDimitry Andric } 1684e8d8bef9SDimitry Andric 1685fe6060f1SDimitry Andric // Match a complicated way to check if a number is odd/even: 1686fe6060f1SDimitry Andric // abs (srem X, 2) --> and X, 1 1687fe6060f1SDimitry Andric const APInt *C; 1688fe6060f1SDimitry Andric if (match(IIOperand, m_SRem(m_Value(X), m_APInt(C))) && *C == 2) 1689fe6060f1SDimitry Andric return BinaryOperator::CreateAnd(X, ConstantInt::get(II->getType(), 1)); 1690fe6060f1SDimitry Andric 1691e8d8bef9SDimitry Andric break; 1692e8d8bef9SDimitry Andric } 1693e8d8bef9SDimitry Andric case Intrinsic::umin: { 1694e8d8bef9SDimitry Andric Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1); 1695fe6060f1SDimitry Andric // umin(x, 1) == zext(x != 0) 1696fe6060f1SDimitry Andric if (match(I1, m_One())) { 1697bdd1243dSDimitry Andric assert(II->getType()->getScalarSizeInBits() != 1 && 1698bdd1243dSDimitry Andric "Expected simplify of umin with max constant"); 1699fe6060f1SDimitry Andric Value *Zero = Constant::getNullValue(I0->getType()); 1700fe6060f1SDimitry Andric Value *Cmp = Builder.CreateICmpNE(I0, Zero); 1701fe6060f1SDimitry Andric return CastInst::Create(Instruction::ZExt, Cmp, II->getType()); 1702fe6060f1SDimitry Andric } 17030fca6ea1SDimitry Andric // umin(cttz(x), const) --> cttz(x | (1 << const)) 17040fca6ea1SDimitry Andric if (Value *FoldedCttz = 17050fca6ea1SDimitry Andric foldMinimumOverTrailingOrLeadingZeroCount<Intrinsic::cttz>( 17060fca6ea1SDimitry Andric I0, I1, DL, Builder)) 17070fca6ea1SDimitry Andric return replaceInstUsesWith(*II, FoldedCttz); 17080fca6ea1SDimitry Andric // umin(ctlz(x), const) --> ctlz(x | (SignedMin >> const)) 17090fca6ea1SDimitry Andric if (Value *FoldedCtlz = 17100fca6ea1SDimitry Andric foldMinimumOverTrailingOrLeadingZeroCount<Intrinsic::ctlz>( 17110fca6ea1SDimitry Andric I0, I1, DL, Builder)) 17120fca6ea1SDimitry Andric return replaceInstUsesWith(*II, FoldedCtlz); 1713bdd1243dSDimitry Andric [[fallthrough]]; 1714fe6060f1SDimitry Andric } 1715fe6060f1SDimitry Andric case Intrinsic::umax: { 1716fe6060f1SDimitry Andric Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1); 1717e8d8bef9SDimitry Andric Value *X, *Y; 1718e8d8bef9SDimitry Andric if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_ZExt(m_Value(Y))) && 1719e8d8bef9SDimitry Andric (I0->hasOneUse() || I1->hasOneUse()) && X->getType() == Y->getType()) { 1720e8d8bef9SDimitry Andric Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y); 1721e8d8bef9SDimitry Andric return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType()); 1722e8d8bef9SDimitry Andric } 1723fe6060f1SDimitry Andric Constant *C; 1724fe6060f1SDimitry Andric if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_Constant(C)) && 1725fe6060f1SDimitry Andric I0->hasOneUse()) { 17265f757f3fSDimitry Andric if (Constant *NarrowC = getLosslessUnsignedTrunc(C, X->getType())) { 1727fe6060f1SDimitry Andric Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC); 1728fe6060f1SDimitry Andric return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType()); 1729fe6060f1SDimitry Andric } 1730fe6060f1SDimitry Andric } 1731e8d8bef9SDimitry Andric // If both operands of unsigned min/max are sign-extended, it is still ok 1732e8d8bef9SDimitry Andric // to narrow the operation. 1733bdd1243dSDimitry Andric [[fallthrough]]; 1734e8d8bef9SDimitry Andric } 1735e8d8bef9SDimitry Andric case Intrinsic::smax: 1736e8d8bef9SDimitry Andric case Intrinsic::smin: { 1737e8d8bef9SDimitry Andric Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1); 1738e8d8bef9SDimitry Andric Value *X, *Y; 1739e8d8bef9SDimitry Andric if (match(I0, m_SExt(m_Value(X))) && match(I1, m_SExt(m_Value(Y))) && 1740e8d8bef9SDimitry Andric (I0->hasOneUse() || I1->hasOneUse()) && X->getType() == Y->getType()) { 1741e8d8bef9SDimitry Andric Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y); 1742e8d8bef9SDimitry Andric return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType()); 1743e8d8bef9SDimitry Andric } 1744fe6060f1SDimitry Andric 1745fe6060f1SDimitry Andric Constant *C; 1746fe6060f1SDimitry Andric if (match(I0, m_SExt(m_Value(X))) && match(I1, m_Constant(C)) && 1747fe6060f1SDimitry Andric I0->hasOneUse()) { 17485f757f3fSDimitry Andric if (Constant *NarrowC = getLosslessSignedTrunc(C, X->getType())) { 1749fe6060f1SDimitry Andric Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC); 1750fe6060f1SDimitry Andric return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType()); 1751fe6060f1SDimitry Andric } 1752fe6060f1SDimitry Andric } 1753fe6060f1SDimitry Andric 17545f757f3fSDimitry Andric // umin(i1 X, i1 Y) -> and i1 X, Y 17555f757f3fSDimitry Andric // smax(i1 X, i1 Y) -> and i1 X, Y 17565f757f3fSDimitry Andric if ((IID == Intrinsic::umin || IID == Intrinsic::smax) && 17575f757f3fSDimitry Andric II->getType()->isIntOrIntVectorTy(1)) { 17585f757f3fSDimitry Andric return BinaryOperator::CreateAnd(I0, I1); 17595f757f3fSDimitry Andric } 17605f757f3fSDimitry Andric 17615f757f3fSDimitry Andric // umax(i1 X, i1 Y) -> or i1 X, Y 17625f757f3fSDimitry Andric // smin(i1 X, i1 Y) -> or i1 X, Y 17635f757f3fSDimitry Andric if ((IID == Intrinsic::umax || IID == Intrinsic::smin) && 17645f757f3fSDimitry Andric II->getType()->isIntOrIntVectorTy(1)) { 17655f757f3fSDimitry Andric return BinaryOperator::CreateOr(I0, I1); 17665f757f3fSDimitry Andric } 17675f757f3fSDimitry Andric 1768349cc55cSDimitry Andric if (IID == Intrinsic::smax || IID == Intrinsic::smin) { 1769349cc55cSDimitry Andric // smax (neg nsw X), (neg nsw Y) --> neg nsw (smin X, Y) 1770349cc55cSDimitry Andric // smin (neg nsw X), (neg nsw Y) --> neg nsw (smax X, Y) 1771349cc55cSDimitry Andric // TODO: Canonicalize neg after min/max if I1 is constant. 1772349cc55cSDimitry Andric if (match(I0, m_NSWNeg(m_Value(X))) && match(I1, m_NSWNeg(m_Value(Y))) && 1773fe6060f1SDimitry Andric (I0->hasOneUse() || I1->hasOneUse())) { 1774349cc55cSDimitry Andric Intrinsic::ID InvID = getInverseMinMaxIntrinsic(IID); 1775fe6060f1SDimitry Andric Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, Y); 1776349cc55cSDimitry Andric return BinaryOperator::CreateNSWNeg(InvMaxMin); 1777349cc55cSDimitry Andric } 1778349cc55cSDimitry Andric } 1779349cc55cSDimitry Andric 178006c3fb27SDimitry Andric // (umax X, (xor X, Pow2)) 178106c3fb27SDimitry Andric // -> (or X, Pow2) 178206c3fb27SDimitry Andric // (umin X, (xor X, Pow2)) 178306c3fb27SDimitry Andric // -> (and X, ~Pow2) 178406c3fb27SDimitry Andric // (smax X, (xor X, Pos_Pow2)) 178506c3fb27SDimitry Andric // -> (or X, Pos_Pow2) 178606c3fb27SDimitry Andric // (smin X, (xor X, Pos_Pow2)) 178706c3fb27SDimitry Andric // -> (and X, ~Pos_Pow2) 178806c3fb27SDimitry Andric // (smax X, (xor X, Neg_Pow2)) 178906c3fb27SDimitry Andric // -> (and X, ~Neg_Pow2) 179006c3fb27SDimitry Andric // (smin X, (xor X, Neg_Pow2)) 179106c3fb27SDimitry Andric // -> (or X, Neg_Pow2) 179206c3fb27SDimitry Andric if ((match(I0, m_c_Xor(m_Specific(I1), m_Value(X))) || 179306c3fb27SDimitry Andric match(I1, m_c_Xor(m_Specific(I0), m_Value(X)))) && 179406c3fb27SDimitry Andric isKnownToBeAPowerOfTwo(X, /* OrZero */ true)) { 179506c3fb27SDimitry Andric bool UseOr = IID == Intrinsic::smax || IID == Intrinsic::umax; 179606c3fb27SDimitry Andric bool UseAndN = IID == Intrinsic::smin || IID == Intrinsic::umin; 179706c3fb27SDimitry Andric 179806c3fb27SDimitry Andric if (IID == Intrinsic::smax || IID == Intrinsic::smin) { 17990fca6ea1SDimitry Andric auto KnownSign = getKnownSign(X, SQ.getWithInstruction(II)); 180006c3fb27SDimitry Andric if (KnownSign == std::nullopt) { 180106c3fb27SDimitry Andric UseOr = false; 180206c3fb27SDimitry Andric UseAndN = false; 180306c3fb27SDimitry Andric } else if (*KnownSign /* true is Signed. */) { 180406c3fb27SDimitry Andric UseOr ^= true; 180506c3fb27SDimitry Andric UseAndN ^= true; 180606c3fb27SDimitry Andric Type *Ty = I0->getType(); 180706c3fb27SDimitry Andric // Negative power of 2 must be IntMin. It's possible to be able to 180806c3fb27SDimitry Andric // prove negative / power of 2 without actually having known bits, so 180906c3fb27SDimitry Andric // just get the value by hand. 181006c3fb27SDimitry Andric X = Constant::getIntegerValue( 181106c3fb27SDimitry Andric Ty, APInt::getSignedMinValue(Ty->getScalarSizeInBits())); 181206c3fb27SDimitry Andric } 181306c3fb27SDimitry Andric } 181406c3fb27SDimitry Andric if (UseOr) 181506c3fb27SDimitry Andric return BinaryOperator::CreateOr(I0, X); 181606c3fb27SDimitry Andric else if (UseAndN) 181706c3fb27SDimitry Andric return BinaryOperator::CreateAnd(I0, Builder.CreateNot(X)); 181806c3fb27SDimitry Andric } 181906c3fb27SDimitry Andric 1820349cc55cSDimitry Andric // If we can eliminate ~A and Y is free to invert: 1821349cc55cSDimitry Andric // max ~A, Y --> ~(min A, ~Y) 1822349cc55cSDimitry Andric // 1823349cc55cSDimitry Andric // Examples: 1824349cc55cSDimitry Andric // max ~A, ~Y --> ~(min A, Y) 1825349cc55cSDimitry Andric // max ~A, C --> ~(min A, ~C) 1826349cc55cSDimitry Andric // max ~A, (max ~Y, ~Z) --> ~min( A, (min Y, Z)) 1827349cc55cSDimitry Andric auto moveNotAfterMinMax = [&](Value *X, Value *Y) -> Instruction * { 1828349cc55cSDimitry Andric Value *A; 1829349cc55cSDimitry Andric if (match(X, m_OneUse(m_Not(m_Value(A)))) && 18305f757f3fSDimitry Andric !isFreeToInvert(A, A->hasOneUse())) { 18315f757f3fSDimitry Andric if (Value *NotY = getFreelyInverted(Y, Y->hasOneUse(), &Builder)) { 1832349cc55cSDimitry Andric Intrinsic::ID InvID = getInverseMinMaxIntrinsic(IID); 1833349cc55cSDimitry Andric Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, A, NotY); 1834fe6060f1SDimitry Andric return BinaryOperator::CreateNot(InvMaxMin); 1835fe6060f1SDimitry Andric } 18365f757f3fSDimitry Andric } 1837349cc55cSDimitry Andric return nullptr; 1838349cc55cSDimitry Andric }; 1839349cc55cSDimitry Andric 1840349cc55cSDimitry Andric if (Instruction *I = moveNotAfterMinMax(I0, I1)) 1841349cc55cSDimitry Andric return I; 1842349cc55cSDimitry Andric if (Instruction *I = moveNotAfterMinMax(I1, I0)) 1843349cc55cSDimitry Andric return I; 1844349cc55cSDimitry Andric 1845349cc55cSDimitry Andric if (Instruction *I = moveAddAfterMinMax(II, Builder)) 1846349cc55cSDimitry Andric return I; 1847fe6060f1SDimitry Andric 18480fca6ea1SDimitry Andric // minmax (X & NegPow2C, Y & NegPow2C) --> minmax(X, Y) & NegPow2C 18490fca6ea1SDimitry Andric const APInt *RHSC; 18500fca6ea1SDimitry Andric if (match(I0, m_OneUse(m_And(m_Value(X), m_NegatedPower2(RHSC)))) && 18510fca6ea1SDimitry Andric match(I1, m_OneUse(m_And(m_Value(Y), m_SpecificInt(*RHSC))))) 18520fca6ea1SDimitry Andric return BinaryOperator::CreateAnd(Builder.CreateBinaryIntrinsic(IID, X, Y), 18530fca6ea1SDimitry Andric ConstantInt::get(II->getType(), *RHSC)); 18540fca6ea1SDimitry Andric 1855fe6060f1SDimitry Andric // smax(X, -X) --> abs(X) 1856fe6060f1SDimitry Andric // smin(X, -X) --> -abs(X) 1857fe6060f1SDimitry Andric // umax(X, -X) --> -abs(X) 1858fe6060f1SDimitry Andric // umin(X, -X) --> abs(X) 1859fe6060f1SDimitry Andric if (isKnownNegation(I0, I1)) { 1860fe6060f1SDimitry Andric // We can choose either operand as the input to abs(), but if we can 1861fe6060f1SDimitry Andric // eliminate the only use of a value, that's better for subsequent 1862fe6060f1SDimitry Andric // transforms/analysis. 1863fe6060f1SDimitry Andric if (I0->hasOneUse() && !I1->hasOneUse()) 1864fe6060f1SDimitry Andric std::swap(I0, I1); 1865fe6060f1SDimitry Andric 1866fe6060f1SDimitry Andric // This is some variant of abs(). See if we can propagate 'nsw' to the abs 1867fe6060f1SDimitry Andric // operation and potentially its negation. 1868fe6060f1SDimitry Andric bool IntMinIsPoison = isKnownNegation(I0, I1, /* NeedNSW */ true); 1869fe6060f1SDimitry Andric Value *Abs = Builder.CreateBinaryIntrinsic( 1870fe6060f1SDimitry Andric Intrinsic::abs, I0, 1871fe6060f1SDimitry Andric ConstantInt::getBool(II->getContext(), IntMinIsPoison)); 1872fe6060f1SDimitry Andric 1873fe6060f1SDimitry Andric // We don't have a "nabs" intrinsic, so negate if needed based on the 1874fe6060f1SDimitry Andric // max/min operation. 1875fe6060f1SDimitry Andric if (IID == Intrinsic::smin || IID == Intrinsic::umax) 18760fca6ea1SDimitry Andric Abs = Builder.CreateNeg(Abs, "nabs", IntMinIsPoison); 1877fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Abs); 1878fe6060f1SDimitry Andric } 1879fe6060f1SDimitry Andric 1880fe6060f1SDimitry Andric if (Instruction *Sel = foldClampRangeOfTwo(II, Builder)) 1881fe6060f1SDimitry Andric return Sel; 1882fe6060f1SDimitry Andric 1883349cc55cSDimitry Andric if (Instruction *SAdd = matchSAddSubSat(*II)) 1884349cc55cSDimitry Andric return SAdd; 1885349cc55cSDimitry Andric 18860fca6ea1SDimitry Andric if (Value *NewMinMax = reassociateMinMaxWithConstants(II, Builder, SQ)) 188706c3fb27SDimitry Andric return replaceInstUsesWith(*II, NewMinMax); 188881ad6265SDimitry Andric 188981ad6265SDimitry Andric if (Instruction *R = reassociateMinMaxWithConstantInOperand(II, Builder)) 189081ad6265SDimitry Andric return R; 189181ad6265SDimitry Andric 1892349cc55cSDimitry Andric if (Instruction *NewMinMax = factorizeMinMaxTree(II)) 1893349cc55cSDimitry Andric return NewMinMax; 1894349cc55cSDimitry Andric 1895cb14a3feSDimitry Andric // Try to fold minmax with constant RHS based on range information 18960fca6ea1SDimitry Andric if (match(I1, m_APIntAllowPoison(RHSC))) { 1897cb14a3feSDimitry Andric ICmpInst::Predicate Pred = 1898cb14a3feSDimitry Andric ICmpInst::getNonStrictPredicate(MinMaxIntrinsic::getPredicate(IID)); 1899cb14a3feSDimitry Andric bool IsSigned = MinMaxIntrinsic::isSigned(IID); 1900cb14a3feSDimitry Andric ConstantRange LHS_CR = computeConstantRangeIncludingKnownBits( 1901cb14a3feSDimitry Andric I0, IsSigned, SQ.getWithInstruction(II)); 1902cb14a3feSDimitry Andric if (!LHS_CR.isFullSet()) { 1903cb14a3feSDimitry Andric if (LHS_CR.icmp(Pred, *RHSC)) 1904cb14a3feSDimitry Andric return replaceInstUsesWith(*II, I0); 1905cb14a3feSDimitry Andric if (LHS_CR.icmp(ICmpInst::getSwappedPredicate(Pred), *RHSC)) 1906cb14a3feSDimitry Andric return replaceInstUsesWith(*II, 1907cb14a3feSDimitry Andric ConstantInt::get(II->getType(), *RHSC)); 1908cb14a3feSDimitry Andric } 1909cb14a3feSDimitry Andric } 1910cb14a3feSDimitry Andric 1911e8d8bef9SDimitry Andric break; 1912e8d8bef9SDimitry Andric } 1913bdd1243dSDimitry Andric case Intrinsic::bitreverse: { 191406c3fb27SDimitry Andric Value *IIOperand = II->getArgOperand(0); 1915bdd1243dSDimitry Andric // bitrev (zext i1 X to ?) --> X ? SignBitC : 0 1916bdd1243dSDimitry Andric Value *X; 191706c3fb27SDimitry Andric if (match(IIOperand, m_ZExt(m_Value(X))) && 1918bdd1243dSDimitry Andric X->getType()->isIntOrIntVectorTy(1)) { 1919bdd1243dSDimitry Andric Type *Ty = II->getType(); 1920bdd1243dSDimitry Andric APInt SignBit = APInt::getSignMask(Ty->getScalarSizeInBits()); 1921bdd1243dSDimitry Andric return SelectInst::Create(X, ConstantInt::get(Ty, SignBit), 1922bdd1243dSDimitry Andric ConstantInt::getNullValue(Ty)); 1923bdd1243dSDimitry Andric } 192406c3fb27SDimitry Andric 192506c3fb27SDimitry Andric if (Instruction *crossLogicOpFold = 192606c3fb27SDimitry Andric foldBitOrderCrossLogicOp<Intrinsic::bitreverse>(IIOperand, Builder)) 192706c3fb27SDimitry Andric return crossLogicOpFold; 192806c3fb27SDimitry Andric 1929bdd1243dSDimitry Andric break; 1930bdd1243dSDimitry Andric } 19310b57cec5SDimitry Andric case Intrinsic::bswap: { 19320b57cec5SDimitry Andric Value *IIOperand = II->getArgOperand(0); 193381ad6265SDimitry Andric 193481ad6265SDimitry Andric // Try to canonicalize bswap-of-logical-shift-by-8-bit-multiple as 193581ad6265SDimitry Andric // inverse-shift-of-bswap: 193681ad6265SDimitry Andric // bswap (shl X, Y) --> lshr (bswap X), Y 193781ad6265SDimitry Andric // bswap (lshr X, Y) --> shl (bswap X), Y 193881ad6265SDimitry Andric Value *X, *Y; 193981ad6265SDimitry Andric if (match(IIOperand, m_OneUse(m_LogicalShift(m_Value(X), m_Value(Y))))) { 194081ad6265SDimitry Andric unsigned BitWidth = IIOperand->getType()->getScalarSizeInBits(); 19410fca6ea1SDimitry Andric if (MaskedValueIsZero(Y, APInt::getLowBitsSet(BitWidth, 3))) { 194281ad6265SDimitry Andric Value *NewSwap = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, X); 194381ad6265SDimitry Andric BinaryOperator::BinaryOps InverseShift = 194481ad6265SDimitry Andric cast<BinaryOperator>(IIOperand)->getOpcode() == Instruction::Shl 194581ad6265SDimitry Andric ? Instruction::LShr 194681ad6265SDimitry Andric : Instruction::Shl; 194781ad6265SDimitry Andric return BinaryOperator::Create(InverseShift, NewSwap, Y); 194881ad6265SDimitry Andric } 194981ad6265SDimitry Andric } 19500b57cec5SDimitry Andric 195104eeddc0SDimitry Andric KnownBits Known = computeKnownBits(IIOperand, 0, II); 195204eeddc0SDimitry Andric uint64_t LZ = alignDown(Known.countMinLeadingZeros(), 8); 195304eeddc0SDimitry Andric uint64_t TZ = alignDown(Known.countMinTrailingZeros(), 8); 195481ad6265SDimitry Andric unsigned BW = Known.getBitWidth(); 195504eeddc0SDimitry Andric 195604eeddc0SDimitry Andric // bswap(x) -> shift(x) if x has exactly one "active byte" 195781ad6265SDimitry Andric if (BW - LZ - TZ == 8) { 195804eeddc0SDimitry Andric assert(LZ != TZ && "active byte cannot be in the middle"); 195904eeddc0SDimitry Andric if (LZ > TZ) // -> shl(x) if the "active byte" is in the low part of x 196004eeddc0SDimitry Andric return BinaryOperator::CreateNUWShl( 196104eeddc0SDimitry Andric IIOperand, ConstantInt::get(IIOperand->getType(), LZ - TZ)); 196204eeddc0SDimitry Andric // -> lshr(x) if the "active byte" is in the high part of x 196304eeddc0SDimitry Andric return BinaryOperator::CreateExactLShr( 196404eeddc0SDimitry Andric IIOperand, ConstantInt::get(IIOperand->getType(), TZ - LZ)); 196504eeddc0SDimitry Andric } 196604eeddc0SDimitry Andric 19670b57cec5SDimitry Andric // bswap(trunc(bswap(x))) -> trunc(lshr(x, c)) 19680b57cec5SDimitry Andric if (match(IIOperand, m_Trunc(m_BSwap(m_Value(X))))) { 196981ad6265SDimitry Andric unsigned C = X->getType()->getScalarSizeInBits() - BW; 19700b57cec5SDimitry Andric Value *CV = ConstantInt::get(X->getType(), C); 19710b57cec5SDimitry Andric Value *V = Builder.CreateLShr(X, CV); 19720b57cec5SDimitry Andric return new TruncInst(V, IIOperand->getType()); 19730b57cec5SDimitry Andric } 197406c3fb27SDimitry Andric 197506c3fb27SDimitry Andric if (Instruction *crossLogicOpFold = 197606c3fb27SDimitry Andric foldBitOrderCrossLogicOp<Intrinsic::bswap>(IIOperand, Builder)) { 197706c3fb27SDimitry Andric return crossLogicOpFold; 197806c3fb27SDimitry Andric } 197906c3fb27SDimitry Andric 1980297eecfbSDimitry Andric // Try to fold into bitreverse if bswap is the root of the expression tree. 1981297eecfbSDimitry Andric if (Instruction *BitOp = matchBSwapOrBitReverse(*II, /*MatchBSwaps*/ false, 1982297eecfbSDimitry Andric /*MatchBitReversals*/ true)) 1983297eecfbSDimitry Andric return BitOp; 19840b57cec5SDimitry Andric break; 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric case Intrinsic::masked_load: 19870b57cec5SDimitry Andric if (Value *SimplifiedMaskedOp = simplifyMaskedLoad(*II)) 19880b57cec5SDimitry Andric return replaceInstUsesWith(CI, SimplifiedMaskedOp); 19890b57cec5SDimitry Andric break; 19900b57cec5SDimitry Andric case Intrinsic::masked_store: 19910b57cec5SDimitry Andric return simplifyMaskedStore(*II); 19920b57cec5SDimitry Andric case Intrinsic::masked_gather: 19930b57cec5SDimitry Andric return simplifyMaskedGather(*II); 19940b57cec5SDimitry Andric case Intrinsic::masked_scatter: 19950b57cec5SDimitry Andric return simplifyMaskedScatter(*II); 19960b57cec5SDimitry Andric case Intrinsic::launder_invariant_group: 19970b57cec5SDimitry Andric case Intrinsic::strip_invariant_group: 19980b57cec5SDimitry Andric if (auto *SkippedBarrier = simplifyInvariantGroupIntrinsic(*II, *this)) 19990b57cec5SDimitry Andric return replaceInstUsesWith(*II, SkippedBarrier); 20000b57cec5SDimitry Andric break; 20010b57cec5SDimitry Andric case Intrinsic::powi: 20020b57cec5SDimitry Andric if (ConstantInt *Power = dyn_cast<ConstantInt>(II->getArgOperand(1))) { 20030b57cec5SDimitry Andric // 0 and 1 are handled in instsimplify 20040b57cec5SDimitry Andric // powi(x, -1) -> 1/x 20050b57cec5SDimitry Andric if (Power->isMinusOne()) 2006e8d8bef9SDimitry Andric return BinaryOperator::CreateFDivFMF(ConstantFP::get(CI.getType(), 1.0), 2007e8d8bef9SDimitry Andric II->getArgOperand(0), II); 20080b57cec5SDimitry Andric // powi(x, 2) -> x*x 20090b57cec5SDimitry Andric if (Power->equalsInt(2)) 2010e8d8bef9SDimitry Andric return BinaryOperator::CreateFMulFMF(II->getArgOperand(0), 2011e8d8bef9SDimitry Andric II->getArgOperand(0), II); 2012349cc55cSDimitry Andric 2013349cc55cSDimitry Andric if (!Power->getValue()[0]) { 2014349cc55cSDimitry Andric Value *X; 2015349cc55cSDimitry Andric // If power is even: 2016349cc55cSDimitry Andric // powi(-x, p) -> powi(x, p) 2017349cc55cSDimitry Andric // powi(fabs(x), p) -> powi(x, p) 2018349cc55cSDimitry Andric // powi(copysign(x, y), p) -> powi(x, p) 2019349cc55cSDimitry Andric if (match(II->getArgOperand(0), m_FNeg(m_Value(X))) || 2020349cc55cSDimitry Andric match(II->getArgOperand(0), m_FAbs(m_Value(X))) || 2021349cc55cSDimitry Andric match(II->getArgOperand(0), 2022349cc55cSDimitry Andric m_Intrinsic<Intrinsic::copysign>(m_Value(X), m_Value()))) 2023349cc55cSDimitry Andric return replaceOperand(*II, 0, X); 2024349cc55cSDimitry Andric } 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric break; 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric case Intrinsic::cttz: 20290b57cec5SDimitry Andric case Intrinsic::ctlz: 20300b57cec5SDimitry Andric if (auto *I = foldCttzCtlz(*II, *this)) 20310b57cec5SDimitry Andric return I; 20320b57cec5SDimitry Andric break; 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric case Intrinsic::ctpop: 20350b57cec5SDimitry Andric if (auto *I = foldCtpop(*II, *this)) 20360b57cec5SDimitry Andric return I; 20370b57cec5SDimitry Andric break; 20380b57cec5SDimitry Andric 20390b57cec5SDimitry Andric case Intrinsic::fshl: 20400b57cec5SDimitry Andric case Intrinsic::fshr: { 20410b57cec5SDimitry Andric Value *Op0 = II->getArgOperand(0), *Op1 = II->getArgOperand(1); 20420b57cec5SDimitry Andric Type *Ty = II->getType(); 20430b57cec5SDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 20440b57cec5SDimitry Andric Constant *ShAmtC; 2045fcaf7f86SDimitry Andric if (match(II->getArgOperand(2), m_ImmConstant(ShAmtC))) { 20460b57cec5SDimitry Andric // Canonicalize a shift amount constant operand to modulo the bit-width. 20470b57cec5SDimitry Andric Constant *WidthC = ConstantInt::get(Ty, BitWidth); 2048753f127fSDimitry Andric Constant *ModuloC = 2049753f127fSDimitry Andric ConstantFoldBinaryOpOperands(Instruction::URem, ShAmtC, WidthC, DL); 2050753f127fSDimitry Andric if (!ModuloC) 2051753f127fSDimitry Andric return nullptr; 20525ffd83dbSDimitry Andric if (ModuloC != ShAmtC) 20535ffd83dbSDimitry Andric return replaceOperand(*II, 2, ModuloC); 20545ffd83dbSDimitry Andric 20550fca6ea1SDimitry Andric assert(match(ConstantFoldCompareInstOperands(ICmpInst::ICMP_UGT, WidthC, 20560fca6ea1SDimitry Andric ShAmtC, DL), 20570fca6ea1SDimitry Andric m_One()) && 20580b57cec5SDimitry Andric "Shift amount expected to be modulo bitwidth"); 20590b57cec5SDimitry Andric 20600b57cec5SDimitry Andric // Canonicalize funnel shift right by constant to funnel shift left. This 20610b57cec5SDimitry Andric // is not entirely arbitrary. For historical reasons, the backend may 20620b57cec5SDimitry Andric // recognize rotate left patterns but miss rotate right patterns. 20630b57cec5SDimitry Andric if (IID == Intrinsic::fshr) { 20640fca6ea1SDimitry Andric // fshr X, Y, C --> fshl X, Y, (BitWidth - C) if C is not zero. 20650fca6ea1SDimitry Andric if (!isKnownNonZero(ShAmtC, SQ.getWithInstruction(II))) 20660fca6ea1SDimitry Andric return nullptr; 20670fca6ea1SDimitry Andric 20680b57cec5SDimitry Andric Constant *LeftShiftC = ConstantExpr::getSub(WidthC, ShAmtC); 20690b57cec5SDimitry Andric Module *Mod = II->getModule(); 20700b57cec5SDimitry Andric Function *Fshl = Intrinsic::getDeclaration(Mod, Intrinsic::fshl, Ty); 20710b57cec5SDimitry Andric return CallInst::Create(Fshl, { Op0, Op1, LeftShiftC }); 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric assert(IID == Intrinsic::fshl && 20740b57cec5SDimitry Andric "All funnel shifts by simple constants should go left"); 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric // fshl(X, 0, C) --> shl X, C 20770b57cec5SDimitry Andric // fshl(X, undef, C) --> shl X, C 20780b57cec5SDimitry Andric if (match(Op1, m_ZeroInt()) || match(Op1, m_Undef())) 20790b57cec5SDimitry Andric return BinaryOperator::CreateShl(Op0, ShAmtC); 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric // fshl(0, X, C) --> lshr X, (BW-C) 20820b57cec5SDimitry Andric // fshl(undef, X, C) --> lshr X, (BW-C) 20830b57cec5SDimitry Andric if (match(Op0, m_ZeroInt()) || match(Op0, m_Undef())) 20840b57cec5SDimitry Andric return BinaryOperator::CreateLShr(Op1, 20850b57cec5SDimitry Andric ConstantExpr::getSub(WidthC, ShAmtC)); 20860b57cec5SDimitry Andric 20870b57cec5SDimitry Andric // fshl i16 X, X, 8 --> bswap i16 X (reduce to more-specific form) 20880b57cec5SDimitry Andric if (Op0 == Op1 && BitWidth == 16 && match(ShAmtC, m_SpecificInt(8))) { 20890b57cec5SDimitry Andric Module *Mod = II->getModule(); 20900b57cec5SDimitry Andric Function *Bswap = Intrinsic::getDeclaration(Mod, Intrinsic::bswap, Ty); 20910b57cec5SDimitry Andric return CallInst::Create(Bswap, { Op0 }); 20920b57cec5SDimitry Andric } 209306c3fb27SDimitry Andric if (Instruction *BitOp = 209406c3fb27SDimitry Andric matchBSwapOrBitReverse(*II, /*MatchBSwaps*/ true, 209506c3fb27SDimitry Andric /*MatchBitReversals*/ true)) 209606c3fb27SDimitry Andric return BitOp; 20970b57cec5SDimitry Andric } 20980b57cec5SDimitry Andric 20990b57cec5SDimitry Andric // Left or right might be masked. 21000b57cec5SDimitry Andric if (SimplifyDemandedInstructionBits(*II)) 21010b57cec5SDimitry Andric return &CI; 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric // The shift amount (operand 2) of a funnel shift is modulo the bitwidth, 21040b57cec5SDimitry Andric // so only the low bits of the shift amount are demanded if the bitwidth is 21050b57cec5SDimitry Andric // a power-of-2. 21060b57cec5SDimitry Andric if (!isPowerOf2_32(BitWidth)) 21070b57cec5SDimitry Andric break; 21080b57cec5SDimitry Andric APInt Op2Demanded = APInt::getLowBitsSet(BitWidth, Log2_32_Ceil(BitWidth)); 21090b57cec5SDimitry Andric KnownBits Op2Known(BitWidth); 21100b57cec5SDimitry Andric if (SimplifyDemandedBits(II, 2, Op2Demanded, Op2Known)) 21110b57cec5SDimitry Andric return &CI; 21120b57cec5SDimitry Andric break; 21130b57cec5SDimitry Andric } 21145f757f3fSDimitry Andric case Intrinsic::ptrmask: { 21155f757f3fSDimitry Andric unsigned BitWidth = DL.getPointerTypeSizeInBits(II->getType()); 21165f757f3fSDimitry Andric KnownBits Known(BitWidth); 21175f757f3fSDimitry Andric if (SimplifyDemandedInstructionBits(*II, Known)) 21185f757f3fSDimitry Andric return II; 21195f757f3fSDimitry Andric 21205f757f3fSDimitry Andric Value *InnerPtr, *InnerMask; 21215f757f3fSDimitry Andric bool Changed = false; 21225f757f3fSDimitry Andric // Combine: 21235f757f3fSDimitry Andric // (ptrmask (ptrmask p, A), B) 21245f757f3fSDimitry Andric // -> (ptrmask p, (and A, B)) 21255f757f3fSDimitry Andric if (match(II->getArgOperand(0), 21265f757f3fSDimitry Andric m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(m_Value(InnerPtr), 21275f757f3fSDimitry Andric m_Value(InnerMask))))) { 21285f757f3fSDimitry Andric assert(II->getArgOperand(1)->getType() == InnerMask->getType() && 21295f757f3fSDimitry Andric "Mask types must match"); 21305f757f3fSDimitry Andric // TODO: If InnerMask == Op1, we could copy attributes from inner 21315f757f3fSDimitry Andric // callsite -> outer callsite. 21325f757f3fSDimitry Andric Value *NewMask = Builder.CreateAnd(II->getArgOperand(1), InnerMask); 21335f757f3fSDimitry Andric replaceOperand(CI, 0, InnerPtr); 21345f757f3fSDimitry Andric replaceOperand(CI, 1, NewMask); 21355f757f3fSDimitry Andric Changed = true; 21365f757f3fSDimitry Andric } 21375f757f3fSDimitry Andric 21385f757f3fSDimitry Andric // See if we can deduce non-null. 21395f757f3fSDimitry Andric if (!CI.hasRetAttr(Attribute::NonNull) && 21405f757f3fSDimitry Andric (Known.isNonZero() || 21410fca6ea1SDimitry Andric isKnownNonZero(II, getSimplifyQuery().getWithInstruction(II)))) { 21425f757f3fSDimitry Andric CI.addRetAttr(Attribute::NonNull); 21435f757f3fSDimitry Andric Changed = true; 21445f757f3fSDimitry Andric } 21455f757f3fSDimitry Andric 21465f757f3fSDimitry Andric unsigned NewAlignmentLog = 21475f757f3fSDimitry Andric std::min(Value::MaxAlignmentExponent, 21485f757f3fSDimitry Andric std::min(BitWidth - 1, Known.countMinTrailingZeros())); 21495f757f3fSDimitry Andric // Known bits will capture if we had alignment information associated with 21505f757f3fSDimitry Andric // the pointer argument. 21515f757f3fSDimitry Andric if (NewAlignmentLog > Log2(CI.getRetAlign().valueOrOne())) { 21525f757f3fSDimitry Andric CI.addRetAttr(Attribute::getWithAlignment( 21535f757f3fSDimitry Andric CI.getContext(), Align(uint64_t(1) << NewAlignmentLog))); 21545f757f3fSDimitry Andric Changed = true; 21555f757f3fSDimitry Andric } 21565f757f3fSDimitry Andric if (Changed) 21575f757f3fSDimitry Andric return &CI; 21585f757f3fSDimitry Andric break; 21595f757f3fSDimitry Andric } 21600b57cec5SDimitry Andric case Intrinsic::uadd_with_overflow: 21610b57cec5SDimitry Andric case Intrinsic::sadd_with_overflow: { 21620b57cec5SDimitry Andric if (Instruction *I = foldIntrinsicWithOverflowCommon(II)) 21630b57cec5SDimitry Andric return I; 21640b57cec5SDimitry Andric 21650b57cec5SDimitry Andric // Given 2 constant operands whose sum does not overflow: 21660b57cec5SDimitry Andric // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1 21670b57cec5SDimitry Andric // saddo (X +nsw C0), C1 -> saddo X, C0 + C1 21680b57cec5SDimitry Andric Value *X; 21690b57cec5SDimitry Andric const APInt *C0, *C1; 21700b57cec5SDimitry Andric Value *Arg0 = II->getArgOperand(0); 21710b57cec5SDimitry Andric Value *Arg1 = II->getArgOperand(1); 21720b57cec5SDimitry Andric bool IsSigned = IID == Intrinsic::sadd_with_overflow; 21730fca6ea1SDimitry Andric bool HasNWAdd = IsSigned 21740fca6ea1SDimitry Andric ? match(Arg0, m_NSWAddLike(m_Value(X), m_APInt(C0))) 21750fca6ea1SDimitry Andric : match(Arg0, m_NUWAddLike(m_Value(X), m_APInt(C0))); 21760b57cec5SDimitry Andric if (HasNWAdd && match(Arg1, m_APInt(C1))) { 21770b57cec5SDimitry Andric bool Overflow; 21780b57cec5SDimitry Andric APInt NewC = 21790b57cec5SDimitry Andric IsSigned ? C1->sadd_ov(*C0, Overflow) : C1->uadd_ov(*C0, Overflow); 21800b57cec5SDimitry Andric if (!Overflow) 21810b57cec5SDimitry Andric return replaceInstUsesWith( 21820b57cec5SDimitry Andric *II, Builder.CreateBinaryIntrinsic( 21830b57cec5SDimitry Andric IID, X, ConstantInt::get(Arg1->getType(), NewC))); 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric break; 21860b57cec5SDimitry Andric } 21870b57cec5SDimitry Andric 21880b57cec5SDimitry Andric case Intrinsic::umul_with_overflow: 21890b57cec5SDimitry Andric case Intrinsic::smul_with_overflow: 21900b57cec5SDimitry Andric case Intrinsic::usub_with_overflow: 21910b57cec5SDimitry Andric if (Instruction *I = foldIntrinsicWithOverflowCommon(II)) 21920b57cec5SDimitry Andric return I; 21930b57cec5SDimitry Andric break; 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric case Intrinsic::ssub_with_overflow: { 21960b57cec5SDimitry Andric if (Instruction *I = foldIntrinsicWithOverflowCommon(II)) 21970b57cec5SDimitry Andric return I; 21980b57cec5SDimitry Andric 21990b57cec5SDimitry Andric Constant *C; 22000b57cec5SDimitry Andric Value *Arg0 = II->getArgOperand(0); 22010b57cec5SDimitry Andric Value *Arg1 = II->getArgOperand(1); 22020b57cec5SDimitry Andric // Given a constant C that is not the minimum signed value 22030b57cec5SDimitry Andric // for an integer of a given bit width: 22040b57cec5SDimitry Andric // 22050b57cec5SDimitry Andric // ssubo X, C -> saddo X, -C 22060b57cec5SDimitry Andric if (match(Arg1, m_Constant(C)) && C->isNotMinSignedValue()) { 22070b57cec5SDimitry Andric Value *NegVal = ConstantExpr::getNeg(C); 22080b57cec5SDimitry Andric // Build a saddo call that is equivalent to the discovered 22090b57cec5SDimitry Andric // ssubo call. 22100b57cec5SDimitry Andric return replaceInstUsesWith( 22110b57cec5SDimitry Andric *II, Builder.CreateBinaryIntrinsic(Intrinsic::sadd_with_overflow, 22120b57cec5SDimitry Andric Arg0, NegVal)); 22130b57cec5SDimitry Andric } 22140b57cec5SDimitry Andric 22150b57cec5SDimitry Andric break; 22160b57cec5SDimitry Andric } 22170b57cec5SDimitry Andric 22180b57cec5SDimitry Andric case Intrinsic::uadd_sat: 22190b57cec5SDimitry Andric case Intrinsic::sadd_sat: 22200b57cec5SDimitry Andric case Intrinsic::usub_sat: 22210b57cec5SDimitry Andric case Intrinsic::ssub_sat: { 22220b57cec5SDimitry Andric SaturatingInst *SI = cast<SaturatingInst>(II); 22230b57cec5SDimitry Andric Type *Ty = SI->getType(); 22240b57cec5SDimitry Andric Value *Arg0 = SI->getLHS(); 22250b57cec5SDimitry Andric Value *Arg1 = SI->getRHS(); 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric // Make use of known overflow information. 22280b57cec5SDimitry Andric OverflowResult OR = computeOverflow(SI->getBinaryOp(), SI->isSigned(), 22290b57cec5SDimitry Andric Arg0, Arg1, SI); 22300b57cec5SDimitry Andric switch (OR) { 22310b57cec5SDimitry Andric case OverflowResult::MayOverflow: 22320b57cec5SDimitry Andric break; 22330b57cec5SDimitry Andric case OverflowResult::NeverOverflows: 22340b57cec5SDimitry Andric if (SI->isSigned()) 22350b57cec5SDimitry Andric return BinaryOperator::CreateNSW(SI->getBinaryOp(), Arg0, Arg1); 22360b57cec5SDimitry Andric else 22370b57cec5SDimitry Andric return BinaryOperator::CreateNUW(SI->getBinaryOp(), Arg0, Arg1); 22380b57cec5SDimitry Andric case OverflowResult::AlwaysOverflowsLow: { 22390b57cec5SDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 22400b57cec5SDimitry Andric APInt Min = APSInt::getMinValue(BitWidth, !SI->isSigned()); 22410b57cec5SDimitry Andric return replaceInstUsesWith(*SI, ConstantInt::get(Ty, Min)); 22420b57cec5SDimitry Andric } 22430b57cec5SDimitry Andric case OverflowResult::AlwaysOverflowsHigh: { 22440b57cec5SDimitry Andric unsigned BitWidth = Ty->getScalarSizeInBits(); 22450b57cec5SDimitry Andric APInt Max = APSInt::getMaxValue(BitWidth, !SI->isSigned()); 22460b57cec5SDimitry Andric return replaceInstUsesWith(*SI, ConstantInt::get(Ty, Max)); 22470b57cec5SDimitry Andric } 22480b57cec5SDimitry Andric } 22490b57cec5SDimitry Andric 22500fca6ea1SDimitry Andric // usub_sat((sub nuw C, A), C1) -> usub_sat(usub_sat(C, C1), A) 22510fca6ea1SDimitry Andric // which after that: 22520fca6ea1SDimitry Andric // usub_sat((sub nuw C, A), C1) -> usub_sat(C - C1, A) if C1 u< C 22530fca6ea1SDimitry Andric // usub_sat((sub nuw C, A), C1) -> 0 otherwise 22540fca6ea1SDimitry Andric Constant *C, *C1; 22550fca6ea1SDimitry Andric Value *A; 22560fca6ea1SDimitry Andric if (IID == Intrinsic::usub_sat && 22570fca6ea1SDimitry Andric match(Arg0, m_NUWSub(m_ImmConstant(C), m_Value(A))) && 22580fca6ea1SDimitry Andric match(Arg1, m_ImmConstant(C1))) { 22590fca6ea1SDimitry Andric auto *NewC = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, C, C1); 22600fca6ea1SDimitry Andric auto *NewSub = 22610fca6ea1SDimitry Andric Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, NewC, A); 22620fca6ea1SDimitry Andric return replaceInstUsesWith(*SI, NewSub); 22630fca6ea1SDimitry Andric } 22640fca6ea1SDimitry Andric 22650b57cec5SDimitry Andric // ssub.sat(X, C) -> sadd.sat(X, -C) if C != MIN 22660b57cec5SDimitry Andric if (IID == Intrinsic::ssub_sat && match(Arg1, m_Constant(C)) && 22670b57cec5SDimitry Andric C->isNotMinSignedValue()) { 22680b57cec5SDimitry Andric Value *NegVal = ConstantExpr::getNeg(C); 22690b57cec5SDimitry Andric return replaceInstUsesWith( 22700b57cec5SDimitry Andric *II, Builder.CreateBinaryIntrinsic( 22710b57cec5SDimitry Andric Intrinsic::sadd_sat, Arg0, NegVal)); 22720b57cec5SDimitry Andric } 22730b57cec5SDimitry Andric 22740b57cec5SDimitry Andric // sat(sat(X + Val2) + Val) -> sat(X + (Val+Val2)) 22750b57cec5SDimitry Andric // sat(sat(X - Val2) - Val) -> sat(X - (Val+Val2)) 22760b57cec5SDimitry Andric // if Val and Val2 have the same sign 22770b57cec5SDimitry Andric if (auto *Other = dyn_cast<IntrinsicInst>(Arg0)) { 22780b57cec5SDimitry Andric Value *X; 22790b57cec5SDimitry Andric const APInt *Val, *Val2; 22800b57cec5SDimitry Andric APInt NewVal; 22810b57cec5SDimitry Andric bool IsUnsigned = 22820b57cec5SDimitry Andric IID == Intrinsic::uadd_sat || IID == Intrinsic::usub_sat; 22830b57cec5SDimitry Andric if (Other->getIntrinsicID() == IID && 22840b57cec5SDimitry Andric match(Arg1, m_APInt(Val)) && 22850b57cec5SDimitry Andric match(Other->getArgOperand(0), m_Value(X)) && 22860b57cec5SDimitry Andric match(Other->getArgOperand(1), m_APInt(Val2))) { 22870b57cec5SDimitry Andric if (IsUnsigned) 22880b57cec5SDimitry Andric NewVal = Val->uadd_sat(*Val2); 22890b57cec5SDimitry Andric else if (Val->isNonNegative() == Val2->isNonNegative()) { 22900b57cec5SDimitry Andric bool Overflow; 22910b57cec5SDimitry Andric NewVal = Val->sadd_ov(*Val2, Overflow); 22920b57cec5SDimitry Andric if (Overflow) { 22930b57cec5SDimitry Andric // Both adds together may add more than SignedMaxValue 22940b57cec5SDimitry Andric // without saturating the final result. 22950b57cec5SDimitry Andric break; 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric } else { 22980b57cec5SDimitry Andric // Cannot fold saturated addition with different signs. 22990b57cec5SDimitry Andric break; 23000b57cec5SDimitry Andric } 23010b57cec5SDimitry Andric 23020b57cec5SDimitry Andric return replaceInstUsesWith( 23030b57cec5SDimitry Andric *II, Builder.CreateBinaryIntrinsic( 23040b57cec5SDimitry Andric IID, X, ConstantInt::get(II->getType(), NewVal))); 23050b57cec5SDimitry Andric } 23060b57cec5SDimitry Andric } 23070b57cec5SDimitry Andric break; 23080b57cec5SDimitry Andric } 23090b57cec5SDimitry Andric 23100b57cec5SDimitry Andric case Intrinsic::minnum: 23110b57cec5SDimitry Andric case Intrinsic::maxnum: 23120b57cec5SDimitry Andric case Intrinsic::minimum: 23130b57cec5SDimitry Andric case Intrinsic::maximum: { 23140b57cec5SDimitry Andric Value *Arg0 = II->getArgOperand(0); 23150b57cec5SDimitry Andric Value *Arg1 = II->getArgOperand(1); 23160b57cec5SDimitry Andric Value *X, *Y; 23170b57cec5SDimitry Andric if (match(Arg0, m_FNeg(m_Value(X))) && match(Arg1, m_FNeg(m_Value(Y))) && 23180b57cec5SDimitry Andric (Arg0->hasOneUse() || Arg1->hasOneUse())) { 23190b57cec5SDimitry Andric // If both operands are negated, invert the call and negate the result: 23200b57cec5SDimitry Andric // min(-X, -Y) --> -(max(X, Y)) 23210b57cec5SDimitry Andric // max(-X, -Y) --> -(min(X, Y)) 23220b57cec5SDimitry Andric Intrinsic::ID NewIID; 23230b57cec5SDimitry Andric switch (IID) { 23240b57cec5SDimitry Andric case Intrinsic::maxnum: 23250b57cec5SDimitry Andric NewIID = Intrinsic::minnum; 23260b57cec5SDimitry Andric break; 23270b57cec5SDimitry Andric case Intrinsic::minnum: 23280b57cec5SDimitry Andric NewIID = Intrinsic::maxnum; 23290b57cec5SDimitry Andric break; 23300b57cec5SDimitry Andric case Intrinsic::maximum: 23310b57cec5SDimitry Andric NewIID = Intrinsic::minimum; 23320b57cec5SDimitry Andric break; 23330b57cec5SDimitry Andric case Intrinsic::minimum: 23340b57cec5SDimitry Andric NewIID = Intrinsic::maximum; 23350b57cec5SDimitry Andric break; 23360b57cec5SDimitry Andric default: 23370b57cec5SDimitry Andric llvm_unreachable("unexpected intrinsic ID"); 23380b57cec5SDimitry Andric } 23390b57cec5SDimitry Andric Value *NewCall = Builder.CreateBinaryIntrinsic(NewIID, X, Y, II); 23405ffd83dbSDimitry Andric Instruction *FNeg = UnaryOperator::CreateFNeg(NewCall); 23410b57cec5SDimitry Andric FNeg->copyIRFlags(II); 23420b57cec5SDimitry Andric return FNeg; 23430b57cec5SDimitry Andric } 23440b57cec5SDimitry Andric 23450b57cec5SDimitry Andric // m(m(X, C2), C1) -> m(X, C) 23460b57cec5SDimitry Andric const APFloat *C1, *C2; 23470b57cec5SDimitry Andric if (auto *M = dyn_cast<IntrinsicInst>(Arg0)) { 23480b57cec5SDimitry Andric if (M->getIntrinsicID() == IID && match(Arg1, m_APFloat(C1)) && 23490b57cec5SDimitry Andric ((match(M->getArgOperand(0), m_Value(X)) && 23500b57cec5SDimitry Andric match(M->getArgOperand(1), m_APFloat(C2))) || 23510b57cec5SDimitry Andric (match(M->getArgOperand(1), m_Value(X)) && 23520b57cec5SDimitry Andric match(M->getArgOperand(0), m_APFloat(C2))))) { 23530b57cec5SDimitry Andric APFloat Res(0.0); 23540b57cec5SDimitry Andric switch (IID) { 23550b57cec5SDimitry Andric case Intrinsic::maxnum: 23560b57cec5SDimitry Andric Res = maxnum(*C1, *C2); 23570b57cec5SDimitry Andric break; 23580b57cec5SDimitry Andric case Intrinsic::minnum: 23590b57cec5SDimitry Andric Res = minnum(*C1, *C2); 23600b57cec5SDimitry Andric break; 23610b57cec5SDimitry Andric case Intrinsic::maximum: 23620b57cec5SDimitry Andric Res = maximum(*C1, *C2); 23630b57cec5SDimitry Andric break; 23640b57cec5SDimitry Andric case Intrinsic::minimum: 23650b57cec5SDimitry Andric Res = minimum(*C1, *C2); 23660b57cec5SDimitry Andric break; 23670b57cec5SDimitry Andric default: 23680b57cec5SDimitry Andric llvm_unreachable("unexpected intrinsic ID"); 23690b57cec5SDimitry Andric } 23700fca6ea1SDimitry Andric Value *V = Builder.CreateBinaryIntrinsic( 23715ffd83dbSDimitry Andric IID, X, ConstantFP::get(Arg0->getType(), Res), II); 23725ffd83dbSDimitry Andric // TODO: Conservatively intersecting FMF. If Res == C2, the transform 23735ffd83dbSDimitry Andric // was a simplification (so Arg0 and its original flags could 23745ffd83dbSDimitry Andric // propagate?) 23750fca6ea1SDimitry Andric if (auto *CI = dyn_cast<CallInst>(V)) 23760fca6ea1SDimitry Andric CI->andIRFlags(M); 23770fca6ea1SDimitry Andric return replaceInstUsesWith(*II, V); 23780b57cec5SDimitry Andric } 23790b57cec5SDimitry Andric } 23800b57cec5SDimitry Andric 2381fe6060f1SDimitry Andric // m((fpext X), (fpext Y)) -> fpext (m(X, Y)) 2382fe6060f1SDimitry Andric if (match(Arg0, m_OneUse(m_FPExt(m_Value(X)))) && 2383fe6060f1SDimitry Andric match(Arg1, m_OneUse(m_FPExt(m_Value(Y)))) && 2384fe6060f1SDimitry Andric X->getType() == Y->getType()) { 2385fe6060f1SDimitry Andric Value *NewCall = 2386fe6060f1SDimitry Andric Builder.CreateBinaryIntrinsic(IID, X, Y, II, II->getName()); 23875ffd83dbSDimitry Andric return new FPExtInst(NewCall, II->getType()); 23885ffd83dbSDimitry Andric } 23895ffd83dbSDimitry Andric 2390fe6060f1SDimitry Andric // max X, -X --> fabs X 2391fe6060f1SDimitry Andric // min X, -X --> -(fabs X) 23920fca6ea1SDimitry Andric // TODO: Remove one-use limitation? That is obviously better for max, 23930fca6ea1SDimitry Andric // hence why we don't check for one-use for that. However, 23940fca6ea1SDimitry Andric // it would be an extra instruction for min (fnabs), but 23950fca6ea1SDimitry Andric // that is still likely better for analysis and codegen. 23960fca6ea1SDimitry Andric auto IsMinMaxOrXNegX = [IID, &X](Value *Op0, Value *Op1) { 23970fca6ea1SDimitry Andric if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Specific(X))) 23980fca6ea1SDimitry Andric return Op0->hasOneUse() || 23990fca6ea1SDimitry Andric (IID != Intrinsic::minimum && IID != Intrinsic::minnum); 24000fca6ea1SDimitry Andric return false; 24010fca6ea1SDimitry Andric }; 24020fca6ea1SDimitry Andric 24030fca6ea1SDimitry Andric if (IsMinMaxOrXNegX(Arg0, Arg1) || IsMinMaxOrXNegX(Arg1, Arg0)) { 2404fe6060f1SDimitry Andric Value *R = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, II); 2405fe6060f1SDimitry Andric if (IID == Intrinsic::minimum || IID == Intrinsic::minnum) 2406fe6060f1SDimitry Andric R = Builder.CreateFNegFMF(R, II); 2407fe6060f1SDimitry Andric return replaceInstUsesWith(*II, R); 2408fe6060f1SDimitry Andric } 2409fe6060f1SDimitry Andric 24100b57cec5SDimitry Andric break; 24110b57cec5SDimitry Andric } 2412bdd1243dSDimitry Andric case Intrinsic::matrix_multiply: { 2413bdd1243dSDimitry Andric // Optimize negation in matrix multiplication. 2414bdd1243dSDimitry Andric 2415bdd1243dSDimitry Andric // -A * -B -> A * B 2416bdd1243dSDimitry Andric Value *A, *B; 2417bdd1243dSDimitry Andric if (match(II->getArgOperand(0), m_FNeg(m_Value(A))) && 2418bdd1243dSDimitry Andric match(II->getArgOperand(1), m_FNeg(m_Value(B)))) { 2419bdd1243dSDimitry Andric replaceOperand(*II, 0, A); 2420bdd1243dSDimitry Andric replaceOperand(*II, 1, B); 2421bdd1243dSDimitry Andric return II; 2422bdd1243dSDimitry Andric } 2423bdd1243dSDimitry Andric 2424bdd1243dSDimitry Andric Value *Op0 = II->getOperand(0); 2425bdd1243dSDimitry Andric Value *Op1 = II->getOperand(1); 2426bdd1243dSDimitry Andric Value *OpNotNeg, *NegatedOp; 2427bdd1243dSDimitry Andric unsigned NegatedOpArg, OtherOpArg; 2428bdd1243dSDimitry Andric if (match(Op0, m_FNeg(m_Value(OpNotNeg)))) { 2429bdd1243dSDimitry Andric NegatedOp = Op0; 2430bdd1243dSDimitry Andric NegatedOpArg = 0; 2431bdd1243dSDimitry Andric OtherOpArg = 1; 2432bdd1243dSDimitry Andric } else if (match(Op1, m_FNeg(m_Value(OpNotNeg)))) { 2433bdd1243dSDimitry Andric NegatedOp = Op1; 2434bdd1243dSDimitry Andric NegatedOpArg = 1; 2435bdd1243dSDimitry Andric OtherOpArg = 0; 2436bdd1243dSDimitry Andric } else 2437bdd1243dSDimitry Andric // Multiplication doesn't have a negated operand. 2438bdd1243dSDimitry Andric break; 2439bdd1243dSDimitry Andric 2440bdd1243dSDimitry Andric // Only optimize if the negated operand has only one use. 2441bdd1243dSDimitry Andric if (!NegatedOp->hasOneUse()) 2442bdd1243dSDimitry Andric break; 2443bdd1243dSDimitry Andric 2444bdd1243dSDimitry Andric Value *OtherOp = II->getOperand(OtherOpArg); 2445bdd1243dSDimitry Andric VectorType *RetTy = cast<VectorType>(II->getType()); 2446bdd1243dSDimitry Andric VectorType *NegatedOpTy = cast<VectorType>(NegatedOp->getType()); 2447bdd1243dSDimitry Andric VectorType *OtherOpTy = cast<VectorType>(OtherOp->getType()); 2448bdd1243dSDimitry Andric ElementCount NegatedCount = NegatedOpTy->getElementCount(); 2449bdd1243dSDimitry Andric ElementCount OtherCount = OtherOpTy->getElementCount(); 2450bdd1243dSDimitry Andric ElementCount RetCount = RetTy->getElementCount(); 2451bdd1243dSDimitry Andric // (-A) * B -> A * (-B), if it is cheaper to negate B and vice versa. 2452bdd1243dSDimitry Andric if (ElementCount::isKnownGT(NegatedCount, OtherCount) && 2453bdd1243dSDimitry Andric ElementCount::isKnownLT(OtherCount, RetCount)) { 2454bdd1243dSDimitry Andric Value *InverseOtherOp = Builder.CreateFNeg(OtherOp); 2455bdd1243dSDimitry Andric replaceOperand(*II, NegatedOpArg, OpNotNeg); 2456bdd1243dSDimitry Andric replaceOperand(*II, OtherOpArg, InverseOtherOp); 2457bdd1243dSDimitry Andric return II; 2458bdd1243dSDimitry Andric } 2459bdd1243dSDimitry Andric // (-A) * B -> -(A * B), if it is cheaper to negate the result 2460bdd1243dSDimitry Andric if (ElementCount::isKnownGT(NegatedCount, RetCount)) { 2461bdd1243dSDimitry Andric SmallVector<Value *, 5> NewArgs(II->args()); 2462bdd1243dSDimitry Andric NewArgs[NegatedOpArg] = OpNotNeg; 2463bdd1243dSDimitry Andric Instruction *NewMul = 2464bdd1243dSDimitry Andric Builder.CreateIntrinsic(II->getType(), IID, NewArgs, II); 2465bdd1243dSDimitry Andric return replaceInstUsesWith(*II, Builder.CreateFNegFMF(NewMul, II)); 2466bdd1243dSDimitry Andric } 2467bdd1243dSDimitry Andric break; 2468bdd1243dSDimitry Andric } 24690b57cec5SDimitry Andric case Intrinsic::fmuladd: { 24708bcb0991SDimitry Andric // Try to simplify the underlying FMul. 247181ad6265SDimitry Andric if (Value *V = simplifyFMulInst(II->getArgOperand(0), II->getArgOperand(1), 24728bcb0991SDimitry Andric II->getFastMathFlags(), 24738bcb0991SDimitry Andric SQ.getWithInstruction(II))) { 24748bcb0991SDimitry Andric auto *FAdd = BinaryOperator::CreateFAdd(V, II->getArgOperand(2)); 24758bcb0991SDimitry Andric FAdd->copyFastMathFlags(II); 24768bcb0991SDimitry Andric return FAdd; 24778bcb0991SDimitry Andric } 24788bcb0991SDimitry Andric 2479bdd1243dSDimitry Andric [[fallthrough]]; 24800b57cec5SDimitry Andric } 24810b57cec5SDimitry Andric case Intrinsic::fma: { 24820b57cec5SDimitry Andric // fma fneg(x), fneg(y), z -> fma x, y, z 24830b57cec5SDimitry Andric Value *Src0 = II->getArgOperand(0); 24840b57cec5SDimitry Andric Value *Src1 = II->getArgOperand(1); 24850b57cec5SDimitry Andric Value *X, *Y; 24860b57cec5SDimitry Andric if (match(Src0, m_FNeg(m_Value(X))) && match(Src1, m_FNeg(m_Value(Y)))) { 24875ffd83dbSDimitry Andric replaceOperand(*II, 0, X); 24885ffd83dbSDimitry Andric replaceOperand(*II, 1, Y); 24890b57cec5SDimitry Andric return II; 24900b57cec5SDimitry Andric } 24910b57cec5SDimitry Andric 24920b57cec5SDimitry Andric // fma fabs(x), fabs(x), z -> fma x, x, z 24930b57cec5SDimitry Andric if (match(Src0, m_FAbs(m_Value(X))) && 24940b57cec5SDimitry Andric match(Src1, m_FAbs(m_Specific(X)))) { 24955ffd83dbSDimitry Andric replaceOperand(*II, 0, X); 24965ffd83dbSDimitry Andric replaceOperand(*II, 1, X); 24970b57cec5SDimitry Andric return II; 24980b57cec5SDimitry Andric } 24990b57cec5SDimitry Andric 25008bcb0991SDimitry Andric // Try to simplify the underlying FMul. We can only apply simplifications 25018bcb0991SDimitry Andric // that do not require rounding. 250281ad6265SDimitry Andric if (Value *V = simplifyFMAFMul(II->getArgOperand(0), II->getArgOperand(1), 25038bcb0991SDimitry Andric II->getFastMathFlags(), 25048bcb0991SDimitry Andric SQ.getWithInstruction(II))) { 25058bcb0991SDimitry Andric auto *FAdd = BinaryOperator::CreateFAdd(V, II->getArgOperand(2)); 25060b57cec5SDimitry Andric FAdd->copyFastMathFlags(II); 25070b57cec5SDimitry Andric return FAdd; 25080b57cec5SDimitry Andric } 25090b57cec5SDimitry Andric 25105ffd83dbSDimitry Andric // fma x, y, 0 -> fmul x, y 25115ffd83dbSDimitry Andric // This is always valid for -0.0, but requires nsz for +0.0 as 25125ffd83dbSDimitry Andric // -0.0 + 0.0 = 0.0, which would not be the same as the fmul on its own. 25135ffd83dbSDimitry Andric if (match(II->getArgOperand(2), m_NegZeroFP()) || 25145ffd83dbSDimitry Andric (match(II->getArgOperand(2), m_PosZeroFP()) && 25155ffd83dbSDimitry Andric II->getFastMathFlags().noSignedZeros())) 25165ffd83dbSDimitry Andric return BinaryOperator::CreateFMulFMF(Src0, Src1, II); 25175ffd83dbSDimitry Andric 25180b57cec5SDimitry Andric break; 25190b57cec5SDimitry Andric } 2520480093f4SDimitry Andric case Intrinsic::copysign: { 2521e8d8bef9SDimitry Andric Value *Mag = II->getArgOperand(0), *Sign = II->getArgOperand(1); 25220fca6ea1SDimitry Andric if (std::optional<bool> KnownSignBit = computeKnownFPSignBit( 25230fca6ea1SDimitry Andric Sign, /*Depth=*/0, getSimplifyQuery().getWithInstruction(II))) { 25240fca6ea1SDimitry Andric if (*KnownSignBit) { 2525480093f4SDimitry Andric // If we know that the sign argument is negative, reduce to FNABS: 2526e8d8bef9SDimitry Andric // copysign Mag, -Sign --> fneg (fabs Mag) 2527e8d8bef9SDimitry Andric Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, Mag, II); 2528480093f4SDimitry Andric return replaceInstUsesWith(*II, Builder.CreateFNegFMF(Fabs, II)); 2529480093f4SDimitry Andric } 2530480093f4SDimitry Andric 25310fca6ea1SDimitry Andric // If we know that the sign argument is positive, reduce to FABS: 25320fca6ea1SDimitry Andric // copysign Mag, +Sign --> fabs Mag 25330fca6ea1SDimitry Andric Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, Mag, II); 25340fca6ea1SDimitry Andric return replaceInstUsesWith(*II, Fabs); 25350fca6ea1SDimitry Andric } 25360fca6ea1SDimitry Andric 2537480093f4SDimitry Andric // Propagate sign argument through nested calls: 2538e8d8bef9SDimitry Andric // copysign Mag, (copysign ?, X) --> copysign Mag, X 2539e8d8bef9SDimitry Andric Value *X; 2540e8d8bef9SDimitry Andric if (match(Sign, m_Intrinsic<Intrinsic::copysign>(m_Value(), m_Value(X)))) 2541e8d8bef9SDimitry Andric return replaceOperand(*II, 1, X); 2542e8d8bef9SDimitry Andric 25430fca6ea1SDimitry Andric // Clear sign-bit of constant magnitude: 25440fca6ea1SDimitry Andric // copysign -MagC, X --> copysign MagC, X 25450fca6ea1SDimitry Andric // TODO: Support constant folding for fabs 25460fca6ea1SDimitry Andric const APFloat *MagC; 25470fca6ea1SDimitry Andric if (match(Mag, m_APFloat(MagC)) && MagC->isNegative()) { 25480fca6ea1SDimitry Andric APFloat PosMagC = *MagC; 25490fca6ea1SDimitry Andric PosMagC.clearSign(); 25500fca6ea1SDimitry Andric return replaceOperand(*II, 0, ConstantFP::get(Mag->getType(), PosMagC)); 25510fca6ea1SDimitry Andric } 25520fca6ea1SDimitry Andric 2553e8d8bef9SDimitry Andric // Peek through changes of magnitude's sign-bit. This call rewrites those: 2554e8d8bef9SDimitry Andric // copysign (fabs X), Sign --> copysign X, Sign 2555e8d8bef9SDimitry Andric // copysign (fneg X), Sign --> copysign X, Sign 2556e8d8bef9SDimitry Andric if (match(Mag, m_FAbs(m_Value(X))) || match(Mag, m_FNeg(m_Value(X)))) 2557e8d8bef9SDimitry Andric return replaceOperand(*II, 0, X); 2558480093f4SDimitry Andric 2559480093f4SDimitry Andric break; 2560480093f4SDimitry Andric } 25610b57cec5SDimitry Andric case Intrinsic::fabs: { 2562e8d8bef9SDimitry Andric Value *Cond, *TVal, *FVal; 25630fca6ea1SDimitry Andric Value *Arg = II->getArgOperand(0); 25640fca6ea1SDimitry Andric Value *X; 25650fca6ea1SDimitry Andric // fabs (-X) --> fabs (X) 25660fca6ea1SDimitry Andric if (match(Arg, m_FNeg(m_Value(X)))) { 25670fca6ea1SDimitry Andric CallInst *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, II); 25680fca6ea1SDimitry Andric return replaceInstUsesWith(CI, Fabs); 25690fca6ea1SDimitry Andric } 25700fca6ea1SDimitry Andric 25710fca6ea1SDimitry Andric if (match(Arg, m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))) { 2572e8d8bef9SDimitry Andric // fabs (select Cond, TrueC, FalseC) --> select Cond, AbsT, AbsF 25730fca6ea1SDimitry Andric if (isa<Constant>(TVal) || isa<Constant>(FVal)) { 2574e8d8bef9SDimitry Andric CallInst *AbsT = Builder.CreateCall(II->getCalledFunction(), {TVal}); 2575e8d8bef9SDimitry Andric CallInst *AbsF = Builder.CreateCall(II->getCalledFunction(), {FVal}); 25760fca6ea1SDimitry Andric SelectInst *SI = SelectInst::Create(Cond, AbsT, AbsF); 25770fca6ea1SDimitry Andric FastMathFlags FMF1 = II->getFastMathFlags(); 25780fca6ea1SDimitry Andric FastMathFlags FMF2 = cast<SelectInst>(Arg)->getFastMathFlags(); 25790fca6ea1SDimitry Andric FMF2.setNoSignedZeros(false); 25800fca6ea1SDimitry Andric SI->setFastMathFlags(FMF1 | FMF2); 25810fca6ea1SDimitry Andric return SI; 2582e8d8bef9SDimitry Andric } 2583e8d8bef9SDimitry Andric // fabs (select Cond, -FVal, FVal) --> fabs FVal 2584e8d8bef9SDimitry Andric if (match(TVal, m_FNeg(m_Specific(FVal)))) 2585e8d8bef9SDimitry Andric return replaceOperand(*II, 0, FVal); 2586e8d8bef9SDimitry Andric // fabs (select Cond, TVal, -TVal) --> fabs TVal 2587e8d8bef9SDimitry Andric if (match(FVal, m_FNeg(m_Specific(TVal)))) 2588e8d8bef9SDimitry Andric return replaceOperand(*II, 0, TVal); 25890b57cec5SDimitry Andric } 25900b57cec5SDimitry Andric 2591bdd1243dSDimitry Andric Value *Magnitude, *Sign; 2592bdd1243dSDimitry Andric if (match(II->getArgOperand(0), 2593bdd1243dSDimitry Andric m_CopySign(m_Value(Magnitude), m_Value(Sign)))) { 2594bdd1243dSDimitry Andric // fabs (copysign x, y) -> (fabs x) 2595bdd1243dSDimitry Andric CallInst *AbsSign = 2596bdd1243dSDimitry Andric Builder.CreateCall(II->getCalledFunction(), {Magnitude}); 2597bdd1243dSDimitry Andric AbsSign->copyFastMathFlags(II); 2598bdd1243dSDimitry Andric return replaceInstUsesWith(*II, AbsSign); 2599bdd1243dSDimitry Andric } 2600bdd1243dSDimitry Andric 2601bdd1243dSDimitry Andric [[fallthrough]]; 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric case Intrinsic::ceil: 26040b57cec5SDimitry Andric case Intrinsic::floor: 26050b57cec5SDimitry Andric case Intrinsic::round: 26065ffd83dbSDimitry Andric case Intrinsic::roundeven: 26070b57cec5SDimitry Andric case Intrinsic::nearbyint: 26080b57cec5SDimitry Andric case Intrinsic::rint: 26090b57cec5SDimitry Andric case Intrinsic::trunc: { 26100b57cec5SDimitry Andric Value *ExtSrc; 26110b57cec5SDimitry Andric if (match(II->getArgOperand(0), m_OneUse(m_FPExt(m_Value(ExtSrc))))) { 26120b57cec5SDimitry Andric // Narrow the call: intrinsic (fpext x) -> fpext (intrinsic x) 26130b57cec5SDimitry Andric Value *NarrowII = Builder.CreateUnaryIntrinsic(IID, ExtSrc, II); 26140b57cec5SDimitry Andric return new FPExtInst(NarrowII, II->getType()); 26150b57cec5SDimitry Andric } 26160b57cec5SDimitry Andric break; 26170b57cec5SDimitry Andric } 26180b57cec5SDimitry Andric case Intrinsic::cos: 26190b57cec5SDimitry Andric case Intrinsic::amdgcn_cos: { 26200fca6ea1SDimitry Andric Value *X, *Sign; 26210b57cec5SDimitry Andric Value *Src = II->getArgOperand(0); 26220fca6ea1SDimitry Andric if (match(Src, m_FNeg(m_Value(X))) || match(Src, m_FAbs(m_Value(X))) || 26230fca6ea1SDimitry Andric match(Src, m_CopySign(m_Value(X), m_Value(Sign)))) { 26240fca6ea1SDimitry Andric // cos(-x) --> cos(x) 26250fca6ea1SDimitry Andric // cos(fabs(x)) --> cos(x) 26260fca6ea1SDimitry Andric // cos(copysign(x, y)) --> cos(x) 26275ffd83dbSDimitry Andric return replaceOperand(*II, 0, X); 26280b57cec5SDimitry Andric } 26290b57cec5SDimitry Andric break; 26300b57cec5SDimitry Andric } 26310fca6ea1SDimitry Andric case Intrinsic::sin: 26320fca6ea1SDimitry Andric case Intrinsic::amdgcn_sin: { 26330b57cec5SDimitry Andric Value *X; 26340b57cec5SDimitry Andric if (match(II->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X))))) { 26350b57cec5SDimitry Andric // sin(-x) --> -sin(x) 26360fca6ea1SDimitry Andric Value *NewSin = Builder.CreateUnaryIntrinsic(IID, X, II); 26370fca6ea1SDimitry Andric return UnaryOperator::CreateFNegFMF(NewSin, II); 26380b57cec5SDimitry Andric } 26390b57cec5SDimitry Andric break; 26400b57cec5SDimitry Andric } 264106c3fb27SDimitry Andric case Intrinsic::ldexp: { 264206c3fb27SDimitry Andric // ldexp(ldexp(x, a), b) -> ldexp(x, a + b) 264306c3fb27SDimitry Andric // 264406c3fb27SDimitry Andric // The danger is if the first ldexp would overflow to infinity or underflow 264506c3fb27SDimitry Andric // to zero, but the combined exponent avoids it. We ignore this with 264606c3fb27SDimitry Andric // reassoc. 264706c3fb27SDimitry Andric // 264806c3fb27SDimitry Andric // It's also safe to fold if we know both exponents are >= 0 or <= 0 since 264906c3fb27SDimitry Andric // it would just double down on the overflow/underflow which would occur 265006c3fb27SDimitry Andric // anyway. 265106c3fb27SDimitry Andric // 265206c3fb27SDimitry Andric // TODO: Could do better if we had range tracking for the input value 265306c3fb27SDimitry Andric // exponent. Also could broaden sign check to cover == 0 case. 265406c3fb27SDimitry Andric Value *Src = II->getArgOperand(0); 265506c3fb27SDimitry Andric Value *Exp = II->getArgOperand(1); 265606c3fb27SDimitry Andric Value *InnerSrc; 265706c3fb27SDimitry Andric Value *InnerExp; 265806c3fb27SDimitry Andric if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ldexp>( 265906c3fb27SDimitry Andric m_Value(InnerSrc), m_Value(InnerExp)))) && 266006c3fb27SDimitry Andric Exp->getType() == InnerExp->getType()) { 266106c3fb27SDimitry Andric FastMathFlags FMF = II->getFastMathFlags(); 266206c3fb27SDimitry Andric FastMathFlags InnerFlags = cast<FPMathOperator>(Src)->getFastMathFlags(); 266306c3fb27SDimitry Andric 266406c3fb27SDimitry Andric if ((FMF.allowReassoc() && InnerFlags.allowReassoc()) || 26650fca6ea1SDimitry Andric signBitMustBeTheSame(Exp, InnerExp, SQ.getWithInstruction(II))) { 266606c3fb27SDimitry Andric // TODO: Add nsw/nuw probably safe if integer type exceeds exponent 266706c3fb27SDimitry Andric // width. 266806c3fb27SDimitry Andric Value *NewExp = Builder.CreateAdd(InnerExp, Exp); 266906c3fb27SDimitry Andric II->setArgOperand(1, NewExp); 267006c3fb27SDimitry Andric II->setFastMathFlags(InnerFlags); // Or the inner flags. 267106c3fb27SDimitry Andric return replaceOperand(*II, 0, InnerSrc); 267206c3fb27SDimitry Andric } 267306c3fb27SDimitry Andric } 267406c3fb27SDimitry Andric 26750fca6ea1SDimitry Andric // ldexp(x, zext(i1 y)) -> fmul x, (select y, 2.0, 1.0) 26760fca6ea1SDimitry Andric // ldexp(x, sext(i1 y)) -> fmul x, (select y, 0.5, 1.0) 26770fca6ea1SDimitry Andric Value *ExtSrc; 26780fca6ea1SDimitry Andric if (match(Exp, m_ZExt(m_Value(ExtSrc))) && 26790fca6ea1SDimitry Andric ExtSrc->getType()->getScalarSizeInBits() == 1) { 26800fca6ea1SDimitry Andric Value *Select = 26810fca6ea1SDimitry Andric Builder.CreateSelect(ExtSrc, ConstantFP::get(II->getType(), 2.0), 26820fca6ea1SDimitry Andric ConstantFP::get(II->getType(), 1.0)); 26830fca6ea1SDimitry Andric return BinaryOperator::CreateFMulFMF(Src, Select, II); 26840fca6ea1SDimitry Andric } 26850fca6ea1SDimitry Andric if (match(Exp, m_SExt(m_Value(ExtSrc))) && 26860fca6ea1SDimitry Andric ExtSrc->getType()->getScalarSizeInBits() == 1) { 26870fca6ea1SDimitry Andric Value *Select = 26880fca6ea1SDimitry Andric Builder.CreateSelect(ExtSrc, ConstantFP::get(II->getType(), 0.5), 26890fca6ea1SDimitry Andric ConstantFP::get(II->getType(), 1.0)); 26900fca6ea1SDimitry Andric return BinaryOperator::CreateFMulFMF(Src, Select, II); 26910fca6ea1SDimitry Andric } 26920fca6ea1SDimitry Andric 26930fca6ea1SDimitry Andric // ldexp(x, c ? exp : 0) -> c ? ldexp(x, exp) : x 26940fca6ea1SDimitry Andric // ldexp(x, c ? 0 : exp) -> c ? x : ldexp(x, exp) 26950fca6ea1SDimitry Andric /// 26960fca6ea1SDimitry Andric // TODO: If we cared, should insert a canonicalize for x 26970fca6ea1SDimitry Andric Value *SelectCond, *SelectLHS, *SelectRHS; 26980fca6ea1SDimitry Andric if (match(II->getArgOperand(1), 26990fca6ea1SDimitry Andric m_OneUse(m_Select(m_Value(SelectCond), m_Value(SelectLHS), 27000fca6ea1SDimitry Andric m_Value(SelectRHS))))) { 27010fca6ea1SDimitry Andric Value *NewLdexp = nullptr; 27020fca6ea1SDimitry Andric Value *Select = nullptr; 27030fca6ea1SDimitry Andric if (match(SelectRHS, m_ZeroInt())) { 27040fca6ea1SDimitry Andric NewLdexp = Builder.CreateLdexp(Src, SelectLHS); 27050fca6ea1SDimitry Andric Select = Builder.CreateSelect(SelectCond, NewLdexp, Src); 27060fca6ea1SDimitry Andric } else if (match(SelectLHS, m_ZeroInt())) { 27070fca6ea1SDimitry Andric NewLdexp = Builder.CreateLdexp(Src, SelectRHS); 27080fca6ea1SDimitry Andric Select = Builder.CreateSelect(SelectCond, Src, NewLdexp); 27090fca6ea1SDimitry Andric } 27100fca6ea1SDimitry Andric 27110fca6ea1SDimitry Andric if (NewLdexp) { 27120fca6ea1SDimitry Andric Select->takeName(II); 27130fca6ea1SDimitry Andric cast<Instruction>(NewLdexp)->copyFastMathFlags(II); 27140fca6ea1SDimitry Andric return replaceInstUsesWith(*II, Select); 27150fca6ea1SDimitry Andric } 27160fca6ea1SDimitry Andric } 27170fca6ea1SDimitry Andric 271806c3fb27SDimitry Andric break; 271906c3fb27SDimitry Andric } 2720bdd1243dSDimitry Andric case Intrinsic::ptrauth_auth: 2721bdd1243dSDimitry Andric case Intrinsic::ptrauth_resign: { 2722bdd1243dSDimitry Andric // (sign|resign) + (auth|resign) can be folded by omitting the middle 2723bdd1243dSDimitry Andric // sign+auth component if the key and discriminator match. 2724bdd1243dSDimitry Andric bool NeedSign = II->getIntrinsicID() == Intrinsic::ptrauth_resign; 27250fca6ea1SDimitry Andric Value *Ptr = II->getArgOperand(0); 2726bdd1243dSDimitry Andric Value *Key = II->getArgOperand(1); 2727bdd1243dSDimitry Andric Value *Disc = II->getArgOperand(2); 27280b57cec5SDimitry Andric 2729bdd1243dSDimitry Andric // AuthKey will be the key we need to end up authenticating against in 2730bdd1243dSDimitry Andric // whatever we replace this sequence with. 2731bdd1243dSDimitry Andric Value *AuthKey = nullptr, *AuthDisc = nullptr, *BasePtr; 27320fca6ea1SDimitry Andric if (const auto *CI = dyn_cast<CallBase>(Ptr)) { 2733bdd1243dSDimitry Andric BasePtr = CI->getArgOperand(0); 2734bdd1243dSDimitry Andric if (CI->getIntrinsicID() == Intrinsic::ptrauth_sign) { 2735bdd1243dSDimitry Andric if (CI->getArgOperand(1) != Key || CI->getArgOperand(2) != Disc) 2736bdd1243dSDimitry Andric break; 2737bdd1243dSDimitry Andric } else if (CI->getIntrinsicID() == Intrinsic::ptrauth_resign) { 2738bdd1243dSDimitry Andric if (CI->getArgOperand(3) != Key || CI->getArgOperand(4) != Disc) 2739bdd1243dSDimitry Andric break; 2740bdd1243dSDimitry Andric AuthKey = CI->getArgOperand(1); 2741bdd1243dSDimitry Andric AuthDisc = CI->getArgOperand(2); 2742bdd1243dSDimitry Andric } else 2743bdd1243dSDimitry Andric break; 27440fca6ea1SDimitry Andric } else if (const auto *PtrToInt = dyn_cast<PtrToIntOperator>(Ptr)) { 27450fca6ea1SDimitry Andric // ptrauth constants are equivalent to a call to @llvm.ptrauth.sign for 27460fca6ea1SDimitry Andric // our purposes, so check for that too. 27470fca6ea1SDimitry Andric const auto *CPA = dyn_cast<ConstantPtrAuth>(PtrToInt->getOperand(0)); 27480fca6ea1SDimitry Andric if (!CPA || !CPA->isKnownCompatibleWith(Key, Disc, DL)) 27490fca6ea1SDimitry Andric break; 27500fca6ea1SDimitry Andric 27510fca6ea1SDimitry Andric // resign(ptrauth(p,ks,ds),ks,ds,kr,dr) -> ptrauth(p,kr,dr) 27520fca6ea1SDimitry Andric if (NeedSign && isa<ConstantInt>(II->getArgOperand(4))) { 27530fca6ea1SDimitry Andric auto *SignKey = cast<ConstantInt>(II->getArgOperand(3)); 27540fca6ea1SDimitry Andric auto *SignDisc = cast<ConstantInt>(II->getArgOperand(4)); 27550fca6ea1SDimitry Andric auto *SignAddrDisc = ConstantPointerNull::get(Builder.getPtrTy()); 27560fca6ea1SDimitry Andric auto *NewCPA = ConstantPtrAuth::get(CPA->getPointer(), SignKey, 27570fca6ea1SDimitry Andric SignDisc, SignAddrDisc); 27580fca6ea1SDimitry Andric replaceInstUsesWith( 27590fca6ea1SDimitry Andric *II, ConstantExpr::getPointerCast(NewCPA, II->getType())); 27600fca6ea1SDimitry Andric return eraseInstFromFunction(*II); 27610fca6ea1SDimitry Andric } 27620fca6ea1SDimitry Andric 27630fca6ea1SDimitry Andric // auth(ptrauth(p,k,d),k,d) -> p 27640fca6ea1SDimitry Andric BasePtr = Builder.CreatePtrToInt(CPA->getPointer(), II->getType()); 2765bdd1243dSDimitry Andric } else 2766bdd1243dSDimitry Andric break; 2767bdd1243dSDimitry Andric 2768bdd1243dSDimitry Andric unsigned NewIntrin; 2769bdd1243dSDimitry Andric if (AuthKey && NeedSign) { 2770bdd1243dSDimitry Andric // resign(0,1) + resign(1,2) = resign(0, 2) 2771bdd1243dSDimitry Andric NewIntrin = Intrinsic::ptrauth_resign; 2772bdd1243dSDimitry Andric } else if (AuthKey) { 2773bdd1243dSDimitry Andric // resign(0,1) + auth(1) = auth(0) 2774bdd1243dSDimitry Andric NewIntrin = Intrinsic::ptrauth_auth; 2775bdd1243dSDimitry Andric } else if (NeedSign) { 2776bdd1243dSDimitry Andric // sign(0) + resign(0, 1) = sign(1) 2777bdd1243dSDimitry Andric NewIntrin = Intrinsic::ptrauth_sign; 2778bdd1243dSDimitry Andric } else { 2779bdd1243dSDimitry Andric // sign(0) + auth(0) = nop 2780bdd1243dSDimitry Andric replaceInstUsesWith(*II, BasePtr); 27810fca6ea1SDimitry Andric return eraseInstFromFunction(*II); 2782bdd1243dSDimitry Andric } 2783bdd1243dSDimitry Andric 2784bdd1243dSDimitry Andric SmallVector<Value *, 4> CallArgs; 2785bdd1243dSDimitry Andric CallArgs.push_back(BasePtr); 2786bdd1243dSDimitry Andric if (AuthKey) { 2787bdd1243dSDimitry Andric CallArgs.push_back(AuthKey); 2788bdd1243dSDimitry Andric CallArgs.push_back(AuthDisc); 2789bdd1243dSDimitry Andric } 2790bdd1243dSDimitry Andric 2791bdd1243dSDimitry Andric if (NeedSign) { 2792bdd1243dSDimitry Andric CallArgs.push_back(II->getArgOperand(3)); 2793bdd1243dSDimitry Andric CallArgs.push_back(II->getArgOperand(4)); 2794bdd1243dSDimitry Andric } 2795bdd1243dSDimitry Andric 2796bdd1243dSDimitry Andric Function *NewFn = Intrinsic::getDeclaration(II->getModule(), NewIntrin); 2797bdd1243dSDimitry Andric return CallInst::Create(NewFn, CallArgs); 2798bdd1243dSDimitry Andric } 27990b57cec5SDimitry Andric case Intrinsic::arm_neon_vtbl1: 28000b57cec5SDimitry Andric case Intrinsic::aarch64_neon_tbl1: 28010b57cec5SDimitry Andric if (Value *V = simplifyNeonTbl1(*II, Builder)) 28020b57cec5SDimitry Andric return replaceInstUsesWith(*II, V); 28030b57cec5SDimitry Andric break; 28040b57cec5SDimitry Andric 28050b57cec5SDimitry Andric case Intrinsic::arm_neon_vmulls: 28060b57cec5SDimitry Andric case Intrinsic::arm_neon_vmullu: 28070b57cec5SDimitry Andric case Intrinsic::aarch64_neon_smull: 28080b57cec5SDimitry Andric case Intrinsic::aarch64_neon_umull: { 28090b57cec5SDimitry Andric Value *Arg0 = II->getArgOperand(0); 28100b57cec5SDimitry Andric Value *Arg1 = II->getArgOperand(1); 28110b57cec5SDimitry Andric 28120b57cec5SDimitry Andric // Handle mul by zero first: 28130b57cec5SDimitry Andric if (isa<ConstantAggregateZero>(Arg0) || isa<ConstantAggregateZero>(Arg1)) { 28140b57cec5SDimitry Andric return replaceInstUsesWith(CI, ConstantAggregateZero::get(II->getType())); 28150b57cec5SDimitry Andric } 28160b57cec5SDimitry Andric 28170b57cec5SDimitry Andric // Check for constant LHS & RHS - in this case we just simplify. 28180b57cec5SDimitry Andric bool Zext = (IID == Intrinsic::arm_neon_vmullu || 28190b57cec5SDimitry Andric IID == Intrinsic::aarch64_neon_umull); 28200b57cec5SDimitry Andric VectorType *NewVT = cast<VectorType>(II->getType()); 28210b57cec5SDimitry Andric if (Constant *CV0 = dyn_cast<Constant>(Arg0)) { 28220b57cec5SDimitry Andric if (Constant *CV1 = dyn_cast<Constant>(Arg1)) { 28235f757f3fSDimitry Andric Value *V0 = Builder.CreateIntCast(CV0, NewVT, /*isSigned=*/!Zext); 28245f757f3fSDimitry Andric Value *V1 = Builder.CreateIntCast(CV1, NewVT, /*isSigned=*/!Zext); 28255f757f3fSDimitry Andric return replaceInstUsesWith(CI, Builder.CreateMul(V0, V1)); 28260b57cec5SDimitry Andric } 28270b57cec5SDimitry Andric 28280b57cec5SDimitry Andric // Couldn't simplify - canonicalize constant to the RHS. 28290b57cec5SDimitry Andric std::swap(Arg0, Arg1); 28300b57cec5SDimitry Andric } 28310b57cec5SDimitry Andric 28320b57cec5SDimitry Andric // Handle mul by one: 28330b57cec5SDimitry Andric if (Constant *CV1 = dyn_cast<Constant>(Arg1)) 28340b57cec5SDimitry Andric if (ConstantInt *Splat = 28350b57cec5SDimitry Andric dyn_cast_or_null<ConstantInt>(CV1->getSplatValue())) 28360b57cec5SDimitry Andric if (Splat->isOne()) 28370b57cec5SDimitry Andric return CastInst::CreateIntegerCast(Arg0, II->getType(), 28380b57cec5SDimitry Andric /*isSigned=*/!Zext); 28390b57cec5SDimitry Andric 28400b57cec5SDimitry Andric break; 28410b57cec5SDimitry Andric } 28420b57cec5SDimitry Andric case Intrinsic::arm_neon_aesd: 28430b57cec5SDimitry Andric case Intrinsic::arm_neon_aese: 28440b57cec5SDimitry Andric case Intrinsic::aarch64_crypto_aesd: 28450b57cec5SDimitry Andric case Intrinsic::aarch64_crypto_aese: { 28460b57cec5SDimitry Andric Value *DataArg = II->getArgOperand(0); 28470b57cec5SDimitry Andric Value *KeyArg = II->getArgOperand(1); 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric // Try to use the builtin XOR in AESE and AESD to eliminate a prior XOR 28500b57cec5SDimitry Andric Value *Data, *Key; 28510b57cec5SDimitry Andric if (match(KeyArg, m_ZeroInt()) && 28520b57cec5SDimitry Andric match(DataArg, m_Xor(m_Value(Data), m_Value(Key)))) { 28535ffd83dbSDimitry Andric replaceOperand(*II, 0, Data); 28545ffd83dbSDimitry Andric replaceOperand(*II, 1, Key); 28550b57cec5SDimitry Andric return II; 28560b57cec5SDimitry Andric } 28570b57cec5SDimitry Andric break; 28580b57cec5SDimitry Andric } 28595ffd83dbSDimitry Andric case Intrinsic::hexagon_V6_vandvrt: 28605ffd83dbSDimitry Andric case Intrinsic::hexagon_V6_vandvrt_128B: { 28615ffd83dbSDimitry Andric // Simplify Q -> V -> Q conversion. 28625ffd83dbSDimitry Andric if (auto Op0 = dyn_cast<IntrinsicInst>(II->getArgOperand(0))) { 28635ffd83dbSDimitry Andric Intrinsic::ID ID0 = Op0->getIntrinsicID(); 28645ffd83dbSDimitry Andric if (ID0 != Intrinsic::hexagon_V6_vandqrt && 28655ffd83dbSDimitry Andric ID0 != Intrinsic::hexagon_V6_vandqrt_128B) 28665ffd83dbSDimitry Andric break; 28675ffd83dbSDimitry Andric Value *Bytes = Op0->getArgOperand(1), *Mask = II->getArgOperand(1); 28685ffd83dbSDimitry Andric uint64_t Bytes1 = computeKnownBits(Bytes, 0, Op0).One.getZExtValue(); 28695ffd83dbSDimitry Andric uint64_t Mask1 = computeKnownBits(Mask, 0, II).One.getZExtValue(); 28705ffd83dbSDimitry Andric // Check if every byte has common bits in Bytes and Mask. 28715ffd83dbSDimitry Andric uint64_t C = Bytes1 & Mask1; 28725ffd83dbSDimitry Andric if ((C & 0xFF) && (C & 0xFF00) && (C & 0xFF0000) && (C & 0xFF000000)) 28735ffd83dbSDimitry Andric return replaceInstUsesWith(*II, Op0->getArgOperand(0)); 28745ffd83dbSDimitry Andric } 28755ffd83dbSDimitry Andric break; 28765ffd83dbSDimitry Andric } 28770b57cec5SDimitry Andric case Intrinsic::stackrestore: { 2878349cc55cSDimitry Andric enum class ClassifyResult { 2879349cc55cSDimitry Andric None, 2880349cc55cSDimitry Andric Alloca, 2881349cc55cSDimitry Andric StackRestore, 2882349cc55cSDimitry Andric CallWithSideEffects, 2883349cc55cSDimitry Andric }; 2884349cc55cSDimitry Andric auto Classify = [](const Instruction *I) { 2885349cc55cSDimitry Andric if (isa<AllocaInst>(I)) 2886349cc55cSDimitry Andric return ClassifyResult::Alloca; 2887349cc55cSDimitry Andric 2888349cc55cSDimitry Andric if (auto *CI = dyn_cast<CallInst>(I)) { 2889349cc55cSDimitry Andric if (auto *II = dyn_cast<IntrinsicInst>(CI)) { 2890349cc55cSDimitry Andric if (II->getIntrinsicID() == Intrinsic::stackrestore) 2891349cc55cSDimitry Andric return ClassifyResult::StackRestore; 2892349cc55cSDimitry Andric 2893349cc55cSDimitry Andric if (II->mayHaveSideEffects()) 2894349cc55cSDimitry Andric return ClassifyResult::CallWithSideEffects; 2895349cc55cSDimitry Andric } else { 2896349cc55cSDimitry Andric // Consider all non-intrinsic calls to be side effects 2897349cc55cSDimitry Andric return ClassifyResult::CallWithSideEffects; 28980b57cec5SDimitry Andric } 28990b57cec5SDimitry Andric } 2900349cc55cSDimitry Andric 2901349cc55cSDimitry Andric return ClassifyResult::None; 2902349cc55cSDimitry Andric }; 2903349cc55cSDimitry Andric 2904349cc55cSDimitry Andric // If the stacksave and the stackrestore are in the same BB, and there is 2905349cc55cSDimitry Andric // no intervening call, alloca, or stackrestore of a different stacksave, 2906349cc55cSDimitry Andric // remove the restore. This can happen when variable allocas are DCE'd. 2907349cc55cSDimitry Andric if (IntrinsicInst *SS = dyn_cast<IntrinsicInst>(II->getArgOperand(0))) { 2908349cc55cSDimitry Andric if (SS->getIntrinsicID() == Intrinsic::stacksave && 2909349cc55cSDimitry Andric SS->getParent() == II->getParent()) { 2910349cc55cSDimitry Andric BasicBlock::iterator BI(SS); 2911349cc55cSDimitry Andric bool CannotRemove = false; 2912349cc55cSDimitry Andric for (++BI; &*BI != II; ++BI) { 2913349cc55cSDimitry Andric switch (Classify(&*BI)) { 2914349cc55cSDimitry Andric case ClassifyResult::None: 2915349cc55cSDimitry Andric // So far so good, look at next instructions. 2916349cc55cSDimitry Andric break; 2917349cc55cSDimitry Andric 2918349cc55cSDimitry Andric case ClassifyResult::StackRestore: 2919349cc55cSDimitry Andric // If we found an intervening stackrestore for a different 2920349cc55cSDimitry Andric // stacksave, we can't remove the stackrestore. Otherwise, continue. 2921349cc55cSDimitry Andric if (cast<IntrinsicInst>(*BI).getArgOperand(0) != SS) 2922349cc55cSDimitry Andric CannotRemove = true; 2923349cc55cSDimitry Andric break; 2924349cc55cSDimitry Andric 2925349cc55cSDimitry Andric case ClassifyResult::Alloca: 2926349cc55cSDimitry Andric case ClassifyResult::CallWithSideEffects: 2927349cc55cSDimitry Andric // If we found an alloca, a non-intrinsic call, or an intrinsic 2928349cc55cSDimitry Andric // call with side effects, we can't remove the stackrestore. 2929349cc55cSDimitry Andric CannotRemove = true; 2930349cc55cSDimitry Andric break; 2931349cc55cSDimitry Andric } 2932349cc55cSDimitry Andric if (CannotRemove) 2933349cc55cSDimitry Andric break; 2934349cc55cSDimitry Andric } 2935349cc55cSDimitry Andric 2936349cc55cSDimitry Andric if (!CannotRemove) 2937349cc55cSDimitry Andric return eraseInstFromFunction(CI); 2938349cc55cSDimitry Andric } 29390b57cec5SDimitry Andric } 29400b57cec5SDimitry Andric 29410b57cec5SDimitry Andric // Scan down this block to see if there is another stack restore in the 29420b57cec5SDimitry Andric // same block without an intervening call/alloca. 29430b57cec5SDimitry Andric BasicBlock::iterator BI(II); 29440b57cec5SDimitry Andric Instruction *TI = II->getParent()->getTerminator(); 29450b57cec5SDimitry Andric bool CannotRemove = false; 29460b57cec5SDimitry Andric for (++BI; &*BI != TI; ++BI) { 2947349cc55cSDimitry Andric switch (Classify(&*BI)) { 2948349cc55cSDimitry Andric case ClassifyResult::None: 2949349cc55cSDimitry Andric // So far so good, look at next instructions. 29500b57cec5SDimitry Andric break; 2951349cc55cSDimitry Andric 2952349cc55cSDimitry Andric case ClassifyResult::StackRestore: 29530b57cec5SDimitry Andric // If there is a stackrestore below this one, remove this one. 29540b57cec5SDimitry Andric return eraseInstFromFunction(CI); 29550b57cec5SDimitry Andric 2956349cc55cSDimitry Andric case ClassifyResult::Alloca: 2957349cc55cSDimitry Andric case ClassifyResult::CallWithSideEffects: 2958349cc55cSDimitry Andric // If we found an alloca, a non-intrinsic call, or an intrinsic call 2959349cc55cSDimitry Andric // with side effects (such as llvm.stacksave and llvm.read_register), 2960349cc55cSDimitry Andric // we can't remove the stack restore. 29610b57cec5SDimitry Andric CannotRemove = true; 29620b57cec5SDimitry Andric break; 29630b57cec5SDimitry Andric } 2964349cc55cSDimitry Andric if (CannotRemove) 29650b57cec5SDimitry Andric break; 29660b57cec5SDimitry Andric } 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric // If the stack restore is in a return, resume, or unwind block and if there 29690b57cec5SDimitry Andric // are no allocas or calls between the restore and the return, nuke the 29700b57cec5SDimitry Andric // restore. 29710b57cec5SDimitry Andric if (!CannotRemove && (isa<ReturnInst>(TI) || isa<ResumeInst>(TI))) 29720b57cec5SDimitry Andric return eraseInstFromFunction(CI); 29730b57cec5SDimitry Andric break; 29740b57cec5SDimitry Andric } 29755ffd83dbSDimitry Andric case Intrinsic::lifetime_end: 29760b57cec5SDimitry Andric // Asan needs to poison memory to detect invalid access which is possible 29770b57cec5SDimitry Andric // even for empty lifetime range. 29780b57cec5SDimitry Andric if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) || 29798bcb0991SDimitry Andric II->getFunction()->hasFnAttribute(Attribute::SanitizeMemory) || 29800b57cec5SDimitry Andric II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress)) 29810b57cec5SDimitry Andric break; 29820b57cec5SDimitry Andric 29835ffd83dbSDimitry Andric if (removeTriviallyEmptyRange(*II, *this, [](const IntrinsicInst &I) { 29845ffd83dbSDimitry Andric return I.getIntrinsicID() == Intrinsic::lifetime_start; 29855ffd83dbSDimitry Andric })) 29860b57cec5SDimitry Andric return nullptr; 29870b57cec5SDimitry Andric break; 29880b57cec5SDimitry Andric case Intrinsic::assume: { 29890b57cec5SDimitry Andric Value *IIOperand = II->getArgOperand(0); 2990e8d8bef9SDimitry Andric SmallVector<OperandBundleDef, 4> OpBundles; 2991e8d8bef9SDimitry Andric II->getOperandBundlesAsDefs(OpBundles); 2992fe6060f1SDimitry Andric 2993fe6060f1SDimitry Andric /// This will remove the boolean Condition from the assume given as 2994fe6060f1SDimitry Andric /// argument and remove the assume if it becomes useless. 2995fe6060f1SDimitry Andric /// always returns nullptr for use as a return values. 2996fe6060f1SDimitry Andric auto RemoveConditionFromAssume = [&](Instruction *Assume) -> Instruction * { 2997fe6060f1SDimitry Andric assert(isa<AssumeInst>(Assume)); 2998fe6060f1SDimitry Andric if (isAssumeWithEmptyBundle(*cast<AssumeInst>(II))) 2999fe6060f1SDimitry Andric return eraseInstFromFunction(CI); 3000fe6060f1SDimitry Andric replaceUse(II->getOperandUse(0), ConstantInt::getTrue(II->getContext())); 3001fe6060f1SDimitry Andric return nullptr; 3002fe6060f1SDimitry Andric }; 30030b57cec5SDimitry Andric // Remove an assume if it is followed by an identical assume. 30040b57cec5SDimitry Andric // TODO: Do we need this? Unless there are conflicting assumptions, the 30050b57cec5SDimitry Andric // computeKnownBits(IIOperand) below here eliminates redundant assumes. 30060b57cec5SDimitry Andric Instruction *Next = II->getNextNonDebugInstruction(); 3007fe6060f1SDimitry Andric if (match(Next, m_Intrinsic<Intrinsic::assume>(m_Specific(IIOperand)))) 3008fe6060f1SDimitry Andric return RemoveConditionFromAssume(Next); 30090b57cec5SDimitry Andric 30100b57cec5SDimitry Andric // Canonicalize assume(a && b) -> assume(a); assume(b); 30110b57cec5SDimitry Andric // Note: New assumption intrinsics created here are registered by 30120b57cec5SDimitry Andric // the InstCombineIRInserter object. 30130b57cec5SDimitry Andric FunctionType *AssumeIntrinsicTy = II->getFunctionType(); 30145ffd83dbSDimitry Andric Value *AssumeIntrinsic = II->getCalledOperand(); 30150b57cec5SDimitry Andric Value *A, *B; 3016e8d8bef9SDimitry Andric if (match(IIOperand, m_LogicalAnd(m_Value(A), m_Value(B)))) { 3017e8d8bef9SDimitry Andric Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, A, OpBundles, 3018e8d8bef9SDimitry Andric II->getName()); 30190b57cec5SDimitry Andric Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, B, II->getName()); 30200b57cec5SDimitry Andric return eraseInstFromFunction(*II); 30210b57cec5SDimitry Andric } 30220b57cec5SDimitry Andric // assume(!(a || b)) -> assume(!a); assume(!b); 3023e8d8bef9SDimitry Andric if (match(IIOperand, m_Not(m_LogicalOr(m_Value(A), m_Value(B))))) { 30240b57cec5SDimitry Andric Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, 3025e8d8bef9SDimitry Andric Builder.CreateNot(A), OpBundles, II->getName()); 30260b57cec5SDimitry Andric Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, 30270b57cec5SDimitry Andric Builder.CreateNot(B), II->getName()); 30280b57cec5SDimitry Andric return eraseInstFromFunction(*II); 30290b57cec5SDimitry Andric } 30300b57cec5SDimitry Andric 30310b57cec5SDimitry Andric // assume( (load addr) != null ) -> add 'nonnull' metadata to load 30320b57cec5SDimitry Andric // (if assume is valid at the load) 30330b57cec5SDimitry Andric CmpInst::Predicate Pred; 30340b57cec5SDimitry Andric Instruction *LHS; 30350b57cec5SDimitry Andric if (match(IIOperand, m_ICmp(Pred, m_Instruction(LHS), m_Zero())) && 30360b57cec5SDimitry Andric Pred == ICmpInst::ICMP_NE && LHS->getOpcode() == Instruction::Load && 30370b57cec5SDimitry Andric LHS->getType()->isPointerTy() && 30380b57cec5SDimitry Andric isValidAssumeForContext(II, LHS, &DT)) { 3039bdd1243dSDimitry Andric MDNode *MD = MDNode::get(II->getContext(), std::nullopt); 30400b57cec5SDimitry Andric LHS->setMetadata(LLVMContext::MD_nonnull, MD); 304106c3fb27SDimitry Andric LHS->setMetadata(LLVMContext::MD_noundef, MD); 3042fe6060f1SDimitry Andric return RemoveConditionFromAssume(II); 30430b57cec5SDimitry Andric 30440b57cec5SDimitry Andric // TODO: apply nonnull return attributes to calls and invokes 30450b57cec5SDimitry Andric // TODO: apply range metadata for range check patterns? 30460b57cec5SDimitry Andric } 30470b57cec5SDimitry Andric 304806c3fb27SDimitry Andric // Separate storage assumptions apply to the underlying allocations, not any 304906c3fb27SDimitry Andric // particular pointer within them. When evaluating the hints for AA purposes 305006c3fb27SDimitry Andric // we getUnderlyingObject them; by precomputing the answers here we can 305106c3fb27SDimitry Andric // avoid having to do so repeatedly there. 305206c3fb27SDimitry Andric for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) { 305306c3fb27SDimitry Andric OperandBundleUse OBU = II->getOperandBundleAt(Idx); 305406c3fb27SDimitry Andric if (OBU.getTagName() == "separate_storage") { 305506c3fb27SDimitry Andric assert(OBU.Inputs.size() == 2); 305606c3fb27SDimitry Andric auto MaybeSimplifyHint = [&](const Use &U) { 305706c3fb27SDimitry Andric Value *Hint = U.get(); 305806c3fb27SDimitry Andric // Not having a limit is safe because InstCombine removes unreachable 305906c3fb27SDimitry Andric // code. 306006c3fb27SDimitry Andric Value *UnderlyingObject = getUnderlyingObject(Hint, /*MaxLookup*/ 0); 306106c3fb27SDimitry Andric if (Hint != UnderlyingObject) 306206c3fb27SDimitry Andric replaceUse(const_cast<Use &>(U), UnderlyingObject); 306306c3fb27SDimitry Andric }; 306406c3fb27SDimitry Andric MaybeSimplifyHint(OBU.Inputs[0]); 306506c3fb27SDimitry Andric MaybeSimplifyHint(OBU.Inputs[1]); 306606c3fb27SDimitry Andric } 306706c3fb27SDimitry Andric } 306806c3fb27SDimitry Andric 3069fe6060f1SDimitry Andric // Convert nonnull assume like: 3070fe6060f1SDimitry Andric // %A = icmp ne i32* %PTR, null 3071fe6060f1SDimitry Andric // call void @llvm.assume(i1 %A) 3072fe6060f1SDimitry Andric // into 3073fe6060f1SDimitry Andric // call void @llvm.assume(i1 true) [ "nonnull"(i32* %PTR) ] 3074fe6060f1SDimitry Andric if (EnableKnowledgeRetention && 3075fe6060f1SDimitry Andric match(IIOperand, m_Cmp(Pred, m_Value(A), m_Zero())) && 3076fe6060f1SDimitry Andric Pred == CmpInst::ICMP_NE && A->getType()->isPointerTy()) { 3077fe6060f1SDimitry Andric if (auto *Replacement = buildAssumeFromKnowledge( 3078fe6060f1SDimitry Andric {RetainedKnowledge{Attribute::NonNull, 0, A}}, Next, &AC, &DT)) { 3079fe6060f1SDimitry Andric 3080fe6060f1SDimitry Andric Replacement->insertBefore(Next); 3081fe6060f1SDimitry Andric AC.registerAssumption(Replacement); 3082fe6060f1SDimitry Andric return RemoveConditionFromAssume(II); 3083fe6060f1SDimitry Andric } 3084fe6060f1SDimitry Andric } 3085fe6060f1SDimitry Andric 3086fe6060f1SDimitry Andric // Convert alignment assume like: 3087fe6060f1SDimitry Andric // %B = ptrtoint i32* %A to i64 3088fe6060f1SDimitry Andric // %C = and i64 %B, Constant 3089fe6060f1SDimitry Andric // %D = icmp eq i64 %C, 0 3090fe6060f1SDimitry Andric // call void @llvm.assume(i1 %D) 3091fe6060f1SDimitry Andric // into 3092fe6060f1SDimitry Andric // call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 Constant + 1)] 3093fe6060f1SDimitry Andric uint64_t AlignMask; 3094fe6060f1SDimitry Andric if (EnableKnowledgeRetention && 3095fe6060f1SDimitry Andric match(IIOperand, 3096fe6060f1SDimitry Andric m_Cmp(Pred, m_And(m_Value(A), m_ConstantInt(AlignMask)), 3097fe6060f1SDimitry Andric m_Zero())) && 3098fe6060f1SDimitry Andric Pred == CmpInst::ICMP_EQ) { 3099fe6060f1SDimitry Andric if (isPowerOf2_64(AlignMask + 1)) { 3100fe6060f1SDimitry Andric uint64_t Offset = 0; 3101fe6060f1SDimitry Andric match(A, m_Add(m_Value(A), m_ConstantInt(Offset))); 3102fe6060f1SDimitry Andric if (match(A, m_PtrToInt(m_Value(A)))) { 3103fe6060f1SDimitry Andric /// Note: this doesn't preserve the offset information but merges 3104fe6060f1SDimitry Andric /// offset and alignment. 3105fe6060f1SDimitry Andric /// TODO: we can generate a GEP instead of merging the alignment with 3106fe6060f1SDimitry Andric /// the offset. 3107fe6060f1SDimitry Andric RetainedKnowledge RK{Attribute::Alignment, 3108fe6060f1SDimitry Andric (unsigned)MinAlign(Offset, AlignMask + 1), A}; 3109fe6060f1SDimitry Andric if (auto *Replacement = 3110fe6060f1SDimitry Andric buildAssumeFromKnowledge(RK, Next, &AC, &DT)) { 3111fe6060f1SDimitry Andric 3112fe6060f1SDimitry Andric Replacement->insertAfter(II); 3113fe6060f1SDimitry Andric AC.registerAssumption(Replacement); 3114fe6060f1SDimitry Andric } 3115fe6060f1SDimitry Andric return RemoveConditionFromAssume(II); 3116fe6060f1SDimitry Andric } 3117fe6060f1SDimitry Andric } 3118fe6060f1SDimitry Andric } 3119fe6060f1SDimitry Andric 3120fe6060f1SDimitry Andric /// Canonicalize Knowledge in operand bundles. 3121fe6060f1SDimitry Andric if (EnableKnowledgeRetention && II->hasOperandBundles()) { 3122fe6060f1SDimitry Andric for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) { 3123fe6060f1SDimitry Andric auto &BOI = II->bundle_op_info_begin()[Idx]; 3124fe6060f1SDimitry Andric RetainedKnowledge RK = 3125fe6060f1SDimitry Andric llvm::getKnowledgeFromBundle(cast<AssumeInst>(*II), BOI); 3126fe6060f1SDimitry Andric if (BOI.End - BOI.Begin > 2) 3127fe6060f1SDimitry Andric continue; // Prevent reducing knowledge in an align with offset since 3128bdd1243dSDimitry Andric // extracting a RetainedKnowledge from them looses offset 3129fe6060f1SDimitry Andric // information 3130fe6060f1SDimitry Andric RetainedKnowledge CanonRK = 3131fe6060f1SDimitry Andric llvm::simplifyRetainedKnowledge(cast<AssumeInst>(II), RK, 3132fe6060f1SDimitry Andric &getAssumptionCache(), 3133fe6060f1SDimitry Andric &getDominatorTree()); 3134fe6060f1SDimitry Andric if (CanonRK == RK) 3135fe6060f1SDimitry Andric continue; 3136fe6060f1SDimitry Andric if (!CanonRK) { 3137fe6060f1SDimitry Andric if (BOI.End - BOI.Begin > 0) { 3138fe6060f1SDimitry Andric Worklist.pushValue(II->op_begin()[BOI.Begin]); 3139fe6060f1SDimitry Andric Value::dropDroppableUse(II->op_begin()[BOI.Begin]); 3140fe6060f1SDimitry Andric } 3141fe6060f1SDimitry Andric continue; 3142fe6060f1SDimitry Andric } 3143fe6060f1SDimitry Andric assert(RK.AttrKind == CanonRK.AttrKind); 3144fe6060f1SDimitry Andric if (BOI.End - BOI.Begin > 0) 3145fe6060f1SDimitry Andric II->op_begin()[BOI.Begin].set(CanonRK.WasOn); 3146fe6060f1SDimitry Andric if (BOI.End - BOI.Begin > 1) 3147fe6060f1SDimitry Andric II->op_begin()[BOI.Begin + 1].set(ConstantInt::get( 3148fe6060f1SDimitry Andric Type::getInt64Ty(II->getContext()), CanonRK.ArgValue)); 3149fe6060f1SDimitry Andric if (RK.WasOn) 3150fe6060f1SDimitry Andric Worklist.pushValue(RK.WasOn); 3151fe6060f1SDimitry Andric return II; 3152fe6060f1SDimitry Andric } 3153fe6060f1SDimitry Andric } 3154fe6060f1SDimitry Andric 31550b57cec5SDimitry Andric // If there is a dominating assume with the same condition as this one, 31560b57cec5SDimitry Andric // then this one is redundant, and should be removed. 31570b57cec5SDimitry Andric KnownBits Known(1); 31580b57cec5SDimitry Andric computeKnownBits(IIOperand, Known, 0, II); 3159fe6060f1SDimitry Andric if (Known.isAllOnes() && isAssumeWithEmptyBundle(cast<AssumeInst>(*II))) 31600b57cec5SDimitry Andric return eraseInstFromFunction(*II); 31610b57cec5SDimitry Andric 316206c3fb27SDimitry Andric // assume(false) is unreachable. 316306c3fb27SDimitry Andric if (match(IIOperand, m_CombineOr(m_Zero(), m_Undef()))) { 316406c3fb27SDimitry Andric CreateNonTerminatorUnreachable(II); 316506c3fb27SDimitry Andric return eraseInstFromFunction(*II); 316606c3fb27SDimitry Andric } 316706c3fb27SDimitry Andric 31680b57cec5SDimitry Andric // Update the cache of affected values for this assumption (we might be 31690b57cec5SDimitry Andric // here because we just simplified the condition). 3170fe6060f1SDimitry Andric AC.updateAffectedValues(cast<AssumeInst>(II)); 31710b57cec5SDimitry Andric break; 31720b57cec5SDimitry Andric } 31730b57cec5SDimitry Andric case Intrinsic::experimental_guard: { 31740b57cec5SDimitry Andric // Is this guard followed by another guard? We scan forward over a small 31750b57cec5SDimitry Andric // fixed window of instructions to handle common cases with conditions 31760b57cec5SDimitry Andric // computed between guards. 3177480093f4SDimitry Andric Instruction *NextInst = II->getNextNonDebugInstruction(); 31780b57cec5SDimitry Andric for (unsigned i = 0; i < GuardWideningWindow; i++) { 31790b57cec5SDimitry Andric // Note: Using context-free form to avoid compile time blow up 31800b57cec5SDimitry Andric if (!isSafeToSpeculativelyExecute(NextInst)) 31810b57cec5SDimitry Andric break; 3182480093f4SDimitry Andric NextInst = NextInst->getNextNonDebugInstruction(); 31830b57cec5SDimitry Andric } 31840b57cec5SDimitry Andric Value *NextCond = nullptr; 31850b57cec5SDimitry Andric if (match(NextInst, 31860b57cec5SDimitry Andric m_Intrinsic<Intrinsic::experimental_guard>(m_Value(NextCond)))) { 31870b57cec5SDimitry Andric Value *CurrCond = II->getArgOperand(0); 31880b57cec5SDimitry Andric 31890b57cec5SDimitry Andric // Remove a guard that it is immediately preceded by an identical guard. 31900b57cec5SDimitry Andric // Otherwise canonicalize guard(a); guard(b) -> guard(a & b). 3191480093f4SDimitry Andric if (CurrCond != NextCond) { 3192480093f4SDimitry Andric Instruction *MoveI = II->getNextNonDebugInstruction(); 31930b57cec5SDimitry Andric while (MoveI != NextInst) { 31940b57cec5SDimitry Andric auto *Temp = MoveI; 3195480093f4SDimitry Andric MoveI = MoveI->getNextNonDebugInstruction(); 31960b57cec5SDimitry Andric Temp->moveBefore(II); 31970b57cec5SDimitry Andric } 31985ffd83dbSDimitry Andric replaceOperand(*II, 0, Builder.CreateAnd(CurrCond, NextCond)); 3199480093f4SDimitry Andric } 3200480093f4SDimitry Andric eraseInstFromFunction(*NextInst); 3201480093f4SDimitry Andric return II; 32020b57cec5SDimitry Andric } 32030b57cec5SDimitry Andric break; 32040b57cec5SDimitry Andric } 320581ad6265SDimitry Andric case Intrinsic::vector_insert: { 3206e8d8bef9SDimitry Andric Value *Vec = II->getArgOperand(0); 3207e8d8bef9SDimitry Andric Value *SubVec = II->getArgOperand(1); 3208e8d8bef9SDimitry Andric Value *Idx = II->getArgOperand(2); 3209e8d8bef9SDimitry Andric auto *DstTy = dyn_cast<FixedVectorType>(II->getType()); 3210e8d8bef9SDimitry Andric auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType()); 3211e8d8bef9SDimitry Andric auto *SubVecTy = dyn_cast<FixedVectorType>(SubVec->getType()); 3212e8d8bef9SDimitry Andric 3213e8d8bef9SDimitry Andric // Only canonicalize if the destination vector, Vec, and SubVec are all 3214e8d8bef9SDimitry Andric // fixed vectors. 3215e8d8bef9SDimitry Andric if (DstTy && VecTy && SubVecTy) { 3216e8d8bef9SDimitry Andric unsigned DstNumElts = DstTy->getNumElements(); 3217e8d8bef9SDimitry Andric unsigned VecNumElts = VecTy->getNumElements(); 3218e8d8bef9SDimitry Andric unsigned SubVecNumElts = SubVecTy->getNumElements(); 3219e8d8bef9SDimitry Andric unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); 3220e8d8bef9SDimitry Andric 3221e8d8bef9SDimitry Andric // An insert that entirely overwrites Vec with SubVec is a nop. 3222fe6060f1SDimitry Andric if (VecNumElts == SubVecNumElts) 3223fe6060f1SDimitry Andric return replaceInstUsesWith(CI, SubVec); 3224e8d8bef9SDimitry Andric 3225e8d8bef9SDimitry Andric // Widen SubVec into a vector of the same width as Vec, since 3226e8d8bef9SDimitry Andric // shufflevector requires the two input vectors to be the same width. 3227e8d8bef9SDimitry Andric // Elements beyond the bounds of SubVec within the widened vector are 3228e8d8bef9SDimitry Andric // undefined. 3229e8d8bef9SDimitry Andric SmallVector<int, 8> WidenMask; 3230e8d8bef9SDimitry Andric unsigned i; 3231e8d8bef9SDimitry Andric for (i = 0; i != SubVecNumElts; ++i) 3232e8d8bef9SDimitry Andric WidenMask.push_back(i); 3233e8d8bef9SDimitry Andric for (; i != VecNumElts; ++i) 323406c3fb27SDimitry Andric WidenMask.push_back(PoisonMaskElem); 3235e8d8bef9SDimitry Andric 3236e8d8bef9SDimitry Andric Value *WidenShuffle = Builder.CreateShuffleVector(SubVec, WidenMask); 3237e8d8bef9SDimitry Andric 3238e8d8bef9SDimitry Andric SmallVector<int, 8> Mask; 3239e8d8bef9SDimitry Andric for (unsigned i = 0; i != IdxN; ++i) 3240e8d8bef9SDimitry Andric Mask.push_back(i); 3241e8d8bef9SDimitry Andric for (unsigned i = DstNumElts; i != DstNumElts + SubVecNumElts; ++i) 3242e8d8bef9SDimitry Andric Mask.push_back(i); 3243e8d8bef9SDimitry Andric for (unsigned i = IdxN + SubVecNumElts; i != DstNumElts; ++i) 3244e8d8bef9SDimitry Andric Mask.push_back(i); 3245e8d8bef9SDimitry Andric 3246e8d8bef9SDimitry Andric Value *Shuffle = Builder.CreateShuffleVector(Vec, WidenShuffle, Mask); 3247fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Shuffle); 3248e8d8bef9SDimitry Andric } 3249e8d8bef9SDimitry Andric break; 3250e8d8bef9SDimitry Andric } 325181ad6265SDimitry Andric case Intrinsic::vector_extract: { 3252e8d8bef9SDimitry Andric Value *Vec = II->getArgOperand(0); 3253e8d8bef9SDimitry Andric Value *Idx = II->getArgOperand(1); 3254e8d8bef9SDimitry Andric 3255bdd1243dSDimitry Andric Type *ReturnType = II->getType(); 3256bdd1243dSDimitry Andric // (extract_vector (insert_vector InsertTuple, InsertValue, InsertIdx), 3257bdd1243dSDimitry Andric // ExtractIdx) 3258bdd1243dSDimitry Andric unsigned ExtractIdx = cast<ConstantInt>(Idx)->getZExtValue(); 3259bdd1243dSDimitry Andric Value *InsertTuple, *InsertIdx, *InsertValue; 3260bdd1243dSDimitry Andric if (match(Vec, m_Intrinsic<Intrinsic::vector_insert>(m_Value(InsertTuple), 3261bdd1243dSDimitry Andric m_Value(InsertValue), 3262bdd1243dSDimitry Andric m_Value(InsertIdx))) && 3263bdd1243dSDimitry Andric InsertValue->getType() == ReturnType) { 3264bdd1243dSDimitry Andric unsigned Index = cast<ConstantInt>(InsertIdx)->getZExtValue(); 3265bdd1243dSDimitry Andric // Case where we get the same index right after setting it. 3266bdd1243dSDimitry Andric // extract.vector(insert.vector(InsertTuple, InsertValue, Idx), Idx) --> 3267bdd1243dSDimitry Andric // InsertValue 3268bdd1243dSDimitry Andric if (ExtractIdx == Index) 3269bdd1243dSDimitry Andric return replaceInstUsesWith(CI, InsertValue); 3270bdd1243dSDimitry Andric // If we are getting a different index than what was set in the 3271bdd1243dSDimitry Andric // insert.vector intrinsic. We can just set the input tuple to the one up 3272bdd1243dSDimitry Andric // in the chain. extract.vector(insert.vector(InsertTuple, InsertValue, 3273bdd1243dSDimitry Andric // InsertIndex), ExtractIndex) 3274bdd1243dSDimitry Andric // --> extract.vector(InsertTuple, ExtractIndex) 3275bdd1243dSDimitry Andric else 3276bdd1243dSDimitry Andric return replaceOperand(CI, 0, InsertTuple); 3277bdd1243dSDimitry Andric } 3278bdd1243dSDimitry Andric 32795f757f3fSDimitry Andric auto *DstTy = dyn_cast<VectorType>(ReturnType); 32805f757f3fSDimitry Andric auto *VecTy = dyn_cast<VectorType>(Vec->getType()); 3281e8d8bef9SDimitry Andric 3282e8d8bef9SDimitry Andric if (DstTy && VecTy) { 32835f757f3fSDimitry Andric auto DstEltCnt = DstTy->getElementCount(); 32845f757f3fSDimitry Andric auto VecEltCnt = VecTy->getElementCount(); 3285e8d8bef9SDimitry Andric unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); 3286e8d8bef9SDimitry Andric 3287e8d8bef9SDimitry Andric // Extracting the entirety of Vec is a nop. 32885f757f3fSDimitry Andric if (DstEltCnt == VecTy->getElementCount()) { 3289e8d8bef9SDimitry Andric replaceInstUsesWith(CI, Vec); 3290e8d8bef9SDimitry Andric return eraseInstFromFunction(CI); 3291e8d8bef9SDimitry Andric } 3292e8d8bef9SDimitry Andric 32935f757f3fSDimitry Andric // Only canonicalize to shufflevector if the destination vector and 32945f757f3fSDimitry Andric // Vec are fixed vectors. 32955f757f3fSDimitry Andric if (VecEltCnt.isScalable() || DstEltCnt.isScalable()) 32965f757f3fSDimitry Andric break; 32975f757f3fSDimitry Andric 3298e8d8bef9SDimitry Andric SmallVector<int, 8> Mask; 32995f757f3fSDimitry Andric for (unsigned i = 0; i != DstEltCnt.getKnownMinValue(); ++i) 3300e8d8bef9SDimitry Andric Mask.push_back(IdxN + i); 3301e8d8bef9SDimitry Andric 3302fe6060f1SDimitry Andric Value *Shuffle = Builder.CreateShuffleVector(Vec, Mask); 3303fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Shuffle); 3304fe6060f1SDimitry Andric } 3305fe6060f1SDimitry Andric break; 3306fe6060f1SDimitry Andric } 33070fca6ea1SDimitry Andric case Intrinsic::vector_reverse: { 3308349cc55cSDimitry Andric Value *BO0, *BO1, *X, *Y; 3309349cc55cSDimitry Andric Value *Vec = II->getArgOperand(0); 3310349cc55cSDimitry Andric if (match(Vec, m_OneUse(m_BinOp(m_Value(BO0), m_Value(BO1))))) { 3311349cc55cSDimitry Andric auto *OldBinOp = cast<BinaryOperator>(Vec); 3312bdd1243dSDimitry Andric if (match(BO0, m_VecReverse(m_Value(X)))) { 3313349cc55cSDimitry Andric // rev(binop rev(X), rev(Y)) --> binop X, Y 3314bdd1243dSDimitry Andric if (match(BO1, m_VecReverse(m_Value(Y)))) 33150fca6ea1SDimitry Andric return replaceInstUsesWith(CI, BinaryOperator::CreateWithCopiedFlags( 33160fca6ea1SDimitry Andric OldBinOp->getOpcode(), X, Y, 33170fca6ea1SDimitry Andric OldBinOp, OldBinOp->getName(), 33180fca6ea1SDimitry Andric II->getIterator())); 3319349cc55cSDimitry Andric // rev(binop rev(X), BO1Splat) --> binop X, BO1Splat 3320349cc55cSDimitry Andric if (isSplatValue(BO1)) 33210fca6ea1SDimitry Andric return replaceInstUsesWith(CI, BinaryOperator::CreateWithCopiedFlags( 3322349cc55cSDimitry Andric OldBinOp->getOpcode(), X, BO1, 33230fca6ea1SDimitry Andric OldBinOp, OldBinOp->getName(), 33240fca6ea1SDimitry Andric II->getIterator())); 3325349cc55cSDimitry Andric } 3326349cc55cSDimitry Andric // rev(binop BO0Splat, rev(Y)) --> binop BO0Splat, Y 3327bdd1243dSDimitry Andric if (match(BO1, m_VecReverse(m_Value(Y))) && isSplatValue(BO0)) 33280fca6ea1SDimitry Andric return replaceInstUsesWith(CI, 33290fca6ea1SDimitry Andric BinaryOperator::CreateWithCopiedFlags( 33300fca6ea1SDimitry Andric OldBinOp->getOpcode(), BO0, Y, OldBinOp, 33310fca6ea1SDimitry Andric OldBinOp->getName(), II->getIterator())); 3332349cc55cSDimitry Andric } 3333349cc55cSDimitry Andric // rev(unop rev(X)) --> unop X 3334bdd1243dSDimitry Andric if (match(Vec, m_OneUse(m_UnOp(m_VecReverse(m_Value(X)))))) { 3335349cc55cSDimitry Andric auto *OldUnOp = cast<UnaryOperator>(Vec); 3336349cc55cSDimitry Andric auto *NewUnOp = UnaryOperator::CreateWithCopiedFlags( 33370fca6ea1SDimitry Andric OldUnOp->getOpcode(), X, OldUnOp, OldUnOp->getName(), 33380fca6ea1SDimitry Andric II->getIterator()); 3339349cc55cSDimitry Andric return replaceInstUsesWith(CI, NewUnOp); 3340349cc55cSDimitry Andric } 3341349cc55cSDimitry Andric break; 3342349cc55cSDimitry Andric } 3343fe6060f1SDimitry Andric case Intrinsic::vector_reduce_or: 3344fe6060f1SDimitry Andric case Intrinsic::vector_reduce_and: { 3345fe6060f1SDimitry Andric // Canonicalize logical or/and reductions: 3346fe6060f1SDimitry Andric // Or reduction for i1 is represented as: 3347fe6060f1SDimitry Andric // %val = bitcast <ReduxWidth x i1> to iReduxWidth 3348fe6060f1SDimitry Andric // %res = cmp ne iReduxWidth %val, 0 3349fe6060f1SDimitry Andric // And reduction for i1 is represented as: 3350fe6060f1SDimitry Andric // %val = bitcast <ReduxWidth x i1> to iReduxWidth 3351fe6060f1SDimitry Andric // %res = cmp eq iReduxWidth %val, 11111 3352fe6060f1SDimitry Andric Value *Arg = II->getArgOperand(0); 3353349cc55cSDimitry Andric Value *Vect; 33540fca6ea1SDimitry Andric 33550fca6ea1SDimitry Andric if (Value *NewOp = 33560fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 33570fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 33580fca6ea1SDimitry Andric return II; 33590fca6ea1SDimitry Andric } 33600fca6ea1SDimitry Andric 3361349cc55cSDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 3362349cc55cSDimitry Andric if (auto *FTy = dyn_cast<FixedVectorType>(Vect->getType())) 3363349cc55cSDimitry Andric if (FTy->getElementType() == Builder.getInt1Ty()) { 3364fe6060f1SDimitry Andric Value *Res = Builder.CreateBitCast( 3365349cc55cSDimitry Andric Vect, Builder.getIntNTy(FTy->getNumElements())); 3366fe6060f1SDimitry Andric if (IID == Intrinsic::vector_reduce_and) { 3367fe6060f1SDimitry Andric Res = Builder.CreateICmpEQ( 3368fe6060f1SDimitry Andric Res, ConstantInt::getAllOnesValue(Res->getType())); 3369fe6060f1SDimitry Andric } else { 3370fe6060f1SDimitry Andric assert(IID == Intrinsic::vector_reduce_or && 3371fe6060f1SDimitry Andric "Expected or reduction."); 3372fe6060f1SDimitry Andric Res = Builder.CreateIsNotNull(Res); 3373fe6060f1SDimitry Andric } 3374349cc55cSDimitry Andric if (Arg != Vect) 3375349cc55cSDimitry Andric Res = Builder.CreateCast(cast<CastInst>(Arg)->getOpcode(), Res, 3376349cc55cSDimitry Andric II->getType()); 3377fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Res); 3378fe6060f1SDimitry Andric } 3379349cc55cSDimitry Andric } 3380bdd1243dSDimitry Andric [[fallthrough]]; 3381fe6060f1SDimitry Andric } 3382fe6060f1SDimitry Andric case Intrinsic::vector_reduce_add: { 3383fe6060f1SDimitry Andric if (IID == Intrinsic::vector_reduce_add) { 3384fe6060f1SDimitry Andric // Convert vector_reduce_add(ZExt(<n x i1>)) to 3385fe6060f1SDimitry Andric // ZExtOrTrunc(ctpop(bitcast <n x i1> to in)). 3386fe6060f1SDimitry Andric // Convert vector_reduce_add(SExt(<n x i1>)) to 3387fe6060f1SDimitry Andric // -ZExtOrTrunc(ctpop(bitcast <n x i1> to in)). 3388fe6060f1SDimitry Andric // Convert vector_reduce_add(<n x i1>) to 3389fe6060f1SDimitry Andric // Trunc(ctpop(bitcast <n x i1> to in)). 3390fe6060f1SDimitry Andric Value *Arg = II->getArgOperand(0); 3391fe6060f1SDimitry Andric Value *Vect; 33920fca6ea1SDimitry Andric 33930fca6ea1SDimitry Andric if (Value *NewOp = 33940fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 33950fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 33960fca6ea1SDimitry Andric return II; 33970fca6ea1SDimitry Andric } 33980fca6ea1SDimitry Andric 3399fe6060f1SDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 3400fe6060f1SDimitry Andric if (auto *FTy = dyn_cast<FixedVectorType>(Vect->getType())) 3401fe6060f1SDimitry Andric if (FTy->getElementType() == Builder.getInt1Ty()) { 3402fe6060f1SDimitry Andric Value *V = Builder.CreateBitCast( 3403fe6060f1SDimitry Andric Vect, Builder.getIntNTy(FTy->getNumElements())); 3404fe6060f1SDimitry Andric Value *Res = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, V); 3405fe6060f1SDimitry Andric if (Res->getType() != II->getType()) 3406fe6060f1SDimitry Andric Res = Builder.CreateZExtOrTrunc(Res, II->getType()); 3407fe6060f1SDimitry Andric if (Arg != Vect && 3408fe6060f1SDimitry Andric cast<Instruction>(Arg)->getOpcode() == Instruction::SExt) 3409fe6060f1SDimitry Andric Res = Builder.CreateNeg(Res); 3410fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Res); 3411fe6060f1SDimitry Andric } 3412fe6060f1SDimitry Andric } 3413fe6060f1SDimitry Andric } 3414bdd1243dSDimitry Andric [[fallthrough]]; 3415fe6060f1SDimitry Andric } 3416349cc55cSDimitry Andric case Intrinsic::vector_reduce_xor: { 3417349cc55cSDimitry Andric if (IID == Intrinsic::vector_reduce_xor) { 3418349cc55cSDimitry Andric // Exclusive disjunction reduction over the vector with 3419349cc55cSDimitry Andric // (potentially-extended) i1 element type is actually a 3420349cc55cSDimitry Andric // (potentially-extended) arithmetic `add` reduction over the original 3421349cc55cSDimitry Andric // non-extended value: 3422349cc55cSDimitry Andric // vector_reduce_xor(?ext(<n x i1>)) 3423349cc55cSDimitry Andric // --> 3424349cc55cSDimitry Andric // ?ext(vector_reduce_add(<n x i1>)) 3425349cc55cSDimitry Andric Value *Arg = II->getArgOperand(0); 3426349cc55cSDimitry Andric Value *Vect; 34270fca6ea1SDimitry Andric 34280fca6ea1SDimitry Andric if (Value *NewOp = 34290fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 34300fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 34310fca6ea1SDimitry Andric return II; 34320fca6ea1SDimitry Andric } 34330fca6ea1SDimitry Andric 3434349cc55cSDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 34350fca6ea1SDimitry Andric if (auto *VTy = dyn_cast<VectorType>(Vect->getType())) 34360fca6ea1SDimitry Andric if (VTy->getElementType() == Builder.getInt1Ty()) { 3437349cc55cSDimitry Andric Value *Res = Builder.CreateAddReduce(Vect); 3438349cc55cSDimitry Andric if (Arg != Vect) 3439349cc55cSDimitry Andric Res = Builder.CreateCast(cast<CastInst>(Arg)->getOpcode(), Res, 3440349cc55cSDimitry Andric II->getType()); 3441349cc55cSDimitry Andric return replaceInstUsesWith(CI, Res); 3442349cc55cSDimitry Andric } 3443349cc55cSDimitry Andric } 3444349cc55cSDimitry Andric } 3445bdd1243dSDimitry Andric [[fallthrough]]; 3446349cc55cSDimitry Andric } 3447349cc55cSDimitry Andric case Intrinsic::vector_reduce_mul: { 3448349cc55cSDimitry Andric if (IID == Intrinsic::vector_reduce_mul) { 3449349cc55cSDimitry Andric // Multiplicative reduction over the vector with (potentially-extended) 3450349cc55cSDimitry Andric // i1 element type is actually a (potentially zero-extended) 3451349cc55cSDimitry Andric // logical `and` reduction over the original non-extended value: 3452349cc55cSDimitry Andric // vector_reduce_mul(?ext(<n x i1>)) 3453349cc55cSDimitry Andric // --> 3454349cc55cSDimitry Andric // zext(vector_reduce_and(<n x i1>)) 3455349cc55cSDimitry Andric Value *Arg = II->getArgOperand(0); 3456349cc55cSDimitry Andric Value *Vect; 34570fca6ea1SDimitry Andric 34580fca6ea1SDimitry Andric if (Value *NewOp = 34590fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 34600fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 34610fca6ea1SDimitry Andric return II; 34620fca6ea1SDimitry Andric } 34630fca6ea1SDimitry Andric 3464349cc55cSDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 34650fca6ea1SDimitry Andric if (auto *VTy = dyn_cast<VectorType>(Vect->getType())) 34660fca6ea1SDimitry Andric if (VTy->getElementType() == Builder.getInt1Ty()) { 3467349cc55cSDimitry Andric Value *Res = Builder.CreateAndReduce(Vect); 3468349cc55cSDimitry Andric if (Res->getType() != II->getType()) 3469349cc55cSDimitry Andric Res = Builder.CreateZExt(Res, II->getType()); 3470349cc55cSDimitry Andric return replaceInstUsesWith(CI, Res); 3471349cc55cSDimitry Andric } 3472349cc55cSDimitry Andric } 3473349cc55cSDimitry Andric } 3474bdd1243dSDimitry Andric [[fallthrough]]; 3475349cc55cSDimitry Andric } 3476fe6060f1SDimitry Andric case Intrinsic::vector_reduce_umin: 3477349cc55cSDimitry Andric case Intrinsic::vector_reduce_umax: { 3478349cc55cSDimitry Andric if (IID == Intrinsic::vector_reduce_umin || 3479349cc55cSDimitry Andric IID == Intrinsic::vector_reduce_umax) { 3480349cc55cSDimitry Andric // UMin/UMax reduction over the vector with (potentially-extended) 3481349cc55cSDimitry Andric // i1 element type is actually a (potentially-extended) 3482349cc55cSDimitry Andric // logical `and`/`or` reduction over the original non-extended value: 3483349cc55cSDimitry Andric // vector_reduce_u{min,max}(?ext(<n x i1>)) 3484349cc55cSDimitry Andric // --> 3485349cc55cSDimitry Andric // ?ext(vector_reduce_{and,or}(<n x i1>)) 3486349cc55cSDimitry Andric Value *Arg = II->getArgOperand(0); 3487349cc55cSDimitry Andric Value *Vect; 34880fca6ea1SDimitry Andric 34890fca6ea1SDimitry Andric if (Value *NewOp = 34900fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 34910fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 34920fca6ea1SDimitry Andric return II; 34930fca6ea1SDimitry Andric } 34940fca6ea1SDimitry Andric 3495349cc55cSDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 34960fca6ea1SDimitry Andric if (auto *VTy = dyn_cast<VectorType>(Vect->getType())) 34970fca6ea1SDimitry Andric if (VTy->getElementType() == Builder.getInt1Ty()) { 3498349cc55cSDimitry Andric Value *Res = IID == Intrinsic::vector_reduce_umin 3499349cc55cSDimitry Andric ? Builder.CreateAndReduce(Vect) 3500349cc55cSDimitry Andric : Builder.CreateOrReduce(Vect); 3501349cc55cSDimitry Andric if (Arg != Vect) 3502349cc55cSDimitry Andric Res = Builder.CreateCast(cast<CastInst>(Arg)->getOpcode(), Res, 3503349cc55cSDimitry Andric II->getType()); 3504349cc55cSDimitry Andric return replaceInstUsesWith(CI, Res); 3505349cc55cSDimitry Andric } 3506349cc55cSDimitry Andric } 3507349cc55cSDimitry Andric } 3508bdd1243dSDimitry Andric [[fallthrough]]; 3509349cc55cSDimitry Andric } 3510fe6060f1SDimitry Andric case Intrinsic::vector_reduce_smin: 3511349cc55cSDimitry Andric case Intrinsic::vector_reduce_smax: { 3512349cc55cSDimitry Andric if (IID == Intrinsic::vector_reduce_smin || 3513349cc55cSDimitry Andric IID == Intrinsic::vector_reduce_smax) { 3514349cc55cSDimitry Andric // SMin/SMax reduction over the vector with (potentially-extended) 3515349cc55cSDimitry Andric // i1 element type is actually a (potentially-extended) 3516349cc55cSDimitry Andric // logical `and`/`or` reduction over the original non-extended value: 3517349cc55cSDimitry Andric // vector_reduce_s{min,max}(<n x i1>) 3518349cc55cSDimitry Andric // --> 3519349cc55cSDimitry Andric // vector_reduce_{or,and}(<n x i1>) 3520349cc55cSDimitry Andric // and 3521349cc55cSDimitry Andric // vector_reduce_s{min,max}(sext(<n x i1>)) 3522349cc55cSDimitry Andric // --> 3523349cc55cSDimitry Andric // sext(vector_reduce_{or,and}(<n x i1>)) 3524349cc55cSDimitry Andric // and 3525349cc55cSDimitry Andric // vector_reduce_s{min,max}(zext(<n x i1>)) 3526349cc55cSDimitry Andric // --> 3527349cc55cSDimitry Andric // zext(vector_reduce_{and,or}(<n x i1>)) 3528349cc55cSDimitry Andric Value *Arg = II->getArgOperand(0); 3529349cc55cSDimitry Andric Value *Vect; 35300fca6ea1SDimitry Andric 35310fca6ea1SDimitry Andric if (Value *NewOp = 35320fca6ea1SDimitry Andric simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) { 35330fca6ea1SDimitry Andric replaceUse(II->getOperandUse(0), NewOp); 35340fca6ea1SDimitry Andric return II; 35350fca6ea1SDimitry Andric } 35360fca6ea1SDimitry Andric 3537349cc55cSDimitry Andric if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) { 35380fca6ea1SDimitry Andric if (auto *VTy = dyn_cast<VectorType>(Vect->getType())) 35390fca6ea1SDimitry Andric if (VTy->getElementType() == Builder.getInt1Ty()) { 3540349cc55cSDimitry Andric Instruction::CastOps ExtOpc = Instruction::CastOps::CastOpsEnd; 3541349cc55cSDimitry Andric if (Arg != Vect) 3542349cc55cSDimitry Andric ExtOpc = cast<CastInst>(Arg)->getOpcode(); 3543349cc55cSDimitry Andric Value *Res = ((IID == Intrinsic::vector_reduce_smin) == 3544349cc55cSDimitry Andric (ExtOpc == Instruction::CastOps::ZExt)) 3545349cc55cSDimitry Andric ? Builder.CreateAndReduce(Vect) 3546349cc55cSDimitry Andric : Builder.CreateOrReduce(Vect); 3547349cc55cSDimitry Andric if (Arg != Vect) 3548349cc55cSDimitry Andric Res = Builder.CreateCast(ExtOpc, Res, II->getType()); 3549349cc55cSDimitry Andric return replaceInstUsesWith(CI, Res); 3550349cc55cSDimitry Andric } 3551349cc55cSDimitry Andric } 3552349cc55cSDimitry Andric } 3553bdd1243dSDimitry Andric [[fallthrough]]; 3554349cc55cSDimitry Andric } 3555fe6060f1SDimitry Andric case Intrinsic::vector_reduce_fmax: 3556fe6060f1SDimitry Andric case Intrinsic::vector_reduce_fmin: 3557fe6060f1SDimitry Andric case Intrinsic::vector_reduce_fadd: 3558fe6060f1SDimitry Andric case Intrinsic::vector_reduce_fmul: { 35590fca6ea1SDimitry Andric bool CanReorderLanes = (IID != Intrinsic::vector_reduce_fadd && 3560fe6060f1SDimitry Andric IID != Intrinsic::vector_reduce_fmul) || 3561fe6060f1SDimitry Andric II->hasAllowReassoc(); 3562fe6060f1SDimitry Andric const unsigned ArgIdx = (IID == Intrinsic::vector_reduce_fadd || 3563fe6060f1SDimitry Andric IID == Intrinsic::vector_reduce_fmul) 3564fe6060f1SDimitry Andric ? 1 3565fe6060f1SDimitry Andric : 0; 3566fe6060f1SDimitry Andric Value *Arg = II->getArgOperand(ArgIdx); 35670fca6ea1SDimitry Andric if (Value *NewOp = simplifyReductionOperand(Arg, CanReorderLanes)) { 35680fca6ea1SDimitry Andric replaceUse(II->getOperandUse(ArgIdx), NewOp); 3569fe6060f1SDimitry Andric return nullptr; 3570e8d8bef9SDimitry Andric } 3571e8d8bef9SDimitry Andric break; 3572e8d8bef9SDimitry Andric } 357306c3fb27SDimitry Andric case Intrinsic::is_fpclass: { 357406c3fb27SDimitry Andric if (Instruction *I = foldIntrinsicIsFPClass(*II)) 357506c3fb27SDimitry Andric return I; 357606c3fb27SDimitry Andric break; 357706c3fb27SDimitry Andric } 35780fca6ea1SDimitry Andric case Intrinsic::threadlocal_address: { 35790fca6ea1SDimitry Andric Align MinAlign = getKnownAlignment(II->getArgOperand(0), DL, II, &AC, &DT); 35800fca6ea1SDimitry Andric MaybeAlign Align = II->getRetAlign(); 35810fca6ea1SDimitry Andric if (MinAlign > Align.valueOrOne()) { 35820fca6ea1SDimitry Andric II->addRetAttr(Attribute::getWithAlignment(II->getContext(), MinAlign)); 35830fca6ea1SDimitry Andric return II; 35840fca6ea1SDimitry Andric } 35850fca6ea1SDimitry Andric break; 35860fca6ea1SDimitry Andric } 3587e8d8bef9SDimitry Andric default: { 3588e8d8bef9SDimitry Andric // Handle target specific intrinsics 3589bdd1243dSDimitry Andric std::optional<Instruction *> V = targetInstCombineIntrinsic(*II); 359081ad6265SDimitry Andric if (V) 3591bdd1243dSDimitry Andric return *V; 3592e8d8bef9SDimitry Andric break; 3593e8d8bef9SDimitry Andric } 35940b57cec5SDimitry Andric } 359581ad6265SDimitry Andric 359606c3fb27SDimitry Andric // Try to fold intrinsic into select operands. This is legal if: 359706c3fb27SDimitry Andric // * The intrinsic is speculatable. 359806c3fb27SDimitry Andric // * The select condition is not a vector, or the intrinsic does not 359906c3fb27SDimitry Andric // perform cross-lane operations. 360006c3fb27SDimitry Andric switch (IID) { 360106c3fb27SDimitry Andric case Intrinsic::ctlz: 360206c3fb27SDimitry Andric case Intrinsic::cttz: 360306c3fb27SDimitry Andric case Intrinsic::ctpop: 360406c3fb27SDimitry Andric case Intrinsic::umin: 360506c3fb27SDimitry Andric case Intrinsic::umax: 360606c3fb27SDimitry Andric case Intrinsic::smin: 360706c3fb27SDimitry Andric case Intrinsic::smax: 360806c3fb27SDimitry Andric case Intrinsic::usub_sat: 360906c3fb27SDimitry Andric case Intrinsic::uadd_sat: 361006c3fb27SDimitry Andric case Intrinsic::ssub_sat: 361106c3fb27SDimitry Andric case Intrinsic::sadd_sat: 361206c3fb27SDimitry Andric for (Value *Op : II->args()) 361306c3fb27SDimitry Andric if (auto *Sel = dyn_cast<SelectInst>(Op)) 361406c3fb27SDimitry Andric if (Instruction *R = FoldOpIntoSelect(*II, Sel)) 361506c3fb27SDimitry Andric return R; 361606c3fb27SDimitry Andric [[fallthrough]]; 361706c3fb27SDimitry Andric default: 361806c3fb27SDimitry Andric break; 361906c3fb27SDimitry Andric } 362006c3fb27SDimitry Andric 362181ad6265SDimitry Andric if (Instruction *Shuf = foldShuffledIntrinsicOperands(II, Builder)) 362281ad6265SDimitry Andric return Shuf; 362381ad6265SDimitry Andric 3624fe6060f1SDimitry Andric // Some intrinsics (like experimental_gc_statepoint) can be used in invoke 3625fe6060f1SDimitry Andric // context, so it is handled in visitCallBase and we should trigger it. 36260b57cec5SDimitry Andric return visitCallBase(*II); 36270b57cec5SDimitry Andric } 36280b57cec5SDimitry Andric 36290b57cec5SDimitry Andric // Fence instruction simplification 3630e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFenceInst(FenceInst &FI) { 36311fd87a68SDimitry Andric auto *NFI = dyn_cast<FenceInst>(FI.getNextNonDebugInstruction()); 36321fd87a68SDimitry Andric // This check is solely here to handle arbitrary target-dependent syncscopes. 36331fd87a68SDimitry Andric // TODO: Can remove if does not matter in practice. 36341fd87a68SDimitry Andric if (NFI && FI.isIdenticalTo(NFI)) 36351fd87a68SDimitry Andric return eraseInstFromFunction(FI); 36361fd87a68SDimitry Andric 36371fd87a68SDimitry Andric // Returns true if FI1 is identical or stronger fence than FI2. 36381fd87a68SDimitry Andric auto isIdenticalOrStrongerFence = [](FenceInst *FI1, FenceInst *FI2) { 36391fd87a68SDimitry Andric auto FI1SyncScope = FI1->getSyncScopeID(); 36401fd87a68SDimitry Andric // Consider same scope, where scope is global or single-thread. 36411fd87a68SDimitry Andric if (FI1SyncScope != FI2->getSyncScopeID() || 36421fd87a68SDimitry Andric (FI1SyncScope != SyncScope::System && 36431fd87a68SDimitry Andric FI1SyncScope != SyncScope::SingleThread)) 36441fd87a68SDimitry Andric return false; 36451fd87a68SDimitry Andric 36461fd87a68SDimitry Andric return isAtLeastOrStrongerThan(FI1->getOrdering(), FI2->getOrdering()); 36471fd87a68SDimitry Andric }; 36481fd87a68SDimitry Andric if (NFI && isIdenticalOrStrongerFence(NFI, &FI)) 36491fd87a68SDimitry Andric return eraseInstFromFunction(FI); 36501fd87a68SDimitry Andric 36511fd87a68SDimitry Andric if (auto *PFI = dyn_cast_or_null<FenceInst>(FI.getPrevNonDebugInstruction())) 36521fd87a68SDimitry Andric if (isIdenticalOrStrongerFence(PFI, &FI)) 36530b57cec5SDimitry Andric return eraseInstFromFunction(FI); 36540b57cec5SDimitry Andric return nullptr; 36550b57cec5SDimitry Andric } 36560b57cec5SDimitry Andric 36570b57cec5SDimitry Andric // InvokeInst simplification 3658e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitInvokeInst(InvokeInst &II) { 36590b57cec5SDimitry Andric return visitCallBase(II); 36600b57cec5SDimitry Andric } 36610b57cec5SDimitry Andric 36620b57cec5SDimitry Andric // CallBrInst simplification 3663e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) { 36640b57cec5SDimitry Andric return visitCallBase(CBI); 36650b57cec5SDimitry Andric } 36660b57cec5SDimitry Andric 3667e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) { 36680b57cec5SDimitry Andric if (!CI->getCalledFunction()) return nullptr; 36690b57cec5SDimitry Andric 36700eae32dcSDimitry Andric // Skip optimizing notail and musttail calls so 36710eae32dcSDimitry Andric // LibCallSimplifier::optimizeCall doesn't have to preserve those invariants. 36720eae32dcSDimitry Andric // LibCallSimplifier::optimizeCall should try to preseve tail calls though. 36730eae32dcSDimitry Andric if (CI->isMustTailCall() || CI->isNoTailCall()) 36740eae32dcSDimitry Andric return nullptr; 36750eae32dcSDimitry Andric 36760b57cec5SDimitry Andric auto InstCombineRAUW = [this](Instruction *From, Value *With) { 36770b57cec5SDimitry Andric replaceInstUsesWith(*From, With); 36780b57cec5SDimitry Andric }; 36790b57cec5SDimitry Andric auto InstCombineErase = [this](Instruction *I) { 36800b57cec5SDimitry Andric eraseInstFromFunction(*I); 36810b57cec5SDimitry Andric }; 368206c3fb27SDimitry Andric LibCallSimplifier Simplifier(DL, &TLI, &AC, ORE, BFI, PSI, InstCombineRAUW, 36830b57cec5SDimitry Andric InstCombineErase); 36845ffd83dbSDimitry Andric if (Value *With = Simplifier.optimizeCall(CI, Builder)) { 36850b57cec5SDimitry Andric ++NumSimplified; 36860b57cec5SDimitry Andric return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With); 36870b57cec5SDimitry Andric } 36880b57cec5SDimitry Andric 36890b57cec5SDimitry Andric return nullptr; 36900b57cec5SDimitry Andric } 36910b57cec5SDimitry Andric 36920b57cec5SDimitry Andric static IntrinsicInst *findInitTrampolineFromAlloca(Value *TrampMem) { 36930b57cec5SDimitry Andric // Strip off at most one level of pointer casts, looking for an alloca. This 36940b57cec5SDimitry Andric // is good enough in practice and simpler than handling any number of casts. 36950b57cec5SDimitry Andric Value *Underlying = TrampMem->stripPointerCasts(); 36960b57cec5SDimitry Andric if (Underlying != TrampMem && 36970b57cec5SDimitry Andric (!Underlying->hasOneUse() || Underlying->user_back() != TrampMem)) 36980b57cec5SDimitry Andric return nullptr; 36990b57cec5SDimitry Andric if (!isa<AllocaInst>(Underlying)) 37000b57cec5SDimitry Andric return nullptr; 37010b57cec5SDimitry Andric 37020b57cec5SDimitry Andric IntrinsicInst *InitTrampoline = nullptr; 37030b57cec5SDimitry Andric for (User *U : TrampMem->users()) { 37040b57cec5SDimitry Andric IntrinsicInst *II = dyn_cast<IntrinsicInst>(U); 37050b57cec5SDimitry Andric if (!II) 37060b57cec5SDimitry Andric return nullptr; 37070b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::init_trampoline) { 37080b57cec5SDimitry Andric if (InitTrampoline) 37090b57cec5SDimitry Andric // More than one init_trampoline writes to this value. Give up. 37100b57cec5SDimitry Andric return nullptr; 37110b57cec5SDimitry Andric InitTrampoline = II; 37120b57cec5SDimitry Andric continue; 37130b57cec5SDimitry Andric } 37140b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::adjust_trampoline) 37150b57cec5SDimitry Andric // Allow any number of calls to adjust.trampoline. 37160b57cec5SDimitry Andric continue; 37170b57cec5SDimitry Andric return nullptr; 37180b57cec5SDimitry Andric } 37190b57cec5SDimitry Andric 37200b57cec5SDimitry Andric // No call to init.trampoline found. 37210b57cec5SDimitry Andric if (!InitTrampoline) 37220b57cec5SDimitry Andric return nullptr; 37230b57cec5SDimitry Andric 37240b57cec5SDimitry Andric // Check that the alloca is being used in the expected way. 37250b57cec5SDimitry Andric if (InitTrampoline->getOperand(0) != TrampMem) 37260b57cec5SDimitry Andric return nullptr; 37270b57cec5SDimitry Andric 37280b57cec5SDimitry Andric return InitTrampoline; 37290b57cec5SDimitry Andric } 37300b57cec5SDimitry Andric 37310b57cec5SDimitry Andric static IntrinsicInst *findInitTrampolineFromBB(IntrinsicInst *AdjustTramp, 37320b57cec5SDimitry Andric Value *TrampMem) { 37330b57cec5SDimitry Andric // Visit all the previous instructions in the basic block, and try to find a 37340b57cec5SDimitry Andric // init.trampoline which has a direct path to the adjust.trampoline. 37350b57cec5SDimitry Andric for (BasicBlock::iterator I = AdjustTramp->getIterator(), 37360b57cec5SDimitry Andric E = AdjustTramp->getParent()->begin(); 37370b57cec5SDimitry Andric I != E;) { 37380b57cec5SDimitry Andric Instruction *Inst = &*--I; 37390b57cec5SDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) 37400b57cec5SDimitry Andric if (II->getIntrinsicID() == Intrinsic::init_trampoline && 37410b57cec5SDimitry Andric II->getOperand(0) == TrampMem) 37420b57cec5SDimitry Andric return II; 37430b57cec5SDimitry Andric if (Inst->mayWriteToMemory()) 37440b57cec5SDimitry Andric return nullptr; 37450b57cec5SDimitry Andric } 37460b57cec5SDimitry Andric return nullptr; 37470b57cec5SDimitry Andric } 37480b57cec5SDimitry Andric 37490b57cec5SDimitry Andric // Given a call to llvm.adjust.trampoline, find and return the corresponding 37500b57cec5SDimitry Andric // call to llvm.init.trampoline if the call to the trampoline can be optimized 37510b57cec5SDimitry Andric // to a direct call to a function. Otherwise return NULL. 37520b57cec5SDimitry Andric static IntrinsicInst *findInitTrampoline(Value *Callee) { 37530b57cec5SDimitry Andric Callee = Callee->stripPointerCasts(); 37540b57cec5SDimitry Andric IntrinsicInst *AdjustTramp = dyn_cast<IntrinsicInst>(Callee); 37550b57cec5SDimitry Andric if (!AdjustTramp || 37560b57cec5SDimitry Andric AdjustTramp->getIntrinsicID() != Intrinsic::adjust_trampoline) 37570b57cec5SDimitry Andric return nullptr; 37580b57cec5SDimitry Andric 37590b57cec5SDimitry Andric Value *TrampMem = AdjustTramp->getOperand(0); 37600b57cec5SDimitry Andric 37610b57cec5SDimitry Andric if (IntrinsicInst *IT = findInitTrampolineFromAlloca(TrampMem)) 37620b57cec5SDimitry Andric return IT; 37630b57cec5SDimitry Andric if (IntrinsicInst *IT = findInitTrampolineFromBB(AdjustTramp, TrampMem)) 37640b57cec5SDimitry Andric return IT; 37650b57cec5SDimitry Andric return nullptr; 37660b57cec5SDimitry Andric } 37670b57cec5SDimitry Andric 376881ad6265SDimitry Andric bool InstCombinerImpl::annotateAnyAllocSite(CallBase &Call, 376981ad6265SDimitry Andric const TargetLibraryInfo *TLI) { 377004eeddc0SDimitry Andric // Note: We only handle cases which can't be driven from generic attributes 377104eeddc0SDimitry Andric // here. So, for example, nonnull and noalias (which are common properties 377204eeddc0SDimitry Andric // of some allocation functions) are expected to be handled via annotation 377304eeddc0SDimitry Andric // of the respective allocator declaration with generic attributes. 377481ad6265SDimitry Andric bool Changed = false; 37758bcb0991SDimitry Andric 3776fcaf7f86SDimitry Andric if (!Call.getType()->isPointerTy()) 3777fcaf7f86SDimitry Andric return Changed; 3778fcaf7f86SDimitry Andric 3779bdd1243dSDimitry Andric std::optional<APInt> Size = getAllocSize(&Call, TLI); 3780fcaf7f86SDimitry Andric if (Size && *Size != 0) { 378104eeddc0SDimitry Andric // TODO: We really should just emit deref_or_null here and then 378204eeddc0SDimitry Andric // let the generic inference code combine that with nonnull. 378381ad6265SDimitry Andric if (Call.hasRetAttr(Attribute::NonNull)) { 378481ad6265SDimitry Andric Changed = !Call.hasRetAttr(Attribute::Dereferenceable); 3785fcaf7f86SDimitry Andric Call.addRetAttr(Attribute::getWithDereferenceableBytes( 3786fcaf7f86SDimitry Andric Call.getContext(), Size->getLimitedValue())); 378781ad6265SDimitry Andric } else { 378881ad6265SDimitry Andric Changed = !Call.hasRetAttr(Attribute::DereferenceableOrNull); 3789349cc55cSDimitry Andric Call.addRetAttr(Attribute::getWithDereferenceableOrNullBytes( 3790fcaf7f86SDimitry Andric Call.getContext(), Size->getLimitedValue())); 379181ad6265SDimitry Andric } 379281ad6265SDimitry Andric } 379304eeddc0SDimitry Andric 37945ffd83dbSDimitry Andric // Add alignment attribute if alignment is a power of two constant. 379504eeddc0SDimitry Andric Value *Alignment = getAllocAlignment(&Call, TLI); 379604eeddc0SDimitry Andric if (!Alignment) 379781ad6265SDimitry Andric return Changed; 379804eeddc0SDimitry Andric 379904eeddc0SDimitry Andric ConstantInt *AlignOpC = dyn_cast<ConstantInt>(Alignment); 380004eeddc0SDimitry Andric if (AlignOpC && AlignOpC->getValue().ult(llvm::Value::MaximumAlignment)) { 380104eeddc0SDimitry Andric uint64_t AlignmentVal = AlignOpC->getZExtValue(); 3802fe6060f1SDimitry Andric if (llvm::isPowerOf2_64(AlignmentVal)) { 380381ad6265SDimitry Andric Align ExistingAlign = Call.getRetAlign().valueOrOne(); 380481ad6265SDimitry Andric Align NewAlign = Align(AlignmentVal); 380581ad6265SDimitry Andric if (NewAlign > ExistingAlign) { 380681ad6265SDimitry Andric Call.addRetAttr( 380781ad6265SDimitry Andric Attribute::getWithAlignment(Call.getContext(), NewAlign)); 380881ad6265SDimitry Andric Changed = true; 38095ffd83dbSDimitry Andric } 3810fe6060f1SDimitry Andric } 38118bcb0991SDimitry Andric } 381281ad6265SDimitry Andric return Changed; 381381ad6265SDimitry Andric } 38148bcb0991SDimitry Andric 38150b57cec5SDimitry Andric /// Improvements for call, callbr and invoke instructions. 3816e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) { 381781ad6265SDimitry Andric bool Changed = annotateAnyAllocSite(Call, &TLI); 38180b57cec5SDimitry Andric 38190b57cec5SDimitry Andric // Mark any parameters that are known to be non-null with the nonnull 38200b57cec5SDimitry Andric // attribute. This is helpful for inlining calls to functions with null 38210b57cec5SDimitry Andric // checks on their arguments. 38220b57cec5SDimitry Andric SmallVector<unsigned, 4> ArgNos; 38230b57cec5SDimitry Andric unsigned ArgNo = 0; 38240b57cec5SDimitry Andric 38250b57cec5SDimitry Andric for (Value *V : Call.args()) { 38260b57cec5SDimitry Andric if (V->getType()->isPointerTy() && 38270b57cec5SDimitry Andric !Call.paramHasAttr(ArgNo, Attribute::NonNull) && 38280fca6ea1SDimitry Andric isKnownNonZero(V, getSimplifyQuery().getWithInstruction(&Call))) 38290b57cec5SDimitry Andric ArgNos.push_back(ArgNo); 38300b57cec5SDimitry Andric ArgNo++; 38310b57cec5SDimitry Andric } 38320b57cec5SDimitry Andric 38334824e7fdSDimitry Andric assert(ArgNo == Call.arg_size() && "Call arguments not processed correctly."); 38340b57cec5SDimitry Andric 38350b57cec5SDimitry Andric if (!ArgNos.empty()) { 38360b57cec5SDimitry Andric AttributeList AS = Call.getAttributes(); 38370b57cec5SDimitry Andric LLVMContext &Ctx = Call.getContext(); 38380b57cec5SDimitry Andric AS = AS.addParamAttribute(Ctx, ArgNos, 38390b57cec5SDimitry Andric Attribute::get(Ctx, Attribute::NonNull)); 38400b57cec5SDimitry Andric Call.setAttributes(AS); 38410b57cec5SDimitry Andric Changed = true; 38420b57cec5SDimitry Andric } 38430b57cec5SDimitry Andric 38440b57cec5SDimitry Andric // If the callee is a pointer to a function, attempt to move any casts to the 38450b57cec5SDimitry Andric // arguments of the call/callbr/invoke. 38465ffd83dbSDimitry Andric Value *Callee = Call.getCalledOperand(); 384781ad6265SDimitry Andric Function *CalleeF = dyn_cast<Function>(Callee); 384881ad6265SDimitry Andric if ((!CalleeF || CalleeF->getFunctionType() != Call.getFunctionType()) && 384981ad6265SDimitry Andric transformConstExprCastCall(Call)) 38500b57cec5SDimitry Andric return nullptr; 38510b57cec5SDimitry Andric 385281ad6265SDimitry Andric if (CalleeF) { 38530b57cec5SDimitry Andric // Remove the convergent attr on calls when the callee is not convergent. 38540b57cec5SDimitry Andric if (Call.isConvergent() && !CalleeF->isConvergent() && 38550b57cec5SDimitry Andric !CalleeF->isIntrinsic()) { 38560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Removing convergent attr from instr " << Call 38570b57cec5SDimitry Andric << "\n"); 38580b57cec5SDimitry Andric Call.setNotConvergent(); 38590b57cec5SDimitry Andric return &Call; 38600b57cec5SDimitry Andric } 38610b57cec5SDimitry Andric 3862fe6060f1SDimitry Andric // If the call and callee calling conventions don't match, and neither one 3863fe6060f1SDimitry Andric // of the calling conventions is compatible with C calling convention 3864fe6060f1SDimitry Andric // this call must be unreachable, as the call is undefined. 3865fe6060f1SDimitry Andric if ((CalleeF->getCallingConv() != Call.getCallingConv() && 3866fe6060f1SDimitry Andric !(CalleeF->getCallingConv() == llvm::CallingConv::C && 3867fe6060f1SDimitry Andric TargetLibraryInfoImpl::isCallingConvCCompatible(&Call)) && 3868fe6060f1SDimitry Andric !(Call.getCallingConv() == llvm::CallingConv::C && 3869fe6060f1SDimitry Andric TargetLibraryInfoImpl::isCallingConvCCompatible(CalleeF))) && 38700b57cec5SDimitry Andric // Only do this for calls to a function with a body. A prototype may 38710b57cec5SDimitry Andric // not actually end up matching the implementation's calling conv for a 38720b57cec5SDimitry Andric // variety of reasons (e.g. it may be written in assembly). 38730b57cec5SDimitry Andric !CalleeF->isDeclaration()) { 38740b57cec5SDimitry Andric Instruction *OldCall = &Call; 38750b57cec5SDimitry Andric CreateNonTerminatorUnreachable(OldCall); 3876fe6060f1SDimitry Andric // If OldCall does not return void then replaceInstUsesWith poison. 38770b57cec5SDimitry Andric // This allows ValueHandlers and custom metadata to adjust itself. 38780b57cec5SDimitry Andric if (!OldCall->getType()->isVoidTy()) 3879fe6060f1SDimitry Andric replaceInstUsesWith(*OldCall, PoisonValue::get(OldCall->getType())); 38800b57cec5SDimitry Andric if (isa<CallInst>(OldCall)) 38810b57cec5SDimitry Andric return eraseInstFromFunction(*OldCall); 38820b57cec5SDimitry Andric 38830b57cec5SDimitry Andric // We cannot remove an invoke or a callbr, because it would change thexi 38840b57cec5SDimitry Andric // CFG, just change the callee to a null pointer. 38850b57cec5SDimitry Andric cast<CallBase>(OldCall)->setCalledFunction( 38860b57cec5SDimitry Andric CalleeF->getFunctionType(), 38870b57cec5SDimitry Andric Constant::getNullValue(CalleeF->getType())); 38880b57cec5SDimitry Andric return nullptr; 38890b57cec5SDimitry Andric } 38900b57cec5SDimitry Andric } 38910b57cec5SDimitry Andric 3892fe6060f1SDimitry Andric // Calling a null function pointer is undefined if a null address isn't 3893fe6060f1SDimitry Andric // dereferenceable. 38940b57cec5SDimitry Andric if ((isa<ConstantPointerNull>(Callee) && 38950b57cec5SDimitry Andric !NullPointerIsDefined(Call.getFunction())) || 38960b57cec5SDimitry Andric isa<UndefValue>(Callee)) { 3897fe6060f1SDimitry Andric // If Call does not return void then replaceInstUsesWith poison. 38980b57cec5SDimitry Andric // This allows ValueHandlers and custom metadata to adjust itself. 38990b57cec5SDimitry Andric if (!Call.getType()->isVoidTy()) 3900fe6060f1SDimitry Andric replaceInstUsesWith(Call, PoisonValue::get(Call.getType())); 39010b57cec5SDimitry Andric 39020b57cec5SDimitry Andric if (Call.isTerminator()) { 39030b57cec5SDimitry Andric // Can't remove an invoke or callbr because we cannot change the CFG. 39040b57cec5SDimitry Andric return nullptr; 39050b57cec5SDimitry Andric } 39060b57cec5SDimitry Andric 39070b57cec5SDimitry Andric // This instruction is not reachable, just remove it. 39080b57cec5SDimitry Andric CreateNonTerminatorUnreachable(&Call); 39090b57cec5SDimitry Andric return eraseInstFromFunction(Call); 39100b57cec5SDimitry Andric } 39110b57cec5SDimitry Andric 39120b57cec5SDimitry Andric if (IntrinsicInst *II = findInitTrampoline(Callee)) 39130b57cec5SDimitry Andric return transformCallThroughTrampoline(Call, *II); 39140b57cec5SDimitry Andric 39150b57cec5SDimitry Andric if (isa<InlineAsm>(Callee) && !Call.doesNotThrow()) { 3916fe6060f1SDimitry Andric InlineAsm *IA = cast<InlineAsm>(Callee); 3917fe6060f1SDimitry Andric if (!IA->canThrow()) { 3918fe6060f1SDimitry Andric // Normal inline asm calls cannot throw - mark them 3919fe6060f1SDimitry Andric // 'nounwind'. 39200b57cec5SDimitry Andric Call.setDoesNotThrow(); 39210b57cec5SDimitry Andric Changed = true; 39220b57cec5SDimitry Andric } 3923fe6060f1SDimitry Andric } 39240b57cec5SDimitry Andric 39250b57cec5SDimitry Andric // Try to optimize the call if possible, we require DataLayout for most of 39260b57cec5SDimitry Andric // this. None of these calls are seen as possibly dead so go ahead and 39270b57cec5SDimitry Andric // delete the instruction now. 39280b57cec5SDimitry Andric if (CallInst *CI = dyn_cast<CallInst>(&Call)) { 39290b57cec5SDimitry Andric Instruction *I = tryOptimizeCall(CI); 39300b57cec5SDimitry Andric // If we changed something return the result, etc. Otherwise let 39310b57cec5SDimitry Andric // the fallthrough check. 39320b57cec5SDimitry Andric if (I) return eraseInstFromFunction(*I); 39330b57cec5SDimitry Andric } 39340b57cec5SDimitry Andric 39355ffd83dbSDimitry Andric if (!Call.use_empty() && !Call.isMustTailCall()) 39365ffd83dbSDimitry Andric if (Value *ReturnedArg = Call.getReturnedArgOperand()) { 39375ffd83dbSDimitry Andric Type *CallTy = Call.getType(); 39385ffd83dbSDimitry Andric Type *RetArgTy = ReturnedArg->getType(); 39395ffd83dbSDimitry Andric if (RetArgTy->canLosslesslyBitCastTo(CallTy)) 39405ffd83dbSDimitry Andric return replaceInstUsesWith( 39415ffd83dbSDimitry Andric Call, Builder.CreateBitOrPointerCast(ReturnedArg, CallTy)); 39425ffd83dbSDimitry Andric } 39435ffd83dbSDimitry Andric 3944bdd1243dSDimitry Andric // Drop unnecessary kcfi operand bundles from calls that were converted 3945bdd1243dSDimitry Andric // into direct calls. 3946bdd1243dSDimitry Andric auto Bundle = Call.getOperandBundle(LLVMContext::OB_kcfi); 3947bdd1243dSDimitry Andric if (Bundle && !Call.isIndirectCall()) { 3948bdd1243dSDimitry Andric DEBUG_WITH_TYPE(DEBUG_TYPE "-kcfi", { 3949bdd1243dSDimitry Andric if (CalleeF) { 3950bdd1243dSDimitry Andric ConstantInt *FunctionType = nullptr; 3951bdd1243dSDimitry Andric ConstantInt *ExpectedType = cast<ConstantInt>(Bundle->Inputs[0]); 3952bdd1243dSDimitry Andric 3953bdd1243dSDimitry Andric if (MDNode *MD = CalleeF->getMetadata(LLVMContext::MD_kcfi_type)) 3954bdd1243dSDimitry Andric FunctionType = mdconst::extract<ConstantInt>(MD->getOperand(0)); 3955bdd1243dSDimitry Andric 3956bdd1243dSDimitry Andric if (FunctionType && 3957bdd1243dSDimitry Andric FunctionType->getZExtValue() != ExpectedType->getZExtValue()) 3958bdd1243dSDimitry Andric dbgs() << Call.getModule()->getName() 3959bdd1243dSDimitry Andric << ": warning: kcfi: " << Call.getCaller()->getName() 3960bdd1243dSDimitry Andric << ": call to " << CalleeF->getName() 3961bdd1243dSDimitry Andric << " using a mismatching function pointer type\n"; 3962bdd1243dSDimitry Andric } 3963bdd1243dSDimitry Andric }); 3964bdd1243dSDimitry Andric 3965bdd1243dSDimitry Andric return CallBase::removeOperandBundle(&Call, LLVMContext::OB_kcfi); 3966bdd1243dSDimitry Andric } 3967bdd1243dSDimitry Andric 3968fcaf7f86SDimitry Andric if (isRemovableAlloc(&Call, &TLI)) 39698bcb0991SDimitry Andric return visitAllocSite(Call); 39708bcb0991SDimitry Andric 3971fe6060f1SDimitry Andric // Handle intrinsics which can be used in both call and invoke context. 3972fe6060f1SDimitry Andric switch (Call.getIntrinsicID()) { 3973fe6060f1SDimitry Andric case Intrinsic::experimental_gc_statepoint: { 3974fe6060f1SDimitry Andric GCStatepointInst &GCSP = *cast<GCStatepointInst>(&Call); 3975fe6060f1SDimitry Andric SmallPtrSet<Value *, 32> LiveGcValues; 3976fe6060f1SDimitry Andric for (const GCRelocateInst *Reloc : GCSP.getGCRelocates()) { 3977fe6060f1SDimitry Andric GCRelocateInst &GCR = *const_cast<GCRelocateInst *>(Reloc); 3978fe6060f1SDimitry Andric 3979fe6060f1SDimitry Andric // Remove the relocation if unused. 3980fe6060f1SDimitry Andric if (GCR.use_empty()) { 3981fe6060f1SDimitry Andric eraseInstFromFunction(GCR); 3982fe6060f1SDimitry Andric continue; 3983fe6060f1SDimitry Andric } 3984fe6060f1SDimitry Andric 3985fe6060f1SDimitry Andric Value *DerivedPtr = GCR.getDerivedPtr(); 3986fe6060f1SDimitry Andric Value *BasePtr = GCR.getBasePtr(); 3987fe6060f1SDimitry Andric 3988fe6060f1SDimitry Andric // Undef is undef, even after relocation. 3989fe6060f1SDimitry Andric if (isa<UndefValue>(DerivedPtr) || isa<UndefValue>(BasePtr)) { 3990fe6060f1SDimitry Andric replaceInstUsesWith(GCR, UndefValue::get(GCR.getType())); 3991fe6060f1SDimitry Andric eraseInstFromFunction(GCR); 3992fe6060f1SDimitry Andric continue; 3993fe6060f1SDimitry Andric } 3994fe6060f1SDimitry Andric 3995fe6060f1SDimitry Andric if (auto *PT = dyn_cast<PointerType>(GCR.getType())) { 3996fe6060f1SDimitry Andric // The relocation of null will be null for most any collector. 3997fe6060f1SDimitry Andric // TODO: provide a hook for this in GCStrategy. There might be some 3998fe6060f1SDimitry Andric // weird collector this property does not hold for. 3999fe6060f1SDimitry Andric if (isa<ConstantPointerNull>(DerivedPtr)) { 4000fe6060f1SDimitry Andric // Use null-pointer of gc_relocate's type to replace it. 4001fe6060f1SDimitry Andric replaceInstUsesWith(GCR, ConstantPointerNull::get(PT)); 4002fe6060f1SDimitry Andric eraseInstFromFunction(GCR); 4003fe6060f1SDimitry Andric continue; 4004fe6060f1SDimitry Andric } 4005fe6060f1SDimitry Andric 4006fe6060f1SDimitry Andric // isKnownNonNull -> nonnull attribute 4007fe6060f1SDimitry Andric if (!GCR.hasRetAttr(Attribute::NonNull) && 40080fca6ea1SDimitry Andric isKnownNonZero(DerivedPtr, 40090fca6ea1SDimitry Andric getSimplifyQuery().getWithInstruction(&Call))) { 4010349cc55cSDimitry Andric GCR.addRetAttr(Attribute::NonNull); 4011fe6060f1SDimitry Andric // We discovered new fact, re-check users. 4012fe6060f1SDimitry Andric Worklist.pushUsersToWorkList(GCR); 4013fe6060f1SDimitry Andric } 4014fe6060f1SDimitry Andric } 4015fe6060f1SDimitry Andric 4016fe6060f1SDimitry Andric // If we have two copies of the same pointer in the statepoint argument 4017fe6060f1SDimitry Andric // list, canonicalize to one. This may let us common gc.relocates. 4018fe6060f1SDimitry Andric if (GCR.getBasePtr() == GCR.getDerivedPtr() && 4019fe6060f1SDimitry Andric GCR.getBasePtrIndex() != GCR.getDerivedPtrIndex()) { 4020fe6060f1SDimitry Andric auto *OpIntTy = GCR.getOperand(2)->getType(); 4021fe6060f1SDimitry Andric GCR.setOperand(2, ConstantInt::get(OpIntTy, GCR.getBasePtrIndex())); 4022fe6060f1SDimitry Andric } 4023fe6060f1SDimitry Andric 4024fe6060f1SDimitry Andric // TODO: bitcast(relocate(p)) -> relocate(bitcast(p)) 4025fe6060f1SDimitry Andric // Canonicalize on the type from the uses to the defs 4026fe6060f1SDimitry Andric 4027fe6060f1SDimitry Andric // TODO: relocate((gep p, C, C2, ...)) -> gep(relocate(p), C, C2, ...) 4028fe6060f1SDimitry Andric LiveGcValues.insert(BasePtr); 4029fe6060f1SDimitry Andric LiveGcValues.insert(DerivedPtr); 4030fe6060f1SDimitry Andric } 4031bdd1243dSDimitry Andric std::optional<OperandBundleUse> Bundle = 4032fe6060f1SDimitry Andric GCSP.getOperandBundle(LLVMContext::OB_gc_live); 4033fe6060f1SDimitry Andric unsigned NumOfGCLives = LiveGcValues.size(); 403481ad6265SDimitry Andric if (!Bundle || NumOfGCLives == Bundle->Inputs.size()) 4035fe6060f1SDimitry Andric break; 4036fe6060f1SDimitry Andric // We can reduce the size of gc live bundle. 4037fe6060f1SDimitry Andric DenseMap<Value *, unsigned> Val2Idx; 4038fe6060f1SDimitry Andric std::vector<Value *> NewLiveGc; 4039bdd1243dSDimitry Andric for (Value *V : Bundle->Inputs) { 4040fe6060f1SDimitry Andric if (Val2Idx.count(V)) 4041fe6060f1SDimitry Andric continue; 4042fe6060f1SDimitry Andric if (LiveGcValues.count(V)) { 4043fe6060f1SDimitry Andric Val2Idx[V] = NewLiveGc.size(); 4044fe6060f1SDimitry Andric NewLiveGc.push_back(V); 4045fe6060f1SDimitry Andric } else 4046fe6060f1SDimitry Andric Val2Idx[V] = NumOfGCLives; 4047fe6060f1SDimitry Andric } 4048fe6060f1SDimitry Andric // Update all gc.relocates 4049fe6060f1SDimitry Andric for (const GCRelocateInst *Reloc : GCSP.getGCRelocates()) { 4050fe6060f1SDimitry Andric GCRelocateInst &GCR = *const_cast<GCRelocateInst *>(Reloc); 4051fe6060f1SDimitry Andric Value *BasePtr = GCR.getBasePtr(); 4052fe6060f1SDimitry Andric assert(Val2Idx.count(BasePtr) && Val2Idx[BasePtr] != NumOfGCLives && 4053fe6060f1SDimitry Andric "Missed live gc for base pointer"); 4054fe6060f1SDimitry Andric auto *OpIntTy1 = GCR.getOperand(1)->getType(); 4055fe6060f1SDimitry Andric GCR.setOperand(1, ConstantInt::get(OpIntTy1, Val2Idx[BasePtr])); 4056fe6060f1SDimitry Andric Value *DerivedPtr = GCR.getDerivedPtr(); 4057fe6060f1SDimitry Andric assert(Val2Idx.count(DerivedPtr) && Val2Idx[DerivedPtr] != NumOfGCLives && 4058fe6060f1SDimitry Andric "Missed live gc for derived pointer"); 4059fe6060f1SDimitry Andric auto *OpIntTy2 = GCR.getOperand(2)->getType(); 4060fe6060f1SDimitry Andric GCR.setOperand(2, ConstantInt::get(OpIntTy2, Val2Idx[DerivedPtr])); 4061fe6060f1SDimitry Andric } 4062fe6060f1SDimitry Andric // Create new statepoint instruction. 4063fe6060f1SDimitry Andric OperandBundleDef NewBundle("gc-live", NewLiveGc); 4064fe6060f1SDimitry Andric return CallBase::Create(&Call, NewBundle); 4065fe6060f1SDimitry Andric } 4066fe6060f1SDimitry Andric default: { break; } 4067fe6060f1SDimitry Andric } 4068fe6060f1SDimitry Andric 40690b57cec5SDimitry Andric return Changed ? &Call : nullptr; 40700b57cec5SDimitry Andric } 40710b57cec5SDimitry Andric 40720b57cec5SDimitry Andric /// If the callee is a constexpr cast of a function, attempt to move the cast to 407306c3fb27SDimitry Andric /// the arguments of the call/invoke. 407406c3fb27SDimitry Andric /// CallBrInst is not supported. 4075e8d8bef9SDimitry Andric bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) { 40765ffd83dbSDimitry Andric auto *Callee = 40775ffd83dbSDimitry Andric dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); 40780b57cec5SDimitry Andric if (!Callee) 40790b57cec5SDimitry Andric return false; 40800b57cec5SDimitry Andric 408106c3fb27SDimitry Andric assert(!isa<CallBrInst>(Call) && 408206c3fb27SDimitry Andric "CallBr's don't have a single point after a def to insert at"); 408306c3fb27SDimitry Andric 40840b57cec5SDimitry Andric // If this is a call to a thunk function, don't remove the cast. Thunks are 40850b57cec5SDimitry Andric // used to transparently forward all incoming parameters and outgoing return 40860b57cec5SDimitry Andric // values, so it's important to leave the cast in place. 40870b57cec5SDimitry Andric if (Callee->hasFnAttribute("thunk")) 40880b57cec5SDimitry Andric return false; 40890b57cec5SDimitry Andric 4090647cbc5dSDimitry Andric // If this is a call to a naked function, the assembly might be 4091647cbc5dSDimitry Andric // using an argument, or otherwise rely on the frame layout, 4092647cbc5dSDimitry Andric // the function prototype will mismatch. 4093647cbc5dSDimitry Andric if (Callee->hasFnAttribute(Attribute::Naked)) 4094647cbc5dSDimitry Andric return false; 4095647cbc5dSDimitry Andric 40960b57cec5SDimitry Andric // If this is a musttail call, the callee's prototype must match the caller's 40970b57cec5SDimitry Andric // prototype with the exception of pointee types. The code below doesn't 40980b57cec5SDimitry Andric // implement that, so we can't do this transform. 40990b57cec5SDimitry Andric // TODO: Do the transform if it only requires adding pointer casts. 41000b57cec5SDimitry Andric if (Call.isMustTailCall()) 41010b57cec5SDimitry Andric return false; 41020b57cec5SDimitry Andric 41030b57cec5SDimitry Andric Instruction *Caller = &Call; 41040b57cec5SDimitry Andric const AttributeList &CallerPAL = Call.getAttributes(); 41050b57cec5SDimitry Andric 41060b57cec5SDimitry Andric // Okay, this is a cast from a function to a different type. Unless doing so 41070b57cec5SDimitry Andric // would cause a type conversion of one of our arguments, change this call to 41080b57cec5SDimitry Andric // be a direct call with arguments casted to the appropriate types. 41090b57cec5SDimitry Andric FunctionType *FT = Callee->getFunctionType(); 41100b57cec5SDimitry Andric Type *OldRetTy = Caller->getType(); 41110b57cec5SDimitry Andric Type *NewRetTy = FT->getReturnType(); 41120b57cec5SDimitry Andric 41130b57cec5SDimitry Andric // Check to see if we are changing the return type... 41140b57cec5SDimitry Andric if (OldRetTy != NewRetTy) { 41150b57cec5SDimitry Andric 41160b57cec5SDimitry Andric if (NewRetTy->isStructTy()) 41170b57cec5SDimitry Andric return false; // TODO: Handle multiple return values. 41180b57cec5SDimitry Andric 41190b57cec5SDimitry Andric if (!CastInst::isBitOrNoopPointerCastable(NewRetTy, OldRetTy, DL)) { 41200b57cec5SDimitry Andric if (Callee->isDeclaration()) 41210b57cec5SDimitry Andric return false; // Cannot transform this return value. 41220b57cec5SDimitry Andric 41230b57cec5SDimitry Andric if (!Caller->use_empty() && 41240b57cec5SDimitry Andric // void -> non-void is handled specially 41250b57cec5SDimitry Andric !NewRetTy->isVoidTy()) 41260b57cec5SDimitry Andric return false; // Cannot transform this return value. 41270b57cec5SDimitry Andric } 41280b57cec5SDimitry Andric 41290b57cec5SDimitry Andric if (!CallerPAL.isEmpty() && !Caller->use_empty()) { 413004eeddc0SDimitry Andric AttrBuilder RAttrs(FT->getContext(), CallerPAL.getRetAttrs()); 41310b57cec5SDimitry Andric if (RAttrs.overlaps(AttributeFuncs::typeIncompatible(NewRetTy))) 41320b57cec5SDimitry Andric return false; // Attribute not compatible with transformed value. 41330b57cec5SDimitry Andric } 41340b57cec5SDimitry Andric 413506c3fb27SDimitry Andric // If the callbase is an invoke instruction, and the return value is 41360b57cec5SDimitry Andric // used by a PHI node in a successor, we cannot change the return type of 41370b57cec5SDimitry Andric // the call because there is no place to put the cast instruction (without 41380b57cec5SDimitry Andric // breaking the critical edge). Bail out in this case. 41390b57cec5SDimitry Andric if (!Caller->use_empty()) { 4140fcaf7f86SDimitry Andric BasicBlock *PhisNotSupportedBlock = nullptr; 4141fcaf7f86SDimitry Andric if (auto *II = dyn_cast<InvokeInst>(Caller)) 4142fcaf7f86SDimitry Andric PhisNotSupportedBlock = II->getNormalDest(); 4143fcaf7f86SDimitry Andric if (PhisNotSupportedBlock) 4144fcaf7f86SDimitry Andric for (User *U : Caller->users()) 41450b57cec5SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(U)) 4146fcaf7f86SDimitry Andric if (PN->getParent() == PhisNotSupportedBlock) 41470b57cec5SDimitry Andric return false; 41480b57cec5SDimitry Andric } 41490b57cec5SDimitry Andric } 41500b57cec5SDimitry Andric 41510b57cec5SDimitry Andric unsigned NumActualArgs = Call.arg_size(); 41520b57cec5SDimitry Andric unsigned NumCommonArgs = std::min(FT->getNumParams(), NumActualArgs); 41530b57cec5SDimitry Andric 41540b57cec5SDimitry Andric // Prevent us turning: 41550b57cec5SDimitry Andric // declare void @takes_i32_inalloca(i32* inalloca) 41560b57cec5SDimitry Andric // call void bitcast (void (i32*)* @takes_i32_inalloca to void (i32)*)(i32 0) 41570b57cec5SDimitry Andric // 41580b57cec5SDimitry Andric // into: 41590b57cec5SDimitry Andric // call void @takes_i32_inalloca(i32* null) 41600b57cec5SDimitry Andric // 41610b57cec5SDimitry Andric // Similarly, avoid folding away bitcasts of byval calls. 41620b57cec5SDimitry Andric if (Callee->getAttributes().hasAttrSomewhere(Attribute::InAlloca) || 416381ad6265SDimitry Andric Callee->getAttributes().hasAttrSomewhere(Attribute::Preallocated)) 41640b57cec5SDimitry Andric return false; 41650b57cec5SDimitry Andric 41660b57cec5SDimitry Andric auto AI = Call.arg_begin(); 41670b57cec5SDimitry Andric for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) { 41680b57cec5SDimitry Andric Type *ParamTy = FT->getParamType(i); 41690b57cec5SDimitry Andric Type *ActTy = (*AI)->getType(); 41700b57cec5SDimitry Andric 41710b57cec5SDimitry Andric if (!CastInst::isBitOrNoopPointerCastable(ActTy, ParamTy, DL)) 41720b57cec5SDimitry Andric return false; // Cannot transform this parameter value. 41730b57cec5SDimitry Andric 417481ad6265SDimitry Andric // Check if there are any incompatible attributes we cannot drop safely. 417504eeddc0SDimitry Andric if (AttrBuilder(FT->getContext(), CallerPAL.getParamAttrs(i)) 417681ad6265SDimitry Andric .overlaps(AttributeFuncs::typeIncompatible( 417781ad6265SDimitry Andric ParamTy, AttributeFuncs::ASK_UNSAFE_TO_DROP))) 41780b57cec5SDimitry Andric return false; // Attribute not compatible with transformed value. 41790b57cec5SDimitry Andric 418081ad6265SDimitry Andric if (Call.isInAllocaArgument(i) || 418181ad6265SDimitry Andric CallerPAL.hasParamAttr(i, Attribute::Preallocated)) 418281ad6265SDimitry Andric return false; // Cannot transform to and from inalloca/preallocated. 41830b57cec5SDimitry Andric 4184349cc55cSDimitry Andric if (CallerPAL.hasParamAttr(i, Attribute::SwiftError)) 4185e8d8bef9SDimitry Andric return false; 4186e8d8bef9SDimitry Andric 4187f3fd488fSDimitry Andric if (CallerPAL.hasParamAttr(i, Attribute::ByVal) != 4188f3fd488fSDimitry Andric Callee->getAttributes().hasParamAttr(i, Attribute::ByVal)) 4189f3fd488fSDimitry Andric return false; // Cannot transform to or from byval. 419081ad6265SDimitry Andric } 41910b57cec5SDimitry Andric 41920b57cec5SDimitry Andric if (Callee->isDeclaration()) { 41930b57cec5SDimitry Andric // Do not delete arguments unless we have a function body. 41940b57cec5SDimitry Andric if (FT->getNumParams() < NumActualArgs && !FT->isVarArg()) 41950b57cec5SDimitry Andric return false; 41960b57cec5SDimitry Andric 41970b57cec5SDimitry Andric // If the callee is just a declaration, don't change the varargsness of the 41980b57cec5SDimitry Andric // call. We don't want to introduce a varargs call where one doesn't 41990b57cec5SDimitry Andric // already exist. 420004eeddc0SDimitry Andric if (FT->isVarArg() != Call.getFunctionType()->isVarArg()) 42010b57cec5SDimitry Andric return false; 42020b57cec5SDimitry Andric 42030b57cec5SDimitry Andric // If both the callee and the cast type are varargs, we still have to make 42040b57cec5SDimitry Andric // sure the number of fixed parameters are the same or we have the same 42050b57cec5SDimitry Andric // ABI issues as if we introduce a varargs call. 420604eeddc0SDimitry Andric if (FT->isVarArg() && Call.getFunctionType()->isVarArg() && 420704eeddc0SDimitry Andric FT->getNumParams() != Call.getFunctionType()->getNumParams()) 42080b57cec5SDimitry Andric return false; 42090b57cec5SDimitry Andric } 42100b57cec5SDimitry Andric 42110b57cec5SDimitry Andric if (FT->getNumParams() < NumActualArgs && FT->isVarArg() && 42120b57cec5SDimitry Andric !CallerPAL.isEmpty()) { 42130b57cec5SDimitry Andric // In this case we have more arguments than the new function type, but we 42140b57cec5SDimitry Andric // won't be dropping them. Check that these extra arguments have attributes 42150b57cec5SDimitry Andric // that are compatible with being a vararg call argument. 42160b57cec5SDimitry Andric unsigned SRetIdx; 42170b57cec5SDimitry Andric if (CallerPAL.hasAttrSomewhere(Attribute::StructRet, &SRetIdx) && 4218349cc55cSDimitry Andric SRetIdx - AttributeList::FirstArgIndex >= FT->getNumParams()) 42190b57cec5SDimitry Andric return false; 42200b57cec5SDimitry Andric } 42210b57cec5SDimitry Andric 42220b57cec5SDimitry Andric // Okay, we decided that this is a safe thing to do: go ahead and start 42230b57cec5SDimitry Andric // inserting cast instructions as necessary. 42240b57cec5SDimitry Andric SmallVector<Value *, 8> Args; 42250b57cec5SDimitry Andric SmallVector<AttributeSet, 8> ArgAttrs; 42260b57cec5SDimitry Andric Args.reserve(NumActualArgs); 42270b57cec5SDimitry Andric ArgAttrs.reserve(NumActualArgs); 42280b57cec5SDimitry Andric 42290b57cec5SDimitry Andric // Get any return attributes. 423004eeddc0SDimitry Andric AttrBuilder RAttrs(FT->getContext(), CallerPAL.getRetAttrs()); 42310b57cec5SDimitry Andric 42320b57cec5SDimitry Andric // If the return value is not being used, the type may not be compatible 42330b57cec5SDimitry Andric // with the existing attributes. Wipe out any problematic attributes. 42340b57cec5SDimitry Andric RAttrs.remove(AttributeFuncs::typeIncompatible(NewRetTy)); 42350b57cec5SDimitry Andric 42360b57cec5SDimitry Andric LLVMContext &Ctx = Call.getContext(); 42370b57cec5SDimitry Andric AI = Call.arg_begin(); 42380b57cec5SDimitry Andric for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) { 42390b57cec5SDimitry Andric Type *ParamTy = FT->getParamType(i); 42400b57cec5SDimitry Andric 42410b57cec5SDimitry Andric Value *NewArg = *AI; 42420b57cec5SDimitry Andric if ((*AI)->getType() != ParamTy) 42430b57cec5SDimitry Andric NewArg = Builder.CreateBitOrPointerCast(*AI, ParamTy); 42440b57cec5SDimitry Andric Args.push_back(NewArg); 42450b57cec5SDimitry Andric 424681ad6265SDimitry Andric // Add any parameter attributes except the ones incompatible with the new 424781ad6265SDimitry Andric // type. Note that we made sure all incompatible ones are safe to drop. 424881ad6265SDimitry Andric AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible( 424981ad6265SDimitry Andric ParamTy, AttributeFuncs::ASK_SAFE_TO_DROP); 425081ad6265SDimitry Andric ArgAttrs.push_back( 425181ad6265SDimitry Andric CallerPAL.getParamAttrs(i).removeAttributes(Ctx, IncompatibleAttrs)); 425281ad6265SDimitry Andric } 42530b57cec5SDimitry Andric 42540b57cec5SDimitry Andric // If the function takes more arguments than the call was taking, add them 42550b57cec5SDimitry Andric // now. 42560b57cec5SDimitry Andric for (unsigned i = NumCommonArgs; i != FT->getNumParams(); ++i) { 42570b57cec5SDimitry Andric Args.push_back(Constant::getNullValue(FT->getParamType(i))); 42580b57cec5SDimitry Andric ArgAttrs.push_back(AttributeSet()); 42590b57cec5SDimitry Andric } 42600b57cec5SDimitry Andric 42610b57cec5SDimitry Andric // If we are removing arguments to the function, emit an obnoxious warning. 42620b57cec5SDimitry Andric if (FT->getNumParams() < NumActualArgs) { 42630b57cec5SDimitry Andric // TODO: if (!FT->isVarArg()) this call may be unreachable. PR14722 42640b57cec5SDimitry Andric if (FT->isVarArg()) { 42650b57cec5SDimitry Andric // Add all of the arguments in their promoted form to the arg list. 42660b57cec5SDimitry Andric for (unsigned i = FT->getNumParams(); i != NumActualArgs; ++i, ++AI) { 42670b57cec5SDimitry Andric Type *PTy = getPromotedType((*AI)->getType()); 42680b57cec5SDimitry Andric Value *NewArg = *AI; 42690b57cec5SDimitry Andric if (PTy != (*AI)->getType()) { 42700b57cec5SDimitry Andric // Must promote to pass through va_arg area! 42710b57cec5SDimitry Andric Instruction::CastOps opcode = 42720b57cec5SDimitry Andric CastInst::getCastOpcode(*AI, false, PTy, false); 42730b57cec5SDimitry Andric NewArg = Builder.CreateCast(opcode, *AI, PTy); 42740b57cec5SDimitry Andric } 42750b57cec5SDimitry Andric Args.push_back(NewArg); 42760b57cec5SDimitry Andric 42770b57cec5SDimitry Andric // Add any parameter attributes. 4278349cc55cSDimitry Andric ArgAttrs.push_back(CallerPAL.getParamAttrs(i)); 42790b57cec5SDimitry Andric } 42800b57cec5SDimitry Andric } 42810b57cec5SDimitry Andric } 42820b57cec5SDimitry Andric 4283349cc55cSDimitry Andric AttributeSet FnAttrs = CallerPAL.getFnAttrs(); 42840b57cec5SDimitry Andric 42850b57cec5SDimitry Andric if (NewRetTy->isVoidTy()) 42860b57cec5SDimitry Andric Caller->setName(""); // Void type should not have a name. 42870b57cec5SDimitry Andric 42880b57cec5SDimitry Andric assert((ArgAttrs.size() == FT->getNumParams() || FT->isVarArg()) && 42890b57cec5SDimitry Andric "missing argument attributes"); 42900b57cec5SDimitry Andric AttributeList NewCallerPAL = AttributeList::get( 42910b57cec5SDimitry Andric Ctx, FnAttrs, AttributeSet::get(Ctx, RAttrs), ArgAttrs); 42920b57cec5SDimitry Andric 42930b57cec5SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles; 42940b57cec5SDimitry Andric Call.getOperandBundlesAsDefs(OpBundles); 42950b57cec5SDimitry Andric 42960b57cec5SDimitry Andric CallBase *NewCall; 42970b57cec5SDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) { 42980b57cec5SDimitry Andric NewCall = Builder.CreateInvoke(Callee, II->getNormalDest(), 42990b57cec5SDimitry Andric II->getUnwindDest(), Args, OpBundles); 43000b57cec5SDimitry Andric } else { 43010b57cec5SDimitry Andric NewCall = Builder.CreateCall(Callee, Args, OpBundles); 43020b57cec5SDimitry Andric cast<CallInst>(NewCall)->setTailCallKind( 43030b57cec5SDimitry Andric cast<CallInst>(Caller)->getTailCallKind()); 43040b57cec5SDimitry Andric } 43050b57cec5SDimitry Andric NewCall->takeName(Caller); 43060b57cec5SDimitry Andric NewCall->setCallingConv(Call.getCallingConv()); 43070b57cec5SDimitry Andric NewCall->setAttributes(NewCallerPAL); 43080b57cec5SDimitry Andric 43095ffd83dbSDimitry Andric // Preserve prof metadata if any. 43105ffd83dbSDimitry Andric NewCall->copyMetadata(*Caller, {LLVMContext::MD_prof}); 43110b57cec5SDimitry Andric 43120b57cec5SDimitry Andric // Insert a cast of the return type as necessary. 43130b57cec5SDimitry Andric Instruction *NC = NewCall; 43140b57cec5SDimitry Andric Value *NV = NC; 43150b57cec5SDimitry Andric if (OldRetTy != NV->getType() && !Caller->use_empty()) { 43160b57cec5SDimitry Andric if (!NV->getType()->isVoidTy()) { 43170b57cec5SDimitry Andric NV = NC = CastInst::CreateBitOrPointerCast(NC, OldRetTy); 43180b57cec5SDimitry Andric NC->setDebugLoc(Caller->getDebugLoc()); 43190b57cec5SDimitry Andric 43205f757f3fSDimitry Andric auto OptInsertPt = NewCall->getInsertionPointAfterDef(); 43215f757f3fSDimitry Andric assert(OptInsertPt && "No place to insert cast"); 43225f757f3fSDimitry Andric InsertNewInstBefore(NC, *OptInsertPt); 43235ffd83dbSDimitry Andric Worklist.pushUsersToWorkList(*Caller); 43240b57cec5SDimitry Andric } else { 4325bdd1243dSDimitry Andric NV = PoisonValue::get(Caller->getType()); 43260b57cec5SDimitry Andric } 43270b57cec5SDimitry Andric } 43280b57cec5SDimitry Andric 43290b57cec5SDimitry Andric if (!Caller->use_empty()) 43300b57cec5SDimitry Andric replaceInstUsesWith(*Caller, NV); 43310b57cec5SDimitry Andric else if (Caller->hasValueHandle()) { 43320b57cec5SDimitry Andric if (OldRetTy == NV->getType()) 43330b57cec5SDimitry Andric ValueHandleBase::ValueIsRAUWd(Caller, NV); 43340b57cec5SDimitry Andric else 43350b57cec5SDimitry Andric // We cannot call ValueIsRAUWd with a different type, and the 43360b57cec5SDimitry Andric // actual tracked value will disappear. 43370b57cec5SDimitry Andric ValueHandleBase::ValueIsDeleted(Caller); 43380b57cec5SDimitry Andric } 43390b57cec5SDimitry Andric 43400b57cec5SDimitry Andric eraseInstFromFunction(*Caller); 43410b57cec5SDimitry Andric return true; 43420b57cec5SDimitry Andric } 43430b57cec5SDimitry Andric 43440b57cec5SDimitry Andric /// Turn a call to a function created by init_trampoline / adjust_trampoline 43450b57cec5SDimitry Andric /// intrinsic pair into a direct call to the underlying function. 43460b57cec5SDimitry Andric Instruction * 4347e8d8bef9SDimitry Andric InstCombinerImpl::transformCallThroughTrampoline(CallBase &Call, 43480b57cec5SDimitry Andric IntrinsicInst &Tramp) { 43490b57cec5SDimitry Andric FunctionType *FTy = Call.getFunctionType(); 43500b57cec5SDimitry Andric AttributeList Attrs = Call.getAttributes(); 43510b57cec5SDimitry Andric 43520b57cec5SDimitry Andric // If the call already has the 'nest' attribute somewhere then give up - 43530b57cec5SDimitry Andric // otherwise 'nest' would occur twice after splicing in the chain. 43540b57cec5SDimitry Andric if (Attrs.hasAttrSomewhere(Attribute::Nest)) 43550b57cec5SDimitry Andric return nullptr; 43560b57cec5SDimitry Andric 43570b57cec5SDimitry Andric Function *NestF = cast<Function>(Tramp.getArgOperand(1)->stripPointerCasts()); 43580b57cec5SDimitry Andric FunctionType *NestFTy = NestF->getFunctionType(); 43590b57cec5SDimitry Andric 43600b57cec5SDimitry Andric AttributeList NestAttrs = NestF->getAttributes(); 43610b57cec5SDimitry Andric if (!NestAttrs.isEmpty()) { 43620b57cec5SDimitry Andric unsigned NestArgNo = 0; 43630b57cec5SDimitry Andric Type *NestTy = nullptr; 43640b57cec5SDimitry Andric AttributeSet NestAttr; 43650b57cec5SDimitry Andric 43660b57cec5SDimitry Andric // Look for a parameter marked with the 'nest' attribute. 43670b57cec5SDimitry Andric for (FunctionType::param_iterator I = NestFTy->param_begin(), 43680b57cec5SDimitry Andric E = NestFTy->param_end(); 43690b57cec5SDimitry Andric I != E; ++NestArgNo, ++I) { 4370349cc55cSDimitry Andric AttributeSet AS = NestAttrs.getParamAttrs(NestArgNo); 43710b57cec5SDimitry Andric if (AS.hasAttribute(Attribute::Nest)) { 43720b57cec5SDimitry Andric // Record the parameter type and any other attributes. 43730b57cec5SDimitry Andric NestTy = *I; 43740b57cec5SDimitry Andric NestAttr = AS; 43750b57cec5SDimitry Andric break; 43760b57cec5SDimitry Andric } 43770b57cec5SDimitry Andric } 43780b57cec5SDimitry Andric 43790b57cec5SDimitry Andric if (NestTy) { 43800b57cec5SDimitry Andric std::vector<Value*> NewArgs; 43810b57cec5SDimitry Andric std::vector<AttributeSet> NewArgAttrs; 43820b57cec5SDimitry Andric NewArgs.reserve(Call.arg_size() + 1); 43830b57cec5SDimitry Andric NewArgAttrs.reserve(Call.arg_size()); 43840b57cec5SDimitry Andric 43850b57cec5SDimitry Andric // Insert the nest argument into the call argument list, which may 43860b57cec5SDimitry Andric // mean appending it. Likewise for attributes. 43870b57cec5SDimitry Andric 43880b57cec5SDimitry Andric { 43890b57cec5SDimitry Andric unsigned ArgNo = 0; 43900b57cec5SDimitry Andric auto I = Call.arg_begin(), E = Call.arg_end(); 43910b57cec5SDimitry Andric do { 43920b57cec5SDimitry Andric if (ArgNo == NestArgNo) { 43930b57cec5SDimitry Andric // Add the chain argument and attributes. 43940b57cec5SDimitry Andric Value *NestVal = Tramp.getArgOperand(2); 43950b57cec5SDimitry Andric if (NestVal->getType() != NestTy) 43960b57cec5SDimitry Andric NestVal = Builder.CreateBitCast(NestVal, NestTy, "nest"); 43970b57cec5SDimitry Andric NewArgs.push_back(NestVal); 43980b57cec5SDimitry Andric NewArgAttrs.push_back(NestAttr); 43990b57cec5SDimitry Andric } 44000b57cec5SDimitry Andric 44010b57cec5SDimitry Andric if (I == E) 44020b57cec5SDimitry Andric break; 44030b57cec5SDimitry Andric 44040b57cec5SDimitry Andric // Add the original argument and attributes. 44050b57cec5SDimitry Andric NewArgs.push_back(*I); 4406349cc55cSDimitry Andric NewArgAttrs.push_back(Attrs.getParamAttrs(ArgNo)); 44070b57cec5SDimitry Andric 44080b57cec5SDimitry Andric ++ArgNo; 44090b57cec5SDimitry Andric ++I; 44100b57cec5SDimitry Andric } while (true); 44110b57cec5SDimitry Andric } 44120b57cec5SDimitry Andric 44130b57cec5SDimitry Andric // The trampoline may have been bitcast to a bogus type (FTy). 44140b57cec5SDimitry Andric // Handle this by synthesizing a new function type, equal to FTy 44150b57cec5SDimitry Andric // with the chain parameter inserted. 44160b57cec5SDimitry Andric 44170b57cec5SDimitry Andric std::vector<Type*> NewTypes; 44180b57cec5SDimitry Andric NewTypes.reserve(FTy->getNumParams()+1); 44190b57cec5SDimitry Andric 44200b57cec5SDimitry Andric // Insert the chain's type into the list of parameter types, which may 44210b57cec5SDimitry Andric // mean appending it. 44220b57cec5SDimitry Andric { 44230b57cec5SDimitry Andric unsigned ArgNo = 0; 44240b57cec5SDimitry Andric FunctionType::param_iterator I = FTy->param_begin(), 44250b57cec5SDimitry Andric E = FTy->param_end(); 44260b57cec5SDimitry Andric 44270b57cec5SDimitry Andric do { 44280b57cec5SDimitry Andric if (ArgNo == NestArgNo) 44290b57cec5SDimitry Andric // Add the chain's type. 44300b57cec5SDimitry Andric NewTypes.push_back(NestTy); 44310b57cec5SDimitry Andric 44320b57cec5SDimitry Andric if (I == E) 44330b57cec5SDimitry Andric break; 44340b57cec5SDimitry Andric 44350b57cec5SDimitry Andric // Add the original type. 44360b57cec5SDimitry Andric NewTypes.push_back(*I); 44370b57cec5SDimitry Andric 44380b57cec5SDimitry Andric ++ArgNo; 44390b57cec5SDimitry Andric ++I; 44400b57cec5SDimitry Andric } while (true); 44410b57cec5SDimitry Andric } 44420b57cec5SDimitry Andric 44430b57cec5SDimitry Andric // Replace the trampoline call with a direct call. Let the generic 44440b57cec5SDimitry Andric // code sort out any function type mismatches. 44455f757f3fSDimitry Andric FunctionType *NewFTy = 44465f757f3fSDimitry Andric FunctionType::get(FTy->getReturnType(), NewTypes, FTy->isVarArg()); 44470b57cec5SDimitry Andric AttributeList NewPAL = 4448349cc55cSDimitry Andric AttributeList::get(FTy->getContext(), Attrs.getFnAttrs(), 4449349cc55cSDimitry Andric Attrs.getRetAttrs(), NewArgAttrs); 44500b57cec5SDimitry Andric 44510b57cec5SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles; 44520b57cec5SDimitry Andric Call.getOperandBundlesAsDefs(OpBundles); 44530b57cec5SDimitry Andric 44540b57cec5SDimitry Andric Instruction *NewCaller; 44550b57cec5SDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(&Call)) { 44565f757f3fSDimitry Andric NewCaller = InvokeInst::Create(NewFTy, NestF, II->getNormalDest(), 44575f757f3fSDimitry Andric II->getUnwindDest(), NewArgs, OpBundles); 44580b57cec5SDimitry Andric cast<InvokeInst>(NewCaller)->setCallingConv(II->getCallingConv()); 44590b57cec5SDimitry Andric cast<InvokeInst>(NewCaller)->setAttributes(NewPAL); 44600b57cec5SDimitry Andric } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(&Call)) { 44610b57cec5SDimitry Andric NewCaller = 44625f757f3fSDimitry Andric CallBrInst::Create(NewFTy, NestF, CBI->getDefaultDest(), 44630b57cec5SDimitry Andric CBI->getIndirectDests(), NewArgs, OpBundles); 44640b57cec5SDimitry Andric cast<CallBrInst>(NewCaller)->setCallingConv(CBI->getCallingConv()); 44650b57cec5SDimitry Andric cast<CallBrInst>(NewCaller)->setAttributes(NewPAL); 44660b57cec5SDimitry Andric } else { 44675f757f3fSDimitry Andric NewCaller = CallInst::Create(NewFTy, NestF, NewArgs, OpBundles); 44680b57cec5SDimitry Andric cast<CallInst>(NewCaller)->setTailCallKind( 44690b57cec5SDimitry Andric cast<CallInst>(Call).getTailCallKind()); 44700b57cec5SDimitry Andric cast<CallInst>(NewCaller)->setCallingConv( 44710b57cec5SDimitry Andric cast<CallInst>(Call).getCallingConv()); 44720b57cec5SDimitry Andric cast<CallInst>(NewCaller)->setAttributes(NewPAL); 44730b57cec5SDimitry Andric } 44740b57cec5SDimitry Andric NewCaller->setDebugLoc(Call.getDebugLoc()); 44750b57cec5SDimitry Andric 44760b57cec5SDimitry Andric return NewCaller; 44770b57cec5SDimitry Andric } 44780b57cec5SDimitry Andric } 44790b57cec5SDimitry Andric 44800b57cec5SDimitry Andric // Replace the trampoline call with a direct call. Since there is no 'nest' 44810b57cec5SDimitry Andric // parameter, there is no need to adjust the argument list. Let the generic 44820b57cec5SDimitry Andric // code sort out any function type mismatches. 44835f757f3fSDimitry Andric Call.setCalledFunction(FTy, NestF); 44840b57cec5SDimitry Andric return &Call; 44850b57cec5SDimitry Andric } 4486