Index: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -276,16 +276,20 @@ } if (auto *Sel = dyn_cast(Src)) { - // We are casting a select. Try to fold the cast into the select, but only - // if the select does not have a compare instruction with matching operand - // types. Creating a select with operands that are different sizes than its + // We are casting a select. Try to fold the cast into the select if the + // select does not have a compare instruction with matching operand types + // or the select is likely better done in a narrow type. + // Creating a select with operands that are different sizes than its // condition may inhibit other folds and lead to worse codegen. auto *Cmp = dyn_cast(Sel->getCondition()); - if (!Cmp || Cmp->getOperand(0)->getType() != Sel->getType()) + if (!Cmp || Cmp->getOperand(0)->getType() != Sel->getType() || + (CI.getOpcode() == Instruction::Trunc && + shouldChangeType(CI.getSrcTy(), CI.getType()))) { if (Instruction *NV = FoldOpIntoSelect(CI, Sel)) { replaceAllDbgUsesWith(*Sel, *NV, CI, DT); return NV; } + } } // If we are casting a PHI, then fold the cast into the PHI. Index: llvm/test/Transforms/InstCombine/cast-select.ll =================================================================== --- llvm/test/Transforms/InstCombine/cast-select.ll +++ llvm/test/Transforms/InstCombine/cast-select.ll @@ -56,8 +56,8 @@ define i16 @trunc(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @trunc( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[Z:%.*]] -; CHECK-NEXT: [[R:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[Z:%.*]] to i16 +; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i16 42, i16 [[TMP1]] ; CHECK-NEXT: ret i16 [[R]] ; %cmp = icmp ult i32 %x, %y Index: llvm/test/Transforms/InstCombine/select-imm-canon.ll =================================================================== --- llvm/test/Transforms/InstCombine/select-imm-canon.ll +++ llvm/test/Transforms/InstCombine/select-imm-canon.ll @@ -39,8 +39,8 @@ ; CHECK-LABEL: @thisdoesnotloop( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L1:%.*]] = icmp slt i32 [[A:%.*]], -128 -; CHECK-NEXT: [[L2:%.*]] = select i1 [[L1]], i32 -128, i32 [[B:%.*]] -; CHECK-NEXT: [[CONV7:%.*]] = trunc i32 [[L2]] to i8 +; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[B:%.*]] to i8 +; CHECK-NEXT: [[CONV7:%.*]] = select i1 [[L1]], i8 -128, i8 [[TMP0]] ; CHECK-NEXT: ret i8 [[CONV7]] ; entry: Index: llvm/test/Transforms/InstCombine/trunc.ll =================================================================== --- llvm/test/Transforms/InstCombine/trunc.ll +++ llvm/test/Transforms/InstCombine/trunc.ll @@ -626,15 +626,13 @@ ret <2 x i8> %tr } -; FIXME: If the select is narrowed based on the target's datalayout, we allow more optimizations. +; If the select is narrowed based on the target's datalayout, we allow more optimizations. define i16 @PR44545(i32 %t0, i32 %data) { ; CHECK-LABEL: @PR44545( -; CHECK-NEXT: [[T1:%.*]] = add nuw nsw i32 [[T0:%.*]], 1 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[DATA:%.*]], 0 -; CHECK-NEXT: [[FFS:%.*]] = select i1 [[ISZERO]], i32 0, i32 [[T1]] -; CHECK-NEXT: [[CAST:%.*]] = trunc i32 [[FFS]] to i16 -; CHECK-NEXT: [[SUB:%.*]] = add nsw i16 [[CAST]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[T0:%.*]] to i16 +; CHECK-NEXT: [[SUB:%.*]] = select i1 [[ISZERO]], i16 -1, i16 [[TMP1]] ; CHECK-NEXT: ret i16 [[SUB]] ; %t1 = add nuw nsw i32 %t0, 1