Index: include/llvm-c/DebugInfo.h
===================================================================
--- include/llvm-c/DebugInfo.h
+++ include/llvm-c/DebugInfo.h
@@ -44,7 +44,6 @@
   LLVMDIFlagStaticMember = 1 << 12,
   LLVMDIFlagLValueReference = 1 << 13,
   LLVMDIFlagRValueReference = 1 << 14,
-  LLVMDIFlagReserved = 1 << 15,
   LLVMDIFlagSingleInheritance = 1 << 16,
   LLVMDIFlagMultipleInheritance = 2 << 16,
   LLVMDIFlagVirtualInheritance = 3 << 16,
@@ -59,6 +58,10 @@
   LLVMDIFlagTrivial = 1 << 26,
   LLVMDIFlagBigEndian = 1 << 27,
   LLVMDIFlagLittleEndian = 1 << 28,
+  LLVMDIFlagExtraSubprogram = 1 << 15,
+  LLVMDIFlagPure = (1 << 15) | (1 << 9),
+  LLVMDIFlagElemental = (1 << 15) | (1 << 19),
+  LLVMDIFlagRecursive = (1 << 15) | (1 << 22),
   LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5),
   LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected |
                             LLVMDIFlagPublic,
Index: include/llvm/IR/DebugInfoFlags.def
===================================================================
--- include/llvm/IR/DebugInfoFlags.def
+++ include/llvm/IR/DebugInfoFlags.def
@@ -35,7 +35,6 @@
 HANDLE_DI_FLAG((1 << 13), LValueReference)
 HANDLE_DI_FLAG((1 << 14), RValueReference)
 // 15 was formerly ExternalTypeRef, but this was never used.
-HANDLE_DI_FLAG((1 << 15), Reserved)
 HANDLE_DI_FLAG((1 << 16), SingleInheritance)
 HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
 HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
@@ -52,6 +51,14 @@
 HANDLE_DI_FLAG((1 << 28), LittleEndian)
 HANDLE_DI_FLAG((1 << 29), AllCallsDescribed)
 
+// Additional subprogram flags: use bit 15 to indicate it's an extended
+// subprogram flag and then overload some flags that otherwise have no semantics
+// with respect to DISubprogram's member functions
+HANDLE_DI_FLAG((1 << 15), ExtraSubprogram)
+HANDLE_DI_FLAG((1 << 15)|(1 << 9), Pure)
+HANDLE_DI_FLAG((1 << 15)|(1 << 19), Elemental)
+HANDLE_DI_FLAG((1 << 15)|(1 << 22), Recursive)
+
 // To avoid needing a dedicated value for IndirectVirtualBase, we use
 // the bitwise or of Virtual and FwdDecl, which does not otherwise
 // make sense for inheritance.
Index: include/llvm/IR/DebugInfoMetadata.h
===================================================================
--- include/llvm/IR/DebugInfoMetadata.h
+++ include/llvm/IR/DebugInfoMetadata.h
@@ -1740,6 +1740,13 @@
     return getFlags() & FlagAllCallsDescribed;
   }
   bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; }
+  bool isPure() const { return (getFlags() & FlagPure) == FlagPure; }
+  bool isElemental() const {
+    return (getFlags() & FlagElemental) == FlagElemental;
+  }
+  bool isRecursive() const {
+    return (getFlags() & FlagRecursive) == FlagRecursive;
+  }
 
   /// Check if this is reference-qualified.
   ///
Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1261,6 +1261,12 @@
 
   if (SP->isMainSubprogram())
     addFlag(SPDie, dwarf::DW_AT_main_subprogram);
+  if (SP->isPure())
+    addFlag(SPDie, dwarf::DW_AT_pure);
+  if (SP->isElemental())
+    addFlag(SPDie, dwarf::DW_AT_elemental);
+  if (SP->isRecursive())
+    addFlag(SPDie, dwarf::DW_AT_recursive);
 }
 
 void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
Index: lib/IR/DebugInfoMetadata.cpp
===================================================================
--- lib/IR/DebugInfoMetadata.cpp
+++ lib/IR/DebugInfoMetadata.cpp
@@ -153,6 +153,15 @@
       SplitFlags.push_back(FlagVirtualInheritance);
     Flags &= ~R;
   }
+  if (Flags & FlagExtraSubprogram) {
+    if ((Flags & FlagPure) == FlagPure)
+      SplitFlags.push_back(FlagPure);
+    if ((Flags & FlagElemental) == FlagElemental)
+      SplitFlags.push_back(FlagElemental);
+    if ((Flags & FlagRecursive) == FlagRecursive)
+      SplitFlags.push_back(FlagRecursive);
+    Flags &= ~(FlagPure|FlagElemental|FlagRecursive);
+  }
   if ((Flags & FlagIndirectVirtualBase) == FlagIndirectVirtualBase) {
     Flags &= ~FlagIndirectVirtualBase;
     SplitFlags.push_back(FlagIndirectVirtualBase);
Index: test/DebugInfo/fortran-subprogram-at.ll
===================================================================
--- /dev/null
+++ test/DebugInfo/fortran-subprogram-at.ll
@@ -0,0 +1,24 @@
+; Test for DIFlagPure, DIFlagElement and DIFlagRecursive. These three
+; DIFlags are used to attach DW_AT_pure, DW_AT_element, and DW_AT_recursive
+; attributes to DW_TAG_subprogram DIEs.
+
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; CHECK: !DISubprogram({{.*}}, flags: DIFlagPure | DIFlagElemental | DIFlagRecursive,
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+define void @subprgm() !dbg !6 {
+L:
+  ret void
+}
+
+!0 = !{i32 2, !"Dwarf Version", i32 2}
+!1 = !{i32 1, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: "Flang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
+!3 = !DIFile(filename: "fortran-subprogram-at.f", directory: "/")
+!4 = !{}
+!5 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
+!6 = distinct !DISubprogram(name: "subprgm", scope: !2, file: !3, line: 256, type: !7, isLocal: false, isDefinition: true, scopeLine: 256, flags: DIFlagPure|DIFlagElemental|DIFlagRecursive, isOptimized: false, unit: !2)
+!7 = !DISubroutineType(types: !8)
+!8 = !{null, !5}