Skip to content

risc-v backend miscompile of cttz-related optimization #155014

@regehr

Description

@regehr

this function:

declare i7 @llvm.cttz.i7(i7, i1 immarg)

define i7 @f(i7 %0) {
  %2 = call i7 @llvm.cttz.i7(i7 %0, i1 false)
  %3 = icmp eq i7 %0, 0
  %4 = select i1 %3, i7 0, i7 %2
  ret i7 %4
}

is getting miscompiled by the RISCV64+B backend as:

f:
	ori	a0, a0, 128
	ctz	a0, a0
	andi	a0, a0, 6
	ret

the 6 in the output doesn't make sense, it is coming from an insufficiently-protected Bitwidth - 1.

@MitchBriles, a student working with me, has the following candidate patch. it certainly fixes this case but we've not fully vetted it yet. actually, if nobody is in a rush to fix this, Mitch would like to be the one to submit the PR for it.

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4a1db80076..7a5ebf74c4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -18740,6 +18740,10 @@ static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG) {
   if (Cond->getOperand(0) != CountZeroesArgument)
     return SDValue();
 
+  unsigned BitWidth = CountZeroes.getValueSizeInBits();
+  if (!isPowerOf2_32(BitWidth))
+    return SDValue();
+
   if (CountZeroes.getOpcode() == ISD::CTTZ_ZERO_UNDEF) {
     CountZeroes = DAG.getNode(ISD::CTTZ, SDLoc(CountZeroes),
                               CountZeroes.getValueType(), CountZeroesArgument);
@@ -18748,7 +18752,6 @@ static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG) {
                               CountZeroes.getValueType(), CountZeroesArgument);
   }
 
-  unsigned BitWidth = CountZeroes.getValueSizeInBits();
   SDValue BitWidthMinusOne =
       DAG.getConstant(BitWidth - 1, SDLoc(N), CountZeroes.getValueType());

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions