[llvm-commits] CVS: llvm/lib/Target/CBackend/Writer.cpp

Reid Spencer reid at x10sys.com
Wed Oct 25 23:16:28 PDT 2006



Changes in directory llvm/lib/Target/CBackend:

Writer.cpp updated: 1.274 -> 1.275
---
Log message:

For PR950: http://llvm.org/PR950 :
Make necessary changes to support DIV -> [SUF]Div. This changes llvm to
have three division instructions: signed, unsigned, floating point. The
bytecode and assembler are bacwards compatible, however.


---
Diffs of the changes:  (+161 -7)

 Writer.cpp |  168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 161 insertions(+), 7 deletions(-)


Index: llvm/lib/Target/CBackend/Writer.cpp
diff -u llvm/lib/Target/CBackend/Writer.cpp:1.274 llvm/lib/Target/CBackend/Writer.cpp:1.275
--- llvm/lib/Target/CBackend/Writer.cpp:1.274	Sun Oct 22 04:58:21 2006
+++ llvm/lib/Target/CBackend/Writer.cpp	Thu Oct 26 01:15:43 2006
@@ -121,6 +121,8 @@
     
     void writeOperand(Value *Operand);
     void writeOperandInternal(Value *Operand);
+    void writeOperandWithCast(Value* Operand, unsigned Opcode);
+    bool writeInstructionCast(const Instruction &I);
 
   private :
     void lowerIntrinsics(Function &F);
@@ -136,6 +138,8 @@
     void printLoop(Loop *L);
 
     void printConstant(Constant *CPV);
+    void printConstantWithCast(Constant *CPV, unsigned Opcode);
+    bool printConstExprCast(const ConstantExpr *CE);
     void printConstantArray(ConstantArray *CPA);
     void printConstantPacked(ConstantPacked *CP);
 
@@ -586,7 +590,9 @@
     case Instruction::Add:
     case Instruction::Sub:
     case Instruction::Mul:
-    case Instruction::Div:
+    case Instruction::SDiv:
+    case Instruction::UDiv:
+    case Instruction::FDiv:
     case Instruction::Rem:
     case Instruction::And:
     case Instruction::Or:
@@ -600,12 +606,15 @@
     case Instruction::Shl:
     case Instruction::Shr:
       Out << '(';
-      printConstant(CE->getOperand(0));
+      bool NeedsClosingParens = printConstExprCast(CE); 
+      printConstantWithCast(CE->getOperand(0), CE->getOpcode());
       switch (CE->getOpcode()) {
       case Instruction::Add: Out << " + "; break;
       case Instruction::Sub: Out << " - "; break;
       case Instruction::Mul: Out << " * "; break;
-      case Instruction::Div: Out << " / "; break;
+      case Instruction::UDiv: 
+      case Instruction::SDiv: 
+      case Instruction::FDiv: Out << " / "; break;
       case Instruction::Rem: Out << " % "; break;
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
@@ -620,7 +629,9 @@
       case Instruction::Shr: Out << " >> "; break;
       default: assert(0 && "Illegal opcode here!");
       }
-      printConstant(CE->getOperand(1));
+      printConstantWithCast(CE->getOperand(1), CE->getOpcode());
+      if (NeedsClosingParens)
+        Out << "))";
       Out << ')';
       return;
 
@@ -805,6 +816,71 @@
   }
 }
 
+// Some constant expressions need to be casted back to the original types
+// because their operands were casted to the expected type. This function takes
+// care of detecting that case and printing the cast for the ConstantExpr.
+bool CWriter::printConstExprCast(const ConstantExpr* CE) {
+  bool Result = false;
+  const Type* Ty = CE->getOperand(0)->getType();
+  switch (CE->getOpcode()) {
+  case Instruction::UDiv: Result = Ty->isSigned(); break;
+  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  default: break;
+  }
+  if (Result) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return Result;
+}
+
+//  Print a constant assuming that it is the operand for a given Opcode. The
+//  opcodes that care about sign need to cast their operands to the expected
+//  type before the operation proceeds. This function does the casting.
+void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = CPV->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Constant is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::UDiv:
+      // For UDiv to have unsigned operands
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::SDiv:
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted constnat if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    printConstant(CPV);
+    Out << ")";
+  } else 
+    writeOperand(CPV);
+
+}
+
 void CWriter::writeOperandInternal(Value *Operand) {
   if (Instruction *I = dyn_cast<Instruction>(Operand))
     if (isInlinableInst(*I) && !isDirectAlloca(I)) {
@@ -833,6 +909,72 @@
     Out << ')';
 }
 
+// Some instructions need to have their result value casted back to the 
+// original types because their operands were casted to the expected type. 
+// This function takes care of detecting that case and printing the cast 
+// for the Instruction.
+bool CWriter::writeInstructionCast(const Instruction &I) {
+  bool Result = false;
+  const Type* Ty = I.getOperand(0)->getType();
+  switch (I.getOpcode()) {
+  case Instruction::UDiv: Result = Ty->isSigned(); break;
+  case Instruction::SDiv: Result = Ty->isUnsigned(); break;
+  default: break;
+  }
+  if (Result) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return Result;
+}
+
+// Write the operand with a cast to another type based on the Opcode being used.
+// This will be used in cases where an instruction has specific type
+// requirements (usually signedness) for its operands. 
+void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = Operand->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Operand is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::UDiv:
+      // For UDiv to have unsigned operands
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::SDiv:
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted operand if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    writeOperand(Operand);
+    Out << ")";
+  } else 
+    writeOperand(Operand);
+
+}
+
 // generateCompilerSpecificCode - This is where we add conditional compilation
 // directives to cater to specific compilers as need be.
 //
@@ -1642,13 +1784,23 @@
     writeOperand(I.getOperand(1));
     Out << ")";
   } else {
-    writeOperand(I.getOperand(0));
+
+    // Write out the cast of the instruction's value back to the proper type
+    // if necessary.
+    bool NeedsClosingParens = writeInstructionCast(I);
+
+    // Certain instructions require the operand to be forced to a specific type
+    // so we use writeOperandWithCast here instead of writeOperand. Similarly
+    // below for operand 1
+    writeOperandWithCast(I.getOperand(0), I.getOpcode());
 
     switch (I.getOpcode()) {
     case Instruction::Add: Out << " + "; break;
     case Instruction::Sub: Out << " - "; break;
     case Instruction::Mul: Out << '*'; break;
-    case Instruction::Div: Out << '/'; break;
+    case Instruction::UDiv:
+    case Instruction::SDiv: 
+    case Instruction::FDiv: Out << '/'; break;
     case Instruction::Rem: Out << '%'; break;
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
@@ -1664,7 +1816,9 @@
     default: std::cerr << "Invalid operator type!" << I; abort();
     }
 
-    writeOperand(I.getOperand(1));
+    writeOperandWithCast(I.getOperand(1), I.getOpcode());
+    if (NeedsClosingParens)
+      Out << "))";
   }
 
   if (needsCast) {






More information about the llvm-commits mailing list