From bb3204a440e3cf5f9bd44f05d34f99b7450341e6 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 25 Nov 2008 05:15:49 +0000 Subject: [PATCH] refactor all the constantexpr/instruction handling code out into a new FindMaximalLegalAddressingModeForOperation helper method. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60011 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/CodeGenPrepare.cpp | 133 ++++++++++++----------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 4a91ca89a44..08c64164a63 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -573,61 +573,22 @@ static bool TryMatchingScaledValue(Value *ScaleReg, int64_t Scale, return true; } - -/// FindMaximalLegalAddressingMode - If we can, try to merge the computation of -/// Addr into the specified addressing mode. If Addr can't be added to AddrMode -/// this returns false. This assumes that Addr is either a pointer type or -/// intptr_t for the target. -/// -/// This method is used to optimize both load/store and inline asms with memory -/// operands. static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, ExtAddrMode &AddrMode, + SmallVectorImpl &AMI, + const TargetLowering &TLI, + unsigned Depth); + +/// FindMaximalLegalAddressingModeForOperation - Given an instruction or +/// constant expr, see if we can fold the operation into the addressing mode. +/// If so, update the addressing mode and return true, otherwise return false. +static bool +FindMaximalLegalAddressingModeForOperation(User *AddrInst, unsigned Opcode, + const Type *AccessTy, + ExtAddrMode &AddrMode, SmallVectorImpl &AddrModeInsts, const TargetLowering &TLI, unsigned Depth) { - - // If this is a global variable, fold it into the addressing mode if possible. - if (GlobalValue *GV = dyn_cast(Addr)) { - if (AddrMode.BaseGV == 0) { - AddrMode.BaseGV = GV; - if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) - return true; - AddrMode.BaseGV = 0; - } - } else if (ConstantInt *CI = dyn_cast(Addr)) { - AddrMode.BaseOffs += CI->getSExtValue(); - if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) - return true; - AddrMode.BaseOffs -= CI->getSExtValue(); - } else if (isa(Addr)) { - return true; - } - - // Look through constant exprs and instructions. - unsigned Opcode = ~0U; - User *AddrInst = 0; - if (Instruction *I = dyn_cast(Addr)) { - Opcode = I->getOpcode(); - AddrInst = I; - } else if (ConstantExpr *CE = dyn_cast(Addr)) { - Opcode = CE->getOpcode(); - AddrInst = CE; - } - - // Limit recursion to avoid exponential behavior. - if (Depth == 5) { AddrInst = 0; Opcode = ~0U; } - - // If this is really an instruction, add it to our list of related - // instructions. - if (Instruction *I = dyn_cast_or_null(AddrInst)) - AddrModeInsts.push_back(I); - -#if 0 - if (AddrInst && !AddrInst->hasOneUse()) - ; - else -#endif switch (Opcode) { case Instruction::PtrToInt: // PtrToInt is always a noop, as we know that the int type is pointer sized. @@ -653,18 +614,18 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy, AddrMode, AddrModeInsts, TLI, Depth+1)) return true; - + // Restore the old addr mode info. AddrMode = BackupAddrMode; AddrModeInsts.resize(OldSize); - + // Otherwise this was over-aggressive. Try merging in the LHS then the RHS. if (FindMaximalLegalAddressingMode(AddrInst->getOperand(0), AccessTy, AddrMode, AddrModeInsts, TLI, Depth+1) && FindMaximalLegalAddressingMode(AddrInst->getOperand(1), AccessTy, AddrMode, AddrModeInsts, TLI, Depth+1)) return true; - + // Otherwise we definitely can't merge the ADD in. AddrMode = BackupAddrMode; AddrModeInsts.resize(OldSize); @@ -684,7 +645,7 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, int64_t Scale = RHS->getSExtValue(); if (Opcode == Instruction::Shl) Scale = 1 << Scale; - + if (TryMatchingScaledValue(AddrInst->getOperand(0), Scale, AccessTy, AddrMode, AddrModeInsts, TLI, Depth)) return true; @@ -695,7 +656,7 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, // one variable offset. int VariableOperand = -1; unsigned VariableScale = 0; - + int64_t ConstantOffset = 0; const TargetData *TD = TLI.getTargetData(); gep_type_iterator GTI = gep_type_begin(AddrInst); @@ -703,7 +664,7 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, if (const StructType *STy = dyn_cast(*GTI)) { const StructLayout *SL = TD->getStructLayout(STy); unsigned Idx = - cast(AddrInst->getOperand(i))->getZExtValue(); + cast(AddrInst->getOperand(i))->getZExtValue(); ConstantOffset += SL->getElementOffset(Idx); } else { uint64_t TypeSize = TD->getABITypeSize(GTI.getIndexedType()); @@ -715,18 +676,18 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, VariableOperand = -2; break; } - + // Remember the variable index. VariableOperand = i; VariableScale = TypeSize; } } } - + // If the GEP had multiple variable indices, punt. if (VariableOperand == -2) break; - + // A common case is for the GEP to only do a constant offset. In this case, // just add it to the disp field and check validity. if (VariableOperand == -1) { @@ -751,14 +712,14 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, AddrMode.BaseReg = AddrInst->getOperand(0); SetBaseReg = true; } - + // See if the scale amount is valid for this target. AddrMode.BaseOffs += ConstantOffset; if (TryMatchingScaledValue(AddrInst->getOperand(VariableOperand), VariableScale, AccessTy, AddrMode, AddrModeInsts, TLI, Depth)) { if (!SetBaseReg) return true; - + // If this match succeeded, we know that we can form an address with the // GepBase as the basereg. See if we can match *more*. AddrMode.HasBaseReg = false; @@ -773,7 +734,7 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, AddrMode.BaseReg = AddrInst->getOperand(0); return true; } - + AddrMode.BaseOffs -= ConstantOffset; if (SetBaseReg) { AddrMode.HasBaseReg = false; @@ -783,12 +744,54 @@ static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, break; } } + return false; +} - if (Instruction *I = dyn_cast_or_null(AddrInst)) { - assert(AddrModeInsts.back() == I && "Stack imbalance"); I = I; - AddrModeInsts.pop_back(); +/// FindMaximalLegalAddressingMode - If we can, try to merge the computation of +/// Addr into the specified addressing mode. If Addr can't be added to AddrMode +/// this returns false. This assumes that Addr is either a pointer type or +/// intptr_t for the target. +/// +/// This method is used to optimize both load/store and inline asms with memory +/// operands. +static bool FindMaximalLegalAddressingMode(Value *Addr, const Type *AccessTy, + ExtAddrMode &AddrMode, + SmallVectorImpl &AddrModeInsts, + const TargetLowering &TLI, + unsigned Depth) { + if (ConstantInt *CI = dyn_cast(Addr)) { + // Fold in immediates if legal for the target. + AddrMode.BaseOffs += CI->getSExtValue(); + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.BaseOffs -= CI->getSExtValue(); + } else if (GlobalValue *GV = dyn_cast(Addr)) { + // If this is a global variable, fold it into the addressing mode if possible. + if (AddrMode.BaseGV == 0) { + AddrMode.BaseGV = GV; + if (TLI.isLegalAddressingMode(AddrMode, AccessTy)) + return true; + AddrMode.BaseGV = 0; + } + } else if (Instruction *I = dyn_cast(Addr)) { + if (Depth < 5 && // Limit recursion to avoid exponential behavior. + FindMaximalLegalAddressingModeForOperation(I, I->getOpcode(), + AccessTy, AddrMode, + AddrModeInsts, TLI, Depth)) { + AddrModeInsts.push_back(I); + return true; + } + } else if (ConstantExpr *CE = dyn_cast(Addr)) { + if (Depth < 5 && // Limit recursion to avoid exponential behavior. + FindMaximalLegalAddressingModeForOperation(CE, CE->getOpcode(), + AccessTy, AddrMode, + AddrModeInsts, TLI, Depth)) + return true; + } else if (isa(Addr)) { + return true; } + // Worse case, the target should support [reg] addressing modes. :) if (!AddrMode.HasBaseReg) { AddrMode.HasBaseReg = true;