[llvm] [DirectX][SPIR-V] Fix `copysign` backend lowering (PR #217421)

Deric C. via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 17:18:52 PDT 2026


================
@@ -1055,6 +1056,31 @@ static Value *expandSignIntrinsic(CallInst *Orig) {
   return Builder.CreateSub(ZextGT, ZextLT);
 }
 
+// Expand llvm.copysign by combining the sign bit with the magnitude bits using
+// bitwise operations.
+static Value *expandCopySignIntrinsic(CallInst *Orig) {
+  Value *Magnitude = Orig->getOperand(0);
+  Value *Sign = Orig->getOperand(1);
+  Type *Ty = Orig->getType();
+
+  IRBuilder<> Builder(Orig);
+
+  unsigned BitWidth = 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);
+
+  Value *MagnitudeInt = Builder.CreateBitCast(Magnitude, IntTy);
+  Value *SignInt = Builder.CreateBitCast(Sign, IntTy);
+  Value *MagnitudeBits = Builder.CreateAnd(MagnitudeInt, NotSignMask);
+  Value *SignBits = Builder.CreateAnd(SignInt, SignMask);
+  Value *Result = Builder.CreateOr(MagnitudeBits, SignBits);
+  return Builder.CreateBitCast(Result, Ty);
----------------
Icohedron wrote:

Lowering `copysign` on `double` via i64 bit ops changes the shader's feature requirements. 

https://hlsl.godbolt.org/z/r7Kdrf1Wd

So a shader that only uses doubles now also demands the Int64Ops feature (D3D12 Int64ShaderOps device support). 

DXC deliberately avoids this by lowering `asuint(double)` with the use of `splitdouble` and `asdouble`.

https://github.com/llvm/llvm-project/pull/217421


More information about the llvm-commits mailing list