[llvm] [DirectX][SPIR-V] Fix `copysign` backend lowering (PR #217421)
Kaitlin Peng via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 11:57:43 PDT 2026
================
@@ -1065,20 +1065,41 @@ static Value *expandCopySignIntrinsic(CallInst *Orig) {
IRBuilder<> Builder(Orig);
- unsigned BitWidth = Ty->getScalarSizeInBits();
+ bool IsDouble = Ty->getScalarType()->isDoubleTy();
+ unsigned BitWidth = IsDouble ? 32 : Ty->getScalarSizeInBits();
Type *IntTy = Ty->getWithNewType(Builder.getIntNTy(BitWidth));
- // `ConstantInt::get` broadcasts to a splat when `IntTy` is a vector.
- APInt SignMaskVal = APInt::getSignMask(BitWidth);
- Constant *SignMask = ConstantInt::get(IntTy, SignMaskVal);
- Constant *NotSignMask = ConstantInt::get(IntTy, ~SignMaskVal);
+ auto CopySignBit = [&](Value *MagnitudeInt, Value *SignInt) {
+ APInt SignMaskVal = APInt::getSignMask(BitWidth);
+ // `ConstantInt::get` broadcasts to a splat when `IntTy` is a vector.
+ Constant *SignMask = ConstantInt::get(IntTy, SignMaskVal);
+ Constant *NotSignMask = ConstantInt::get(IntTy, ~SignMaskVal);
+
+ Value *MagnitudeBits = Builder.CreateAnd(MagnitudeInt, NotSignMask);
+ Value *SignBits = Builder.CreateAnd(SignInt, SignMask);
+ return Builder.CreateOr(MagnitudeBits, SignBits);
+ };
+
+ // Avoid i64 bitwise ops, which require the Int64Ops shader feature.
+ if (IsDouble) {
----------------
kmpeng wrote:
What metadata did you have in mind? My understanding is Int64Ops isn't a declared capability, it only seems to exist after being computed on the final IR by scanning for i64 instructions. We could do the scan/computation ourselves here, but it would become circular since the i64 we'd emit for copysign would set Int64Ops.
Or did you mean just gating on whether int64 is supported? In that case though we still run into the problem of the Int64Ops requirement being set on shaders that only need doubles.
https://github.com/llvm/llvm-project/pull/217421
More information about the llvm-commits
mailing list