[llvm] [DirectX][SPIR-V] Fix `copysign` backend lowering (PR #217421)
Farzon Lotfi via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 11:42:27 PDT 2026
================
@@ -1575,6 +1578,57 @@ bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
return false;
}
+bool SPIRVInstructionSelector::selectCopySign(Register ResVReg,
+ SPIRVTypeInst ResType,
+ MachineInstr &I) const {
+ if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std))
+ return selectExtInst(ResVReg, ResType, I, CL::copysign);
+
+ // There is no copysign instruction in the GLSL Extended Instruction set, so
+ // it is implemented with bit manipulation:
+ // bitcast((bitcast(magnitude) & ~signBit) | (bitcast(sign) & signBit))
+ Register MagnitudeReg = I.getOperand(1).getReg();
+ Register SignReg = I.getOperand(2).getReg();
+
+ const unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
+ const unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
+ const bool IsVector = ComponentCount > 1;
+
+ SPIRVTypeInst IntType = GR.getOrCreateSPIRVIntegerType(BitWidth, I, TII);
+ if (IsVector)
+ IntType = GR.getOrCreateSPIRVVectorType(IntType, ComponentCount, I, TII);
+
+ const APInt SignMaskVal = APInt::getSignMask(BitWidth);
+ Register SignMask =
+ IsVector ? GR.getOrCreateConstVector(SignMaskVal, I, IntType, TII)
+ : GR.getOrCreateConstInt(SignMaskVal, I, IntType, TII);
+ Register NotSignMask =
+ IsVector ? GR.getOrCreateConstVector(~SignMaskVal, I, IntType, TII)
+ : GR.getOrCreateConstInt(~SignMaskVal, I, IntType, TII);
+
+ const unsigned AndOpcode =
+ IsVector ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
+ const unsigned OrOpcode =
+ IsVector ? SPIRV::OpBitwiseOrV : SPIRV::OpBitwiseOrS;
+
+ Register MagnitudeInt = MRI->createVirtualRegister(GR.getRegClass(IntType));
+ Register SignInt = MRI->createVirtualRegister(GR.getRegClass(IntType));
+ Register MagnitudeBits = MRI->createVirtualRegister(GR.getRegClass(IntType));
+ Register SignBits = MRI->createVirtualRegister(GR.getRegClass(IntType));
+ Register ResInt = MRI->createVirtualRegister(GR.getRegClass(IntType));
+
+ if (!selectOpWithSrcs(MagnitudeInt, IntType, I, {MagnitudeReg},
+ SPIRV::OpBitcast) ||
----------------
farzonl wrote:
maybe we should be doing this in stages so we don't have to create the SignInt register if the first selectOpWithSrcs of MagnitudeInt comes back making us hit this condition. The way this is written we don't have the ability to short circuit for register creation.
https://github.com/llvm/llvm-project/pull/217421
More information about the llvm-commits
mailing list