$OpenBSD: patch-lib_Target_Mips_MipsISelLowering_cpp,v 1.1 2019/07/09 13:21:37 jca Exp $

- Implement the 'h' register constraint on mips64. This lets clang build
  pieces of software that use the constraint if the compiler claims
  to be compatible with GCC 4.2.1.
  Note that the constraint was removed in GCC 4.4. The reason was that
  'h' could generate code whose result is unpredictable. The underlying
  reason is that the HI and LO registers are special, and the optimizer
  has to be careful when choosing the order of HI/LO accesses. It looks
  that LLVM has the needed logic.

Index: lib/Target/Mips/MipsISelLowering.cpp
--- lib/Target/Mips/MipsISelLowering.cpp.orig
+++ lib/Target/Mips/MipsISelLowering.cpp
@@ -3685,6 +3685,7 @@ MipsTargetLowering::getConstraintType(StringRef Constr
   //       backwards compatibility.
   // 'c' : A register suitable for use in an indirect
   //       jump. This will always be $25 for -mabicalls.
+  // 'h' : The hi register. 1 word storage.
   // 'l' : The lo register. 1 word storage.
   // 'x' : The hilo register pair. Double word storage.
   if (Constraint.size() == 1) {
@@ -3694,6 +3695,7 @@ MipsTargetLowering::getConstraintType(StringRef Constr
       case 'y':
       case 'f':
       case 'c':
+      case 'h':
       case 'l':
       case 'x':
         return C_RegisterClass;
@@ -3739,6 +3741,7 @@ MipsTargetLowering::getSingleConstraintMatchWeight(
       weight = CW_Register;
     break;
   case 'c': // $25 for indirect jumps
+  case 'h': // hi register
   case 'l': // lo register
   case 'x': // hilo register pair
     if (type->isIntegerTy())
@@ -3913,6 +3916,11 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const
         return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass);
       // This will generate an error message
       return std::make_pair(0U, nullptr);
+    case 'h': // use the `hi` register to store values
+              // that are no bigger than a word
+      if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8)
+        return std::make_pair((unsigned)Mips::HI0, &Mips::HI32RegClass);
+      return std::make_pair((unsigned)Mips::HI0_64, &Mips::HI64RegClass);
     case 'l': // use the `lo` register to store values
               // that are no bigger than a word
       if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8)
