Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4461,11 +4461,15 @@ // and CodeGen. And in this case, at least one of the comparison // operands has at least one user besides the compare (the select), // which would often largely negate the benefit of folding anyway. + // + // Do the same for the other patterns recognized by matchSelectPattern. if (I.hasOneUse()) - if (SelectInst *SI = dyn_cast(*I.user_begin())) - if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) || - (SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1)) + if (SelectInst *SI = dyn_cast(I.user_back())) { + Value *A, *B; + SelectPatternResult SPR = matchSelectPattern(SI, A, B); + if (SPR.Flavor != SPF_UNKNOWN) return nullptr; + } // Do this after checking for min/max to prevent infinite looping. if (Instruction *Res = foldICmpWithZero(I)) @@ -4944,10 +4948,12 @@ // operands has at least one user besides the compare (the select), // which would often largely negate the benefit of folding anyway. if (I.hasOneUse()) - if (SelectInst *SI = dyn_cast(*I.user_begin())) - if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) || - (SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1)) + if (SelectInst *SI = dyn_cast(I.user_back())) { + Value *A, *B; + SelectPatternResult SPR = matchSelectPattern(SI, A, B); + if (SPR.Flavor != SPF_UNKNOWN) return nullptr; + } // Handle fcmp with constant RHS if (Constant *RHSC = dyn_cast(Op1)) { Index: llvm/trunk/test/Transforms/InstCombine/icmp.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/icmp.ll +++ llvm/trunk/test/Transforms/InstCombine/icmp.ll @@ -3270,3 +3270,19 @@ %c = icmp sgt i8 %b2, %a2 ret i1 %c } + +; Make sure InstCombine doesn't try too hard to simplify the icmp and break the abs idiom +define i32 @abs_preserve(i32 %x) { +; CHECK-LABEL: @abs_preserve( +; CHECK-NEXT: [[A:%.*]] = shl nsw i32 [[X:%.*]], 1 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A]], -1 +; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[C]], i32 [[A]], i32 [[NEGA]] +; CHECK-NEXT: ret i32 [[ABS]] +; + %a = mul nsw i32 %x, 2 + %c = icmp sge i32 %a, 0 + %nega = sub i32 0, %a + %abs = select i1 %c, i32 %a, i32 %nega + ret i32 %abs +}