diff options
author | Sanjay Patel <spatel@rotateright.com> | 2021-12-14 10:46:25 -0500 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2021-12-14 11:18:36 -0500 |
commit | bb2fc19c6355d990a4cfb94be20528fbe37950a8 (patch) | |
tree | 0bebf13ed4ed7a698fc16b2164a25e9a5f87592e | |
parent | d2be9ae0da2f440a0d42f928d33f5797e2a84500 (diff) | |
download | llvm-bb2fc19c6355d990a4cfb94be20528fbe37950a8.tar.gz |
[InstCombine] prevent infinite looping from opposing cmp and select transforms (PR52684)
As noted in the code comment, we might want to simply give up on this select
transform completely (given how many exceptions there are already and the
risk of future conflicts), but for now, carve out one more bailout to
avoid an infinite loop.
Fixes #52684:
https://github.com/llvm/llvm-project/issues/52684
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 7 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll | 29 |
2 files changed, 34 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 518d3952dce5..a6d6b5199105 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1482,7 +1482,12 @@ tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp, if (C0->getType() != Sel.getType()) return nullptr; - // FIXME: are there any magic icmp predicate+constant pairs we must not touch? + // ULT with 'add' of a constant is canonical. See foldICmpAddConstant(). + // FIXME: Are there more magic icmp predicate+constant pairs we must avoid? + // Or should we just abandon this transform entirely? + if (Pred == CmpInst::ICMP_ULT && match(X, m_Add(m_Value(), m_Constant()))) + return nullptr; + Value *SelVal0, *SelVal1; // We do not care which one is from where. match(&Sel, m_Select(m_Value(), m_Value(SelVal0), m_Value(SelVal1))); diff --git a/llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll b/llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll index 6eb21466e603..1c768f9d0818 100644 --- a/llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll +++ b/llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll @@ -19,7 +19,7 @@ define i32 @p0_ult_65536(i32 %x, i32 %y) { ; CHECK-LABEL: @p0_ult_65536( ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof !0 +; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof [[PROF0:![0-9]+]] ; CHECK-NEXT: ret i32 [[R]] ; %t = icmp ult i32 %x, 65536 @@ -331,6 +331,33 @@ define i32 @n26_all_good1(i32 %x, i32 %y) { ret i32 %r } +; https://llvm.org/PR52684 +; Do not infinite loop by opposing 'ult' canonicalization. +define i32 @ult_inf_loop(i32 %x) { +; CHECK-LABEL: @ult_inf_loop( +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 2 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 1, i32 -3 +; CHECK-NEXT: ret i32 [[SEL]] +; + %add = add i32 %x, -1 + %cmp = icmp ult i32 %add, 2 + %sel = select i1 %cmp, i32 1, i32 -3 + ret i32 %sel +} + +define <2 x i32> @ult_inf_loop_vec(<2 x i32> %x) { +; CHECK-LABEL: @ult_inf_loop_vec( +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 38, i32 38> +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 -4, i32 -4> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i32> <i32 -5, i32 -5>, <2 x i32> <i32 3, i32 3> +; CHECK-NEXT: ret <2 x i32> [[SEL]] +; + %add = add <2 x i32> %x, <i32 42, i32 42> + %cmp = icmp ugt <2 x i32> %add, <i32 3, i32 3> + %sel = select <2 x i1> %cmp, <2 x i32> <i32 -5, i32 -5>, <2 x i32> <i32 3, i32 3> + ret <2 x i32> %sel +} ; CHECK: !0 = !{!"branch_weights", i32 1, i32 2000} |