From a211c92c4bf0582e5988a38d85cd6ef273e926da Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 3 Jan 2018 15:31:15 +0100 Subject: [PATCH] nv50/ir: add lowering helper if we start supporting multiple input IRs we might want to move lowering code into a common place and keep the initial translation simplier. This will also allows us to react on ISA changes more easily. v5: also handle SAT v6: rename type variables fixed lowering of NEG add lowering of NOT v8: don't require C++11 features Signed-off-by: Karol Herbst Reviewed-by: Pierre Moreau --- src/gallium/drivers/nouveau/Makefile.sources | 2 + .../codegen/nv50_ir_lowering_helper.cpp | 275 ++++++++++++++++++ .../nouveau/codegen/nv50_ir_lowering_helper.h | 53 ++++ src/gallium/drivers/nouveau/meson.build | 2 + 4 files changed, 332 insertions(+) create mode 100644 src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.cpp create mode 100644 src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.h diff --git a/src/gallium/drivers/nouveau/Makefile.sources b/src/gallium/drivers/nouveau/Makefile.sources index fee5e59522e..ec344c63169 100644 --- a/src/gallium/drivers/nouveau/Makefile.sources +++ b/src/gallium/drivers/nouveau/Makefile.sources @@ -122,6 +122,8 @@ NV50_CODEGEN_SOURCES := \ codegen/nv50_ir_graph.h \ codegen/nv50_ir.h \ codegen/nv50_ir_inlines.h \ + codegen/nv50_ir_lowering_helper.cpp \ + codegen/nv50_ir_lowering_helper.h \ codegen/nv50_ir_lowering_nv50.cpp \ codegen/nv50_ir_peephole.cpp \ codegen/nv50_ir_print.cpp \ diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.cpp new file mode 100644 index 00000000000..02380f12b9f --- /dev/null +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.cpp @@ -0,0 +1,275 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Karol Herbst + */ + +#include "codegen/nv50_ir_lowering_helper.h" + +namespace nv50_ir { + +bool +LoweringHelper::visit(Instruction *insn) +{ + switch (insn->op) { + case OP_ABS: + return handleABS(insn); + case OP_CVT: + return handleCVT(insn); + case OP_MAX: + case OP_MIN: + return handleMAXMIN(insn); + case OP_MOV: + return handleMOV(insn); + case OP_NEG: + return handleNEG(insn); + case OP_SAT: + return handleSAT(insn); + case OP_SLCT: + return handleSLCT(insn->asCmp()); + case OP_AND: + case OP_NOT: + case OP_OR: + case OP_XOR: + return handleLogOp(insn); + default: + return true; + } +} + +bool +LoweringHelper::handleABS(Instruction *insn) +{ + DataType dTy = insn->dType; + if (!(dTy == TYPE_U64 || dTy == TYPE_S64)) + return true; + + bld.setPosition(insn, false); + + Value *neg = bld.getSSA(8); + Value *negComp[2], *srcComp[2]; + Value *lo = bld.getSSA(), *hi = bld.getSSA(); + bld.mkOp2(OP_SUB, dTy, neg, bld.mkImm((uint64_t)0), insn->getSrc(0)); + bld.mkSplit(negComp, 4, neg); + bld.mkSplit(srcComp, 4, insn->getSrc(0)); + bld.mkCmp(OP_SLCT, CC_LT, TYPE_S32, lo, TYPE_S32, negComp[0], srcComp[0], srcComp[1]); + bld.mkCmp(OP_SLCT, CC_LT, TYPE_S32, hi, TYPE_S32, negComp[1], srcComp[1], srcComp[1]); + insn->op = OP_MERGE; + insn->setSrc(0, lo); + insn->setSrc(1, hi); + + return true; +} + +bool +LoweringHelper::handleCVT(Instruction *insn) +{ + DataType dTy = insn->dType; + DataType sTy = insn->sType; + + if (typeSizeof(dTy) <= 4 && typeSizeof(sTy) <= 4) + return true; + + bld.setPosition(insn, false); + + if ((dTy == TYPE_S32 && sTy == TYPE_S64) || + (dTy == TYPE_U32 && sTy == TYPE_U64)) { + Value *src[2]; + bld.mkSplit(src, 4, insn->getSrc(0)); + insn->op = OP_MOV; + insn->setSrc(0, src[0]); + } else if (dTy == TYPE_S64 && sTy == TYPE_S32) { + Value *tmp = bld.getSSA(); + bld.mkOp2(OP_SHR, TYPE_S32, tmp, insn->getSrc(0), bld.loadImm(bld.getSSA(), 31)); + insn->op = OP_MERGE; + insn->setSrc(1, tmp); + } else if (dTy == TYPE_U64 && sTy == TYPE_U32) { + insn->op = OP_MERGE; + insn->setSrc(1, bld.loadImm(bld.getSSA(), 0)); + } + + return true; +} + +bool +LoweringHelper::handleMAXMIN(Instruction *insn) +{ + DataType dTy = insn->dType; + if (!(dTy == TYPE_U64 || dTy == TYPE_S64)) + return true; + + DataType sTy = typeOfSize(4, false, isSignedIntType(dTy)); + bld.setPosition(insn, false); + + Value *flag = bld.getSSA(1, FILE_FLAGS); + Value *src0[2]; + Value *src1[2]; + Value *def[2]; + + bld.mkSplit(src0, 4, insn->getSrc(0)); + bld.mkSplit(src1, 4, insn->getSrc(1)); + + def[0] = bld.getSSA(); + def[1] = bld.getSSA(); + + Instruction *hi = bld.mkOp2(insn->op, sTy, def[1], src0[1], src1[1]); + hi->subOp = NV50_IR_SUBOP_MINMAX_HIGH; + hi->setFlagsDef(1, flag); + + Instruction *lo = bld.mkOp2(insn->op, sTy, def[0], src0[0], src1[0]); + lo->subOp = NV50_IR_SUBOP_MINMAX_LOW; + lo->setFlagsSrc(2, flag); + + insn->op = OP_MERGE; + insn->setSrc(0, def[0]); + insn->setSrc(1, def[1]); + + return true; +} + +bool +LoweringHelper::handleMOV(Instruction *insn) +{ + DataType dTy = insn->dType; + + if (typeSizeof(dTy) != 8) + return true; + + Storage ® = insn->getSrc(0)->reg; + + if (reg.file != FILE_IMMEDIATE) + return true; + + bld.setPosition(insn, false); + + Value *hi = bld.getSSA(); + Value *lo = bld.getSSA(); + + bld.loadImm(lo, (uint32_t)(reg.data.u64 & 0xffffffff)); + bld.loadImm(hi, (uint32_t)(reg.data.u64 >> 32)); + + insn->op = OP_MERGE; + insn->setSrc(0, lo); + insn->setSrc(1, hi); + + return true; +} + +bool +LoweringHelper::handleNEG(Instruction *insn) +{ + if (typeSizeof(insn->dType) != 8 || isFloatType(insn->dType)) + return true; + + bld.setPosition(insn, false); + + insn->op = OP_SUB; + insn->setSrc(1, insn->getSrc(0)); + insn->setSrc(0, bld.mkImm((uint64_t)0)); + return true; +} + +bool +LoweringHelper::handleSAT(Instruction *insn) +{ + DataType dTy = insn->dType; + + if (typeSizeof(dTy) != 8 || !isFloatType(dTy)) + return true; + + bld.setPosition(insn, false); + + Value *tmp = bld.mkOp2v(OP_MAX, dTy, bld.getSSA(8), insn->getSrc(0), bld.loadImm(bld.getSSA(8), 0.0)); + insn->op = OP_MIN; + insn->setSrc(0, tmp); + insn->setSrc(1, bld.loadImm(bld.getSSA(8), 1.0)); + return true; +} + +bool +LoweringHelper::handleSLCT(CmpInstruction *insn) +{ + DataType dTy = insn->dType; + DataType sTy = insn->sType; + + if (typeSizeof(dTy) != 8 || typeSizeof(sTy) == 8) + return true; + + CondCode cc = insn->getCondition(); + DataType hdTy = typeOfSize(4, isFloatType(dTy), isSignedIntType(dTy)); + bld.setPosition(insn, false); + + Value *src0[2]; + Value *src1[2]; + Value *def[2]; + + bld.mkSplit(src0, 4, insn->getSrc(0)); + bld.mkSplit(src1, 4, insn->getSrc(1)); + + def[0] = bld.getSSA(); + def[1] = bld.getSSA(); + + bld.mkCmp(OP_SLCT, cc, hdTy, def[0], sTy, src0[0], src1[0], insn->getSrc(2)); + bld.mkCmp(OP_SLCT, cc, hdTy, def[1], sTy, src0[1], src1[1], insn->getSrc(2)); + + insn->op = OP_MERGE; + insn->setSrc(0, def[0]); + insn->setSrc(1, def[1]); + insn->setSrc(2, NULL); + + return true; +} + +bool +LoweringHelper::handleLogOp(Instruction *insn) +{ + DataType dTy = insn->dType; + DataType sTy = typeOfSize(4, isFloatType(dTy), isSignedIntType(dTy)); + + if (typeSizeof(dTy) != 8) + return true; + + bld.setPosition(insn, false); + + Value *src0[2]; + Value *src1[2]; + Value *def0 = bld.getSSA(); + Value *def1 = bld.getSSA(); + + bld.mkSplit(src0, 4, insn->getSrc(0)); + if (insn->srcExists(1)) + bld.mkSplit(src1, 4, insn->getSrc(1)); + + Instruction *lo = bld.mkOp1(insn->op, sTy, def0, src0[0]); + Instruction *hi = bld.mkOp1(insn->op, sTy, def1, src0[1]); + if (insn->srcExists(1)) { + lo->setSrc(1, src1[0]); + hi->setSrc(1, src1[1]); + } + + insn->op = OP_MERGE; + insn->setSrc(0, def0); + insn->setSrc(1, def1); + + return true; +} + +} // namespace nv50_ir diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.h new file mode 100644 index 00000000000..c59e7cc6f3f --- /dev/null +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_helper.h @@ -0,0 +1,53 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Karol Herbst + */ + +#ifndef __NV50_IR_LOWERING_HELPER__ +#define __NV50_IR_LOWERING_HELPER__ + +#include "codegen/nv50_ir.h" +#include "codegen/nv50_ir_build_util.h" + +namespace nv50_ir { + +class LoweringHelper : public Pass +{ +private: + virtual bool visit(Instruction *); + + BuildUtil bld; +public: + bool handleABS(Instruction *); + bool handleCVT(Instruction *); + bool handleMAXMIN(Instruction *); + bool handleMOV(Instruction *); + bool handleNEG(Instruction *); + bool handleSAT(Instruction *); + bool handleSLCT(CmpInstruction *); + + bool handleLogOp(Instruction *); +}; + +} // namespace nv50_ir + +#endif // __NV50_IR_LOWERING_HELPER__ diff --git a/src/gallium/drivers/nouveau/meson.build b/src/gallium/drivers/nouveau/meson.build index 4558c5810c1..aff1b62436c 100644 --- a/src/gallium/drivers/nouveau/meson.build +++ b/src/gallium/drivers/nouveau/meson.build @@ -136,6 +136,8 @@ files_libnouveau = files( 'codegen/nv50_ir_graph.h', 'codegen/nv50_ir.h', 'codegen/nv50_ir_inlines.h', + 'codegen/nv50_ir_lowering_helper.cpp', + 'codegen/nv50_ir_lowering_helper.h', 'codegen/nv50_ir_lowering_nv50.cpp', 'codegen/nv50_ir_peephole.cpp', 'codegen/nv50_ir_print.cpp', -- 2.30.2