|
28 | 28 | #include "llvm/CodeGen/MachineInstrBuilder.h"
|
29 | 29 | #include "llvm/CodeGen/MachineModuleInfoImpls.h"
|
30 | 30 | #include "llvm/CodeGen/MachineRegisterInfo.h"
|
| 31 | +#include "llvm/CodeGen/Register.h" |
31 | 32 | #include "llvm/CodeGen/TargetOpcodes.h"
|
32 | 33 | #include "llvm/IR/IntrinsicsSPIRV.h"
|
33 | 34 | #include "llvm/Support/Debug.h"
|
@@ -178,6 +179,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
|
178 | 179 | bool selectRsqrt(Register ResVReg, const SPIRVType *ResType,
|
179 | 180 | MachineInstr &I) const;
|
180 | 181 |
|
| 182 | + bool selectSign(Register ResVReg, const SPIRVType *ResType, |
| 183 | + MachineInstr &I) const; |
| 184 | + |
181 | 185 | void renderImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
|
182 | 186 | int OpIdx) const;
|
183 | 187 | void renderFImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
|
@@ -1366,6 +1370,52 @@ bool SPIRVInstructionSelector::selectRsqrt(Register ResVReg,
|
1366 | 1370 | .constrainAllUses(TII, TRI, RBI);
|
1367 | 1371 | }
|
1368 | 1372 |
|
| 1373 | +bool SPIRVInstructionSelector::selectSign(Register ResVReg, |
| 1374 | + const SPIRVType *ResType, |
| 1375 | + MachineInstr &I) const { |
| 1376 | + assert(I.getNumOperands() == 3); |
| 1377 | + assert(I.getOperand(2).isReg()); |
| 1378 | + MachineBasicBlock &BB = *I.getParent(); |
| 1379 | + Register InputRegister = I.getOperand(2).getReg(); |
| 1380 | + SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister); |
| 1381 | + auto &DL = I.getDebugLoc(); |
| 1382 | + |
| 1383 | + if (!InputType) |
| 1384 | + report_fatal_error("Input Type could not be determined."); |
| 1385 | + |
| 1386 | + bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat); |
| 1387 | + |
| 1388 | + unsigned SignBitWidth = GR.getScalarOrVectorBitWidth(InputType); |
| 1389 | + unsigned ResBitWidth = GR.getScalarOrVectorBitWidth(ResType); |
| 1390 | + |
| 1391 | + bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth; |
| 1392 | + |
| 1393 | + auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign; |
| 1394 | + Register SignReg = NeedsConversion |
| 1395 | + ? MRI->createVirtualRegister(&SPIRV::IDRegClass) |
| 1396 | + : ResVReg; |
| 1397 | + |
| 1398 | + bool Result = |
| 1399 | + BuildMI(BB, I, DL, TII.get(SPIRV::OpExtInst)) |
| 1400 | + .addDef(SignReg) |
| 1401 | + .addUse(GR.getSPIRVTypeID(InputType)) |
| 1402 | + .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450)) |
| 1403 | + .addImm(SignOpcode) |
| 1404 | + .addUse(InputRegister) |
| 1405 | + .constrainAllUses(TII, TRI, RBI); |
| 1406 | + |
| 1407 | + if (NeedsConversion) { |
| 1408 | + auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert; |
| 1409 | + Result |= BuildMI(*I.getParent(), I, DL, TII.get(ConvertOpcode)) |
| 1410 | + .addDef(ResVReg) |
| 1411 | + .addUse(GR.getSPIRVTypeID(ResType)) |
| 1412 | + .addUse(SignReg) |
| 1413 | + .constrainAllUses(TII, TRI, RBI); |
| 1414 | + } |
| 1415 | + |
| 1416 | + return Result; |
| 1417 | +} |
| 1418 | + |
1369 | 1419 | bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
|
1370 | 1420 | const SPIRVType *ResType,
|
1371 | 1421 | MachineInstr &I) const {
|
@@ -2082,6 +2132,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
|
2082 | 2132 | return selectFrac(ResVReg, ResType, I);
|
2083 | 2133 | case Intrinsic::spv_rsqrt:
|
2084 | 2134 | return selectRsqrt(ResVReg, ResType, I);
|
| 2135 | + case Intrinsic::spv_sign: |
| 2136 | + return selectSign(ResVReg, ResType, I); |
2085 | 2137 | case Intrinsic::spv_lifetime_start:
|
2086 | 2138 | case Intrinsic::spv_lifetime_end: {
|
2087 | 2139 | unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
|
|
0 commit comments