summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp')
-rw-r--r--src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp102
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;
}