diff --git a/gcc/recog.cc b/gcc/recog.cc
index ed084fa88086a54027ba66fb6746c280b0295994..1138a7934bd30c73cbd4bab343a39816fb991c07 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -3199,13 +3199,17 @@ constrain_operands (int strict, alternative_mask alternatives)
 		   strictly valid, i.e., that all pseudos requiring hard regs
 		   have gotten them.  We also want to make sure we have a
 		   valid mode.  */
-		if ((GET_MODE (op) == VOIDmode
-		     || SCALAR_INT_MODE_P (GET_MODE (op)))
-		    && (strict <= 0
-			|| (strict_memory_address_p
-			     (recog_data.operand_mode[opno], op))))
-		  win = true;
-		break;
+		{
+		  auto mem_mode = (recog_data.is_asm
+				   ? VOIDmode
+				   : recog_data.operand_mode[opno]);
+		  if ((GET_MODE (op) == VOIDmode
+		       || SCALAR_INT_MODE_P (GET_MODE (op)))
+		      && (strict <= 0
+			  || strict_memory_address_p (mem_mode, op)))
+		    win = true;
+		  break;
+		}
 
 		/* No need to check general_operand again;
 		   it was done in insn-recog.cc.  Well, except that reload
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 2f2d12d5f30ba48f3f643b7eee4810f71a0a8fef..443d0575df5b6e7e3fa385afae46e2927b425458 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -986,8 +986,10 @@ recog_level2 (insn_change &change, add_regno_clobber_fn add_regno_clobber)
       pat = newpat;
     }
 
+  // check_asm_operands checks the constraints after RA, so we don't
+  // need to do it again.
   INSN_CODE (rtl) = icode;
-  if (reload_completed)
+  if (reload_completed && !asm_p)
     {
       extract_insn (rtl);
       if (!constrain_operands (1, get_preferred_alternatives (rtl)))
diff --git a/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c b/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..2dd695157f200fa418d823b8d1dd7abf5bafe3b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c
@@ -0,0 +1 @@
+void f(char *p) { asm("prfm pldl1keep, %a0\n" :: "p" (p + 6)); }