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:
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)