[llvm] [RISCV] Disable generic DAG combines at -O0 to preserve debuggability (PR #219082)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 00:05:36 PDT 2026
topperc wrote:
> > Doesn't this mean invalid immediate shift amounts won't get canonicalized. Or ANDing with all ones won't be removed. I think there might be some code in RISCVISelDAGToDAG.cpp for selecting shift+and that assume these things happened.
>
> All three canonicalizations happen in `SelectionDAG::getNode`, not in DAGCombiner, so `disableGenericCombines()` doesn't turn them off.
>
> Shift amount 0 and out-of-range shift amounts — `getNode` routes `SHL`/`SRA`/`SRL` through `SelectionDAG::simplifyShift` (`SelectionDAG.cpp:8588`), which does:
>
> ```c++
> // shift 0, Y --> 0
> // shift X, 0 --> X
> if (isNullOrNullSplat(X) || isNullOrNullSplat(Y))
> return X;
>
> // shift X, C >= bitwidth(X) --> undef
> auto isShiftTooBig = [X](ConstantSDNode *Val) {
> return !Val || Val->getAPIntValue().uge(X.getScalarValueSizeInBits());
> };
> if (ISD::matchUnaryPredicate(Y, isShiftTooBig, true))
> return getUNDEF(X.getValueType());
> ```
>
> AND with all ones — also `getNode`, at `SelectionDAG.cpp:8450`:
>
> ```c++
> if (N2CV && N2CV->isAllOnes()) // X & -1 -> X
> return N1;
> ```
>
> Since every node is constructed through `getNode` regardless of opt level, and legalization builds its nodes the same way, these invariants hold at `-O0` too. So the two asserts you're thinking of — `assert((C2 > 0 && C2 < XLen) && "Unexpected shift amount!")` in the `ISD::AND` case of `Select()` (`RISCVISelDAGToDAG.cpp:1520`, and again at `:1756` for the `SRA` sub-case) — are still satisfied.
It is possible to bypass the canonicalization in getNode. For example, you can use type legalization to cause a value to become a constant once it is legalized.
This test case produces a shift by 32 after type legalization when compiled without vector support
```
define i32 @foo(i32 %x, <4 x i32> %y) {
%a = insertelement <4 x i32> %y, i32 32, i32 1
%b = shufflevector <4 x i32> %a, <4 x i32> %a, <4 x i32> <i32 1, i32 2, i32 3, i32 0>
%c = extractelement <4 x i32> %b, i32 0
%d = shl i32 %x, %c
ret i32 %d
}
```
```
Legalized selection DAG: %bb.0 'foo:'
SelectionDAG has 30 nodes:
t0: ch,glue = EntryToken
t4: i32,ch = CopyFromReg t0, Register:i32 %1
t6: i32,ch = load<(load (s32))> t0, t4, poison:i32
t22: ch = CopyToReg t0, Register:i32 %2, t6
t8: i32 = add t4, Constant:i32<4>
t9: i32,ch = load<(load (s32))> t0, t8, poison:i32
t24: ch = CopyToReg t0, Register:i32 %3, t9
t11: i32 = add t4, Constant:i32<8>
t12: i32,ch = load<(load (s32))> t0, t11, poison:i32
t26: ch = CopyToReg t0, Register:i32 %4, t12
t14: i32 = add t4, Constant:i32<12>
t15: i32,ch = load<(load (s32))> t0, t14, poison:i32
t28: ch = CopyToReg t0, Register:i32 %5, t15
t29: ch = TokenFactor t22, t24, t26, t28
t2: i32,ch = CopyFromReg t0, Register:i32 %0
t35: i32 = shl t2, Constant:i32<32> <---- Bad shift
t37: ch,glue = CopyToReg t29, Register:i32 $x10, t35
t38: ch = RISCVISD::RET_GLUE t37, Register:i32 $x10, t37:1
```
https://github.com/llvm/llvm-project/pull/219082
More information about the llvm-commits
mailing list