summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2017-08-24 01:08:27 +0000
committerHans Wennborg <hans@hanshq.net>2017-08-24 01:08:27 +0000
commitc39ec95d886b2dd1977021cdf7a52dc43a76f8c8 (patch)
tree3679fdf5455d7ce35e5f9f9d67366eca47ef3f4d /llvm
parentc064881a361ce46687eec2695777f092d417496f (diff)
downloadbcm5719-llvm-c39ec95d886b2dd1977021cdf7a52dc43a76f8c8.tar.gz
bcm5719-llvm-c39ec95d886b2dd1977021cdf7a52dc43a76f8c8.zip
[DAG] Fix Node Replacement in PromoteIntBinOp
When one operand is a user of another in a promoted binary operation we may replace and delete the returned value before returning triggering an assertion. Reorder node replacements to prevent this. Fixes PR34137. Landing on behalf of Nirav. Differential Revision: https://reviews.llvm.org/D36581 llvm-svn: 311623
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp28
-rw-r--r--llvm/test/CodeGen/X86/pr34137.ll53
2 files changed, 71 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ab459cd7ea0..e6f2eb5480e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1168,22 +1168,30 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) {
SDValue RV =
DAG.getNode(ISD::TRUNCATE, DL, VT, DAG.getNode(Opc, DL, PVT, NN0, NN1));
- // New replace instances of N0 and N1
- if (Replace0 && N0 && N0.getOpcode() != ISD::DELETED_NODE && NN0 &&
- NN0.getOpcode() != ISD::DELETED_NODE) {
+ // We are always replacing N0/N1's use in N and only need
+ // additional replacements if there are additional uses.
+ Replace0 &= !N0->hasOneUse();
+ Replace1 &= (N0 != N1) && !N1->hasOneUse();
+
+ // Combine Op here so it is presreved past replacements.
+ CombineTo(Op.getNode(), RV);
+
+ // If operands have a use ordering, make sur we deal with
+ // predecessor first.
+ if (Replace0 && Replace1 && N0.getNode()->isPredecessorOf(N1.getNode())) {
+ std::swap(N0, N1);
+ std::swap(NN0, NN1);
+ }
+
+ if (Replace0) {
AddToWorklist(NN0.getNode());
ReplaceLoadWithPromotedLoad(N0.getNode(), NN0.getNode());
}
-
- if (Replace1 && N1 && N1.getOpcode() != ISD::DELETED_NODE && NN1 &&
- NN1.getOpcode() != ISD::DELETED_NODE) {
+ if (Replace1) {
AddToWorklist(NN1.getNode());
ReplaceLoadWithPromotedLoad(N1.getNode(), NN1.getNode());
}
-
- // Deal with Op being deleted.
- if (Op && Op.getOpcode() != ISD::DELETED_NODE)
- return RV;
+ return Op;
}
return SDValue();
}
diff --git a/llvm/test/CodeGen/X86/pr34137.ll b/llvm/test/CodeGen/X86/pr34137.ll
new file mode 100644
index 00000000000..3b767e4f96b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr34137.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+@var_3 = external global i16, align 2
+@var_13 = external global i16, align 2
+@var_212 = external global i64, align 8
+
+define void @pr34127() {
+; CHECK-LABEL: pr34127:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: movzwl {{.*}}(%rip), %eax
+; CHECK-NEXT: movw {{.*}}(%rip), %cx
+; CHECK-NEXT: andw %ax, %cx
+; CHECK-NEXT: andl %eax, %ecx
+; CHECK-NEXT: movl %ecx, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: testw %cx, %cx
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andl %eax, %edx
+; CHECK-NEXT: movq %rdx, {{.*}}(%rip)
+; CHECK-NEXT: movw $0, (%rax)
+; CHECK-NEXT: retq
+entry:
+ %a = alloca i32, align 4
+ %0 = load i16, i16* @var_3, align 2
+ %conv = zext i16 %0 to i32
+ %1 = load i16, i16* @var_3, align 2
+ %conv1 = zext i16 %1 to i32
+ %2 = load i16, i16* @var_13, align 2
+ %conv2 = zext i16 %2 to i32
+ %and = and i32 %conv1, %conv2
+ %and3 = and i32 %conv, %and
+ store i32 %and3, i32* %a, align 4
+ %3 = load i16, i16* @var_3, align 2
+ %conv4 = zext i16 %3 to i32
+ %4 = load i16, i16* @var_3, align 2
+ %conv5 = zext i16 %4 to i32
+ %5 = load i16, i16* @var_13, align 2
+ %conv6 = zext i16 %5 to i32
+ %and7 = and i32 %conv5, %conv6
+ %and8 = and i32 %conv4, %and7
+ %tobool = icmp ne i32 %and8, 0
+ %lnot = xor i1 %tobool, true
+ %conv9 = zext i1 %lnot to i32
+ %6 = load i16, i16* @var_3, align 2
+ %conv10 = zext i16 %6 to i32
+ %and11 = and i32 %conv9, %conv10
+ %conv12 = sext i32 %and11 to i64
+ store i64 %conv12, i64* @var_212, align 8
+ %conv14 = zext i1 undef to i16
+ store i16 %conv14, i16* undef, align 2
+ ret void
+}
OpenPOWER on IntegriCloud