This optimization pre-promotes the input and constants for a
switch instruction to a legal type so that all the generated compares
share the same extend. Since RISCV prefers sext for i32 to i64
extends, we should honor that to use sext.w instead of a pair
of shifts.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/CodeGen/CodeGenPrepare.cpp | ||
---|---|---|
7018–7020 | Do we not want to avoid this in the case this is a function argument that is already being zero-extended? i.e. something like: Instruction::CastOps ExtType = Instruction::CastOpsEnd; if (auto *Arg = dyn_cast<Argument>(Cond)) { if (Arg->hasSExtAttr()) ExtType = Instruction::SExt; else if (Arg->hasZExtAttr()) ExtType = Instruction::ZExt; } if (ExtType == Instruction::CastOpsEnd) { if (TLI->isSExtCheaperThanZExt(OldVT, RegType)) ExtType = Instruction::SExt; else ExtType = Instruction::ZExt; } (slightly abusing CastOpsEnd as being one past the last valid op, and thus a sentinel, though you could write it in other ways too if you wanted) |
llvm/lib/CodeGen/CodeGenPrepare.cpp | ||
---|---|---|
7018–7020 | Or maybe the fact that sext is cheaper means the saving for each case's extending to match outweighs the cost of having to also extend the argument? |
llvm/lib/CodeGen/CodeGenPrepare.cpp | ||
---|---|---|
7018–7020 | It's a non-issue for RISCV since I don't think we ever create i32 zext arguments, but it would be more consistent. Could probably just do the isSExtCheaperThanZExt first and then check if it is an Argument after. |
llvm/lib/CodeGen/CodeGenPrepare.cpp | ||
---|---|---|
7018–7020 | True, only i16 and i8, and those aren't so cheap to sext. Your suggestion is indeed the cleaner way to express the same thing, not sure how I missed that... |
Do we not want to avoid this in the case this is a function argument that is already being zero-extended? i.e. something like:
(slightly abusing CastOpsEnd as being one past the last valid op, and thus a sentinel, though you could write it in other ways too if you wanted)