Rewrite TargetMaterializeConstant splitting it out into two functions
authorEric Christopher <echristo@apple.com>
Thu, 9 Sep 2010 00:19:41 +0000 (00:19 +0000)
committerEric Christopher <echristo@apple.com>
Thu, 9 Sep 2010 00:19:41 +0000 (00:19 +0000)
for integer and fp constants. Implement todo to use vfp3 instructions
to materialize easy constants if we can.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113453 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMFastISel.cpp

index dabfe9c9f2ff504482d274ee3b8cacd4c43fe15a..ca42079eb808f3218e00503b93906666c654d045 100644 (file)
@@ -124,6 +124,8 @@ class ARMFastISel : public FastISel {
     bool ARMLoadAlloca(const Instruction *I, EVT VT);
     bool ARMStoreAlloca(const Instruction *I, unsigned SrcReg, EVT VT);
     bool ARMComputeRegOffset(const Value *Obj, unsigned &Reg, int &Offset);
+    unsigned ARMMaterializeFP(const ConstantFP *CFP, EVT VT);
+    unsigned ARMMaterializeInt(const Constant *C);
     
     bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR);
     const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB);
@@ -323,18 +325,40 @@ unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT,
   return ResultReg;
 }
 
-unsigned ARMFastISel::TargetMaterializeConstant(const Constant *C) {
-  EVT VT = TLI.getValueType(C->getType(), true);
-
-  // Only handle simple types.
-  if (!VT.isSimple()) return 0;
-
-  // Handle double width floating point?
-  if (VT.getSimpleVT().SimpleTy == MVT::f64) return 0;
+// For double width floating point we need to materialize two constants
+// (the high and the low) into integer registers then use a move to get
+// the combined constant into an FP reg.
+unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, EVT VT) {
+  const APFloat Val = CFP->getValueAPF();
+  bool is64bit = VT.getSimpleVT().SimpleTy == MVT::f64;
   
-  // TODO: Theoretically we could materialize fp constants directly with
-  // instructions from VFP3.
+  // This checks to see if we can use VFP3 instructions to materialize
+  // a constant, otherwise we have to go through the constant pool.
+  if (TLI.isFPImmLegal(Val, VT)) {
+    unsigned Opc = is64bit ? ARM::FCONSTD : ARM::FCONSTS;
+    unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
+    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc),
+                            DestReg)
+                    .addFPImm(CFP));
+    return DestReg;
+  }
+  
+  // No 64-bit at the moment.
+  if (is64bit) return 0;
+  
+  // Load this from the constant pool.
+  unsigned DestReg = ARMMaterializeInt(cast<Constant>(CFP));
+
+  // If we have a floating point constant we expect it in a floating point
+  // register.
+  unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT));
+  AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
+                          TII.get(ARM::VMOVRS), MoveReg)
+                  .addReg(DestReg));
+  return MoveReg;
+}
 
+unsigned ARMFastISel::ARMMaterializeInt(const Constant *C) {
   // MachineConstantPool wants an explicit alignment.
   unsigned Align = TD.getPrefTypeAlignment(C->getType());
   if (Align == 0) {
@@ -353,21 +377,21 @@ unsigned ARMFastISel::TargetMaterializeConstant(const Constant *C) {
                             TII.get(ARM::LDRcp))
                             .addReg(DestReg).addConstantPoolIndex(Idx)
                     .addReg(0).addImm(0));
-                  
-  // If we have a floating point constant we expect it in a floating point
-  // register.
-  // TODO: Make this use ARMBaseInstrInfo::copyPhysReg.
-  if (C->getType()->isFloatTy()) {
-    unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT));
-    AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
-                            TII.get(ARM::VMOVRS), MoveReg)
-                    .addReg(DestReg));
-    return MoveReg;
-  }
     
   return DestReg;
 }
 
+unsigned ARMFastISel::TargetMaterializeConstant(const Constant *C) {
+  EVT VT = TLI.getValueType(C->getType(), true);
+
+  // Only handle simple types.
+  if (!VT.isSimple()) return 0;
+
+  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
+    return ARMMaterializeFP(CFP, VT);
+  return ARMMaterializeInt(C);
+}
+
 bool ARMFastISel::isTypeLegal(const Type *Ty, EVT &VT) {
   VT = TLI.getValueType(Ty, true);