summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorJuergen Ributzka <juergen@apple.com>2014-01-24 06:47:57 +0000
committerJuergen Ributzka <juergen@apple.com>2014-01-24 06:47:57 +0000
commite758ddcd16f701225ac673c5f38e2e04b9d24faa (patch)
treee657861491a7d737167b0c6ed7ebc81ae3c06186 /llvm
parent05ae2d671549d080ec81627299ccd61809355c29 (diff)
downloadbcm5719-llvm-e758ddcd16f701225ac673c5f38e2e04b9d24faa.tar.gz
bcm5719-llvm-e758ddcd16f701225ac673c5f38e2e04b9d24faa.zip
[X86] Prevent the creation of redundant ops for sadd and ssub with overflow.
This commit teaches the X86 backend to create the same X86 instructions when it lowers an sadd/ssub with overflow intrinsic and a conditional branch that uses that overflow result. This allows SelectionDAG to recognize and remove one of the redundant operations. This fixes <rdar://problem/15874016> and <rdar://problem/15661073>. Reviewed by Nadav llvm-svn: 199976
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp19
-rw-r--r--llvm/test/CodeGen/X86/saddo-redundant-add.ll34
2 files changed, 51 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 4b30ff67c9f..03eb57a4084 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -10715,11 +10715,26 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
unsigned X86Opcode;
unsigned X86Cond;
SDVTList VTs;
+ // Keep this in sync with LowerXALUO, otherwise we might create redundant
+ // instructions that can't be removed afterwards (i.e. X86ISD::ADD and
+ // X86ISD::INC).
switch (CondOpcode) {
case ISD::UADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_B; break;
- case ISD::SADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break;
+ case ISD::SADDO:
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS))
+ if (C->isOne()) {
+ X86Opcode = X86ISD::INC; X86Cond = X86::COND_O;
+ break;
+ }
+ X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break;
case ISD::USUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_B; break;
- case ISD::SSUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break;
+ case ISD::SSUBO:
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS))
+ if (C->isOne()) {
+ X86Opcode = X86ISD::DEC; X86Cond = X86::COND_O;
+ break;
+ }
+ X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break;
case ISD::UMULO: X86Opcode = X86ISD::UMUL; X86Cond = X86::COND_O; break;
case ISD::SMULO: X86Opcode = X86ISD::SMUL; X86Cond = X86::COND_O; break;
default: llvm_unreachable("unexpected overflowing operator");
diff --git a/llvm/test/CodeGen/X86/saddo-redundant-add.ll b/llvm/test/CodeGen/X86/saddo-redundant-add.ll
new file mode 100644
index 00000000000..c56c68674a4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/saddo-redundant-add.ll
@@ -0,0 +1,34 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
+
+define void @redundant_add(i64 %n) {
+; Check that we don't create two additions for the sadd.with.overflow.
+; CHECK-LABEL: redundant_add
+; CHECK-NOT: leaq
+; CHECK-NOT: addq
+; CHECK: incq
+; CHECK-NEXT: jno
+entry:
+ br label %exit_check
+
+exit_check:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+ %c = icmp slt i64 %i, %n
+ br i1 %c, label %loop, label %exit
+
+loop:
+ %i.o = tail call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %i, i64 1)
+ %i.next = extractvalue { i64, i1 } %i.o, 0
+ %o = extractvalue { i64, i1 } %i.o, 1
+ br i1 %o, label %overflow, label %exit_check
+
+exit:
+ ret void
+
+overflow:
+ tail call void @llvm.trap()
+ unreachable
+}
+
+declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64)
+declare void @llvm.trap()
+
OpenPOWER on IntegriCloud