Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -362,6 +362,22 @@ return Builder->CreateOr(V, Y); } +static Value *foldSelectICmpAndSub(SelectInst &SI, Value *TrueVal, + Value *FalseVal, + InstCombiner::BuilderTy *Builder) { + const ICmpInst *IC = dyn_cast(SI.getCondition()); + Value *CmpLHS = IC->getOperand(0); + Value *CmpRHS = IC->getOperand(1); + + if (match(FalseVal, m_Sub(m_Value(CmpLHS), m_Value(CmpRHS))) && + match(TrueVal, m_Zero())) { + Value *A = Builder->CreateSelect(SI.getCondition(), CmpRHS, CmpLHS); + return Builder->CreateSub(A, CmpRHS); + } + + return nullptr; +} + /// Attempt to fold a cttz/ctlz followed by a icmp plus select into a single /// call to cttz/ctlz with flag 'is_zero_undef' cleared. /// @@ -667,6 +683,9 @@ if (Value *V = foldSelectICmpAndOr(SI, TrueVal, FalseVal, Builder)) return replaceInstUsesWith(SI, V); + if (Value *V = foldSelectICmpAndSub(SI, TrueVal, FalseVal, Builder)) + return replaceInstUsesWith(SI, V); + if (Value *V = foldSelectCttzCtlz(ICI, TrueVal, FalseVal, Builder)) return replaceInstUsesWith(SI, V);