Subzero: Legalize FP constants directly into memory operands.

Previously, the legalize() function would always force a floating point constant into an xmm register before it could be used in an instruction.  This uses an extra register unnecessarily when the instruction allows a memory operand for that operand.

We improve this by lowering the FP constant operand to an OperandX8632Mem that wraps a ConstantRelocatable representing the label for the constant pool entry, e.g. [.L$float$0].  (This may end up being copied into an xmm register if the instruction doesn't allow a memory operand for that operand.)

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

Review URL: https://codereview.chromium.org/1163943005
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 45d6892..b8b633a 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -4590,6 +4590,7 @@
 
 Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
                                int32_t RegNum) {
+  Type Ty = From->getType();
   // Assert that a physical register is allowed.  To date, all calls
   // to legalize() allow a physical register.  If a physical register
   // needs to be explicitly disallowed, then new code will need to be
@@ -4614,9 +4615,9 @@
       RegIndex = legalizeToVar(Index);
     }
     if (Base != RegBase || Index != RegIndex) {
-      From = OperandX8632Mem::create(
-          Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex,
-          Mem->getShift(), Mem->getSegmentRegister());
+      From =
+          OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex,
+                                  Mem->getShift(), Mem->getSegmentRegister());
     }
 
     if (!(Allowed & Legal_Mem)) {
@@ -4637,17 +4638,27 @@
       // overestimated.  If the constant being lowered is a 64 bit value,
       // then the result should be split and the lo and hi components will
       // need to go in uninitialized registers.
-      if (isVectorType(From->getType()))
-        return makeVectorOfZeros(From->getType(), RegNum);
-      From = Ctx->getConstantZero(From->getType());
+      if (isVectorType(Ty))
+        return makeVectorOfZeros(Ty, RegNum);
+      From = Ctx->getConstantZero(Ty);
     }
     // There should be no constants of vector type (other than undef).
-    assert(!isVectorType(From->getType()));
+    assert(!isVectorType(Ty));
+    // Convert a scalar floating point constant into an explicit
+    // memory operand.
+    if (isScalarFloatingType(Ty)) {
+      Variable *Base = nullptr;
+      std::string Buffer;
+      llvm::raw_string_ostream StrBuf(Buffer);
+      llvm::cast<Constant>(From)->emitPoolLabel(StrBuf);
+      Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
+      From = OperandX8632Mem::create(Func, Ty, Base, Offset);
+    }
     bool NeedsReg = false;
-    if (!(Allowed & Legal_Imm))
+    if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty))
       // Immediate specifically not allowed
       NeedsReg = true;
-    if (!(Allowed & Legal_Mem) && isScalarFloatingType(From->getType()))
+    if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty))
       // On x86, FP constants are lowered to mem operands.
       NeedsReg = true;
     if (NeedsReg) {
diff --git a/tests_lit/llvm2ice_tests/bitcast.ll b/tests_lit/llvm2ice_tests/bitcast.ll
index 3e7c778..40a654c 100644
--- a/tests_lit/llvm2ice_tests/bitcast.ll
+++ b/tests_lit/llvm2ice_tests/bitcast.ll
@@ -10,7 +10,6 @@
 }
 ; CHECK-LABEL: cast_f2i
 ; CHECK: mov eax
-; CHECK: ret
 
 define internal float @cast_i2f(i32 %i) {
 entry:
@@ -19,7 +18,6 @@
 }
 ; CHECK-LABEL: cast_i2f
 ; CHECK: fld DWORD PTR
-; CHECK: ret
 
 define internal i64 @cast_d2ll(double %d) {
 entry:
@@ -28,7 +26,6 @@
 }
 ; CHECK-LABEL: cast_d2ll
 ; CHECK: mov edx
-; CHECK: ret
 
 define internal i64 @cast_d2ll_const() {
 entry:
@@ -36,9 +33,8 @@
   ret i64 %v0
 }
 ; CHECK-LABEL: cast_d2ll_const
-; CHECK: movsd xmm{{.*}},QWORD PTR
-; CHECK: mov edx
-; CHECK: ret
+; CHECK: mov e{{..}},DWORD PTR ds:0x0 {{.*}} .L$double$0
+; CHECK: mov e{{..}},DWORD PTR ds:0x4 {{.*}} .L$double$0
 
 define internal double @cast_ll2d(i64 %ll) {
 entry:
@@ -47,7 +43,6 @@
 }
 ; CHECK-LABEL: cast_ll2d
 ; CHECK: fld QWORD PTR
-; CHECK: ret
 
 define internal double @cast_ll2d_const() {
 entry:
@@ -58,4 +53,3 @@
 ; CHECK: mov {{.*}},0x73ce2ff2
 ; CHECK: mov {{.*}},0xb3a
 ; CHECK: fld QWORD PTR
-; CHECK: ret
diff --git a/tests_lit/llvm2ice_tests/undef.ll b/tests_lit/llvm2ice_tests/undef.ll
index 1f2dd6b..9d9014a 100644
--- a/tests_lit/llvm2ice_tests/undef.ll
+++ b/tests_lit/llvm2ice_tests/undef.ll
@@ -182,7 +182,7 @@
   %val = insertelement <4 x float> %arg, float undef, i32 0
   ret <4 x float> %val
 ; CHECK-LABEL: vector_insertelement_arg2
-; CHECK: movss {{.*}},DWORD PTR {{.*}} .L$float$0
+; CHECK: {{movss|insertps}} {{.*}},DWORD PTR {{.*}} .L$float$0
 }
 
 define float @vector_extractelement_v4f32_index_0() {