This DAGCombine is not valid for some combinations of the known bits
of x and non-power-of-two widths of x. As shown in the bug:
- The bitwidth of x is 35 (n=5)
- The unknown bits of x is only the least significant bit
- This gives the result of the ctlz two possible values: 34 or 35, both
of which will give 1 when left-shifted 5 bits.
- So the `eor x, 1` that this optimisation would give is not correct.
A similar instcombine optimisation is only applied when the width of x is
a power-of-two. GlobalISel does not have this bug, as shown by the testcase.
Fixes #61549
Differential Revision: https://reviews.llvm.org/D147518
return DAG.getNode(ISD::SRL, SDLoc(N), VT, N0.getOperand(0), N1);
}
- // fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit).
+ // fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit), and x has a power
+ // of two bitwidth. The "5" represents (log2 (bitwidth x)).
if (N1C && N0.getOpcode() == ISD::CTLZ &&
+ isPowerOf2_32(OpSizeInBits) &&
N1C->getAPIntValue() == Log2_32(OpSizeInBits)) {
KnownBits Known = DAG.computeKnownBits(N0.getOperand(0));
; CHECK-NEXT: sbfx x9, x0, #0, #35
; CHECK-NEXT: sdiv x10, x8, x9
; CHECK-NEXT: msub x8, x10, x9, x8
-; CHECK-NEXT: eor x0, x8, #0x1
+; CHECK-NEXT: clz x8, x8
+; CHECK-NEXT: sub x8, x8, #29
+; CHECK-NEXT: ubfx x0, x8, #5, #30
; CHECK-NEXT: ret
;
; GISEL-LABEL: f: