mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[InstCombine] avoid infinite loops with select folds of constant expressions
This pair of transforms was added recently with: 8591640379ac9175a And could lead to conflicting folds: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399
This commit is contained in:
parent
48ca532a9e
commit
f90ab103b5
@ -2709,13 +2709,15 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
|
||||
// DeMorgan in select form: !a && !b --> !(a || b)
|
||||
// select !a, !b, false --> not (select a, true, b)
|
||||
if (match(&SI, m_LogicalAnd(m_Not(m_Value(A)), m_Not(m_Value(B)))) &&
|
||||
(CondVal->hasOneUse() || TrueVal->hasOneUse()))
|
||||
(CondVal->hasOneUse() || TrueVal->hasOneUse()) &&
|
||||
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr()))
|
||||
return BinaryOperator::CreateNot(Builder.CreateSelect(A, One, B));
|
||||
|
||||
// DeMorgan in select form: !a || !b --> !(a && b)
|
||||
// select !a, true, !b --> not (select a, b, false)
|
||||
if (match(&SI, m_LogicalOr(m_Not(m_Value(A)), m_Not(m_Value(B)))) &&
|
||||
(CondVal->hasOneUse() || FalseVal->hasOneUse()))
|
||||
(CondVal->hasOneUse() || FalseVal->hasOneUse()) &&
|
||||
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr()))
|
||||
return BinaryOperator::CreateNot(Builder.CreateSelect(A, B, Zero));
|
||||
|
||||
// select (select a, true, b), true, b -> select a, true, b
|
||||
|
@ -420,3 +420,31 @@ define i1 @not_false_not_use3(i1 %x, i1 %y) {
|
||||
%r = select i1 %notx, i1 false, i1 %noty
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399
|
||||
|
||||
@g1 = external global i16
|
||||
@g2 = external global i16
|
||||
|
||||
define i1 @demorgan_select_infloop1(i1 %L) {
|
||||
; CHECK-LABEL: @demorgan_select_infloop1(
|
||||
; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
|
||||
; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false
|
||||
; CHECK-NEXT: ret i1 [[C15]]
|
||||
;
|
||||
%not.L = xor i1 %L, true
|
||||
%C15 = select i1 %not.L, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false
|
||||
ret i1 %C15
|
||||
}
|
||||
|
||||
|
||||
define i1 @demorgan_select_infloop2(i1 %L) {
|
||||
; CHECK-LABEL: @demorgan_select_infloop2(
|
||||
; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
|
||||
; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true)
|
||||
; CHECK-NEXT: ret i1 [[C15]]
|
||||
;
|
||||
%not.L = xor i1 %L, true
|
||||
%C15 = select i1 %not.L, i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true)
|
||||
ret i1 %C15
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user