Add support for multiple results to the printer/parser, add support
for forward references to the parser, add initial support for SSA
use-list iteration and RAUW.

PiperOrigin-RevId: 205484031
diff --git a/lib/IR/AsmPrinter.cpp b/lib/IR/AsmPrinter.cpp
index b56c775..ff6ce3e 100644
--- a/lib/IR/AsmPrinter.cpp
+++ b/lib/IR/AsmPrinter.cpp
@@ -519,14 +519,30 @@
     valueIDs[value] = nextValueID++;
   }
 
-  void printValueID(const SSAValue *value) const {
-    // TODO: If this is the result of an operation with multiple results, look
-    // up the first result, and print the #32 syntax.
-    auto it = valueIDs.find(value);
-    if (it != valueIDs.end())
-      os << '%' << it->getSecond();
-    else
+  void printValueID(const SSAValue *value,
+                    bool dontPrintResultNo = false) const {
+    int resultNo = -1;
+    auto lookupValue = value;
+
+    // If this is a reference to the result of a multi-result instruction, print
+    // out the # identifier and make sure to map our lookup to the first result
+    // of the instruction.
+    if (auto *result = dyn_cast<InstResult>(value)) {
+      if (result->getOwner()->getNumResults() != 1) {
+        resultNo = result->getResultNumber();
+        lookupValue = result->getOwner()->getResult(0);
+      }
+    }
+
+    auto it = valueIDs.find(lookupValue);
+    if (it == valueIDs.end()) {
       os << "<<INVALID SSA VALUE>>";
+      return;
+    }
+
+    os << '%' << it->getSecond();
+    if (resultNo != -1 && !dontPrintResultNo)
+      os << '#' << resultNo;
   }
 
 private:
@@ -543,7 +559,7 @@
   // Operation this check can go away.
   if (auto *inst = dyn_cast<OperationInst>(op)) {
     if (inst->getNumResults()) {
-      printValueID(inst->getResult(0));
+      printValueID(inst->getResult(0), /*dontPrintResultNo*/ true);
       os << " = ";
     }
   }
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 57cedfe..b925cef 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -19,6 +19,23 @@
 #include "mlir/IR/BasicBlock.h"
 using namespace mlir;
 
+/// Replace all uses of 'this' value with the new value, updating anything in
+/// the IR that uses 'this' to use the other value instead.  When this returns
+/// there are zero uses of 'this'.
+void SSAValue::replaceAllUsesWith(SSAValue *newValue) {
+  assert(this != newValue && "cannot RAUW a value with itself");
+  while (!use_empty()) {
+    use_begin()->set(newValue);
+  }
+}
+
+/// Return the result number of this result.
+unsigned InstResult::getResultNumber() const {
+  // Results are always stored consecutively, so use pointer subtraction to
+  // figure out what number this is.
+  return this - &getOwner()->getInstResults()[0];
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction
 //===----------------------------------------------------------------------===//
@@ -30,20 +47,25 @@
 }
 
 /// Destroy this instruction or one of its subclasses.
-void Instruction::destroy(Instruction *inst) {
-  switch (inst->getKind()) {
+void Instruction::destroy() {
+  switch (getKind()) {
   case Kind::Operation:
-    delete cast<OperationInst>(inst);
+    cast<OperationInst>(this)->destroy();
     break;
   case Kind::Branch:
-    delete cast<BranchInst>(inst);
+    delete cast<BranchInst>(this);
     break;
   case Kind::Return:
-    delete cast<ReturnInst>(inst);
+    delete cast<ReturnInst>(this);
     break;
   }
 }
 
+void OperationInst::destroy() {
+  this->~OperationInst();
+  free(this);
+}
+
 CFGFunction *Instruction::getFunction() const {
   return getBlock()->getFunction();
 }
@@ -60,7 +82,7 @@
                                      MLIRContext *context) {
   auto byteSize = totalSizeToAlloc<InstOperand, InstResult>(operands.size(),
                                                             resultTypes.size());
-  void *rawMem = ::operator new(byteSize);
+  void *rawMem = malloc(byteSize);
 
   // Initialize the OperationInst part of the instruction.
   auto inst = ::new (rawMem) OperationInst(
@@ -141,6 +163,14 @@
   getBlock()->getOperations().erase(this);
 }
 
+/// If this value is the result of an OperationInst, return the instruction
+/// that defines it.
+OperationInst *SSAValue::getDefiningInst() {
+  if (auto *result = dyn_cast<InstResult>(this))
+    return result->getOwner();
+  return nullptr;
+}
+
 //===----------------------------------------------------------------------===//
 // Terminators
 //===----------------------------------------------------------------------===//
@@ -149,7 +179,7 @@
 void TerminatorInst::eraseFromBlock() {
   assert(getBlock() && "Instruction has no parent");
   getBlock()->setTerminator(nullptr);
-  TerminatorInst::destroy(this);
+  destroy();
 }