Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -3931,70 +3931,89 @@ if (!I) return nullptr; - // Consider: - // %cmp = icmp eq i32 %x, 2147483647 - // %add = add nsw i32 %x, 1 - // %sel = select i1 %cmp, i32 -2147483648, i32 %add - // - // We can't replace %sel with %add unless we strip away the flags (which will - // be done in InstCombine). - // TODO: This is unsound, because it only catches some forms of refinement. - if (!AllowRefinement && canCreatePoison(cast(I))) - return nullptr; - - // The simplification queries below may return the original value. Consider: - // %div = udiv i32 %arg, %arg2 - // %mul = mul nsw i32 %div, %arg2 - // %cmp = icmp eq i32 %mul, %arg - // %sel = select i1 %cmp, i32 %div, i32 undef - // Replacing %arg by %mul, %div becomes "udiv i32 %mul, %arg2", which - // simplifies back to %arg. This can only happen because %mul does not - // dominate %div. To ensure a consistent return value contract, we make sure - // that this case returns nullptr as well. - auto PreventSelfSimplify = [V](Value *Simplified) { - return Simplified != V ? Simplified : nullptr; - }; - - // If this is a binary operator, try to simplify it with the replaced op. - if (auto *B = dyn_cast(I)) { - if (MaxRecurse) { - if (B->getOperand(0) == Op) - return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), RepOp, - B->getOperand(1), Q, - MaxRecurse - 1)); - if (B->getOperand(1) == Op) - return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), - B->getOperand(0), RepOp, Q, - MaxRecurse - 1)); + if (!AllowRefinement) { + // General InstSimplify functions may refine the result. To avoid this, + // implement only a few non-refining but profitable transforms here. + + // x & x -> x, x | x -> x + if (match(I, m_c_And(m_Specific(Op), m_Specific(RepOp)))) + return RepOp; + if (match(I, m_c_Or(m_Specific(Op), m_Specific(RepOp)))) + return RepOp; + + if (auto *GEP = dyn_cast(I)) { + // getelementptr x, 0 -> x + if (GEP->getNumIndices() == 1 && *GEP->idx_begin() == Op && + match(RepOp, m_Zero()) && !GEP->isInBounds()) + return GEP->getPointerOperand(); } - } - // Same for CmpInsts. - if (CmpInst *C = dyn_cast(I)) { - if (MaxRecurse) { - if (C->getOperand(0) == Op) - return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), RepOp, - C->getOperand(1), Q, + // Consider: + // %cmp = icmp eq i32 %x, 2147483647 + // %add = add nsw i32 %x, 1 + // %sel = select i1 %cmp, i32 -2147483648, i32 %add + // + // We can't replace %sel with %add unless we strip away the flags (which + // will be done in InstCombine). + // TODO: Now that this only guards the constant folding case, it might + // be possible to drop this check. + if (canCreatePoison(cast(I))) + return nullptr; + } else { + // The simplification queries below may return the original value. Consider: + // %div = udiv i32 %arg, %arg2 + // %mul = mul nsw i32 %div, %arg2 + // %cmp = icmp eq i32 %mul, %arg + // %sel = select i1 %cmp, i32 %div, i32 undef + // Replacing %arg by %mul, %div becomes "udiv i32 %mul, %arg2", which + // simplifies back to %arg. This can only happen because %mul does not + // dominate %div. To ensure a consistent return value contract, we make sure + // that this case returns nullptr as well. + auto PreventSelfSimplify = [V](Value *Simplified) { + return Simplified != V ? Simplified : nullptr; + }; + + // If this is a binary operator, try to simplify it with the replaced op. + if (auto *B = dyn_cast(I)) { + if (MaxRecurse) { + if (B->getOperand(0) == Op) + return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), RepOp, + B->getOperand(1), Q, MaxRecurse - 1)); - if (C->getOperand(1) == Op) - return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), - C->getOperand(0), RepOp, Q, + if (B->getOperand(1) == Op) + return PreventSelfSimplify(SimplifyBinOp(B->getOpcode(), + B->getOperand(0), RepOp, Q, MaxRecurse - 1)); + } } - } - // Same for GEPs. - if (auto *GEP = dyn_cast(I)) { - if (MaxRecurse) { - SmallVector NewOps(GEP->getNumOperands()); - transform(GEP->operands(), NewOps.begin(), - [&](Value *V) { return V == Op ? RepOp : V; }); - return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(), - NewOps, Q, MaxRecurse - 1)); + // Same for CmpInsts. + if (CmpInst *C = dyn_cast(I)) { + if (MaxRecurse) { + if (C->getOperand(0) == Op) + return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), RepOp, + C->getOperand(1), Q, + MaxRecurse - 1)); + if (C->getOperand(1) == Op) + return PreventSelfSimplify(SimplifyCmpInst(C->getPredicate(), + C->getOperand(0), RepOp, Q, + MaxRecurse - 1)); + } } - } - // TODO: We could hand off more cases to instsimplify here. + // Same for GEPs. + if (auto *GEP = dyn_cast(I)) { + if (MaxRecurse) { + SmallVector NewOps(GEP->getNumOperands()); + transform(GEP->operands(), NewOps.begin(), + [&](Value *V) { return V == Op ? RepOp : V; }); + return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(), + NewOps, Q, MaxRecurse - 1)); + } + } + + // TODO: We could hand off more cases to instsimplify here. + } // If all operands are constant after substituting Op for RepOp then we can // constant fold the instruction. Index: llvm/test/Transforms/InstCombine/select.ll =================================================================== --- llvm/test/Transforms/InstCombine/select.ll +++ llvm/test/Transforms/InstCombine/select.ll @@ -902,7 +902,9 @@ define i32 @test57(i32 %x, i32 %y) { ; CHECK-LABEL: @test57( ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[X]], 0 +; CHECK-NEXT: [[DOTAND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[AND]] +; CHECK-NEXT: ret i32 [[DOTAND]] ; %and = and i32 %x, %y %tobool = icmp eq i32 %x, 0 @@ -2680,7 +2682,7 @@ define i32 @pr47322_more_poisonous_replacement(i32 %arg) { ; CHECK-LABEL: @pr47322_more_poisonous_replacement( ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], 0 -; CHECK-NEXT: [[TRAILING:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 immarg true), [[RNG0:!range !.*]] +; CHECK-NEXT: [[TRAILING:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 immarg true), !range [[RNG0:![0-9]+]] ; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i32 [[ARG]], [[TRAILING]] ; CHECK-NEXT: [[R1_SROA_0_1:%.*]] = select i1 [[CMP]], i32 0, i32 [[SHIFTED]] ; CHECK-NEXT: ret i32 [[R1_SROA_0_1]] Index: llvm/test/Transforms/InstSimplify/pr49495.ll =================================================================== --- llvm/test/Transforms/InstSimplify/pr49495.ll +++ llvm/test/Transforms/InstSimplify/pr49495.ll @@ -4,9 +4,11 @@ ; The first comparison (a != b) should not be dropped define i1 @test1(i8* %a, i8* %b) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i64 -1 -; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8* [[A2]], [[B:%.*]] -; CHECK-NEXT: ret i1 [[COND2]] +; CHECK-NEXT: [[COND1:%.*]] = icmp ne i8* [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 -1 +; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8* [[A2]], [[B]] +; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND1]], i1 [[COND2]], i1 false +; CHECK-NEXT: ret i1 [[RES]] ; %cond1 = icmp ne i8* %a, %b %a2 = getelementptr inbounds i8, i8* %a, i64 -1 @@ -18,9 +20,11 @@ ; The first comparison (a != b) should not be dropped define i1 @test2(i32 %a, i32 %b) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[A2:%.*]] = add nuw i32 [[A:%.*]], 1 -; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[A2]], [[B:%.*]] -; CHECK-NEXT: ret i1 [[COND2]] +; CHECK-NEXT: [[COND1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[A2:%.*]] = add nuw i32 [[A]], 1 +; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[A2]], [[B]] +; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND1]], i1 [[COND2]], i1 false +; CHECK-NEXT: ret i1 [[RES]] ; %cond1 = icmp ne i32 %a, %b %a2 = add nuw i32 %a, 1