[llvm] 53ec484 - [SelectionDAG] Add CTLS to FoldConstantArithmetic and optimize i1 CTLS to 0. (#178552)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 29 08:00:14 PST 2026


Author: Craig Topper
Date: 2026-01-29T08:00:10-08:00
New Revision: 53ec484ebf6c1b08c68bb449c728f8845fecf7d7

URL: https://github.com/llvm/llvm-project/commit/53ec484ebf6c1b08c68bb449c728f8845fecf7d7
DIFF: https://github.com/llvm/llvm-project/commit/53ec484ebf6c1b08c68bb449c728f8845fecf7d7.diff

LOG: [SelectionDAG] Add CTLS to FoldConstantArithmetic and optimize i1 CTLS to 0. (#178552)

Since we don't have a CTLS intrinsic, it likely gets constant folded
while it is still a CTLZ pattern so I'm using a unittest to test it.

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index b92b35feb53e3..349a3fbd41b9c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6559,6 +6559,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
   case ISD::CTTZ:
   case ISD::CTTZ_ZERO_UNDEF:
   case ISD::CTPOP:
+  case ISD::CTLS:
   case ISD::STEP_VECTOR: {
     SDValue Ops = {N1};
     if (SDValue Fold = FoldConstantArithmetic(Opcode, DL, VT, Ops))
@@ -6844,6 +6845,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
     if (N1.getValueType().getScalarType() == MVT::i1)
       return getNOT(DL, N1, N1.getValueType());
     break;
+  case ISD::CTLS:
+    if (N1.getValueType().getScalarType() == MVT::i1)
+      return getConstant(0, DL, VT);
+    break;
   case ISD::VECREDUCE_ADD:
     if (N1.getValueType().getScalarType() == MVT::i1)
       return getNode(ISD::VECREDUCE_XOR, DL, VT, N1);
@@ -7094,6 +7099,10 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
       case ISD::CTTZ_ZERO_UNDEF:
         return getConstant(Val.countr_zero(), DL, VT, C->isTargetOpcode(),
                            C->isOpaque());
+      case ISD::CTLS:
+        // CTLS returns the number of extra sign bits so subtract one.
+        return getConstant(Val.getNumSignBits() - 1, DL, VT,
+                           C->isTargetOpcode(), C->isOpaque());
       case ISD::UINT_TO_FP:
       case ISD::SINT_TO_FP: {
         APFloat FPV(VT.getFltSemantics(), APInt::getZero(VT.getSizeInBits()));

diff  --git a/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp b/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
index b2c1420215c3f..a99f10c522fed 100644
--- a/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
@@ -315,3 +315,26 @@ TEST_F(SelectionDAGNodeConstructionTest, XOR) {
   EXPECT_EQ(DAG->getNode(ISD::XOR, DL, MVT::i32, Undef, Op), Undef);
   EXPECT_EQ(DAG->getNode(ISD::XOR, DL, MVT::i32, Undef, Undef), Zero);
 }
+
+TEST_F(SelectionDAGNodeConstructionTest, CTLS) {
+  SDLoc DL;
+  SDValue Zero = DAG->getConstant(0, DL, MVT::i32);
+  SDValue MaxInt = DAG->getConstant(0x7fffffff, DL, MVT::i32);
+  SDValue MinInt = DAG->getConstant(0x80000000, DL, MVT::i32);
+  SDValue MinShort = DAG->getConstant(0xffff8000, DL, MVT::i32);
+
+  SDValue CtlsZero = DAG->getNode(ISD::CTLS, DL, MVT::i32, Zero);
+  SDValue CtlsMinInt = DAG->getNode(ISD::CTLS, DL, MVT::i32, MinInt);
+  SDValue CtlsMaxInt = DAG->getNode(ISD::CTLS, DL, MVT::i32, MaxInt);
+  SDValue CtlsMinShort = DAG->getNode(ISD::CTLS, DL, MVT::i32, MinShort);
+  EXPECT_TRUE(isa<ConstantSDNode>(CtlsZero) &&
+              cast<ConstantSDNode>(CtlsZero)->getZExtValue() == 31);
+  EXPECT_TRUE(isNullConstant(CtlsMinInt));
+  EXPECT_TRUE(isNullConstant(CtlsMaxInt));
+  EXPECT_TRUE(isa<ConstantSDNode>(CtlsMinShort) &&
+              cast<ConstantSDNode>(CtlsMinShort)->getZExtValue() == 16);
+
+  SDValue i1Op = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, MVT::i1);
+  SDValue Ctlsi1 = DAG->getNode(ISD::CTLS, DL, MVT::i32, i1Op);
+  EXPECT_TRUE(isNullConstant(Ctlsi1));
+}


        


More information about the llvm-commits mailing list