Generate something sensible for an [SU]ADDO op when the overflow/carry flag is
authorBill Wendling <isanbard@gmail.com>
Wed, 26 Nov 2008 22:37:40 +0000 (22:37 +0000)
committerBill Wendling <isanbard@gmail.com>
Wed, 26 Nov 2008 22:37:40 +0000 (22:37 +0000)
the conditional for the BRCOND statement. For instance, it will generate:

    addl %eax, %ecx
    jo LOF

instead of

    addl %eax, %ecx
    ; About 10 instructions to compare the signs of LHS, RHS, and sum.
    jl LOF

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

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86InstrInfo.h
lib/Target/X86/X86InstrInfo.td

index efe7bac72eb0870d45ab73f42e72f2e0b31a2fa6..13bbf53ebb67b23a7bafc61c27b7a033dd0e7318 100644 (file)
@@ -6150,6 +6150,26 @@ SDValue X86TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) {
 
 SDValue X86TargetLowering::LowerXADDO(SDValue Op, SelectionDAG &DAG,
                                       ISD::NodeType NTy) {
+  SDNode *N = Op.getNode();
+
+  for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
+    SDNode *UseNode = *I;
+
+    if (UseNode->getOpcode() == ISD::BRCOND) {
+      // Lower a branch on the overflow/carry flag into a "JO"/"JC"
+      // instruction. Convert the addition into an actual addition, not just a
+      // pseudo node.
+      SDValue LHS = N->getOperand(0);
+      SDValue RHS = N->getOperand(1);
+      SDValue Sum = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS);
+
+      SDValue Ops[] = { UseNode->getOperand(2), UseNode->getOperand(0) };
+      DAG.SelectNodeTo(UseNode, (NTy == ISD::SADDO) ? X86::JO : X86::JC,
+                       MVT::Other, Ops, 2);
+      return Sum;
+    }
+  }
+
   return SDValue();
 }
 
index 2e449b99316aaddf740e74f841d6ce1233b585ab..ba73f49f883aa149fcb143f7f2fc5cec393d839e 100644 (file)
@@ -1382,6 +1382,8 @@ static X86::CondCode GetCondFromBranchOpc(unsigned BrOpc) {
   case X86::JNP: return X86::COND_NP;
   case X86::JO:  return X86::COND_O;
   case X86::JNO: return X86::COND_NO;
+  case X86::JC:  return X86::COND_C;
+  case X86::JNC: return X86::COND_NC;
   }
 }
 
@@ -1404,6 +1406,8 @@ unsigned X86::GetCondBranchFromCond(X86::CondCode CC) {
   case X86::COND_NP: return X86::JNP;
   case X86::COND_O:  return X86::JO;
   case X86::COND_NO: return X86::JNO;
+  case X86::COND_C:  return X86::JC;
+  case X86::COND_NC: return X86::JNC;
   }
 }
 
@@ -1428,6 +1432,8 @@ X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) {
   case X86::COND_NP: return X86::COND_P;
   case X86::COND_O:  return X86::COND_NO;
   case X86::COND_NO: return X86::COND_O;
+  case X86::COND_C:  return X86::COND_NC;
+  case X86::COND_NC: return X86::COND_C;
   }
 }
 
index cf8be96b0b3930ecbfd292d52116ca088742ff5f..a0e0124676a91b91eeff467199ef6c2a2a1fa7cb 100644 (file)
@@ -41,9 +41,11 @@ namespace X86 {
     COND_NO = 10,
     COND_NP = 11,
     COND_NS = 12,
-    COND_O  = 13,
-    COND_P  = 14,
-    COND_S  = 15,
+    COND_NC = 13,
+    COND_O  = 14,
+    COND_P  = 15,
+    COND_S  = 16,
+    COND_C  = 17,
 
     // Artificial condition codes. These are used by AnalyzeBranch
     // to indicate a block terminated with two conditional branches to
index fd463973fdacd28828f2932587534f86f8239500..e6ec25be133d1ddb1fe6970ffe2d5da8c3c61402 100644 (file)
@@ -235,9 +235,11 @@ def X86_COND_NE  : PatLeaf<(i8 9)>;
 def X86_COND_NO  : PatLeaf<(i8 10)>;
 def X86_COND_NP  : PatLeaf<(i8 11)>;
 def X86_COND_NS  : PatLeaf<(i8 12)>;
-def X86_COND_O   : PatLeaf<(i8 13)>;
-def X86_COND_P   : PatLeaf<(i8 14)>;
-def X86_COND_S   : PatLeaf<(i8 15)>;
+def X86_COND_NC  : PatLeaf<(i8 13)>;
+def X86_COND_O   : PatLeaf<(i8 14)>;
+def X86_COND_P   : PatLeaf<(i8 15)>;
+def X86_COND_S   : PatLeaf<(i8 16)>;
+def X86_COND_C   : PatLeaf<(i8 17)>;
 
 def i16immSExt8  : PatLeaf<(i16 imm), [{
   // i16immSExt8 predicate - True if the 16-bit immediate fits in a 8-bit
@@ -449,6 +451,10 @@ def JO  : IBr<0x80, (ins brtarget:$dst), "jo\t$dst",
               [(X86brcond bb:$dst, X86_COND_O, EFLAGS)]>, TB;
 def JNO : IBr<0x81, (ins brtarget:$dst), "jno\t$dst",
               [(X86brcond bb:$dst, X86_COND_NO, EFLAGS)]>, TB;
+def JC  : IBr<0x82, (ins brtarget:$dst), "jc\t$dst",
+              [(X86brcond bb:$dst, X86_COND_C, EFLAGS)]>, TB;
+def JNC : IBr<0x83, (ins brtarget:$dst), "jnc\t$dst",
+              [(X86brcond bb:$dst, X86_COND_NC, EFLAGS)]>, TB;
 } // Uses = [EFLAGS]
 
 //===----------------------------------------------------------------------===//