[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