summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2021-12-14 10:46:25 -0500
committerSanjay Patel <spatel@rotateright.com>2021-12-14 11:18:36 -0500
commitbb2fc19c6355d990a4cfb94be20528fbe37950a8 (patch)
tree0bebf13ed4ed7a698fc16b2164a25e9a5f87592e
parentd2be9ae0da2f440a0d42f928d33f5797e2a84500 (diff)
downloadllvm-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.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}