For PR950:
The long awaited CAST patch. This introduces 12 new instructions into LLVM
to replace the cast instruction. Corresponding changes throughout LLVM are
provided. This passes llvm-test, llvm/test, and SPEC CPUINT2000 with the
exception of 175.vpr which fails only on a slight floating point output
difference.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31931 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 806372a..202c384 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -824,14 +824,14 @@
 /// instruction. This function handles converting div -> [usf]div appropriately.
 /// @brief Convert obsolete BinaryOps opcodes to new values
 static void 
-sanitizeOpCode(OpcodeInfo<Instruction::BinaryOps> &OI, const Type *Ty)
+sanitizeOpcode(OpcodeInfo<Instruction::BinaryOps> &OI, const Type *Ty)
 {
   // If its not obsolete, don't do anything
   if (!OI.obsolete) 
     return;
 
   // If its a packed type we want to use the element type
-  if (const PackedType* PTy = dyn_cast<PackedType>(Ty))
+  if (const PackedType *PTy = dyn_cast<PackedType>(Ty))
     Ty = PTy->getElementType();
 
   // Depending on the opcode ..
@@ -857,11 +857,11 @@
   OI.obsolete = false;
 }
 
-/// This function is similar to the previous overload of sanitizeOpCode but
+/// This function is similar to the previous overload of sanitizeOpcode but
 /// operates on Instruction::OtherOps instead of Instruction::BinaryOps.
 /// @brief Convert obsolete OtherOps opcodes to new values
 static void 
-sanitizeOpCode(OpcodeInfo<Instruction::OtherOps> &OI, const Type *Ty)
+sanitizeOpcode(OpcodeInfo<Instruction::OtherOps> &OI, const Type *Ty)
 {
   // If its not obsolete, don't do anything
   if (!OI.obsolete) 
@@ -1072,6 +1072,7 @@
   BinaryOpInfo                      BinaryOpVal;
   TermOpInfo                        TermOpVal;
   MemOpInfo                         MemOpVal;
+  CastOpInfo                        CastOpVal;
   OtherOpInfo                       OtherOpVal;
   llvm::Module::Endianness          Endianness;
 }
@@ -1147,9 +1148,14 @@
 // Memory Instructions
 %token <MemOpVal> MALLOC ALLOCA FREE LOAD STORE GETELEMENTPTR
 
+// Cast Operators
+%type <CastOpVal> CastOps
+%token <CastOpVal> TRUNC ZEXT SEXT FPTRUNC FPEXT BITCAST
+%token <CastOpVal> UITOFP SITOFP FPTOUI FPTOSI INTTOPTR PTRTOINT
+
 // Other Operators
 %type  <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI_TOK CAST SELECT SHL LSHR ASHR VAARG
+%token <OtherOpVal> PHI_TOK SELECT SHL LSHR ASHR VAARG
 %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
 %token VAARG_old VANEXT_old //OBSOLETE
 
@@ -1182,8 +1188,9 @@
 ArithmeticOps: ADD | SUB | MUL | UDIV | SDIV | FDIV | UREM | SREM | FREM;
 LogicalOps   : AND | OR | XOR;
 SetCondOps   : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
-
-ShiftOps  : SHL | LSHR | ASHR;
+CastOps      : TRUNC | ZEXT | SEXT | FPTRUNC | FPEXT | BITCAST | 
+               UITOFP | SITOFP | FPTOUI | FPTOSI | INTTOPTR | PTRTOINT;
+ShiftOps     : SHL | LSHR | ASHR;
 
 // These are some types that allow classification if we only want a particular 
 // thing... for example, only a signed, unsigned, or integral type.
@@ -1676,16 +1683,31 @@
   };
 
 
-ConstExpr: CAST '(' ConstVal TO Types ')' {
-    if (!$3->getType()->isFirstClassType())
+ConstExpr: CastOps '(' ConstVal TO Types ')' {
+    Constant *Val = $3;
+    const Type *Ty = $5.type->get();
+    if (!Val->getType()->isFirstClassType())
       GEN_ERROR("cast constant expression from a non-primitive type: '" +
-                     $3->getType()->getDescription() + "'!");
-    if (!$5.type->get()->isFirstClassType())
+                     Val->getType()->getDescription() + "'!");
+    if (!Ty->isFirstClassType())
       GEN_ERROR("cast constant expression to a non-primitive type: '" +
-                     $5.type->get()->getDescription() + "'!");
-    $$ = ConstantExpr::getCast($3, $5.type->get());
+                Ty->getDescription() + "'!");
+    if ($1.obsolete) {
+      if (Ty == Type::BoolTy) {
+        // The previous definition of cast to bool was a compare against zero. 
+        // We have to retain that semantic so we do it here.
+        $$ = ConstantExpr::get(Instruction::SetNE, Val, 
+                               Constant::getNullValue(Val->getType()));
+      } else if (Val->getType()->isFloatingPoint() && isa<PointerType>(Ty)) {
+        Constant *CE = ConstantExpr::getFPToUI(Val, Type::ULongTy);
+        $$ = ConstantExpr::getIntToPtr(CE, Ty);
+      } else {
+        $$ = ConstantExpr::getCast(Val, Ty);
+      }
+    } else {
+      $$ = ConstantExpr::getCast($1.opcode, $3, $5.type->get());
+    }
     delete $5.type;
-    CHECK_FOR_ERROR
   }
   | GETELEMENTPTR '(' ConstVal IndexList ')' {
     if (!isa<PointerType>($3->getType()))
@@ -1732,7 +1754,7 @@
       GEN_ERROR("Binary operator types must match!");
     // First, make sure we're dealing with the right opcode by upgrading from
     // obsolete versions.
-    sanitizeOpCode($1,$3->getType());
+    sanitizeOpcode($1, $3->getType());
     CHECK_FOR_ERROR;
 
     // HACK: llvm 1.3 and earlier used to emit invalid pointer constant exprs.
@@ -1777,7 +1799,7 @@
     if (!$3->getType()->isInteger())
       GEN_ERROR("Shift constant expression requires integer operand!");
     // Handle opcode upgrade situations
-    sanitizeOpCode($1, $3->getType());
+    sanitizeOpcode($1, $3->getType());
     CHECK_FOR_ERROR;
     $$ = ConstantExpr::get($1.opcode, $3, $5);
     CHECK_FOR_ERROR
@@ -2296,6 +2318,10 @@
   };
 
 InstructionList : InstructionList Inst {
+    if (CastInst *CI1 = dyn_cast<CastInst>($2))
+      if (CastInst *CI2 = dyn_cast<CastInst>(CI1->getOperand(0)))
+        if (CI2->getParent() == 0)
+          $1->getInstList().push_back(CI2);
     $1->getInstList().push_back($2);
     $$ = $1;
     CHECK_FOR_ERROR
@@ -2527,7 +2553,7 @@
          $1.opcode == Instruction::FRem))
       GEN_ERROR("U/S/FRem not supported on packed types!");
     // Upgrade the opcode from obsolete versions before we do anything with it.
-    sanitizeOpCode($1,$2.type->get());
+    sanitizeOpcode($1,$2.type->get());
     CHECK_FOR_ERROR;
     Value* val1 = getVal($2.type->get(), $3); 
     CHECK_FOR_ERROR
@@ -2586,18 +2612,36 @@
     if (!$2->getType()->isInteger())
       GEN_ERROR("Shift constant expression requires integer operand!");
     // Handle opcode upgrade situations
-    sanitizeOpCode($1, $2->getType());
+    sanitizeOpcode($1, $2->getType());
     CHECK_FOR_ERROR;
     $$ = new ShiftInst($1.opcode, $2, $4);
     CHECK_FOR_ERROR
   }
-  | CAST ResolvedVal TO Types {
-    if (!$4.type->get()->isFirstClassType())
-      GEN_ERROR("cast instruction to a non-primitive type: '" +
-                     $4.type->get()->getDescription() + "'!");
-    $$ = new CastInst($2, $4.type->get());
+  | CastOps ResolvedVal TO Types {
+    Value* Val = $2;
+    const Type* Ty = $4.type->get();
+    if (!Val->getType()->isFirstClassType())
+      GEN_ERROR("cast from a non-primitive type: '" +
+                Val->getType()->getDescription() + "'!");
+    if (!Ty->isFirstClassType())
+      GEN_ERROR("cast to a non-primitive type: '" + Ty->getDescription() +"'!");
+
+    if ($1.obsolete) {
+      if (Ty == Type::BoolTy) {
+        // The previous definition of cast to bool was a compare against zero. 
+        // We have to retain that semantic so we do it here.
+        $$ = new SetCondInst(Instruction::SetNE, $2, 
+                               Constant::getNullValue($2->getType()));
+      } else if (Val->getType()->isFloatingPoint() && isa<PointerType>(Ty)) {
+        CastInst *CI = new FPToUIInst(Val, Type::ULongTy);
+        $$ = new IntToPtrInst(CI, Ty);
+      } else {
+        $$ = CastInst::createInferredCast(Val, Ty);
+      }
+    } else {
+      $$ = CastInst::create($1.opcode, $2, $4.type->get());
+    }
     delete $4.type;
-    CHECK_FOR_ERROR
   }
   | SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
     if ($2->getType() != Type::BoolTy)