[llvm] 0d83e72 - [InstCombine] fix infinite loop from shift transform
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 6 08:29:38 PDT 2021
Author: Sanjay Patel
Date: 2021-09-06T11:13:39-04:00
New Revision: 0d83e7203479d6bc7368d5b94351e4907c2afafc
URL: https://github.com/llvm/llvm-project/commit/0d83e7203479d6bc7368d5b94351e4907c2afafc
DIFF: https://github.com/llvm/llvm-project/commit/0d83e7203479d6bc7368d5b94351e4907c2afafc.diff
LOG: [InstCombine] fix infinite loop from shift transform
I'm not sure if there is a better way or another bug
still here, but this is enough to avoid the loop from:
https://llvm.org/PR51657
The test requires multiple blocks and datalayout to
trigger the problem path.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9d5e5b7dd34e..81f18ee4472e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -696,13 +696,14 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
// Fold shift2(trunc(shift1(x,c1)), c2) -> trunc(shift2(shift1(x,c1),c2))
// If 'shift2' is an ashr, we would have to get the sign bit into a funny
// place. Don't try to do this transformation in this case. Also, we
- // require that the input operand is a shift-by-constant so that we have
- // confidence that the shifts will get folded together. We could do this
+ // require that the input operand is a non-poison shift-by-constant so that we
+ // have confidence that the shifts will get folded together. We could do this
// xform in more cases, but it is unlikely to be profitable.
Instruction *TrOp;
const APInt *TrShiftAmt;
if (I.isLogicalShift() && match(Op0, m_Trunc(m_Instruction(TrOp))) &&
- match(TrOp, m_Shift(m_Value(), m_APInt(TrShiftAmt)))) {
+ match(TrOp, m_Shift(m_Value(), m_APInt(TrShiftAmt))) &&
+ TrShiftAmt->ult(TrOp->getType()->getScalarSizeInBits())) {
Type *SrcTy = TrOp->getType();
// Okay, we'll do this xform. Make the shift of shift.
diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
index 6c1d29d0990e..cbd5d66c6367 100644
--- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
+++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
+target datalayout = "n8:16:32"
+
; Given pattern:
; (trunc (x << Q) to iDst) << K
; we should rewrite it as
@@ -227,3 +229,34 @@ define i16 @shl_tr_shl_constant_shift_amount_uses(i32 %x) {
%r = shl i16 %tr, 4
ret i16 %r
}
+
+; This would infinite loop because we did not process the
+; poison shift before trying to fold shift-of-shift. To reach
+; the problematic transform, it needs a datalayout to specify
+; that the narrow types are legal, but i64 is not.
+
+define i1 @PR51657(i64 %x) {
+; CHECK-LABEL: @PR51657(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 undef, label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
+; CHECK: cond.false:
+; CHECK-NEXT: br label [[COND_END]]
+; CHECK: cond.end:
+; CHECK-NEXT: ret i1 true
+;
+entry:
+ br i1 undef, label %cond.false, label %cond.end
+
+cond.false:
+ %shl = shl i64 %x, 64
+ %conv26 = trunc i64 %shl to i32
+ %t1 = trunc i64 %shl to i8
+ br label %cond.end
+
+cond.end:
+ %cond = phi i32 [ %conv26, %cond.false ], [ 0, %entry ]
+ %t2 = phi i8 [ %t1, %cond.false ], [ 0, %entry ]
+ %conv27 = sext i8 %t2 to i32
+ %eq = icmp eq i32 %cond, %conv27
+ ret i1 %eq
+}
More information about the llvm-commits
mailing list