diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 780b91d9215d5..b1b527b569a88 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -375,7 +375,12 @@ impl<'tcx> Inliner<'tcx> {
             return Err("incompatible sanitizer set");
         }
 
-        if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
+        // Two functions are compatible if the callee has no attribute (meaning
+        // that it's codegen agnostic), or sets an attribute that is identical
+        // to this function's attribute.
+        if callee_attrs.instruction_set.is_some()
+            && callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
+        {
             return Err("incompatible instruction set");
         }
 
@@ -453,6 +458,15 @@ impl<'tcx> Inliner<'tcx> {
                 if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
                         work_list.push(unwind);
                     }
+            } else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
+                && matches!(term.kind, TerminatorKind::InlineAsm { .. })
+            {
+                // During the attribute checking stage we allow a callee with no
+                // instruction_set assigned to count as compatible with a function that does
+                // assign one. However, during this stage we require an exact match when any
+                // inline-asm is detected. LLVM will still possibly do an inline later on
+                // if the no-attribute function ends up with the same instruction set anyway.
+                return Err("Cannot move inline-asm across instruction sets");
             } else {
                 work_list.extend(term.successors())
             }
diff --git a/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff
index e421428dcdff5..f1988ea4bd678 100644
--- a/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff
+++ b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff
@@ -6,14 +6,19 @@
       let _1: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
       let _2: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
       let _3: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
-+     scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30
+      let _4: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
++     scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30
++     }
++     scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41
++         scope 3 {
++         }
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
           _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
-                                           // + span: $DIR/inline_instruction_set.rs:51:5: 51:24
+                                           // + span: $DIR/inline_instruction_set.rs:57:5: 57:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
       }
   
@@ -22,7 +27,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
           _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
                                            // mir::Constant
-                                           // + span: $DIR/inline_instruction_set.rs:52:5: 52:24
+                                           // + span: $DIR/inline_instruction_set.rs:58:5: 58:24
                                            // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
       }
   
@@ -31,14 +36,25 @@
           StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -                                          // mir::Constant
--                                          // + span: $DIR/inline_instruction_set.rs:53:5: 53:28
+-                                          // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
 -                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
 -     }
 - 
 -     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
-          _0 = const ();                   // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2
-          return;                          // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2
+          StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
+-                                          // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
++         asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
+      }
+  
+-     bb4: {
++     bb3: {
+          StorageDead(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
+          _0 = const ();                   // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2
+          return;                          // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_instruction_set.rs b/src/test/mir-opt/inline/inline_instruction_set.rs
index be36ff50c7ef1..5dfb04943e39f 100644
--- a/src/test/mir-opt/inline/inline_instruction_set.rs
+++ b/src/test/mir-opt/inline/inline_instruction_set.rs
@@ -1,5 +1,7 @@
 // Checks that only functions with the compatible instruction_set attributes are inlined.
 //
+// A function is "compatible" when the *callee* has the same attribute or no attribute.
+//
 // compile-flags: --target thumbv4t-none-eabi
 // needs-llvm-components: arm
 
@@ -36,14 +38,18 @@ fn instruction_set_t32() {}
 #[inline]
 fn instruction_set_default() {}
 
+#[inline(always)]
+fn inline_always_and_using_inline_asm() {
+    unsafe { asm!("/* do nothing */") };
+}
+
 // EMIT_MIR inline_instruction_set.t32.Inline.diff
 #[instruction_set(arm::t32)]
 pub fn t32() {
     instruction_set_a32();
     instruction_set_t32();
-    // The default instruction set is currently
-    // conservatively assumed to be incompatible.
     instruction_set_default();
+    inline_always_and_using_inline_asm();
 }
 
 // EMIT_MIR inline_instruction_set.default.Inline.diff
@@ -51,4 +57,5 @@ pub fn default() {
     instruction_set_a32();
     instruction_set_t32();
     instruction_set_default();
+    inline_always_and_using_inline_asm();
 }
diff --git a/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff
index 1ea2b87e53acd..e777b2cc29eb3 100644
--- a/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff
+++ b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff
@@ -5,15 +5,18 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:14: +0:14
       let _1: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
       let _2: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
-      let _3: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
-+     scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:43:5: 43:26
+      let _3: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+      let _4: ();                          // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
++     scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:50:5: 50:26
++     }
++     scope 2 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:51:5: 51:30
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
           _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
-                                           // + span: $DIR/inline_instruction_set.rs:42:5: 42:24
+                                           // + span: $DIR/inline_instruction_set.rs:49:5: 49:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
       }
   
@@ -22,25 +25,34 @@
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
 -         _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
 -                                          // mir::Constant
--                                          // + span: $DIR/inline_instruction_set.rs:43:5: 43:24
+-                                          // + span: $DIR/inline_instruction_set.rs:50:5: 50:24
 -                                          // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
 -     }
 - 
 -     bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
-          StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
--         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
-+         _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
+          StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline_instruction_set.rs:51:5: 51:28
+-                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
+-     }
+- 
+-     bb3: {
+          StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
+          StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
++         _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
                                            // mir::Constant
-                                           // + span: $DIR/inline_instruction_set.rs:46:5: 46:28
-                                           // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
+                                           // + span: $DIR/inline_instruction_set.rs:52:5: 52:39
+                                           // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
       }
   
--     bb3: {
+-     bb4: {
 +     bb2: {
-          StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+5:30: +5:31
-          _0 = const ();                   // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +6:2
-          return;                          // scope 0 at $DIR/inline_instruction_set.rs:+6:2: +6:2
+          StorageDead(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
+          _0 = const ();                   // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +5:2
+          return;                          // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
       }
   }