X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnouveau%2Fcodegen%2Fnv50_ir_target_nvc0.cpp;h=d2255c2cd2bbdeef04892676ea607aff27c5dad7;hp=a03afa8dc8dc4d4776452ad63ef71a404c84b75f;hb=1c9efcd7a6faa2e12361f5aa3007311563792095;hpb=37b67db6ae34fb6586d640a7a1b6232f091dd812 diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp index a03afa8dc8d..d2255c2cd2b 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nvc0.cpp @@ -30,7 +30,7 @@ Target *getTargetNVC0(unsigned int chipset) } TargetNVC0::TargetNVC0(unsigned int card) : - Target(card < 0x110, false, card >= 0xe4) + Target(card < 0x110, false, card >= 0xe4 && card < 0x140) { chipset = card; initOpInfo(); @@ -85,7 +85,7 @@ TargetNVC0::getBuiltinOffset(int builtin) const } } -struct opProperties +struct nvc0_opProperties { operation op; unsigned int mNeg : 4; @@ -96,7 +96,7 @@ struct opProperties unsigned int fImmd : 4; // last bit indicates if full immediate is suppoted }; -static const struct opProperties _initProps[] = +static const struct nvc0_opProperties _initProps[] = { // neg abs not sat c[] imm { OP_ADD, 0x3, 0x3, 0x0, 0x8, 0x2, 0x2 | 0x8 }, @@ -104,7 +104,9 @@ static const struct opProperties _initProps[] = { OP_MUL, 0x3, 0x0, 0x0, 0x8, 0x2, 0x2 | 0x8 }, { OP_MAX, 0x3, 0x3, 0x0, 0x0, 0x2, 0x2 }, { OP_MIN, 0x3, 0x3, 0x0, 0x0, 0x2, 0x2 }, - { OP_MAD, 0x7, 0x0, 0x0, 0x8, 0x6, 0x2 | 0x8 }, // special c[] constraint + { OP_MAD, 0x7, 0x0, 0x0, 0x8, 0x6, 0x2 }, // special c[] constraint + { OP_FMA, 0x7, 0x0, 0x0, 0x8, 0x6, 0x2 }, // keep the same as OP_MAD + { OP_SHLADD, 0x5, 0x0, 0x0, 0x0, 0x4, 0x6 }, { OP_MADSP, 0x0, 0x0, 0x0, 0x0, 0x6, 0x2 }, { OP_ABS, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0 }, { OP_NEG, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0 }, @@ -127,6 +129,7 @@ static const struct opProperties _initProps[] = { OP_LG2, 0x1, 0x1, 0x0, 0x8, 0x0, 0x0 }, { OP_RCP, 0x1, 0x1, 0x0, 0x8, 0x0, 0x0 }, { OP_RSQ, 0x1, 0x1, 0x0, 0x8, 0x0, 0x0 }, + { OP_SQRT, 0x1, 0x1, 0x0, 0x8, 0x0, 0x0 }, { OP_DFDX, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0 }, { OP_DFDY, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0 }, { OP_CALL, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0 }, @@ -141,7 +144,9 @@ static const struct opProperties _initProps[] = // saturate only: { OP_LINTERP, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0 }, { OP_PINTERP, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0 }, - // nve4 ops: +}; + +static const struct nvc0_opProperties _initPropsNVE4[] = { { OP_SULDB, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0 }, { OP_SUSTB, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0 }, { OP_SUSTP, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0 }, @@ -150,20 +155,53 @@ static const struct opProperties _initProps[] = { OP_SUEAU, 0x0, 0x0, 0x0, 0x0, 0x6, 0x2 } }; +static const struct nvc0_opProperties _initPropsGM107[] = { + { OP_SULDB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }, + { OP_SULDP, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }, + { OP_SUSTB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 }, + { OP_SUSTP, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 }, + { OP_SUREDB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 }, + { OP_SUREDP, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 }, + { OP_XMAD, 0x0, 0x0, 0x0, 0x0, 0x6, 0x2 }, +}; + +void TargetNVC0::initProps(const struct nvc0_opProperties *props, int size) +{ + for (int i = 0; i < size; ++i) { + const struct nvc0_opProperties *prop = &props[i]; + + for (int s = 0; s < 3; ++s) { + if (prop->mNeg & (1 << s)) + opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NEG; + if (prop->mAbs & (1 << s)) + opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_ABS; + if (prop->mNot & (1 << s)) + opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NOT; + if (prop->fConst & (1 << s)) + opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_MEMORY_CONST; + if (prop->fImmd & (1 << s)) + opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_IMMEDIATE; + if (prop->fImmd & 8) + opInfo[prop->op].immdBits = 0xffffffff; + } + if (prop->mSat & 8) + opInfo[prop->op].dstMods = NV50_IR_MOD_SAT; + } +} + void TargetNVC0::initOpInfo() { unsigned int i, j; - static const uint32_t commutative[(OP_LAST + 31) / 32] = + static const operation commutative[] = { - // ADD, MAD, MUL, AND, OR, XOR, MAX, MIN - 0x0670ca00, 0x0000003f, 0x00000000, 0x00000000 + OP_ADD, OP_MUL, OP_MAD, OP_FMA, OP_AND, OP_OR, OP_XOR, OP_MAX, OP_MIN, + OP_SET_AND, OP_SET_OR, OP_SET_XOR, OP_SET, OP_SELP, OP_SLCT }; - static const uint32_t shortForm[(OP_LAST + 31) / 32] = + static const operation shortForm[] = { - // ADD, MAD, MUL, AND, OR, XOR, PRESIN, PREEX2, SFN, CVT, PINTERP, MOV - 0x0670ca00, 0x00000000, 0x00000000, 0x00000000 + OP_ADD, OP_MUL, OP_MAD, OP_FMA, OP_AND, OP_OR, OP_XOR, OP_MAX, OP_MIN }; static const operation noDest[] = @@ -202,45 +240,36 @@ void TargetNVC0::initOpInfo() opInfo[i].hasDest = 1; opInfo[i].vector = (i >= OP_TEX && i <= OP_TEXCSAA); - opInfo[i].commutative = (commutative[i / 32] >> (i % 32)) & 1; + opInfo[i].commutative = false; /* set below */ opInfo[i].pseudo = (i < OP_MOV); opInfo[i].predicate = !opInfo[i].pseudo; opInfo[i].flow = (i >= OP_BRA && i <= OP_JOIN); - opInfo[i].minEncSize = (shortForm[i / 32] & (1 << (i % 32))) ? 4 : 8; + opInfo[i].minEncSize = 8; /* set below */ } - for (i = 0; i < sizeof(noDest) / sizeof(noDest[0]); ++i) + for (i = 0; i < ARRAY_SIZE(commutative); ++i) + opInfo[commutative[i]].commutative = true; + for (i = 0; i < ARRAY_SIZE(shortForm); ++i) + opInfo[shortForm[i]].minEncSize = 4; + for (i = 0; i < ARRAY_SIZE(noDest); ++i) opInfo[noDest[i]].hasDest = 0; - for (i = 0; i < sizeof(noPred) / sizeof(noPred[0]); ++i) + for (i = 0; i < ARRAY_SIZE(noPred); ++i) opInfo[noPred[i]].predicate = 0; - for (i = 0; i < sizeof(_initProps) / sizeof(_initProps[0]); ++i) { - const struct opProperties *prop = &_initProps[i]; - - for (int s = 0; s < 3; ++s) { - if (prop->mNeg & (1 << s)) - opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NEG; - if (prop->mAbs & (1 << s)) - opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_ABS; - if (prop->mNot & (1 << s)) - opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NOT; - if (prop->fConst & (1 << s)) - opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_MEMORY_CONST; - if (prop->fImmd & (1 << s)) - opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_IMMEDIATE; - if (prop->fImmd & 8) - opInfo[prop->op].immdBits = 0xffffffff; - } - if (prop->mSat & 8) - opInfo[prop->op].dstMods = NV50_IR_MOD_SAT; - } + initProps(_initProps, ARRAY_SIZE(_initProps)); + if (chipset >= NVISA_GM107_CHIPSET) + initProps(_initPropsGM107, ARRAY_SIZE(_initPropsGM107)); + else if (chipset >= NVISA_GK104_CHIPSET) + initProps(_initPropsNVE4, ARRAY_SIZE(_initPropsNVE4)); } unsigned int TargetNVC0::getFileSize(DataFile file) const { + const unsigned int gprs = (chipset >= NVISA_GK20A_CHIPSET) ? 255 : 63; + const unsigned int smregs = (chipset >= NVISA_GK104_CHIPSET) ? 65536 : 32768; switch (file) { case FILE_NULL: return 0; - case FILE_GPR: return (chipset >= NVISA_GK20A_CHIPSET) ? 255 : 63; + case FILE_GPR: return MIN2(gprs, smregs / threads); case FILE_PREDICATE: return 7; case FILE_FLAGS: return 1; case FILE_ADDRESS: return 0; @@ -248,6 +277,7 @@ TargetNVC0::getFileSize(DataFile file) const case FILE_MEMORY_CONST: return 65536; case FILE_SHADER_INPUT: return 0x400; case FILE_SHADER_OUTPUT: return 0x400; + case FILE_MEMORY_BUFFER: return 0xffffffff; case FILE_MEMORY_GLOBAL: return 0xffffffff; case FILE_MEMORY_SHARED: return 16 << 10; case FILE_MEMORY_LOCAL: return 48 << 10; @@ -292,6 +322,7 @@ TargetNVC0::getSVAddress(DataFile shaderFile, const Symbol *sym) const case SV_NTID: return kepler ? (0x00 + idx * 4) : ~0; case SV_NCTAID: return kepler ? (0x0c + idx * 4) : ~0; case SV_GRIDID: return kepler ? 0x18 : ~0; + case SV_WORK_DIM: return 0x1c; case SV_SAMPLE_INDEX: return 0; case SV_SAMPLE_POS: return 0; case SV_SAMPLE_MASK: return 0; @@ -323,20 +354,45 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s, // indirect loads can only be done by OP_LOAD/VFETCH/INTERP on nvc0 if (ld->src(0).isIndirect(0)) return false; + // these are implemented using shf.r and shf.l which can't load consts + if ((i->op == OP_SHL || i->op == OP_SHR) && typeSizeof(i->sType) == 8 && + sf == FILE_MEMORY_CONST) + return false; + // constant buffer loads can't be used with cbcc xmads + if (i->op == OP_XMAD && sf == FILE_MEMORY_CONST && + (i->subOp & NV50_IR_SUBOP_XMAD_CMODE_MASK) == NV50_IR_SUBOP_XMAD_CBCC) + return false; + // constant buffer loads for the third operand can't be used with psl/mrg xmads + if (i->op == OP_XMAD && sf == FILE_MEMORY_CONST && s == 2 && + (i->subOp & (NV50_IR_SUBOP_XMAD_PSL | NV50_IR_SUBOP_XMAD_MRG))) + return false; + // for xmads, immediates can't have the h1 flag set + if (i->op == OP_XMAD && sf == FILE_IMMEDIATE && s < 2 && + i->subOp & NV50_IR_SUBOP_XMAD_H1(s)) + return false; for (int k = 0; i->srcExists(k); ++k) { if (i->src(k).getFile() == FILE_IMMEDIATE) { if (k == 2 && i->op == OP_SUCLAMP) // special case continue; + if (k == 1 && i->op == OP_SHLADD) // special case + continue; if (i->getSrc(k)->reg.data.u64 != 0) return false; } else if (i->src(k).getFile() != FILE_GPR && - i->src(k).getFile() != FILE_PREDICATE) { + i->src(k).getFile() != FILE_PREDICATE && + i->src(k).getFile() != FILE_FLAGS) { return false; } } + // only loads can do sub 4 byte addressing + if (sf == FILE_MEMORY_CONST && + (ld->getSrc(0)->reg.data.offset & 0x3) + && i->op != OP_LOAD) + return false; + // not all instructions support full 32 bit immediates if (sf == FILE_IMMEDIATE) { Storage ® = ld->getSrc(0)->asImm()->reg; @@ -356,6 +412,9 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s, // with u32, 0xfffff counts as 0xffffffff as well if (reg.data.s32 > 0x7ffff || reg.data.s32 < -0x80000) return false; + // XMADs can only have 16-bit immediates + if (i->op == OP_XMAD && reg.data.u32 > 0xffff) + return false; break; case TYPE_U8: case TYPE_S8: @@ -367,12 +426,6 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s, return false; } } else - if (i->op == OP_MAD || i->op == OP_FMA) { - // requires src == dst, cannot decide before RA - // (except if we implement more constraints) - if (ld->getSrc(0)->asImm()->reg.data.u32 & 0xfff) - return false; - } else if (i->op == OP_ADD && i->sType == TYPE_F32) { // add f32 LIMM cannot saturate if (i->saturate && (reg.data.u32 & 0xfff)) @@ -387,6 +440,7 @@ bool TargetNVC0::insnCanLoadOffset(const Instruction *insn, int s, int offset) const { const ValueRef& ref = insn->src(s); + offset += insn->src(s).get()->reg.data.offset; if (ref.getFile() == FILE_MEMORY_CONST && (insn->op != OP_LOAD || insn->subOp != NV50_IR_SUBOP_LDC_IS)) return offset >= -0x8000 && offset < 0x8000; @@ -398,8 +452,13 @@ TargetNVC0::isAccessSupported(DataFile file, DataType ty) const { if (ty == TYPE_NONE) return false; - if (file == FILE_MEMORY_CONST && getChipset() >= 0xe0) // wrong encoding ? - return typeSizeof(ty) <= 8; + if (file == FILE_MEMORY_CONST) { + if (getChipset() >= NVISA_GM107_CHIPSET) + return typeSizeof(ty) <= 4; + else + if (getChipset() >= NVISA_GK104_CHIPSET) // wrong encoding ? + return typeSizeof(ty) <= 8; + } if (ty == TYPE_B96) return false; return true; @@ -412,6 +471,8 @@ TargetNVC0::isOpSupported(operation op, DataType ty) const return false; if (op == OP_POW || op == OP_SQRT || op == OP_DIV || op == OP_MOD) return false; + if (op == OP_XMAD) + return false; return true; } @@ -431,6 +492,7 @@ TargetNVC0::isModSupported(const Instruction *insn, int s, Modifier mod) const case OP_XOR: case OP_POPCNT: case OP_BFIND: + case OP_XMAD: break; case OP_SET: if (insn->sType != TYPE_F32) @@ -446,6 +508,12 @@ TargetNVC0::isModSupported(const Instruction *insn, int s, Modifier mod) const if (s == 0) return insn->src(1).mod.neg() ? false : true; break; + case OP_SHLADD: + if (s == 1) + return false; + if (insn->src(s ? 0 : 2).mod.neg()) + return false; + break; default: return false; } @@ -611,20 +679,36 @@ bool TargetNVC0::canDualIssue(const Instruction *a, const Instruction *b) const // not if the 2nd instruction isn't necessarily executed if (clA == OPCLASS_TEXTURE || clA == OPCLASS_FLOW) return false; + + // Check that a and b don't write to the same sources, nor that b reads + // anything that a writes. + if (!a->canCommuteDefDef(b) || !a->canCommuteDefSrc(b)) + return false; + // anything with MOV if (a->op == OP_MOV || b->op == OP_MOV) return true; if (clA == clB) { - // only F32 arith or integer additions - if (clA != OPCLASS_ARITH) + switch (clA) { + // there might be more + case OPCLASS_COMPARE: + if ((a->op == OP_MIN || a->op == OP_MAX) && + (b->op == OP_MIN || b->op == OP_MAX)) + break; + return false; + case OPCLASS_ARITH: + break; + default: return false; + } + // only F32 arith or integer additions return (a->dType == TYPE_F32 || a->op == OP_ADD || b->dType == TYPE_F32 || b->op == OP_ADD); } // nothing with TEXBAR if (a->op == OP_TEXBAR || b->op == OP_TEXBAR) return false; - // no loads and stores accessing the the same space + // no loads and stores accessing the same space if ((clA == OPCLASS_LOAD && clB == OPCLASS_STORE) || (clB == OPCLASS_LOAD && clA == OPCLASS_STORE)) if (a->src(0).getFile() == b->src(0).getFile())