1 //===-- llvm/CodeGen/SelectionDAGAddressAnalysis.cpp ------- DAG Address 2 //Analysis ---*- C++ -*-===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 12 #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" 13 #include "llvm/CodeGen/ISDOpcodes.h" 14 #include "llvm/CodeGen/SelectionDAG.h" 15 #include "llvm/CodeGen/SelectionDAGNodes.h" 16 17 namespace llvm { 18 19 bool BaseIndexOffset::equalBaseIndex(BaseIndexOffset &Other, 20 const SelectionDAG &DAG, int64_t &Off) { 21 // Obvious equivalent 22 Off = Other.Offset - Offset; 23 if (Other.Base == Base && Other.Index == Index && 24 Other.IsIndexSignExt == IsIndexSignExt) 25 return true; 26 27 // Match GlobalAddresses 28 if (Index == Other.Index) 29 if (GlobalAddressSDNode *A = dyn_cast<GlobalAddressSDNode>(Base)) 30 if (GlobalAddressSDNode *B = dyn_cast<GlobalAddressSDNode>(Other.Base)) 31 if (A->getGlobal() == B->getGlobal()) { 32 Off += B->getOffset() - A->getOffset(); 33 return true; 34 } 35 36 // TODO: we should be able to add FrameIndex analysis improvements here. 37 38 return false; 39 } 40 41 /// Parses tree in Ptr for base, index, offset addresses. 42 BaseIndexOffset BaseIndexOffset::match(SDValue Ptr) { 43 // (((B + I*M) + c)) + c ... 44 SDValue Base = Ptr; 45 SDValue Index = SDValue(); 46 int64_t Offset = 0; 47 bool IsIndexSignExt = false; 48 49 // Consume constant adds 50 while (Base->getOpcode() == ISD::ADD && 51 isa<ConstantSDNode>(Base->getOperand(1))) { 52 int64_t POffset = cast<ConstantSDNode>(Base->getOperand(1))->getSExtValue(); 53 Offset += POffset; 54 Base = Base->getOperand(0); 55 } 56 57 if (Base->getOpcode() == ISD::ADD) { 58 // TODO: The following code appears to be needless as it just 59 // bails on some Ptrs early, reducing the cases where we 60 // find equivalence. We should be able to remove this. 61 // Inside a loop the current BASE pointer is calculated using an ADD and a 62 // MUL instruction. In this case Base is the actual BASE pointer. 63 // (i64 add (i64 %array_ptr) 64 // (i64 mul (i64 %induction_var) 65 // (i64 %element_size))) 66 if (Base->getOperand(1)->getOpcode() == ISD::MUL) 67 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); 68 69 // Look at Base + Index + Offset cases. 70 Index = Base->getOperand(1); 71 SDValue PotentialBase = Base->getOperand(0); 72 73 // Skip signextends. 74 if (Index->getOpcode() == ISD::SIGN_EXTEND) { 75 Index = Index->getOperand(0); 76 IsIndexSignExt = true; 77 } 78 79 // Check if Index Offset pattern 80 if (Index->getOpcode() != ISD::ADD || 81 !isa<ConstantSDNode>(Index->getOperand(1))) 82 return BaseIndexOffset(PotentialBase, Index, Offset, IsIndexSignExt); 83 84 Offset += cast<ConstantSDNode>(Index->getOperand(1))->getSExtValue(); 85 Index = Index->getOperand(0); 86 if (Index->getOpcode() == ISD::SIGN_EXTEND) { 87 Index = Index->getOperand(0); 88 IsIndexSignExt = true; 89 } else 90 IsIndexSignExt = false; 91 Base = PotentialBase; 92 } 93 return BaseIndexOffset(Base, Index, Offset, IsIndexSignExt); 94 } 95 } // end namespace llvm 96