[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);
----------------
Icohedron wrote:

The `bitcast half <-> i16` is rejected by the DXIL validator unless the module is in native 16-bit mode.
This isn't an issue with Clang today because a `half` without `-enable-16-bit-types` is just a float.
However, if we ever support the `min16float` type then this will be a validation error with a shader like: https://hlsl.godbolt.org/z/1ns1YPdY4 

Suggestion: when the scalar type is 16-bit and native low precision is off, promote to f32 (`fpext` -> 32-bit bit trick -> `fptrunc`), or just bail out with a diagnostic.

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


More information about the llvm-commits mailing list