[llvm] r233063 - [mips] Distinguish 'R', 'ZC', and 'm' inline assembly memory constraint.

Daniel Sanders daniel.sanders at imgtec.com
Tue Mar 24 04:26:34 PDT 2015


Author: dsanders
Date: Tue Mar 24 06:26:34 2015
New Revision: 233063

URL: http://llvm.org/viewvc/llvm-project?rev=233063&view=rev
Log:
[mips] Distinguish 'R', 'ZC', and 'm' inline assembly memory constraint.

Summary:
Previous behaviour of 'R' and 'm' has been preserved for now. They will be
improved in subsequent commits.

The offset permitted by ZC varies according to the subtarget since it is
intended to match the restrictions of the pref, ll, and sc instructions.

The restrictions on these instructions are:
* For microMIPS: 12-bit signed offset.
* For Mips32r6/Mips64r6: 9-bit signed offset.
* Otherwise: 16-bit signed offset.

Reviewers: vkalintiris

Reviewed By: vkalintiris

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D8414

Added:
    llvm/trunk/test/CodeGen/Mips/inlineasm_constraint_ZC.ll
Modified:
    llvm/trunk/include/llvm/IR/InlineAsm.h
    llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
    llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
    llvm/trunk/lib/Target/Mips/MipsISelLowering.h
    llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h

Modified: llvm/trunk/include/llvm/IR/InlineAsm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InlineAsm.h?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InlineAsm.h (original)
+++ llvm/trunk/include/llvm/IR/InlineAsm.h Tue Mar 24 06:26:34 2015
@@ -249,6 +249,7 @@ public:
     Constraint_S,
     Constraint_T,
     Constraint_Z,
+    Constraint_ZC,
     Constraint_Zy,
     Constraints_Max = Constraint_Zy,
     Constraints_ShiftAmount = 16,

Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp Tue Mar 24 06:26:34 2015
@@ -437,7 +437,7 @@ bool MipsAsmPrinter::isBlockOnlyReachabl
 
 // Print out an operand for an inline asm expression.
 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                                     unsigned AsmVariant,const char *ExtraCode,
+                                     unsigned AsmVariant, const char *ExtraCode,
                                      raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
@@ -539,18 +539,24 @@ bool MipsAsmPrinter::PrintAsmMemoryOpera
                                            unsigned OpNum, unsigned AsmVariant,
                                            const char *ExtraCode,
                                            raw_ostream &O) {
-  int Offset = 0;
+  assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
+  const MachineOperand &BaseMO = MI->getOperand(OpNum);
+  const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
+  assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
+  assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
+  int Offset = OffsetMO.getImm();
+
   // Currently we are expecting either no ExtraCode or 'D'
   if (ExtraCode) {
     if (ExtraCode[0] == 'D')
-      Offset = 4;
+      Offset += 4;
     else
       return true; // Unknown modifier.
+    // FIXME: M = high order bits
+    // FIXME: L = low order bits
   }
 
-  const MachineOperand &MO = MI->getOperand(OpNum);
-  assert(MO.isReg() && "unexpected inline asm memory operand");
-  O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")";
+  O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) << ")";
 
   return false;
 }

Modified: llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp Tue Mar 24 06:26:34 2015
@@ -232,8 +232,16 @@ SDNode* MipsDAGToDAGISel::Select(SDNode
 bool MipsDAGToDAGISel::
 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
                              std::vector<SDValue> &OutOps) {
-  assert(ConstraintID == InlineAsm::Constraint_m &&
-         "unexpected asm memory constraint");
-  OutOps.push_back(Op);
-  return false;
+  // All memory constraints can at least accept raw pointers.
+  switch(ConstraintID) {
+  default:
+    llvm_unreachable("Unexpected asm memory constraint");
+  case InlineAsm::Constraint_i:
+  case InlineAsm::Constraint_m:
+  case InlineAsm::Constraint_R:
+  case InlineAsm::Constraint_ZC:
+    OutOps.push_back(Op);
+    return false;
+  }
+  return true;
 }

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Tue Mar 24 06:26:34 2015
@@ -3173,6 +3173,10 @@ getConstraintType(const std::string &Con
         return C_Memory;
     }
   }
+
+  if (Constraint == "ZC")
+    return C_Memory;
+
   return TargetLowering::getConstraintType(Constraint);
 }
 

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.h?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.h Tue Mar 24 06:26:34 2015
@@ -507,8 +507,11 @@ namespace llvm {
 
     unsigned getInlineAsmMemConstraint(
         const std::string &ConstraintCode) const override {
-      // FIXME: Map different constraints differently.
-      return InlineAsm::Constraint_m;
+      if (ConstraintCode == "R")
+        return InlineAsm::Constraint_R;
+      else if (ConstraintCode == "ZC")
+        return InlineAsm::Constraint_ZC;
+      return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
     }
 
     bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override;

Modified: llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp Tue Mar 24 06:26:34 2015
@@ -382,6 +382,17 @@ bool MipsSEDAGToDAGISel::selectIntAddr(S
     selectAddrDefault(Addr, Base, Offset);
 }
 
+bool MipsSEDAGToDAGISel::selectAddrRegImm9(SDValue Addr, SDValue &Base,
+                                           SDValue &Offset) const {
+  if (selectAddrFrameIndex(Addr, Base, Offset))
+    return true;
+
+  if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9))
+    return true;
+
+  return false;
+}
+
 bool MipsSEDAGToDAGISel::selectAddrRegImm10(SDValue Addr, SDValue &Base,
                                             SDValue &Offset) const {
   if (selectAddrFrameIndex(Addr, Base, Offset))
@@ -405,6 +416,17 @@ bool MipsSEDAGToDAGISel::selectAddrRegIm
   return false;
 }
 
+bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base,
+                                            SDValue &Offset) const {
+  if (selectAddrFrameIndex(Addr, Base, Offset))
+    return true;
+
+  if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16))
+    return true;
+
+  return false;
+}
+
 bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
                                          SDValue &Offset) const {
   return selectAddrRegImm12(Addr, Base, Offset) ||
@@ -916,6 +938,52 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGI
   return std::make_pair(false, nullptr);
 }
 
+bool MipsSEDAGToDAGISel::
+SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
+                             std::vector<SDValue> &OutOps) {
+  SDValue Base, Offset;
+
+  switch(ConstraintID) {
+  default:
+    llvm_unreachable("Unexpected asm memory constraint");
+  // All memory constraints can at least accept raw pointers.
+  case InlineAsm::Constraint_i:
+  case InlineAsm::Constraint_m:
+  case InlineAsm::Constraint_R:
+    OutOps.push_back(Op);
+    OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));
+    return false;
+  case InlineAsm::Constraint_ZC:
+    // ZC matches whatever the pref, ll, and sc instructions can handle for the
+    // given subtarget.
+    if (Subtarget->inMicroMipsMode()) {
+      // On microMIPS, they can handle 12-bit offsets.
+      if (selectAddrRegImm12(Op, Base, Offset)) {
+        OutOps.push_back(Base);
+        OutOps.push_back(Offset);
+        return false;
+      }
+    } else if (Subtarget->hasMips32r6()) {
+      // On MIPS32r6/MIPS64r6, they can only handle 9-bit offsets.
+      if (selectAddrRegImm9(Op, Base, Offset)) {
+        OutOps.push_back(Base);
+        OutOps.push_back(Offset);
+        return false;
+      }
+    } else if (selectAddrRegImm16(Op, Base, Offset)) {
+      // Prior to MIPS32r6/MIPS64r6, they can handle 16-bit offsets.
+      OutOps.push_back(Base);
+      OutOps.push_back(Offset);
+      return false;
+    }
+    // In all cases, 0-bit offsets are acceptable.
+    OutOps.push_back(Op);
+    OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));
+    return false;
+  }
+  return true;
+}
+
 FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) {
   return new MipsSEDAGToDAGISel(TM);
 }

Modified: llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h?rev=233063&r1=233062&r2=233063&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h Tue Mar 24 06:26:34 2015
@@ -56,12 +56,18 @@ private:
   bool selectIntAddr(SDValue Addr, SDValue &Base,
                      SDValue &Offset) const override;
 
+  bool selectAddrRegImm9(SDValue Addr, SDValue &Base,
+                         SDValue &Offset) const;
+
   bool selectAddrRegImm10(SDValue Addr, SDValue &Base,
                           SDValue &Offset) const;
 
   bool selectAddrRegImm12(SDValue Addr, SDValue &Base,
                           SDValue &Offset) const;
 
+  bool selectAddrRegImm16(SDValue Addr, SDValue &Base,
+                          SDValue &Offset) const;
+
   bool selectIntAddrMM(SDValue Addr, SDValue &Base,
                        SDValue &Offset) const override;
 
@@ -111,6 +117,10 @@ private:
   // Insert instructions to initialize the global base register in the
   // first MBB of the function.
   void initGlobalBaseReg(MachineFunction &MF);
+
+  bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+                                    unsigned ConstraintID,
+                                    std::vector<SDValue> &OutOps) override;
 };
 
 FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM);

Added: llvm/trunk/test/CodeGen/Mips/inlineasm_constraint_ZC.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/inlineasm_constraint_ZC.ll?rev=233063&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/inlineasm_constraint_ZC.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/inlineasm_constraint_ZC.ll Tue Mar 24 06:26:34 2015
@@ -0,0 +1,167 @@
+; RUN: llc -march=mipsel -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=09BIT
+; RUN: llc -march=mipsel -mattr=+micromips < %s | FileCheck %s -check-prefix=ALL -check-prefix=12BIT
+; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=ALL -check-prefix=16BIT
+
+ at data = global [8193 x i32] zeroinitializer
+
+define void @ZC(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 0))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+  ; ALL: #APP
+  ; ALL: lw $1, 0($[[BASEPTR]])
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_n4(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_n4:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 -1))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+  ; ALL: #APP
+  ; ALL: lw $1, -4($[[BASEPTR]])
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_4(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_4:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 1))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+  ; ALL: #APP
+  ; ALL: lw $1, 4($[[BASEPTR]])
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_252(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_252:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 63))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+  ; ALL: #APP
+  ; ALL: lw $1, 252($[[BASEPTR]])
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_256(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_256:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 64))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+
+  ; 09BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 256
+
+  ; ALL: #APP
+
+  ; 09BIT: lw $1, 0($[[BASEPTR2]])
+  ; 12BIT: lw $1, 256($[[BASEPTR]])
+  ; 16BIT: lw $1, 256($[[BASEPTR]])
+
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_2044(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_2044:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 511))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+
+  ; 09BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 2044
+
+  ; ALL: #APP
+
+  ; 09BIT: lw $1, 0($[[BASEPTR2]])
+  ; 12BIT: lw $1, 2044($[[BASEPTR]])
+  ; 16BIT: lw $1, 2044($[[BASEPTR]])
+
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_2048(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_2048:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 512))
+
+  ; ALL: lw $[[BASEPTR:[0-9]+]], %got(data)(
+
+  ; 09BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 2048
+  ; 12BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 2048
+
+  ; ALL: #APP
+
+  ; 09BIT: lw $1, 0($[[BASEPTR2]])
+  ; 12BIT: lw $1, 0($[[BASEPTR2]])
+  ; 16BIT: lw $1, 2048($[[BASEPTR]])
+
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_32764(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_32764:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 8191))
+
+  ; ALL-DAG: lw $[[BASEPTR:[0-9]+]], %got(data)(
+
+  ; 09BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 32764
+  ; 12BIT: addiu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], 32764
+
+  ; ALL: #APP
+
+  ; 09BIT: lw $1, 0($[[BASEPTR2]])
+  ; 12BIT: lw $1, 0($[[BASEPTR2]])
+  ; 16BIT: lw $1, 32764($[[BASEPTR]])
+
+  ; ALL: #NO_APP
+
+  ret void
+}
+
+define void @ZC_offset_32768(i32 *%p) nounwind {
+entry:
+  ; ALL-LABEL: ZC_offset_32768:
+
+  call void asm sideeffect "lw $$1, $0", "*^ZC,~{$1}"(i32* getelementptr inbounds ([8193 x i32], [8193 x i32]* @data, i32 0, i32 8192))
+
+  ; ALL-DAG: lw $[[BASEPTR:[0-9]+]], %got(data)(
+  ; ALL-DAG: ori $[[T0:[0-9]+]], $zero, 32768
+
+  ; 09BIT: addu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], $[[T0]]
+  ; 12BIT: addu16 $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], $[[T0]]
+  ; 16BIT: addu $[[BASEPTR2:[0-9]+]], $[[BASEPTR]], $[[T0]]
+
+  ; ALL: #APP
+  ; ALL: lw $1, 0($[[BASEPTR2]])
+  ; ALL: #NO_APP
+
+  ret void
+}





More information about the llvm-commits mailing list