[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