Subzero: x86-64: Allow immediates in 64-bit instructions.

The original code legalized *all* i64 constants into a register move, creating unnecessary instructions and slightly higher register pressure in most cases.

Generally, immediates can be used in 64-bit instructions as long as the immediate can be represented as a sign-extended 32-bit value.

BUG= none
R=jpp@chromium.org

Review URL: https://codereview.chromium.org/2063053002 .
diff --git a/src/IceAssemblerX86BaseImpl.h b/src/IceAssemblerX86BaseImpl.h
index 554f533..85d9302 100644
--- a/src/IceAssemblerX86BaseImpl.h
+++ b/src/IceAssemblerX86BaseImpl.h
@@ -295,7 +295,6 @@
 template <typename TraitsType>
 void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst,
                                        const Immediate &imm) {
-  assert(Ty != IceType_i64 && "i64 not supported yet.");
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
@@ -2641,7 +2640,7 @@
 void AssemblerX86Base<TraitsType>::imul(Type Ty, GPRRegister reg,
                                         const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  assert(Ty == IceType_i16 || Ty == IceType_i32);
+  assert(Ty == IceType_i16 || Ty == IceType_i32 || Ty == IceType_i64);
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
   emitRexRB(Ty, reg, reg);
diff --git a/src/IceInstX86BaseImpl.h b/src/IceInstX86BaseImpl.h
index bc5811e..cfc36d4 100644
--- a/src/IceInstX86BaseImpl.h
+++ b/src/IceInstX86BaseImpl.h
@@ -738,6 +738,10 @@
                               Mem->toAsmAddress(Asm, Target, IsLea));
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
+  } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
+    assert(Traits::Is64Bit);
+    assert(Utils::IsInt(32, Imm->getValue()));
+    (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
@@ -765,6 +769,10 @@
     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
+  } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
+    assert(Traits::Is64Bit);
+    assert(Utils::IsInt(32, Imm->getValue()));
+    (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
@@ -816,6 +824,10 @@
     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
+  } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
+    assert(Traits::Is64Bit);
+    assert(Utils::IsInt(32, Imm->getValue()));
+    (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
   } else {
     llvm_unreachable("Unexpected operand type");
   }
@@ -2042,7 +2054,8 @@
   Type SrcTy = Src->getType();
   Type DestTy = this->getDest()->getType();
   if (Traits::Is64Bit && DestTy == IceType_i64 &&
-      llvm::isa<ConstantInteger64>(Src)) {
+      llvm::isa<ConstantInteger64>(Src) &&
+      !Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
     Str << "\t"
            "movabs"
            "\t";
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 6b25823..fcfe6ed 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -2228,21 +2228,24 @@
     break;
   case InstArithmetic::Shl:
     _mov(T, Src0);
-    if (!llvm::isa<ConstantInteger32>(Src1))
+    if (!llvm::isa<ConstantInteger32>(Src1) &&
+        !llvm::isa<ConstantInteger64>(Src1))
       Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
     _shl(T, Src1);
     _mov(Dest, T);
     break;
   case InstArithmetic::Lshr:
     _mov(T, Src0);
-    if (!llvm::isa<ConstantInteger32>(Src1))
+    if (!llvm::isa<ConstantInteger32>(Src1) &&
+        !llvm::isa<ConstantInteger64>(Src1))
       Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
     _shr(T, Src1);
     _mov(Dest, T);
     break;
   case InstArithmetic::Ashr:
     _mov(T, Src0);
-    if (!llvm::isa<ConstantInteger32>(Src1))
+    if (!llvm::isa<ConstantInteger32>(Src1) &&
+        !llvm::isa<ConstantInteger64>(Src1))
       Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
     _sar(T, Src1);
     _mov(Dest, T);
@@ -7339,11 +7342,13 @@
     // If the operand is a 64 bit constant integer we need to legalize it to a
     // register in x86-64.
     if (Traits::Is64Bit) {
-      if (llvm::isa<ConstantInteger64>(Const)) {
-        if (RegNum.hasValue()) {
-          assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
+      if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Const)) {
+        if (!Utils::IsInt(32, C64->getValue())) {
+          if (RegNum.hasValue()) {
+            assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
+          }
+          return copyToReg(Const, RegNum);
         }
-        return copyToReg(Const, RegNum);
       }
     }