[llvm] [DirectX] Add lowering support for `llvm.fsh[l|r].*` (PR #170570)

Finn Plummer via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 11 13:22:01 PST 2025


================
@@ -656,6 +659,32 @@ static Value *expandAtan2Intrinsic(CallInst *Orig) {
   return Result;
 }
 
+template <bool LeftFunnel>
+static Value *expandFunnelShiftIntrinsic(CallInst *Orig) {
+  Type *Ty = Orig->getType();
+  Value *A = Orig->getOperand(0);
+  Value *B = Orig->getOperand(1);
+  Value *Shift = Orig->getOperand(2);
+
+  IRBuilder<> Builder(Orig);
+
+  unsigned BitWidth = Ty->getScalarSizeInBits();
+  Constant *Mask = ConstantInt::get(Ty, BitWidth - 1);
+  Constant *Size = ConstantInt::get(Ty, BitWidth);
+
+  // The shift is not required to be masked as DXIL op will do so automatically
+  Value *Left =
+      LeftFunnel ? Builder.CreateShl(A, Shift) : Builder.CreateLShr(B, Shift);
+
+  Value *MaskedShift = Builder.CreateAnd(Shift, Mask);
+  Value *InverseShift = Builder.CreateSub(Size, MaskedShift);
+  Value *Right = LeftFunnel ? Builder.CreateLShr(B, InverseShift)
+                            : Builder.CreateShl(A, InverseShift);
----------------
inbelic wrote:

Good catch, thanks!

We do need to handle the case when it is 0 with a dynamic or static variable, and as pointed out this was missing.

I have updated the implementation to follow the lowering as used in GlobalISel, [here](https://github.com/llvm/llvm-project/blob/71ee84acc4f7c93b9292af90ef5d79dd05687410/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp#L7831). Which accounts for this by creating two shifts of valid amounts.

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


More information about the llvm-commits mailing list