Index: llvm/lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- llvm/lib/Transforms/Scalar/Reassociate.cpp +++ llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -195,6 +195,13 @@ } } +static bool isSelectOfConstants(Instruction &I) { + Value *Cond; + Constant *TrueC, *FalseC; + return match(&I, + m_Select(m_Value(Cond), m_Constant(TrueC), m_Constant(FalseC))); +} + unsigned ReassociatePass::getRank(Value *V) { Instruction *I = dyn_cast(V); if (!I) { @@ -202,6 +209,13 @@ return 0; // Otherwise it's a global or constant, rank 0. } + // TODO: what should we do if we have several selects of constants? + // What if conditions of selects are different? + if (isSelectOfConstants(*I)) + // We want to group select of constants with constants, so that + // InstCombine can absorb addition of constant into the select. + return 0; + if (unsigned Rank = ValueRankMap[I]) return Rank; // Rank already known? Index: llvm/test/Transforms/Reassociate/select-of-constants.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Reassociate/select-of-constants.ll @@ -0,0 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=reassociate < %s | FileCheck %s + +; Test that reassociation groups select of constants together with constants. + +define dso_local signext i32 @select_of_constants(i32 noundef signext %a, i1 %c) { +; CHECK-LABEL: @select_of_constants( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SELECT_:%.*]] = select i1 [[C:%.*]], i32 8, i32 2 +; CHECK-NEXT: [[ADD4:%.*]] = add i32 [[SELECT_]], 4 +; CHECK-NEXT: [[ADD_:%.*]] = add i32 [[ADD4]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[ADD_]] +; +entry: + %select_ = select i1 %c, i32 8, i32 2 + %add4 = add i32 %a, 4 + %add_ = add i32 %add4, %select_ + ret i32 %add_ +}