diff options
-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} |