Subzero: Fold icmp into br/select lowering.

Originally there was a peephole-style optimization in lowerIcmp() that looks ahead to see if the next instruction is a conditional branch with the right properties, and if so, folds the icmp and br into a single lowering sequence.

However, sometimes extra instructions come between the icmp and br instructions, disabling the folding even though it would still be possible.

One thought is to do the folding inside lowerBr() instead of lowerIcmp(), by looking backward for a suitable icmp instruction.  The problem here is that the icmp lowering code may leave lowered instructions that can't easily be dead-code eliminated, e.g. instructions lacking a dest variable.

Instead, before lowering a basic block, we do a prepass on the block to identify folding candidates.  For the icmp/br example, the prepass would tentatively delete the icmp instruction and then the br lowering would fold in the icmp.

This folding can also be extended to several producers:
  icmp (i32 operands), icmp (i64 operands), fcmp, trunc .. to i1
and several consumers:
  br, select, sext, zext

This CL starts with 2 combinations: icmp32 paired with br & select.  Other combinations will be added in later CLs.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4162
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4095
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/1141213004
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index d0929a0..2fa0397 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -126,82 +126,85 @@
 void TargetLowering::lower() {
   assert(!Context.atEnd());
   Inst *Inst = Context.getCur();
-  // Mark the current instruction as deleted before lowering,
-  // otherwise the Dest variable will likely get marked as non-SSA.
-  // See Variable::setDefinition().
-  Inst->setDeleted();
-  switch (Inst->getKind()) {
-  case Inst::Alloca:
-    lowerAlloca(llvm::dyn_cast<InstAlloca>(Inst));
-    break;
-  case Inst::Arithmetic:
-    lowerArithmetic(llvm::dyn_cast<InstArithmetic>(Inst));
-    break;
-  case Inst::Assign:
-    lowerAssign(llvm::dyn_cast<InstAssign>(Inst));
-    break;
-  case Inst::Br:
-    lowerBr(llvm::dyn_cast<InstBr>(Inst));
-    break;
-  case Inst::Call:
-    lowerCall(llvm::dyn_cast<InstCall>(Inst));
-    break;
-  case Inst::Cast:
-    lowerCast(llvm::dyn_cast<InstCast>(Inst));
-    break;
-  case Inst::ExtractElement:
-    lowerExtractElement(llvm::dyn_cast<InstExtractElement>(Inst));
-    break;
-  case Inst::Fcmp:
-    lowerFcmp(llvm::dyn_cast<InstFcmp>(Inst));
-    break;
-  case Inst::Icmp:
-    lowerIcmp(llvm::dyn_cast<InstIcmp>(Inst));
-    break;
-  case Inst::InsertElement:
-    lowerInsertElement(llvm::dyn_cast<InstInsertElement>(Inst));
-    break;
-  case Inst::IntrinsicCall: {
-    InstIntrinsicCall *Call = llvm::dyn_cast<InstIntrinsicCall>(Inst);
-    if (Call->getIntrinsicInfo().ReturnsTwice)
-      setCallsReturnsTwice(true);
-    lowerIntrinsicCall(Call);
-    break;
-  }
-  case Inst::Load:
-    lowerLoad(llvm::dyn_cast<InstLoad>(Inst));
-    break;
-  case Inst::Phi:
-    lowerPhi(llvm::dyn_cast<InstPhi>(Inst));
-    break;
-  case Inst::Ret:
-    lowerRet(llvm::dyn_cast<InstRet>(Inst));
-    break;
-  case Inst::Select:
-    lowerSelect(llvm::dyn_cast<InstSelect>(Inst));
-    break;
-  case Inst::Store:
-    lowerStore(llvm::dyn_cast<InstStore>(Inst));
-    break;
-  case Inst::Switch:
-    lowerSwitch(llvm::dyn_cast<InstSwitch>(Inst));
-    break;
-  case Inst::Unreachable:
-    lowerUnreachable(llvm::dyn_cast<InstUnreachable>(Inst));
-    break;
-  case Inst::BundleLock:
-  case Inst::BundleUnlock:
-  case Inst::FakeDef:
-  case Inst::FakeUse:
-  case Inst::FakeKill:
-  case Inst::Target:
-    // These are all Target instruction types and shouldn't be
-    // encountered at this stage.
-    Func->setError("Can't lower unsupported instruction type");
-    break;
-  }
+  Inst->deleteIfDead();
+  if (!Inst->isDeleted()) {
+    // Mark the current instruction as deleted before lowering,
+    // otherwise the Dest variable will likely get marked as non-SSA.
+    // See Variable::setDefinition().
+    Inst->setDeleted();
+    switch (Inst->getKind()) {
+    case Inst::Alloca:
+      lowerAlloca(llvm::cast<InstAlloca>(Inst));
+      break;
+    case Inst::Arithmetic:
+      lowerArithmetic(llvm::cast<InstArithmetic>(Inst));
+      break;
+    case Inst::Assign:
+      lowerAssign(llvm::cast<InstAssign>(Inst));
+      break;
+    case Inst::Br:
+      lowerBr(llvm::cast<InstBr>(Inst));
+      break;
+    case Inst::Call:
+      lowerCall(llvm::cast<InstCall>(Inst));
+      break;
+    case Inst::Cast:
+      lowerCast(llvm::cast<InstCast>(Inst));
+      break;
+    case Inst::ExtractElement:
+      lowerExtractElement(llvm::cast<InstExtractElement>(Inst));
+      break;
+    case Inst::Fcmp:
+      lowerFcmp(llvm::cast<InstFcmp>(Inst));
+      break;
+    case Inst::Icmp:
+      lowerIcmp(llvm::cast<InstIcmp>(Inst));
+      break;
+    case Inst::InsertElement:
+      lowerInsertElement(llvm::cast<InstInsertElement>(Inst));
+      break;
+    case Inst::IntrinsicCall: {
+      InstIntrinsicCall *Call = llvm::cast<InstIntrinsicCall>(Inst);
+      if (Call->getIntrinsicInfo().ReturnsTwice)
+        setCallsReturnsTwice(true);
+      lowerIntrinsicCall(Call);
+      break;
+    }
+    case Inst::Load:
+      lowerLoad(llvm::cast<InstLoad>(Inst));
+      break;
+    case Inst::Phi:
+      lowerPhi(llvm::cast<InstPhi>(Inst));
+      break;
+    case Inst::Ret:
+      lowerRet(llvm::cast<InstRet>(Inst));
+      break;
+    case Inst::Select:
+      lowerSelect(llvm::cast<InstSelect>(Inst));
+      break;
+    case Inst::Store:
+      lowerStore(llvm::cast<InstStore>(Inst));
+      break;
+    case Inst::Switch:
+      lowerSwitch(llvm::cast<InstSwitch>(Inst));
+      break;
+    case Inst::Unreachable:
+      lowerUnreachable(llvm::cast<InstUnreachable>(Inst));
+      break;
+    case Inst::BundleLock:
+    case Inst::BundleUnlock:
+    case Inst::FakeDef:
+    case Inst::FakeUse:
+    case Inst::FakeKill:
+    case Inst::Target:
+      // These are all Target instruction types and shouldn't be
+      // encountered at this stage.
+      Func->setError("Can't lower unsupported instruction type");
+      break;
+    }
 
-  postLower();
+    postLower();
+  }
 
   Context.advanceCur();
   Context.advanceNext();