summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp7
-rw-r--r--llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll29
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}