[llvm] r199976 - [X86] Prevent the creation of redundant ops for sadd and ssub with overflow.

Juergen Ributzka juergen at apple.com
Thu Jan 23 22:47:57 PST 2014


Author: ributzka
Date: Fri Jan 24 00:47:57 2014
New Revision: 199976

URL: http://llvm.org/viewvc/llvm-project?rev=199976&view=rev
Log:
[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

Added:
    llvm/trunk/test/CodeGen/X86/saddo-redundant-add.ll
Modified:
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=199976&r1=199975&r2=199976&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Jan 24 00:47:57 2014
@@ -10715,11 +10715,26 @@ SDValue X86TargetLowering::LowerBRCOND(S
     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");

Added: llvm/trunk/test/CodeGen/X86/saddo-redundant-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/saddo-redundant-add.ll?rev=199976&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/saddo-redundant-add.ll (added)
+++ llvm/trunk/test/CodeGen/X86/saddo-redundant-add.ll Fri Jan 24 00:47:57 2014
@@ -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()
+





More information about the llvm-commits mailing list