diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2526,6 +2526,28 @@ return nullptr; } +static Value *foldSelectWithFrozenICmp(SelectInst &Sel, InstCombiner::BuilderTy &Builder) { + FreezeInst *FI = dyn_cast(Sel.getCondition()); + if (!FI) + return nullptr; + + Value *Cond = FI->getOperand(0); + Value *TrueVal = Sel.getTrueValue(), *FalseVal = Sel.getFalseValue(); + + // select (freeze(x == y)), x, y --> freeze(y) + // select (freeze(x != y)), x, y --> freeze(x) + CmpInst::Predicate Pred; + if (match(Cond, m_c_ICmp(Pred, m_Specific(TrueVal), m_Specific(FalseVal))) && + (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE)) { + auto *NewFr = Builder.CreateFreeze(Pred == ICmpInst::ICMP_EQ ? + FalseVal : TrueVal); + NewFr->takeName(&Sel); + return NewFr; + } + + return nullptr; +} + Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { Value *CondVal = SI.getCondition(); Value *TrueVal = SI.getTrueValue(); @@ -2977,5 +2999,8 @@ if (Instruction *PN = foldSelectToPhi(SI, DT, Builder)) return replaceInstUsesWith(SI, PN); + if (Value *Fr = foldSelectWithFrozenICmp(SI, Builder)) + return replaceInstUsesWith(SI, Fr); + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -2540,9 +2540,7 @@ define i32 @select_freeze_icmp_eq(i32 %x, i32 %y) { ; CHECK-LABEL: @select_freeze_icmp_eq( -; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] -; CHECK-NEXT: [[V:%.*]] = select i1 [[C_FR]], i32 [[X]], i32 [[Y]] +; CHECK-NEXT: [[V:%.*]] = freeze i32 [[Y:%.*]] ; CHECK-NEXT: ret i32 [[V]] ; %c = icmp eq i32 %x, %y @@ -2553,9 +2551,7 @@ define i32 @select_freeze_icmp_ne(i32 %x, i32 %y) { ; CHECK-LABEL: @select_freeze_icmp_ne( -; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] -; CHECK-NEXT: [[V:%.*]] = select i1 [[C_FR]], i32 [[X]], i32 [[Y]] +; CHECK-NEXT: [[V:%.*]] = freeze i32 [[X:%.*]] ; CHECK-NEXT: ret i32 [[V]] ; %c = icmp ne i32 %x, %y