diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -6988,7 +6988,8 @@ Value *Cond = SI->getCondition(); Type *OldType = Cond->getType(); LLVMContext &Context = Cond->getContext(); - MVT RegType = TLI->getRegisterType(Context, TLI->getValueType(*DL, OldType)); + EVT OldVT = TLI->getValueType(*DL, OldType); + MVT RegType = TLI->getRegisterType(Context, OldVT); unsigned RegWidth = RegType.getSizeInBits(); if (RegWidth <= cast(OldType)->getBitWidth()) @@ -7002,14 +7003,21 @@ // where N is the number of cases in the switch. auto *NewType = Type::getIntNTy(Context, RegWidth); - // Zero-extend the switch condition and case constants unless the switch - // condition is a function argument that is already being sign-extended. - // In that case, we can avoid an unnecessary mask/extension by sign-extending - // everything instead. + // Extend the switch condition and case constants using the target preferred + // extend unless the switch condition is a function argument with an extend + // attribute. In that case, we can avoid an unnecessary mask/extension by + // matching the argument extension instead. Instruction::CastOps ExtType = Instruction::ZExt; - if (auto *Arg = dyn_cast(Cond)) + // Some targets prefer SExt over ZExt. + if (TLI->isSExtCheaperThanZExt(OldVT, RegType)) + ExtType = Instruction::SExt; + + if (auto *Arg = dyn_cast(Cond)) { if (Arg->hasSExtAttr()) ExtType = Instruction::SExt; + if (Arg->hasZExtAttr()) + ExtType = Instruction::ZExt; + } auto *ExtInst = CastInst::Create(ExtType, Cond, NewType); ExtInst->insertBefore(SI); diff --git a/llvm/test/CodeGen/RISCV/jumptable.ll b/llvm/test/CodeGen/RISCV/jumptable.ll --- a/llvm/test/CodeGen/RISCV/jumptable.ll +++ b/llvm/test/CodeGen/RISCV/jumptable.ll @@ -75,8 +75,7 @@ ; ; RV64I-SMALL-LABEL: below_threshold: ; RV64I-SMALL: # %bb.0: # %entry -; RV64I-SMALL-NEXT: slli a0, a0, 32 -; RV64I-SMALL-NEXT: srli a0, a0, 32 +; RV64I-SMALL-NEXT: sext.w a0, a0 ; RV64I-SMALL-NEXT: addi a2, zero, 2 ; RV64I-SMALL-NEXT: blt a2, a0, .LBB0_4 ; RV64I-SMALL-NEXT: # %bb.1: # %entry @@ -109,8 +108,7 @@ ; ; RV64I-MEDIUM-LABEL: below_threshold: ; RV64I-MEDIUM: # %bb.0: # %entry -; RV64I-MEDIUM-NEXT: slli a0, a0, 32 -; RV64I-MEDIUM-NEXT: srli a0, a0, 32 +; RV64I-MEDIUM-NEXT: sext.w a0, a0 ; RV64I-MEDIUM-NEXT: addi a2, zero, 2 ; RV64I-MEDIUM-NEXT: blt a2, a0, .LBB0_4 ; RV64I-MEDIUM-NEXT: # %bb.1: # %entry @@ -236,8 +234,7 @@ ; ; RV64I-SMALL-LABEL: above_threshold: ; RV64I-SMALL: # %bb.0: # %entry -; RV64I-SMALL-NEXT: slli a0, a0, 32 -; RV64I-SMALL-NEXT: srli a0, a0, 32 +; RV64I-SMALL-NEXT: sext.w a0, a0 ; RV64I-SMALL-NEXT: addi a0, a0, -1 ; RV64I-SMALL-NEXT: addi a2, zero, 5 ; RV64I-SMALL-NEXT: bltu a2, a0, .LBB1_9 @@ -272,8 +269,7 @@ ; ; RV64I-MEDIUM-LABEL: above_threshold: ; RV64I-MEDIUM: # %bb.0: # %entry -; RV64I-MEDIUM-NEXT: slli a0, a0, 32 -; RV64I-MEDIUM-NEXT: srli a0, a0, 32 +; RV64I-MEDIUM-NEXT: sext.w a0, a0 ; RV64I-MEDIUM-NEXT: addi a0, a0, -1 ; RV64I-MEDIUM-NEXT: addi a2, zero, 5 ; RV64I-MEDIUM-NEXT: bltu a2, a0, .LBB1_9