From 2071b043eb18b0c4821462f445143a9ef72b97fa Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 5 Oct 2020 21:13:02 +0200 Subject: [PATCH] [InstCombine] Handle GEP inbounds in select op replacement (PR47730) When retrying the "simplify with operand replaced" select optimization without poison flags, also handle inbounds on GEPs. Of course, this particular example would also be safe to transform while keeping inbounds, but the underlying machinery does not know this (yet). --- lib/Transforms/InstCombine/InstCombineSelect.cpp | 8 +++++++- test/Transforms/InstCombine/select.ll | 7 +++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 087586ede80..2501c564c3f 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1200,7 +1200,7 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, // InstSimplify already performed this fold if it was possible subject to // current poison-generating flags. Try the transform again with // poison-generating flags temporarily dropped. - bool WasNUW = false, WasNSW = false, WasExact = false; + bool WasNUW = false, WasNSW = false, WasExact = false, WasInBounds = false; if (auto *OBO = dyn_cast(FalseVal)) { WasNUW = OBO->hasNoUnsignedWrap(); WasNSW = OBO->hasNoSignedWrap(); @@ -1211,6 +1211,10 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, WasExact = PEO->isExact(); FalseInst->setIsExact(false); } + if (auto *GEP = dyn_cast(FalseVal)) { + WasInBounds = GEP->isInBounds(); + GEP->setIsInBounds(false); + } // Try each equivalence substitution possibility. // We have an 'EQ' comparison, so the select's false value will propagate. @@ -1230,6 +1234,8 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, FalseInst->setHasNoSignedWrap(); if (WasExact) FalseInst->setIsExact(); + if (WasInBounds) + cast(FalseInst)->setIsInBounds(); return nullptr; } diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 326050c5a20..987f34e52ad 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -2725,12 +2725,11 @@ define i32 @select_replacement_loop2(i32 %arg, i32 %arg2) { ret i32 %sel } +; TODO: Dropping the inbounds flag should not be necessary for this fold. define i8* @select_replacement_gep_inbounds(i8* %base, i64 %offset) { ; CHECK-LABEL: @select_replacement_gep_inbounds( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[OFFSET:%.*]], 0 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[BASE:%.*]], i64 [[OFFSET]] -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8* [[BASE]], i8* [[GEP]] -; CHECK-NEXT: ret i8* [[SEL]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i64 [[OFFSET:%.*]] +; CHECK-NEXT: ret i8* [[GEP]] ; %cmp = icmp eq i64 %offset, 0 %gep = getelementptr inbounds i8, i8* %base, i64 %offset