[X86] Avoid emitting unnecessary test instructions.
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 9 Jun 2014 12:34:50 +0000 (12:34 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 9 Jun 2014 12:34:50 +0000 (12:34 +0000)
This patch teaches the backend how to check for the 'NoSignedWrap' flag on
binary operations to improve the emission of 'test' instructions.

If the result of a binary operation is known not to overflow we know that
resetting the Overflow flag is unnecessary and so we can avoid emitting
the test instruction.

Patch by Marcello Maggioni.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210468 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/2014-05-29-factorial.ll [new file with mode: 0644]

index e11522db79e9e149dc79c09e2f2ac32622fe4d1d..df86064d282d50b4399044f7a848ffd2c4499d4d 100644 (file)
@@ -10074,10 +10074,27 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, SDLoc dl,
     break;
   case X86::COND_G: case X86::COND_GE:
   case X86::COND_L: case X86::COND_LE:
-  case X86::COND_O: case X86::COND_NO:
-    NeedOF = true;
+  case X86::COND_O: case X86::COND_NO: {
+    // Check if we really need to set the
+    // Overflow flag. If NoSignedWrap is present
+    // that is not actually needed.
+    switch (Op->getOpcode()) {
+    case ISD::ADD:
+    case ISD::SUB:
+    case ISD::MUL:
+    case ISD::SHL: {
+      const BinaryWithFlagsSDNode *BinNode =
+          cast<BinaryWithFlagsSDNode>(Op.getNode());
+      if (BinNode->hasNoSignedWrap())
+        break;
+    }
+    default:
+      NeedOF = true;
+      break;
+    }
     break;
   }
+  }
   // See if we can use the EFLAGS value from the operand instead of
   // doing a separate TEST. TEST always sets OF and CF to 0, so unless
   // we prove that the arithmetic won't overflow, we can't use OF or CF.
diff --git a/test/CodeGen/X86/2014-05-29-factorial.ll b/test/CodeGen/X86/2014-05-29-factorial.ll
new file mode 100644 (file)
index 0000000..70255bd
--- /dev/null
@@ -0,0 +1,24 @@
+; RUN: llc < %s -march=x86-64 | FileCheck %s
+; CHECK: decq %rdi
+; CHECK-NOT: testq %rdi, %rdi
+
+define i64 @fact2(i64 %x) {
+entry:
+  br label %while.body
+
+while.body:
+  %result.06 = phi i64 [ %mul, %while.body ], [ 1, %entry ]
+  %x.addr.05 = phi i64 [ %dec, %while.body ], [ %x, %entry ]
+  %mul = mul nsw i64 %result.06, %x.addr.05
+  %dec = add nsw i64 %x.addr.05, -1
+  %cmp = icmp sgt i64 %dec, 0
+  br i1 %cmp, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:
+  %mul.lcssa = phi i64 [ %mul, %while.body ]
+  br label %while.end
+
+while.end:
+  %result.0.lcssa = phi i64 [ %mul.lcssa, %while.end.loopexit ]
+  ret i64 %result.0.lcssa
+}