Index: llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -386,6 +386,9 @@ if (Instruction *Res = FoldShiftByConstant(Op0, CUI, I)) return Res; + if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) + return replaceInstUsesWith(I, V); + if (auto *NewShift = cast_or_null( reassociateShiftAmtsOfTwoSameDirectionShifts(&I, SQ))) return NewShift; Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -843,16 +843,28 @@ else if (True && !False) False = Builder.CreateBinOp(Opcode, C, F); } - } else if (LHSIsSelect && LHS->hasOneUse()) { + } else if (LHSIsSelect) { // (A ? B : C) op Y -> A ? (B op Y) : (C op Y) - Cond = A; - True = SimplifyBinOp(Opcode, B, RHS, FMF, Q); - False = SimplifyBinOp(Opcode, C, RHS, FMF, Q); - } else if (RHSIsSelect && RHS->hasOneUse()) { + auto *TempTrue = SimplifyBinOp(Opcode, B, RHS, FMF, Q); + auto *TempFalse = SimplifyBinOp(Opcode, C, RHS, FMF, Q); + // We optimise single uses and folding into constants + if (LHS->hasOneUse() || (isa_and_nonnull(TempTrue) && + isa_and_nonnull(TempFalse))) { + Cond = A; + True = TempTrue; + False = TempFalse; + } + } else if (RHSIsSelect) { // X op (D ? E : F) -> D ? (X op E) : (X op F) - Cond = D; - True = SimplifyBinOp(Opcode, LHS, E, FMF, Q); - False = SimplifyBinOp(Opcode, LHS, F, FMF, Q); + auto *TempTrue = SimplifyBinOp(Opcode, LHS, E, FMF, Q); + auto *TempFalse = SimplifyBinOp(Opcode, LHS, F, FMF, Q); + // We optimise single uses and folding into constants + if (RHS->hasOneUse() || (isa_and_nonnull(TempTrue) && + isa_and_nonnull(TempFalse))) { + Cond = D; + True = TempTrue; + False = TempFalse; + } } if (!True || !False) Index: llvm/test/Transforms/InstCombine/lshr-select-const.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/lshr-select-const.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Instcombine should be able to eliminate the 'lshr' shift because +; the 'select' uses constant source operands that will be shifted +; by a constant amount. + +define i64 @fold_lshr(i1 %arg) { +; CHECK-LABEL: @fold_lshr( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[V8:%.*]] = select i1 [[ARG:%.*]], i64 5369111361, i64 5369111591 +; CHECK-NEXT: ret i64 [[V8]] +entry: + %v0 = select i1 %arg, i64 64, i64 0 + %v1 = lshr exact i64 %v0, 6 + %v2 = xor i64 %v1, 1 + %v3 = shl nuw i64 %v0, 57 + %v4 = ashr exact i64 %v3, 63 + %v5 = sub nsw i64 0, %v2 + %v6 = and i64 %v5, 5369111591 + %v7 = and i64 %v4, 5369111361 + %v8 = add nuw nsw i64 %v7, %v6 + ret i64 %v8 +}