diff options
Diffstat (limited to 'src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp')
-rw-r--r-- | src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp b/src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp index ff04d9d55bf..b8898828dd6 100644 --- a/src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp +++ b/src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp @@ -13,9 +13,12 @@ #include "AMDILDevices.h" #include "AMDILTargetMachine.h" #include "AMDILUtilityFunctions.h" +#include "llvm/ADT/ValueMap.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Compiler.h" +#include <list> +#include <queue> using namespace llvm; @@ -35,13 +38,21 @@ class AMDILDAGToDAGISel : public SelectionDAGISel { public: AMDILDAGToDAGISel(AMDILTargetMachine &TM AMDIL_OPT_LEVEL_DECL); virtual ~AMDILDAGToDAGISel(); - inline SDValue getSmallIPtrImm(unsigned Imm); SDNode *Select(SDNode *N); + virtual const char *getPassName() const; + +private: + inline SDValue getSmallIPtrImm(unsigned Imm); + // Complex pattern selectors bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2); bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2); bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2); + + static bool checkType(const Value *ptr, unsigned int addrspace); + static const Value *getBasePointerValue(const Value *V); + static bool isGlobalStore(const StoreSDNode *N); static bool isPrivateStore(const StoreSDNode *N); static bool isLocalStore(const StoreSDNode *N); @@ -54,8 +65,6 @@ public: static bool isLocalLoad(const LoadSDNode *N); static bool isRegionLoad(const LoadSDNode *N); - virtual const char *getPassName() const; -private: SDNode *xformAtomicInst(SDNode *N); // Include the pieces autogenerated from the target description. @@ -165,26 +174,75 @@ SDNode *AMDILDAGToDAGISel::Select(SDNode *N) { return SelectCode(N); } +bool AMDILDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) { + if (!ptr) { + return false; + } + Type *ptrType = ptr->getType(); + return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace; +} + +const Value * AMDILDAGToDAGISel::getBasePointerValue(const Value *V) +{ + if (!V) { + return NULL; + } + const Value *ret = NULL; + ValueMap<const Value *, bool> ValueBitMap; + std::queue<const Value *, std::list<const Value *> > ValueQueue; + ValueQueue.push(V); + while (!ValueQueue.empty()) { + V = ValueQueue.front(); + if (ValueBitMap.find(V) == ValueBitMap.end()) { + ValueBitMap[V] = true; + if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) { + ret = V; + break; + } else if (dyn_cast<GlobalVariable>(V)) { + ret = V; + break; + } else if (dyn_cast<Constant>(V)) { + const ConstantExpr *CE = dyn_cast<ConstantExpr>(V); + if (CE) { + ValueQueue.push(CE->getOperand(0)); + } + } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) { + ret = AI; + break; + } else if (const Instruction *I = dyn_cast<Instruction>(V)) { + uint32_t numOps = I->getNumOperands(); + for (uint32_t x = 0; x < numOps; ++x) { + ValueQueue.push(I->getOperand(x)); + } + } else { + // assert(0 && "Found a Value that we didn't know how to handle!"); + } + } + ValueQueue.pop(); + } + return ret; +} + bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS); } bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode *N) { - return (!check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS)); + return (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS)); } bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS); } bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS); } bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) { - if (check_type(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) { + if (checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) { return true; } MachineMemOperand *MMO = N->getMemOperand(); @@ -195,27 +253,27 @@ bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) { && ((V && dyn_cast<GlobalValue>(V)) || (BV && dyn_cast<GlobalValue>( getBasePointerValue(MMO->getValue()))))) { - return check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS); } else { return false; } } bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS); } bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS); } bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode *N) { - return check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS); + return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS); } bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) { MachineMemOperand *MMO = N->getMemOperand(); - if (check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) { + if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) { if (MMO) { const Value *V = MMO->getValue(); const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V); @@ -228,19 +286,19 @@ bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) { } bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) { - if (check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) { + if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) { // Check to make sure we are not a constant pool load or a constant load // that is marked as a private load if (isCPLoad(N) || isConstantLoad(N, -1)) { return false; } } - if (!check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS) - && !check_type(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS)) + if (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS) + && !checkType(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS)) { return true; } |