From 1532726dd6c8238fee8eef47d7357966b7c4c921 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 6 Jan 2026 10:13:36 -0800 Subject: [PATCH 1/2] Pre-commit tests --- llvm/test/CodeGen/RISCV/rv64p.ll | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll index 931771154f485..eedd98d63aed2 100644 --- a/llvm/test/CodeGen/RISCV/rv64p.ll +++ b/llvm/test/CodeGen/RISCV/rv64p.ll @@ -222,6 +222,73 @@ define i32 @cls_i32_2(i32 %x) { ret i32 %e } +; The result is in the range [1-31], so we don't need an andi after the cls. +define i32 @cls_i32_knownbits(i32 %x) { +; CHECK-LABEL: cls_i32_knownbits: +; CHECK: # %bb.0: +; CHECK-NEXT: clsw a0, a0 +; CHECK-NEXT: andi a0, a0, 31 +; CHECK-NEXT: ret + %a = ashr i32 %x, 31 + %b = xor i32 %x, %a + %c = call i32 @llvm.ctlz.i32(i32 %b, i1 false) + %d = sub i32 %c, 1 + %e = and i32 %d, 31 + ret i32 %e +} + +; There are at least 16 redundant sign bits so we don't need an ori after the clsw. +define i32 @cls_i32_knownbits_2(i16 signext %x) { +; CHECK-LABEL: cls_i32_knownbits_2: +; CHECK: # %bb.0: +; CHECK-NEXT: clsw a0, a0 +; CHECK-NEXT: ori a0, a0, 16 +; CHECK-NEXT: ret + %sext = sext i16 %x to i32 + %a = ashr i32 %sext, 31 + %b = xor i32 %sext, %a + %c = call i32 @llvm.ctlz.i32(i32 %b, i1 false) + %d = sub i32 %c, 1 + %e = or i32 %d, 16 + ret i32 %e +} + +; There are at least 24 redundant sign bits so we don't need an ori after the clsw. +define i32 @cls_i32_knownbits_3(i8 signext %x) { +; CHECK-LABEL: cls_i32_knownbits_3: +; CHECK: # %bb.0: +; CHECK-NEXT: clsw a0, a0 +; CHECK-NEXT: ori a0, a0, 24 +; CHECK-NEXT: ret + %sext = sext i8 %x to i32 + %a = ashr i32 %sext, 31 + %b = xor i32 %sext, %a + %c = call i32 @llvm.ctlz.i32(i32 %b, i1 false) + %d = sub i32 %c, 1 + %e = or i32 %d, 24 + ret i32 %e +} + +; Negative test. We only know there is at least 1 redundant sign bit. We can't +; remove the ori. +define i32 @cls_i32_knownbits_4(i32 signext %x) { +; CHECK-LABEL: cls_i32_knownbits_4: +; CHECK: # %bb.0: +; CHECK-NEXT: slli a0, a0, 33 +; CHECK-NEXT: srai a0, a0, 33 +; CHECK-NEXT: clsw a0, a0 +; CHECK-NEXT: ori a0, a0, 1 +; CHECK-NEXT: ret + %shl = shl i32 %x, 1 + %ashr = ashr i32 %shl, 1 + %a = ashr i32 %ashr, 31 + %b = xor i32 %ashr, %a + %c = call i32 @llvm.ctlz.i32(i32 %b, i1 false) + %d = sub i32 %c, 1 + %e = or i32 %d, 1 + ret i32 %e +} + define i64 @cls_i64(i64 %x) { ; CHECK-LABEL: cls_i64: ; CHECK: # %bb.0: From 5c944c25af8a07a69f84ab93afbed05c86c97f7c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 6 Jan 2026 11:10:33 -0800 Subject: [PATCH 2/2] [RISCV] Add computeKnownBits for CLSW. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 15 +++++++++++++++ llvm/test/CodeGen/RISCV/rv64p.ll | 3 --- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index d6b62736bdf60..4a7d2e9321c41 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -22429,6 +22429,21 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op, Known.Zero.setBitsFrom(LowBits); break; } + case RISCVISD::CLSW: { + // The upper 32 bits are ignored by the instruction, but ComputeNumSignBits + // doesn't give us a way to ignore them. If there are fewer than 33 sign + // bits in the input consider it as having no redundant sign bits. Otherwise + // the lower bound of the result is NumSignBits-33. The maximum value of the + // the result is 31. + unsigned NumSignBits = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1); + unsigned MinRedundantSignBits = NumSignBits < 33 ? 0 : NumSignBits - 33; + // Create a ConstantRange [MinRedundantSignBits, 32) and convert it to + // KnownBits. + ConstantRange Range(APInt(BitWidth, MinRedundantSignBits), + APInt(BitWidth, 32)); + Known = Range.toKnownBits(); + break; + } case RISCVISD::BREV8: case RISCVISD::ORC_B: { // FIXME: This is based on the non-ratified Zbp GREV and GORC where a diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll index eedd98d63aed2..21779543ed011 100644 --- a/llvm/test/CodeGen/RISCV/rv64p.ll +++ b/llvm/test/CodeGen/RISCV/rv64p.ll @@ -227,7 +227,6 @@ define i32 @cls_i32_knownbits(i32 %x) { ; CHECK-LABEL: cls_i32_knownbits: ; CHECK: # %bb.0: ; CHECK-NEXT: clsw a0, a0 -; CHECK-NEXT: andi a0, a0, 31 ; CHECK-NEXT: ret %a = ashr i32 %x, 31 %b = xor i32 %x, %a @@ -242,7 +241,6 @@ define i32 @cls_i32_knownbits_2(i16 signext %x) { ; CHECK-LABEL: cls_i32_knownbits_2: ; CHECK: # %bb.0: ; CHECK-NEXT: clsw a0, a0 -; CHECK-NEXT: ori a0, a0, 16 ; CHECK-NEXT: ret %sext = sext i16 %x to i32 %a = ashr i32 %sext, 31 @@ -258,7 +256,6 @@ define i32 @cls_i32_knownbits_3(i8 signext %x) { ; CHECK-LABEL: cls_i32_knownbits_3: ; CHECK: # %bb.0: ; CHECK-NEXT: clsw a0, a0 -; CHECK-NEXT: ori a0, a0, 24 ; CHECK-NEXT: ret %sext = sext i8 %x to i32 %a = ashr i32 %sext, 31