ShouldBuildLookupTable contains a check to make sure the type of the Phi is legal for the target. This currently prevents i32 lookup tables from being formed on RISCV64 which only has i64 as a legal type. Obviously i32 is going to be a more widespread type than i64 for C code so I would like to improve this. But i8/i16 are also disabled on RISCV, ARM, AArch64, and probably other targets which can do an i8/i16 load.
What is the right check here? Can we make sure it fits in the largest native integer type from data layout instead? Or should we add another TTI hook to ask the target?
This logic was originally added in https://reviews.llvm.org/rG65df808f6254617b9eee931d00e95d900610b660 . I’m not sure what the code is trying to do.
In general, the number of instructions it takes to load a value into registers from memory should be comparable to the number of instructions it takes to synthesize it in registers. It shouldn’t really matter if the type is legal. I can think of two reasons the type would matter:
What about types like i24 that likely need 2 or more loads with shifts? I imagine synthesizing an i24 constant in a register might be simpler than that?
Are you suggesting to remove the check altogether?
i24 has ABI alignment 4; if you have a global variable containing an array of i24, there should be a byte of padding after each i24, so we should be able to load it in a single load. We could restrict integers that aren’t powers of two, or explicitly zero-extend them, if you’re concerned that’s too fragile.
I think we need some guard to ensure that we aren’t generating excessively large tables (if someone has a PHI with type i1024, or [100 x i8], or <64 x i8>). But I don’t think it needs to be tied to whether the type is legal.