[llvm] dccf5c7 - [M68k] Support for inline asm operands w/ simple constraints

Min-Yih Hsu via llvm-commits llvm-commits at lists.llvm.org
Thu May 20 14:01:18 PDT 2021


Author: Min-Yih Hsu
Date: 2021-05-20T14:00:09-07:00
New Revision: dccf5c7dfb9e68f8750947f5c10ad3227cd92b50

URL: https://github.com/llvm/llvm-project/commit/dccf5c7dfb9e68f8750947f5c10ad3227cd92b50
DIFF: https://github.com/llvm/llvm-project/commit/dccf5c7dfb9e68f8750947f5c10ad3227cd92b50.diff

LOG: [M68k] Support for inline asm operands w/ simple constraints

This patch adds supports for inline assembly operands and some simple
operand constraints, including register and constant operands.

Differential Revision: https://reviews.llvm.org/D102585

Added: 
    clang/test/Sema/inline-asm-validate-m68k.c
    llvm/test/CodeGen/M68k/inline-asm.ll

Modified: 
    clang/lib/Basic/Targets/M68k.cpp
    clang/lib/Basic/Targets/M68k.h
    llvm/lib/Target/M68k/M68kAsmPrinter.cpp
    llvm/lib/Target/M68k/M68kAsmPrinter.h
    llvm/lib/Target/M68k/M68kISelLowering.cpp
    llvm/lib/Target/M68k/M68kISelLowering.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/Basic/Targets/M68k.cpp b/clang/lib/Basic/Targets/M68k.cpp
index 8e8a69f75c8b0..9fcd58ee6401a 100644
--- a/clang/lib/Basic/Targets/M68k.cpp
+++ b/clang/lib/Basic/Targets/M68k.cpp
@@ -18,7 +18,9 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/TargetParser.h"
+#include <cstdint>
 #include <cstring>
+#include <limits>
 
 namespace clang {
 namespace targets {
@@ -142,18 +144,61 @@ bool M68kTargetInfo::validateAsmConstraint(
   switch (*Name) {
   case 'a': // address register
   case 'd': // data register
-  case 'f': // floating point register
     info.setAllowsRegister();
     return true;
-  case 'K': // the constant 1
-  case 'L': // constant -1^20 .. 1^19
-  case 'M': // constant 1-4:
+  case 'I': // constant integer in the range [1,8]
+    info.setRequiresImmediate(1, 8);
     return true;
+  case 'J': // constant signed 16-bit integer
+    info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
+                              std::numeric_limits<int16_t>::max());
+    return true;
+  case 'K': // constant that is NOT in the range of [-0x80, 0x80)
+    info.setRequiresImmediate();
+    return true;
+  case 'L': // constant integer in the range [-8,-1]
+    info.setRequiresImmediate(-8, -1);
+    return true;
+  case 'M': // constant that is NOT in the range of [-0x100, 0x100]
+    info.setRequiresImmediate();
+    return true;
+  case 'N': // constant integer in the range [24,31]
+    info.setRequiresImmediate(24, 31);
+    return true;
+  case 'O': // constant integer 16
+    info.setRequiresImmediate(16);
+    return true;
+  case 'P': // constant integer in the range [8,15]
+    info.setRequiresImmediate(8, 15);
+    return true;
+  case 'C':
+    ++Name;
+    switch (*Name) {
+    case '0': // constant integer 0
+      info.setRequiresImmediate(0);
+      return true;
+    case 'i': // constant integer
+    case 'j': // integer constant that doesn't fit in 16 bits
+      info.setRequiresImmediate();
+      return true;
+    default:
+      break;
+    }
+    break;
+  default:
+    break;
   }
-  // FIXME: Support all constraints like 'N', 'O', 'P', 'R'
   return false;
 }
 
+std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
+  if (*Constraint == 'C')
+    // Two-character constraint; add "^" hint for later parsing
+    return std::string("^") + std::string(Constraint++, 2);
+
+  return std::string(1, *Constraint);
+}
+
 const char *M68kTargetInfo::getClobbers() const {
   // FIXME: Is this really right?
   return "";

diff  --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h
index db001be76c65f..be2462bbd7acd 100644
--- a/clang/lib/Basic/Targets/M68k.h
+++ b/clang/lib/Basic/Targets/M68k.h
@@ -44,6 +44,7 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
   bool hasFeature(StringRef Feature) const override;
   ArrayRef<const char *> getGCCRegNames() const override;
   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+  std::string convertConstraint(const char *&Constraint) const override;
   bool validateAsmConstraint(const char *&Name,
                              TargetInfo::ConstraintInfo &info) const override;
   const char *getClobbers() const override;

diff  --git a/clang/test/Sema/inline-asm-validate-m68k.c b/clang/test/Sema/inline-asm-validate-m68k.c
new file mode 100644
index 0000000000000..a0b75304eba00
--- /dev/null
+++ b/clang/test/Sema/inline-asm-validate-m68k.c
@@ -0,0 +1,86 @@
+// REQUIRES: m68k-registered-target
+// RUN: %clang_cc1 -triple m68k -fsyntax-only -verify %s -DINVALID
+// RUN: %clang_cc1 -triple m68k -fsyntax-only -verify %s
+
+#ifdef INVALID
+
+// Invalid constraint usages that can be blocked by frontend
+
+void I() {
+  static const int BelowMin = 0;
+  static const int AboveMax = 9;
+  asm ("" :: "I"(BelowMin)); // expected-error{{value '0' out of range for constraint 'I'}}
+  asm ("" :: "I"(AboveMax)); // expected-error{{value '9' out of range for constraint 'I'}}
+}
+
+void J() {
+  static const int BelowMin = -0x8001;
+  static const int AboveMax = 0x8000;
+  asm ("" :: "J"(BelowMin)); // expected-error{{value '-32769' out of range for constraint 'J'}}
+  asm ("" :: "J"(AboveMax)); // expected-error{{value '32768' out of range for constraint 'J'}}
+}
+
+void L() {
+  static const int BelowMin = -9;
+  static const int AboveMax = 0;
+  asm ("" :: "L"(BelowMin)); // expected-error{{value '-9' out of range for constraint 'L'}}
+  asm ("" :: "L"(AboveMax)); // expected-error{{value '0' out of range for constraint 'L'}}
+}
+
+void N() {
+  static const int BelowMin = 23;
+  static const int AboveMax = 32;
+  asm ("" :: "N"(BelowMin)); // expected-error{{value '23' out of range for constraint 'N'}}
+  asm ("" :: "N"(AboveMax)); // expected-error{{value '32' out of range for constraint 'N'}}
+}
+
+void O() {
+  // Valid only if it's 16
+  static const int IncorrectVal = 18;
+  asm ("" :: "O"(IncorrectVal)); // expected-error{{value '18' out of range for constraint 'O'}}
+}
+
+void P() {
+  static const int BelowMin = 7;
+  static const int AboveMax = 16;
+  asm ("" :: "P"(BelowMin)); // expected-error{{value '7' out of range for constraint 'P'}}
+  asm ("" :: "P"(AboveMax)); // expected-error{{value '16' out of range for constraint 'P'}}
+}
+
+void C0() {
+  // Valid only if it's 0
+  static const int IncorrectVal = 1;
+  asm ("" :: "C0"(IncorrectVal)); // expected-error{{value '1' out of range for constraint 'C0'}}
+}
+
+#else
+// Valid constraint usages.
+// Note that these constraints can not be fully validated by frontend.
+// So we're only testing the availability of their letters here.
+// expected-no-diagnostics
+
+void K() {
+  asm ("" :: "K"(0x80));
+}
+
+void M() {
+  asm ("" :: "M"(0x100));
+}
+void Ci() {
+  asm ("" :: "Ci"(0));
+}
+
+void Cj() {
+  asm ("" :: "Cj"(0x8000));
+}
+
+// Register constraints
+void a(int x) {
+  asm ("" :: "a"(x));
+}
+
+void d(int x) {
+  asm ("" :: "d"(x));
+}
+#endif
+

diff  --git a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
index d3f9a5eb1d42e..a6fc58b5a277c 100644
--- a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
+++ b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
@@ -18,6 +18,7 @@
 
 #include "M68k.h"
 #include "M68kMachineFunction.h"
+#include "MCTargetDesc/M68kInstPrinter.h"
 #include "TargetInfo/M68kTargetInfo.h"
 
 #include "llvm/Support/TargetRegistry.h"
@@ -33,6 +34,48 @@ bool M68kAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   return true;
 }
 
+void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
+                                  raw_ostream &OS) {
+  const MachineOperand &MO = MI->getOperand(OpNum);
+  switch (MO.getType()) {
+  case MachineOperand::MO_Register:
+    OS << "%" << M68kInstPrinter::getRegisterName(MO.getReg());
+    break;
+  case MachineOperand::MO_Immediate:
+    OS << '#' << MO.getImm();
+    break;
+  case MachineOperand::MO_MachineBasicBlock:
+    MO.getMBB()->getSymbol()->print(OS, MAI);
+    break;
+  case MachineOperand::MO_GlobalAddress:
+    PrintSymbolOperand(MO, OS);
+    break;
+  case MachineOperand::MO_BlockAddress:
+    GetBlockAddressSymbol(MO.getBlockAddress())->print(OS, MAI);
+    break;
+  case MachineOperand::MO_ConstantPoolIndex: {
+    const DataLayout &DL = getDataLayout();
+    OS << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+       << MO.getIndex();
+    break;
+  }
+  default:
+    llvm_unreachable("not implemented");
+  }
+}
+
+bool M68kAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                     const char *ExtraCode, raw_ostream &OS) {
+  // Print the operand if there is no operand modifier.
+  if (!ExtraCode || !ExtraCode[0]) {
+    printOperand(MI, OpNo, OS);
+    return false;
+  }
+
+  // Fallback to the default implementation.
+  return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
+}
+
 void M68kAsmPrinter::emitInstruction(const MachineInstr *MI) {
   switch (MI->getOpcode()) {
   default: {

diff  --git a/llvm/lib/Target/M68k/M68kAsmPrinter.h b/llvm/lib/Target/M68k/M68kAsmPrinter.h
index f17a90fd475d0..dff3bb876336e 100644
--- a/llvm/lib/Target/M68k/M68kAsmPrinter.h
+++ b/llvm/lib/Target/M68k/M68kAsmPrinter.h
@@ -38,6 +38,8 @@ class LLVM_LIBRARY_VISIBILITY M68kAsmPrinter : public AsmPrinter {
 
   void EmitInstrWithMacroNoAT(const MachineInstr *MI);
 
+  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
+
 public:
   const M68kSubtarget *Subtarget;
   const M68kMachineFunctionInfo *MMFI;
@@ -53,6 +55,9 @@ class LLVM_LIBRARY_VISIBILITY M68kAsmPrinter : public AsmPrinter {
 
   virtual bool runOnMachineFunction(MachineFunction &MF) override;
 
+  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                       const char *ExtraCode, raw_ostream &OS) override;
+
   void emitInstruction(const MachineInstr *MI) override;
   void emitFunctionBodyStart() override;
   void emitFunctionBodyEnd() override;

diff  --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp
index 7c2e253a37c88..c79e9d124db57 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.cpp
+++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp
@@ -2689,6 +2689,193 @@ const MCExpr *M68kTargetLowering::getPICJumpTableRelocBaseExpr(
   return MCSymbolRefExpr::create(MF->getJTISymbol(JTI, Ctx), Ctx);
 }
 
+M68kTargetLowering::ConstraintType
+M68kTargetLowering::getConstraintType(StringRef Constraint) const {
+  if (Constraint.size() > 0) {
+    switch (Constraint[0]) {
+    case 'a':
+    case 'd':
+      return C_RegisterClass;
+    case 'I':
+    case 'J':
+    case 'K':
+    case 'L':
+    case 'M':
+    case 'N':
+    case 'O':
+    case 'P':
+      return C_Immediate;
+    case 'C':
+      if (Constraint.size() == 2)
+        switch (Constraint[1]) {
+        case '0':
+        case 'i':
+        case 'j':
+          return C_Immediate;
+        default:
+          break;
+        }
+      break;
+    default:
+      break;
+    }
+  }
+
+  return TargetLowering::getConstraintType(Constraint);
+}
+
+void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
+                                                      std::string &Constraint,
+                                                      std::vector<SDValue> &Ops,
+                                                      SelectionDAG &DAG) const {
+  SDValue Result;
+
+  if (Constraint.size() == 1) {
+    // Constant constraints
+    switch (Constraint[0]) {
+    case 'I':
+    case 'J':
+    case 'K':
+    case 'L':
+    case 'M':
+    case 'N':
+    case 'O':
+    case 'P': {
+      auto *C = dyn_cast<ConstantSDNode>(Op);
+      if (!C)
+        return;
+
+      int64_t Val = C->getSExtValue();
+      switch (Constraint[0]) {
+      case 'I': // constant integer in the range [1,8]
+        if (Val > 0 && Val <= 8)
+          break;
+        return;
+      case 'J': // constant signed 16-bit integer
+        if (isInt<16>(Val))
+          break;
+        return;
+      case 'K': // constant that is NOT in the range of [-0x80, 0x80)
+        if (Val < -0x80 || Val >= 0x80)
+          break;
+        return;
+      case 'L': // constant integer in the range [-8,-1]
+        if (Val < 0 && Val >= -8)
+          break;
+        return;
+      case 'M': // constant that is NOT in the range of [-0x100, 0x100]
+        if (Val < -0x100 || Val >= 0x100)
+          break;
+        return;
+      case 'N': // constant integer in the range [24,31]
+        if (Val >= 24 && Val <= 31)
+          break;
+        return;
+      case 'O': // constant integer 16
+        if (Val == 16)
+          break;
+        return;
+      case 'P': // constant integer in the range [8,15]
+        if (Val >= 8 && Val <= 15)
+          break;
+        return;
+      default:
+        llvm_unreachable("Unhandled constant constraint");
+      }
+
+      Result = DAG.getTargetConstant(Val, SDLoc(Op), Op.getValueType());
+      break;
+    }
+    default:
+      break;
+    }
+  }
+
+  if (Constraint.size() == 2) {
+    switch (Constraint[0]) {
+    case 'C':
+      // Constant constraints start with 'C'
+      switch (Constraint[1]) {
+      case '0':
+      case 'i':
+      case 'j': {
+        auto *C = dyn_cast<ConstantSDNode>(Op);
+        if (!C)
+          break;
+
+        int64_t Val = C->getSExtValue();
+        switch (Constraint[1]) {
+        case '0': // constant integer 0
+          if (!Val)
+            break;
+          return;
+        case 'i': // constant integer
+          break;
+        case 'j': // integer constant that doesn't fit in 16 bits
+          if (!isInt<16>(C->getSExtValue()))
+            break;
+          return;
+        default:
+          llvm_unreachable("Unhandled constant constraint");
+        }
+
+        Result = DAG.getTargetConstant(Val, SDLoc(Op), Op.getValueType());
+        break;
+      }
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (Result.getNode()) {
+    Ops.push_back(Result);
+    return;
+  }
+
+  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
+}
+
+std::pair<unsigned, const TargetRegisterClass *>
+M68kTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+                                                 StringRef Constraint,
+                                                 MVT VT) const {
+  if (Constraint.size() == 1) {
+    switch (Constraint[0]) {
+    case 'r':
+    case 'd':
+      switch (VT.SimpleTy) {
+      case MVT::i8:
+        return std::make_pair(0U, &M68k::DR8RegClass);
+      case MVT::i16:
+        return std::make_pair(0U, &M68k::DR16RegClass);
+      case MVT::i32:
+        return std::make_pair(0U, &M68k::DR32RegClass);
+      default:
+        break;
+      }
+      break;
+    case 'a':
+      switch (VT.SimpleTy) {
+      case MVT::i16:
+        return std::make_pair(0U, &M68k::AR16RegClass);
+      case MVT::i32:
+        return std::make_pair(0U, &M68k::AR32RegClass);
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+}
+
 /// Determines whether the callee is required to pop its own arguments.
 /// Callee pop is necessary to support tail calls.
 bool M68k::isCalleePop(CallingConv::ID CallingConv, bool IsVarArg,

diff  --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h
index 004ebe0929fb1..8c3c0511ecf80 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.h
+++ b/llvm/lib/Target/M68k/M68kISelLowering.h
@@ -156,6 +156,17 @@ class M68kTargetLowering : public TargetLowering {
                                              unsigned JTI,
                                              MCContext &Ctx) const override;
 
+  ConstraintType getConstraintType(StringRef ConstraintStr) const override;
+
+  std::pair<unsigned, const TargetRegisterClass *>
+  getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+                               StringRef Constraint, MVT VT) const override;
+
+  // Lower operand with C_Immediate and C_Other constraint type
+  void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
+                                    std::vector<SDValue> &Ops,
+                                    SelectionDAG &DAG) const override;
+
   MachineBasicBlock *
   EmitInstrWithCustomInserter(MachineInstr &MI,
                               MachineBasicBlock *MBB) const override;

diff  --git a/llvm/test/CodeGen/M68k/inline-asm.ll b/llvm/test/CodeGen/M68k/inline-asm.ll
new file mode 100644
index 0000000000000..daa412b6e8773
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/inline-asm.ll
@@ -0,0 +1,122 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=m68k < %s -o - | FileCheck %s
+
+; This function is primarily testing constant constraints that can NOT
+; be easily checked by Clang. For example, 'K' and 'M' are both
+; constraints for values that are outside certain numerical range.
+define void @constant_constraints() {
+; CHECK-LABEL: constant_constraints:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0: ; %entry
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #1, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #8, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-32768, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #32767, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-129, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #128, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-8, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-1, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-257, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #256, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #24, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #31, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #16, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #8, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #15, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #0, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #1, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #-32769, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #32768, %d1
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    rts
+entry:
+  call void asm sideeffect "move.l $0, %d1", "I"(i32 1)
+  call void asm sideeffect "move.l $0, %d1", "I"(i32 8)
+  call void asm sideeffect "move.l $0, %d1", "J"(i32 -32768)
+  call void asm sideeffect "move.l $0, %d1", "J"(i32 32767)
+  call void asm sideeffect "move.l $0, %d1", "K"(i32 -129)
+  call void asm sideeffect "move.l $0, %d1", "K"(i32 128)
+  call void asm sideeffect "move.l $0, %d1", "L"(i32 -8)
+  call void asm sideeffect "move.l $0, %d1", "L"(i32 -1)
+  call void asm sideeffect "move.l $0, %d1", "M"(i32 -257)
+  call void asm sideeffect "move.l $0, %d1", "M"(i32 256)
+  call void asm sideeffect "move.l $0, %d1", "N"(i32 24)
+  call void asm sideeffect "move.l $0, %d1", "N"(i32 31)
+  call void asm sideeffect "move.l $0, %d1", "O"(i32 16)
+  call void asm sideeffect "move.l $0, %d1", "P"(i32 8)
+  call void asm sideeffect "move.l $0, %d1", "P"(i32 15)
+  call void asm sideeffect "move.l $0, %d1", "^C0"(i32 0)
+  call void asm sideeffect "move.l $0, %d1", "^Ci"(i32 1)
+  call void asm sideeffect "move.l $0, %d1", "^Cj"(i32 -32769)
+  call void asm sideeffect "move.l $0, %d1", "^Cj"(i32 32768)
+  ret void
+}
+
+define void @register_constraints() {
+; CHECK-LABEL: register_constraints:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0: ; %entry
+; CHECK-NEXT:    sub.l #4, %sp
+; CHECK-NEXT:    .cfi_def_cfa_offset -8
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #94, %d0
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    move.l %d0, (0,%sp)
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #87, %d0
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    move.l %d0, (0,%sp)
+; CHECK-NEXT:    ;APP
+; CHECK-NEXT:    move.l #66, %a0
+; CHECK-NEXT:    ;NO_APP
+; CHECK-NEXT:    move.l %a0, (0,%sp)
+; CHECK-NEXT:    add.l #4, %sp
+; CHECK-NEXT:    rts
+entry:
+  %out = alloca i32, align 4
+  %0 = call i32 asm sideeffect "move.l #94, $0", "=r"()
+  store i32 %0, i32* %out, align 4
+  %1 = call i32 asm sideeffect "move.l #87, $0", "=d"()
+  store i32 %1, i32* %out, align 4
+  %2 = call i32 asm sideeffect "move.l #66, $0", "=a"()
+  store i32 %2, i32* %out, align 4
+  ret void
+}
+


        


More information about the llvm-commits mailing list