Changeset View
Standalone View
include/llvm/Analysis/TargetTransformInfoImpl.h
Show All 13 Lines | |||||
#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H | #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H | ||||
#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H | #define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H | ||||
#include "llvm/Analysis/TargetTransformInfo.h" | #include "llvm/Analysis/TargetTransformInfo.h" | ||||
#include "llvm/IR/CallSite.h" | #include "llvm/IR/CallSite.h" | ||||
#include "llvm/IR/DataLayout.h" | #include "llvm/IR/DataLayout.h" | ||||
#include "llvm/IR/Function.h" | #include "llvm/IR/Function.h" | ||||
#include "llvm/IR/GetElementPtrTypeIterator.h" | |||||
#include "llvm/IR/Operator.h" | #include "llvm/IR/Operator.h" | ||||
#include "llvm/IR/Type.h" | #include "llvm/IR/Type.h" | ||||
namespace llvm { | namespace llvm { | ||||
/// \brief Base class for use as a mix-in that aids implementing | /// \brief Base class for use as a mix-in that aids implementing | ||||
/// a TargetTransformInfo-compatible class. | /// a TargetTransformInfo-compatible class. | ||||
class TargetTransformInfoImplBase { | class TargetTransformInfoImplBase { | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | case Instruction::Trunc: | ||||
// shift-right of the same width). | // shift-right of the same width). | ||||
if (DL.isLegalInteger(DL.getTypeSizeInBits(Ty))) | if (DL.isLegalInteger(DL.getTypeSizeInBits(Ty))) | ||||
return TTI::TCC_Free; | return TTI::TCC_Free; | ||||
return TTI::TCC_Basic; | return TTI::TCC_Basic; | ||||
} | } | ||||
} | } | ||||
unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) { | unsigned getGEPCost(Type *PointeeType, const Value *Ptr, | ||||
ArrayRef<const Value *> Operands) { | |||||
// In the basic model, we just assume that all-constant GEPs will be folded | // In the basic model, we just assume that all-constant GEPs will be folded | ||||
// into their uses via addressing modes. | // into their uses via addressing modes. | ||||
for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) | for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) | ||||
if (!isa<Constant>(Operands[Idx])) | if (!isa<Constant>(Operands[Idx])) | ||||
return TTI::TCC_Basic; | return TTI::TCC_Basic; | ||||
return TTI::TCC_Free; | return TTI::TCC_Free; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | public: | ||||
unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) { | unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) { | ||||
// Simply delegate to generic handling of the call. | // Simply delegate to generic handling of the call. | ||||
// FIXME: We should use instsimplify or something else to catch calls which | // FIXME: We should use instsimplify or something else to catch calls which | ||||
// will constant fold with these arguments. | // will constant fold with these arguments. | ||||
return static_cast<T *>(this)->getCallCost(F, Arguments.size()); | return static_cast<T *>(this)->getCallCost(F, Arguments.size()); | ||||
} | } | ||||
using BaseT::getGEPCost; | |||||
unsigned getGEPCost(Type *PointeeType, const Value *Ptr, | |||||
ArrayRef<const Value *> Operands) { | |||||
hfinkel: You should call stripPointerCasts before doing the dyn_cast. | |||||
Not Done ReplyInline ActionsShould be dyn_cast_or_null b/c the cost model should not require the base pointer be known when estimating costs. hfinkel: Should be dyn_cast_or_null b/c the cost model should not require the base pointer be known when… | |||||
Not Done ReplyInline ActionsInteresting -- when Ptr == nullptr, what is a good estimation? Fall back to using getAddressComputationCost? jingyue: Interesting -- when Ptr == nullptr, what is a good estimation? Fall back to using… | |||||
Not Done ReplyInline ActionsNo, but there is another issue here. We're currently moving to give pointer an opaque type, and so you'll need to separately require a Type* on this interface. Please add that. Once you have the Type *, you should:
hfinkel: No, but there is another issue here. We're currently moving to give pointer an opaque type, and… | |||||
const GlobalValue *BaseGV = nullptr; | |||||
if (Ptr != nullptr) { | |||||
// TODO: will remove this when a pointer can have an opaque type. | |||||
pointer can have -> pointers have hfinkel: pointer can have -> pointers have | |||||
hfinkelUnsubmitted Not Done ReplyInline Actionsa pointer can have -> pointers have (when we make the change, there will be no 'can' about it, they'll have to have an opaque type). hfinkel: a pointer can have -> pointers have
(when we make the change, there will be no 'can' about it… | |||||
assert(Ptr->getType()->getScalarType()->getPointerElementType() == | |||||
PointeeType && | |||||
"explicit pointee type doesn't match operand's pointee type"); | |||||
BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts()); | |||||
} | |||||
bool HasBaseReg = (BaseGV == nullptr); | |||||
int64_t BaseOffset = 0; | |||||
int64_t Scale = 0; | |||||
// Assumes the address space is 0 when Ptr is nullptr. | |||||
unsigned AS = | |||||
(Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace()); | |||||
auto GTI = gep_type_begin(PointerType::get(PointeeType, AS), Operands); | |||||
I don't understand why you're doing this. Will gep_type_begin not compile with an ArrayRef<const Value *>? If so, we should just fix that. hfinkel: I don't understand why you're doing this. Will gep_type_begin not compile with an… | |||||
for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) { | |||||
if (isa<SequentialType>(*GTI)) { | |||||
int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType()); | |||||
That's not right. isLegalAddressingMode takes the address space as an optional last parameter. Please propagate it. hfinkel: That's not right. isLegalAddressingMode takes the address space as an optional last parameter. | |||||
if (const ConstantInt *ConstIdx = dyn_cast<ConstantInt>(*I)) { | |||||
BaseOffset += ConstIdx->getSExtValue() * ElementSize; | |||||
} else { | |||||
// Needs scale register. | |||||
if (Scale != 0) { | |||||
// No addressing mode takes two scale registers. | |||||
return TTI::TCC_Basic; | |||||
} | |||||
Scale = ElementSize; | |||||
} | |||||
} else { | |||||
StructType *STy = cast<StructType>(*GTI); | |||||
uint64_t Field = cast<ConstantInt>(*I)->getZExtValue(); | |||||
BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field); | |||||
} | |||||
} | |||||
if (static_cast<T *>(this)->isLegalAddressingMode( | |||||
PointerType::get(*GTI, AS), const_cast<GlobalValue *>(BaseGV), | |||||
Not Done ReplyInline ActionsI think we should use *GTI here rather than PointerType::get(*GTI, AS). For example, on AArch64, the GEP in the following IRs can be folded %"class.boost::array.16" = type { [24 x i32] } %arrayidx.i17 = getelementptr inbounds %"class.boost::array.16", %"class.boost::array.16"* %moves, i64 0, i32 0, i64 %conv7 store i32 %add, i32* %arrayidx.i17, align 4, !tbaa !18 The assembly is simple as str w24, [x20, x8, lsl #2] However, isLegalAddressingMode() here returns false because we pass a wrong type. I checked the implementation of isLegalAddressingMode() in several different backends (including ARM) and several other passes (LoopStrengthReduce and CodeGenPrepare) that call isLegalAddressingMode(). It think I am correct. haicheng: I think we should use *GTI here rather than PointerType::get(*GTI, AS).
For example, on… | |||||
Not Done ReplyInline ActionsThanks! I think you are right. Can you create a patch and add a unit test for this? jingyue: Thanks! I think you are right. Can you create a patch and add a unit test for this? | |||||
BaseOffset, HasBaseReg, Scale, AS)) { | |||||
return TTI::TCC_Free; | |||||
} | |||||
return TTI::TCC_Basic; | |||||
} | |||||
using BaseT::getIntrinsicCost; | using BaseT::getIntrinsicCost; | ||||
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, | unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, | ||||
ArrayRef<const Value *> Arguments) { | ArrayRef<const Value *> Arguments) { | ||||
// Delegate to the generic intrinsic handling code. This mostly provides an | // Delegate to the generic intrinsic handling code. This mostly provides an | ||||
// opportunity for targets to (for example) special case the cost of | // opportunity for targets to (for example) special case the cost of | ||||
// certain intrinsics based on constants used as arguments. | // certain intrinsics based on constants used as arguments. | ||||
SmallVector<Type *, 8> ParamTys; | SmallVector<Type *, 8> ParamTys; | ||||
ParamTys.reserve(Arguments.size()); | ParamTys.reserve(Arguments.size()); | ||||
for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) | for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) | ||||
ParamTys.push_back(Arguments[Idx]->getType()); | ParamTys.push_back(Arguments[Idx]->getType()); | ||||
return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys); | return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys); | ||||
} | } | ||||
unsigned getUserCost(const User *U) { | unsigned getUserCost(const User *U) { | ||||
if (isa<PHINode>(U)) | if (isa<PHINode>(U)) | ||||
return TTI::TCC_Free; // Model all PHI nodes as free. | return TTI::TCC_Free; // Model all PHI nodes as free. | ||||
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) { | if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) { | ||||
SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end()); | SmallVector<Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end()); | ||||
return static_cast<T *>(this) | return static_cast<T *>(this)->getGEPCost( | ||||
->getGEPCost(GEP->getPointerOperand(), Indices); | GEP->getSourceElementType(), GEP->getPointerOperand(), Indices); | ||||
} | } | ||||
if (auto CS = ImmutableCallSite(U)) { | if (auto CS = ImmutableCallSite(U)) { | ||||
const Function *F = CS.getCalledFunction(); | const Function *F = CS.getCalledFunction(); | ||||
if (!F) { | if (!F) { | ||||
// Just use the called value type. | // Just use the called value type. | ||||
Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); | Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); | ||||
return static_cast<T *>(this) | return static_cast<T *>(this) | ||||
Show All 23 Lines |
You should call stripPointerCasts before doing the dyn_cast.