1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00

[InstCombine] return when SimplifyAssociativeOrCommutative makes a change

This bug was created by rL335258 because we used to always call instsimplify
after trying the associative folds. After that change it became possible
for subsequent folds to encounter unsimplified code (and potentially assert
because of it). 

Instead of carrying changed state through instcombine, we can just return 
immediately. This allows instsimplify to run, so we can continue assuming
that easy folds have already occurred.

llvm-svn: 336965
This commit is contained in:
Sanjay Patel 2018-07-13 01:18:07 +00:00
parent 5579dfa88e
commit 97dd061531
4 changed files with 82 additions and 12 deletions

View File

@ -1126,7 +1126,9 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -1367,6 +1369,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// TODO(jingyue): Consider willNotOverflowSignedAdd and // TODO(jingyue): Consider willNotOverflowSignedAdd and
// willNotOverflowUnsignedAdd to reduce the number of invocations of // willNotOverflowUnsignedAdd to reduce the number of invocations of
// computeKnownBits. // computeKnownBits.
bool Changed = false;
if (!I.hasNoSignedWrap() && willNotOverflowSignedAdd(LHS, RHS, I)) { if (!I.hasNoSignedWrap() && willNotOverflowSignedAdd(LHS, RHS, I)) {
Changed = true; Changed = true;
I.setHasNoSignedWrap(true); I.setHasNoSignedWrap(true);
@ -1388,7 +1391,9 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -1471,7 +1476,7 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
} }
return Changed ? &I : nullptr; return nullptr;
} }
/// Optimize pointer differences into the same array into a size. Consider: /// Optimize pointer differences into the same array into a size. Consider:

View File

@ -1405,7 +1405,9 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -1648,7 +1650,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
A->getType()->isIntOrIntVectorTy(1)) A->getType()->isIntOrIntVectorTy(1))
return SelectInst::Create(A, Op0, Constant::getNullValue(I.getType())); return SelectInst::Create(A, Op0, Constant::getNullValue(I.getType()));
return Changed ? &I : nullptr; return nullptr;
} }
/// Given an OR instruction, check to see if this is a bswap idiom. If so, /// Given an OR instruction, check to see if this is a bswap idiom. If so,
@ -2020,7 +2022,9 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -2287,7 +2291,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
} }
} }
return Changed ? &I : nullptr; return nullptr;
} }
/// A ^ B can be specified using other logic ops in a variety of patterns. We /// A ^ B can be specified using other logic ops in a variety of patterns. We
@ -2474,7 +2478,9 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -2785,5 +2791,5 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
} }
} }
return Changed ? &I : nullptr; return nullptr;
} }

View File

@ -130,7 +130,9 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -393,6 +395,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
} }
} }
bool Changed = false;
if (!I.hasNoSignedWrap() && willNotOverflowSignedMul(Op0, Op1, I)) { if (!I.hasNoSignedWrap() && willNotOverflowSignedMul(Op0, Op1, I)) {
Changed = true; Changed = true;
I.setHasNoSignedWrap(true); I.setHasNoSignedWrap(true);
@ -412,7 +415,9 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
SQ.getWithInstruction(&I))) SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V); return replaceInstUsesWith(I, V);
bool Changed = SimplifyAssociativeOrCommutative(I); if (SimplifyAssociativeOrCommutative(I))
return &I;
if (Instruction *X = foldShuffledBinop(I)) if (Instruction *X = foldShuffledBinop(I))
return X; return X;
@ -542,7 +547,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
} }
} }
return Changed ? &I : nullptr; return nullptr;
} }
/// Fold a divide or remainder with a select instruction divisor when one of the /// Fold a divide or remainder with a select instruction divisor when one of the

View File

@ -199,3 +199,57 @@ define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) {
ret <2 x i1> %and ret <2 x i1> %and
} }
; This is a fuzzer-generated test that would assert because
; we'd get into foldAndOfICmps() without running InstSimplify
; on an 'and' that should have been killed. It's not obvious
; why, but removing anything hides the bug, hence the long test.
define void @simplify_before_foldAndOfICmps() {
; CHECK-LABEL: @simplify_before_foldAndOfICmps(
; CHECK-NEXT: [[A8:%.*]] = alloca i16, align 2
; CHECK-NEXT: [[L7:%.*]] = load i16, i16* [[A8]], align 2
; CHECK-NEXT: [[C10:%.*]] = icmp ult i16 [[L7]], 2
; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0
; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[C10]]
; CHECK-NEXT: [[L7_LOBIT:%.*]] = ashr i16 [[L7]], 15
; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[L7_LOBIT]] to i64
; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, i1* null, i64 [[TMP1]]
; CHECK-NEXT: store i16 [[L7]], i16* undef, align 2
; CHECK-NEXT: store i1 [[C18]], i1* undef, align 1
; CHECK-NEXT: store i1* [[G26]], i1** undef, align 8
; CHECK-NEXT: ret void
;
%A8 = alloca i16
%L7 = load i16, i16* %A8
%G21 = getelementptr i16, i16* %A8, i8 -1
%B11 = udiv i16 %L7, -1
%G4 = getelementptr i16, i16* %A8, i16 %B11
%L2 = load i16, i16* %G4
%L = load i16, i16* %G4
%B23 = mul i16 %B11, %B11
%L4 = load i16, i16* %A8
%B21 = sdiv i16 %L7, %L4
%B7 = sub i16 0, %B21
%B18 = mul i16 %B23, %B7
%C10 = icmp ugt i16 %L, %B11
%B20 = and i16 %L7, %L2
%B1 = mul i1 %C10, true
%C5 = icmp sle i16 %B21, %L
%C11 = icmp ule i16 %B21, %L
%C7 = icmp slt i16 %B20, 0
%B29 = srem i16 %L4, %B18
%B15 = add i1 %C7, %C10
%B19 = add i1 %C11, %B15
%C6 = icmp sge i1 %C11, %B19
%B33 = or i16 %B29, %L4
%C13 = icmp uge i1 %C5, %B1
%C3 = icmp ult i1 %C13, %C6
store i16 undef, i16* %G21
%C18 = icmp ule i1 %C10, %C7
%G26 = getelementptr i1, i1* null, i1 %C3
store i16 %B33, i16* undef
store i1 %C18, i1* undef
store i1* %G26, i1** undef
ret void
}