[llvm-branch-commits] [llvm-branch] r68906 - in /llvm/branches/Apple/Dib: include/llvm/CodeGen/FastISel.h include/llvm/Target/TargetInstrDesc.h lib/CodeGen/SelectionDAG/FastISel.cpp lib/Target/X86/X86FastISel.cpp test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll

Bill Wendling isanbard at gmail.com
Sun Apr 12 12:30:00 PDT 2009


Author: void
Date: Sun Apr 12 14:29:59 2009
New Revision: 68906

URL: http://llvm.org/viewvc/llvm-project?rev=68906&view=rev
Log:
--- Merging (from foreign repository) r68886 into '.':
U    include/llvm/Target/TargetInstrDesc.h
U    lib/Target/X86/X86FastISel.cpp
--- Merging (from foreign repository) r68887 into '.':
G    lib/Target/X86/X86FastISel.cpp
--- Merging (from foreign repository) r68888 into '.':
U    include/llvm/CodeGen/FastISel.h
U    lib/CodeGen/SelectionDAG/FastISel.cpp
--- Merging (from foreign repository) r68889 into '.':
G    lib/CodeGen/SelectionDAG/FastISel.cpp
--- Merging (from foreign repository) r68890 into '.':
A    test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll
G    lib/Target/X86/X86FastISel.cpp

Added:
    llvm/branches/Apple/Dib/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll
Modified:
    llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h
    llvm/branches/Apple/Dib/include/llvm/Target/TargetInstrDesc.h
    llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp
    llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp

Modified: llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h?rev=68906&r1=68905&r2=68906&view=diff

==============================================================================
--- llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h Sun Apr 12 14:29:59 2009
@@ -279,7 +279,7 @@
   /// the CFG.
   void FastEmitBranch(MachineBasicBlock *MBB);
 
-  void UpdateValueMap(Value* I, unsigned Reg);
+  unsigned UpdateValueMap(Value* I, unsigned Reg);
 
   unsigned createResultReg(const TargetRegisterClass *RC);
   

Modified: llvm/branches/Apple/Dib/include/llvm/Target/TargetInstrDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/include/llvm/Target/TargetInstrDesc.h?rev=68906&r1=68905&r2=68906&view=diff

==============================================================================
--- llvm/branches/Apple/Dib/include/llvm/Target/TargetInstrDesc.h (original)
+++ llvm/branches/Apple/Dib/include/llvm/Target/TargetInstrDesc.h Sun Apr 12 14:29:59 2009
@@ -203,6 +203,24 @@
   const unsigned *getImplicitDefs() const {
     return ImplicitDefs;
   }
+  
+  /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly
+  /// uses the specified physical register.
+  bool hasImplicitUseOfPhysReg(unsigned Reg) const {
+    if (const unsigned *ImpUses = ImplicitUses)
+      for (; *ImpUses; ++ImpUses)
+        if (*ImpUses == Reg) return true;
+    return false;
+  }
+  
+  /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly
+  /// defines the specified physical register.
+  bool hasImplicitDefOfPhysReg(unsigned Reg) const {
+    if (const unsigned *ImpDefs = ImplicitDefs)
+      for (; *ImpDefs; ++ImpDefs)
+        if (*ImpDefs == Reg) return true;
+    return false;
+  }
 
   /// getRegClassBarriers - Return a list of register classes that are
   /// completely clobbered by this machine instruction. For example, on X86

Modified: llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=68906&r1=68905&r2=68906&view=diff

==============================================================================
--- llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp Sun Apr 12 14:29:59 2009
@@ -145,16 +145,21 @@
 /// NOTE: This is only necessary because we might select a block that uses
 /// a value before we select the block that defines the value.  It might be
 /// possible to fix this by selecting blocks in reverse postorder.
-void FastISel::UpdateValueMap(Value* I, unsigned Reg) {
+unsigned FastISel::UpdateValueMap(Value* I, unsigned Reg) {
   if (!isa<Instruction>(I)) {
     LocalValueMap[I] = Reg;
-    return;
+    return Reg;
   }
-  if (!ValueMap.count(I))
-    ValueMap[I] = Reg;
-  else
-    TII.copyRegToReg(*MBB, MBB->end(), ValueMap[I],
-                     Reg, MRI.getRegClass(Reg), MRI.getRegClass(Reg));
+  
+  unsigned &AssignedReg = ValueMap[I];
+  if (AssignedReg == 0)
+    AssignedReg = Reg;
+  else if (Reg != AssignedReg) {
+    const TargetRegisterClass *RegClass = MRI.getRegClass(Reg);
+    TII.copyRegToReg(*MBB, MBB->end(), AssignedReg,
+                     Reg, RegClass, RegClass);
+  }
+  return AssignedReg;
 }
 
 unsigned FastISel::getRegForGEPIndex(Value *Idx) {

Modified: llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp?rev=68906&r1=68905&r2=68906&view=diff

==============================================================================
--- llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp Sun Apr 12 14:29:59 2009
@@ -23,7 +23,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/GlobalVariable.h"
 #include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
+#include "llvm/IntrinsicInst.h"
 #include "llvm/CodeGen/FastISel.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -112,7 +112,7 @@
 
   bool X86SelectExtractValue(Instruction *I);
 
-  bool X86VisitIntrinsicCall(CallInst &I, unsigned Intrinsic);
+  bool X86VisitIntrinsicCall(IntrinsicInst &I);
   bool X86SelectCall(Instruction *I);
 
   CCAssignFn *CCAssignFnForCall(unsigned CC, bool isTailCall = false);
@@ -777,67 +777,45 @@
     // looking for the SETO/SETB instruction. If an instruction modifies the
     // EFLAGS register before we reach the SETO/SETB instruction, then we can't
     // convert the branch into a JO/JB instruction.
-
-    Value *Agg = EI->getAggregateOperand();
-
-    if (CallInst *CI = dyn_cast<CallInst>(Agg)) {
-      Function *F = CI->getCalledFunction();
-
-      if (F && F->isDeclaration()) {
-        switch (F->getIntrinsicID()) {
-        default: break;
-        case Intrinsic::sadd_with_overflow:
-        case Intrinsic::uadd_with_overflow: {
-          const MachineInstr *SetMI = 0;
-          unsigned Reg = lookUpRegForValue(EI);
-
-          for (MachineBasicBlock::const_reverse_iterator
-                 RI = MBB->rbegin(), RE = MBB->rend(); RI != RE; ++RI) {
-            const MachineInstr &MI = *RI;
-
-            if (MI.modifiesRegister(Reg)) {
-              unsigned Src, Dst, SrcSR, DstSR;
-
-              if (getInstrInfo()->isMoveInstr(MI, Src, Dst, SrcSR, DstSR)) {
-                Reg = Src;
-                continue;
-              }
-
-              SetMI = &MI;
-              break;
-            }
-
-            const TargetInstrDesc &TID = MI.getDesc();
-            const unsigned *ImpDefs = TID.getImplicitDefs();
-
-            if (TID.hasUnmodeledSideEffects()) break;
-
-            bool ModifiesEFlags = false;
-
-            if (ImpDefs) {
-              for (unsigned u = 0; ImpDefs[u]; ++u)
-                if (ImpDefs[u] == X86::EFLAGS) {
-                  ModifiesEFlags = true;
-                  break;
-                }
+    if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(EI->getAggregateOperand())){
+      if (CI->getIntrinsicID() == Intrinsic::sadd_with_overflow ||
+          CI->getIntrinsicID() == Intrinsic::uadd_with_overflow) {
+        const MachineInstr *SetMI = 0;
+        unsigned Reg = lookUpRegForValue(EI);
+
+        for (MachineBasicBlock::const_reverse_iterator
+               RI = MBB->rbegin(), RE = MBB->rend(); RI != RE; ++RI) {
+          const MachineInstr &MI = *RI;
+
+          if (MI.modifiesRegister(Reg)) {
+            unsigned Src, Dst, SrcSR, DstSR;
+
+            if (getInstrInfo()->isMoveInstr(MI, Src, Dst, SrcSR, DstSR)) {
+              Reg = Src;
+              continue;
             }
 
-            if (ModifiesEFlags) break;
+            SetMI = &MI;
+            break;
           }
 
-          if (SetMI) {
-            unsigned OpCode = SetMI->getOpcode();
+          const TargetInstrDesc &TID = MI.getDesc();
+          if (TID.hasUnmodeledSideEffects() ||
+              TID.hasImplicitDefOfPhysReg(X86::EFLAGS))
+            break;
+        }
 
-            if (OpCode == X86::SETOr || OpCode == X86::SETBr) {
-              BuildMI(MBB, DL, TII.get((OpCode == X86::SETOr) ? 
-                                   X86::JO : X86::JB)).addMBB(TrueMBB);
-              FastEmitBranch(FalseMBB);
-              MBB->addSuccessor(TrueMBB);
-              return true;
-            }
+        if (SetMI) {
+          unsigned OpCode = SetMI->getOpcode();
+
+          if (OpCode == X86::SETOr || OpCode == X86::SETBr) {
+            BuildMI(MBB, DL, TII.get(OpCode == X86::SETOr ? X86::JO : X86::JB))
+              .addMBB(TrueMBB);
+            FastEmitBranch(FalseMBB);
+            MBB->addSuccessor(TrueMBB);
+            return true;
           }
         }
-        }
       }
     }
   }
@@ -1039,30 +1017,26 @@
   ExtractValueInst *EI = cast<ExtractValueInst>(I);
   Value *Agg = EI->getAggregateOperand();
 
-  if (CallInst *CI = dyn_cast<CallInst>(Agg)) {
-    Function *F = CI->getCalledFunction();
-
-    if (F && F->isDeclaration()) {
-      switch (F->getIntrinsicID()) {
-      default: break;
-      case Intrinsic::sadd_with_overflow:
-      case Intrinsic::uadd_with_overflow:
-        // Cheat a little. We know that the registers for "add" and "seto" are
-        // allocated sequentially. However, we only keep track of the register
-        // for "add" in the value map. Use extractvalue's index to get the
-        // correct register for "seto".
-        UpdateValueMap(I, lookUpRegForValue(Agg) + *EI->idx_begin());
-        return true;
-      }
+  if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(Agg)) {
+    switch (CI->getIntrinsicID()) {
+    default: break;
+    case Intrinsic::sadd_with_overflow:
+    case Intrinsic::uadd_with_overflow:
+      // Cheat a little. We know that the registers for "add" and "seto" are
+      // allocated sequentially. However, we only keep track of the register
+      // for "add" in the value map. Use extractvalue's index to get the
+      // correct register for "seto".
+      UpdateValueMap(I, lookUpRegForValue(Agg) + *EI->idx_begin());
+      return true;
     }
   }
 
   return false;
 }
 
-bool X86FastISel::X86VisitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
+bool X86FastISel::X86VisitIntrinsicCall(IntrinsicInst &I) {
   // FIXME: Handle more intrinsics.
-  switch (Intrinsic) {
+  switch (I.getIntrinsicID()) {
   default: return false;
   case Intrinsic::sadd_with_overflow:
   case Intrinsic::uadd_with_overflow: {
@@ -1071,11 +1045,11 @@
     // instructions are encountered, we use the fact that two registers were
     // created sequentially to get the correct registers for the "sum" and the
     // "overflow bit".
-    MVT VT;
     const Function *Callee = I.getCalledFunction();
     const Type *RetTy =
       cast<StructType>(Callee->getReturnType())->getTypeAtIndex(unsigned(0));
 
+    MVT VT;
     if (!isTypeLegal(RetTy, VT))
       return false;
 
@@ -1089,7 +1063,6 @@
       return false;
 
     unsigned OpC = 0;
-
     if (VT == MVT::i32)
       OpC = X86::ADD32rr;
     else if (VT == MVT::i64)
@@ -1099,11 +1072,24 @@
 
     unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
     BuildMI(MBB, DL, TII.get(OpC), ResultReg).addReg(Reg1).addReg(Reg2);
-    UpdateValueMap(&I, ResultReg);
+    unsigned DestReg1 = UpdateValueMap(&I, ResultReg);
 
-    ResultReg = createResultReg(TLI.getRegClassFor(MVT::i8));
-    BuildMI(MBB, DL, TII.get((Intrinsic == Intrinsic::sadd_with_overflow) ?
-                         X86::SETOr : X86::SETBr), ResultReg);
+    // If the add with overflow is an intra-block value then we just want to
+    // create temporaries for it like normal.  If it is a cross-block value then
+    // UpdateValueMap will return the cross-block register used.  Since we
+    // *really* want the value to be live in the register pair known by
+    // UpdateValueMap, we have to use DestReg1+1 as the destination register in
+    // the cross block case.  In the non-cross-block case, we should just make
+    // another register for the value.
+    if (DestReg1 != ResultReg)
+      ResultReg = DestReg1+1;
+    else
+      ResultReg = createResultReg(TLI.getRegClassFor(MVT::i8));
+    
+    unsigned Opc = X86::SETBr;
+    if (I.getIntrinsicID() == Intrinsic::sadd_with_overflow)
+      Opc = X86::SETOr;
+    BuildMI(MBB, DL, TII.get(Opc), ResultReg);
     return true;
   }
   }
@@ -1118,10 +1104,8 @@
     return false;
 
   // Handle intrinsic calls.
-  if (Function *F = CI->getCalledFunction())
-    if (F->isDeclaration())
-      if (unsigned IID = F->getIntrinsicID())
-        return X86VisitIntrinsicCall(*CI, IID);
+  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI))
+    return X86VisitIntrinsicCall(*II);
 
   // Handle only C and fastcc calling conventions for now.
   CallSite CS(CI);

Added: llvm/branches/Apple/Dib/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll?rev=68906&view=auto

==============================================================================
--- llvm/branches/Apple/Dib/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll (added)
+++ llvm/branches/Apple/Dib/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll Sun Apr 12 14:29:59 2009
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | llc -fast-isel
+; radr://6772169
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin10"
+	type { i32, i1 }		; type %0
+
+declare %0 @llvm.sadd.with.overflow.i32(i32, i32) nounwind
+
+define fastcc i32 @test() nounwind {
+entry:
+	%tmp1 = call %0 @llvm.sadd.with.overflow.i32(i32 1, i32 0)
+	%tmp2 = extractvalue %0 %tmp1, 1
+	br i1 %tmp2, label %.backedge, label %BB3
+
+BB3:
+	%tmp4 = extractvalue %0 %tmp1, 0
+	br label %.backedge
+
+.backedge:
+	ret i32 0
+}





More information about the llvm-branch-commits mailing list