1/* 2 * Copyright 2018 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Karol Herbst <kherbst@redhat.com> 23 */ 24 25#include "nv50_ir_lowering_helper.h" 26 27namespace nv50_ir { 28 29bool 30LoweringHelper::visit(Instruction *insn) 31{ 32 switch (insn->op) { 33 case OP_ABS: 34 return handleABS(insn); 35 case OP_CVT: 36 return handleCVT(insn); 37 case OP_MAX: 38 case OP_MIN: 39 return handleMAXMIN(insn); 40 case OP_MOV: 41 return handleMOV(insn); 42 case OP_NEG: 43 return handleNEG(insn); 44 case OP_SAT: 45 return handleSAT(insn); 46 case OP_SLCT: 47 return handleSLCT(insn->asCmp()); 48 case OP_AND: 49 case OP_NOT: 50 case OP_OR: 51 case OP_XOR: 52 return handleLogOp(insn); 53 default: 54 return true; 55 } 56} 57 58bool 59LoweringHelper::handleABS(Instruction *insn) 60{ 61 DataType dTy = insn->dType; 62 if (!(dTy == TYPE_U64 || dTy == TYPE_S64)) 63 return true; 64 65 bld.setPosition(insn, false); 66 67 Value *neg = bld.getSSA(8); 68 Value *negComp[2], *srcComp[2]; 69 Value *lo = bld.getSSA(), *hi = bld.getSSA(); 70 bld.mkOp2(OP_SUB, dTy, neg, bld.mkImm((uint64_t)0), insn->getSrc(0)); 71 bld.mkSplit(negComp, 4, neg); 72 bld.mkSplit(srcComp, 4, insn->getSrc(0)); 73 bld.mkCmp(OP_SLCT, CC_LT, TYPE_S32, lo, TYPE_S32, negComp[0], srcComp[0], srcComp[1]); 74 bld.mkCmp(OP_SLCT, CC_LT, TYPE_S32, hi, TYPE_S32, negComp[1], srcComp[1], srcComp[1]); 75 insn->op = OP_MERGE; 76 insn->setSrc(0, lo); 77 insn->setSrc(1, hi); 78 79 return true; 80} 81 82bool 83LoweringHelper::handleCVT(Instruction *insn) 84{ 85 DataType dTy = insn->dType; 86 DataType sTy = insn->sType; 87 88 if (typeSizeof(dTy) <= 4 && typeSizeof(sTy) <= 4) 89 return true; 90 91 bld.setPosition(insn, false); 92 93 if ((dTy == TYPE_S32 && sTy == TYPE_S64) || 94 (dTy == TYPE_U32 && sTy == TYPE_U64)) { 95 Value *src[2]; 96 bld.mkSplit(src, 4, insn->getSrc(0)); 97 insn->op = OP_MOV; 98 insn->setSrc(0, src[0]); 99 } else if (dTy == TYPE_S64 && sTy == TYPE_S32) { 100 Value *tmp = bld.getSSA(); 101 bld.mkOp2(OP_SHR, TYPE_S32, tmp, insn->getSrc(0), bld.loadImm(bld.getSSA(), 31)); 102 insn->op = OP_MERGE; 103 insn->setSrc(1, tmp); 104 } else if (dTy == TYPE_U64 && sTy == TYPE_U32) { 105 insn->op = OP_MERGE; 106 insn->setSrc(1, bld.loadImm(bld.getSSA(), 0)); 107 } 108 109 return true; 110} 111 112bool 113LoweringHelper::handleMAXMIN(Instruction *insn) 114{ 115 DataType dTy = insn->dType; 116 if (!(dTy == TYPE_U64 || dTy == TYPE_S64)) 117 return true; 118 119 DataType sTy = typeOfSize(4, false, isSignedIntType(dTy)); 120 bld.setPosition(insn, false); 121 122 Value *flag = bld.getSSA(1, FILE_FLAGS); 123 Value *src0[2]; 124 Value *src1[2]; 125 Value *def[2]; 126 127 bld.mkSplit(src0, 4, insn->getSrc(0)); 128 bld.mkSplit(src1, 4, insn->getSrc(1)); 129 130 def[0] = bld.getSSA(); 131 def[1] = bld.getSSA(); 132 133 Instruction *hi = bld.mkOp2(insn->op, sTy, def[1], src0[1], src1[1]); 134 hi->subOp = NV50_IR_SUBOP_MINMAX_HIGH; 135 hi->setFlagsDef(1, flag); 136 137 Instruction *lo = bld.mkOp2(insn->op, sTy, def[0], src0[0], src1[0]); 138 lo->subOp = NV50_IR_SUBOP_MINMAX_LOW; 139 lo->setFlagsSrc(2, flag); 140 141 insn->op = OP_MERGE; 142 insn->setSrc(0, def[0]); 143 insn->setSrc(1, def[1]); 144 145 return true; 146} 147 148bool 149LoweringHelper::handleMOV(Instruction *insn) 150{ 151 DataType dTy = insn->dType; 152 153 if (typeSizeof(dTy) != 8) 154 return true; 155 156 Storage ® = insn->getSrc(0)->reg; 157 158 if (reg.file != FILE_IMMEDIATE) 159 return true; 160 161 bld.setPosition(insn, false); 162 163 Value *hi = bld.getSSA(); 164 Value *lo = bld.getSSA(); 165 166 bld.loadImm(lo, (uint32_t)(reg.data.u64 & 0xffffffff)); 167 bld.loadImm(hi, (uint32_t)(reg.data.u64 >> 32)); 168 169 insn->op = OP_MERGE; 170 insn->setSrc(0, lo); 171 insn->setSrc(1, hi); 172 173 return true; 174} 175 176bool 177LoweringHelper::handleNEG(Instruction *insn) 178{ 179 if (typeSizeof(insn->dType) != 8 || isFloatType(insn->dType)) 180 return true; 181 182 bld.setPosition(insn, false); 183 184 insn->op = OP_SUB; 185 insn->setSrc(1, insn->getSrc(0)); 186 insn->setSrc(0, bld.mkImm((uint64_t)0)); 187 return true; 188} 189 190bool 191LoweringHelper::handleSAT(Instruction *insn) 192{ 193 DataType dTy = insn->dType; 194 195 if (typeSizeof(dTy) != 8 || !isFloatType(dTy)) 196 return true; 197 198 bld.setPosition(insn, false); 199 200 Value *tmp = bld.mkOp2v(OP_MAX, dTy, bld.getSSA(8), insn->getSrc(0), bld.loadImm(bld.getSSA(8), 0.0)); 201 insn->op = OP_MIN; 202 insn->setSrc(0, tmp); 203 insn->setSrc(1, bld.loadImm(bld.getSSA(8), 1.0)); 204 return true; 205} 206 207bool 208LoweringHelper::handleSLCT(CmpInstruction *insn) 209{ 210 DataType dTy = insn->dType; 211 DataType sTy = insn->sType; 212 213 if (typeSizeof(dTy) != 8 || typeSizeof(sTy) == 8) 214 return true; 215 216 CondCode cc = insn->getCondition(); 217 DataType hdTy = typeOfSize(4, isFloatType(dTy), isSignedIntType(dTy)); 218 bld.setPosition(insn, false); 219 220 Value *src0[2]; 221 Value *src1[2]; 222 Value *def[2]; 223 224 bld.mkSplit(src0, 4, insn->getSrc(0)); 225 bld.mkSplit(src1, 4, insn->getSrc(1)); 226 227 def[0] = bld.getSSA(); 228 def[1] = bld.getSSA(); 229 230 bld.mkCmp(OP_SLCT, cc, hdTy, def[0], sTy, src0[0], src1[0], insn->getSrc(2)); 231 bld.mkCmp(OP_SLCT, cc, hdTy, def[1], sTy, src0[1], src1[1], insn->getSrc(2)); 232 233 insn->op = OP_MERGE; 234 insn->setSrc(0, def[0]); 235 insn->setSrc(1, def[1]); 236 insn->setSrc(2, NULL); 237 238 return true; 239} 240 241bool 242LoweringHelper::handleLogOp(Instruction *insn) 243{ 244 DataType dTy = insn->dType; 245 DataType sTy = typeOfSize(4, isFloatType(dTy), isSignedIntType(dTy)); 246 247 if (typeSizeof(dTy) != 8) 248 return true; 249 250 bld.setPosition(insn, false); 251 252 Value *src0[2]; 253 Value *src1[2]; 254 Value *def0 = bld.getSSA(); 255 Value *def1 = bld.getSSA(); 256 257 bld.mkSplit(src0, 4, insn->getSrc(0)); 258 if (insn->srcExists(1)) 259 bld.mkSplit(src1, 4, insn->getSrc(1)); 260 261 Instruction *lo = bld.mkOp1(insn->op, sTy, def0, src0[0]); 262 Instruction *hi = bld.mkOp1(insn->op, sTy, def1, src0[1]); 263 if (insn->srcExists(1)) { 264 lo->setSrc(1, src1[0]); 265 hi->setSrc(1, src1[1]); 266 } 267 268 insn->op = OP_MERGE; 269 insn->setSrc(0, def0); 270 insn->setSrc(1, def1); 271 272 return true; 273} 274 275} // namespace nv50_ir 276