+/* Expand a call to __builtin_prefetch. For a target that does not support
+ data prefetch, evaluate the memory address argument in case it has side
+ effects. */
+
+static void
+expand_builtin_prefetch (arglist)
+ tree arglist;
+{
+ tree arg0, arg1, arg2;
+ rtx op0, op1, op2;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, 0))
+ return;
+
+ arg0 = TREE_VALUE (arglist);
+ /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
+ zero (read) and argument 2 (locality) defaults to 3 (high degree of
+ locality). */
+ if (TREE_CHAIN (arglist))
+ {
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ if (TREE_CHAIN (TREE_CHAIN (arglist)))
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ else
+ arg2 = build_int_2 (3, 0);
+ }
+ else
+ {
+ arg1 = integer_zero_node;
+ arg2 = build_int_2 (3, 0);
+ }
+
+ /* Argument 0 is an address. */
+ op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
+
+ /* Argument 1 (read/write flag) must be a compile-time constant int. */
+ if (TREE_CODE (arg1) != INTEGER_CST)
+ {
+ error ("second arg to `__builtin_prefetch' must be a constant");
+ arg1 = integer_zero_node;
+ }
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ /* Argument 1 must be either zero or one. */
+ if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
+ {
+ warning ("invalid second arg to __builtin_prefetch; using zero");
+ op1 = const0_rtx;
+ }
+
+ /* Argument 2 (locality) must be a compile-time constant int. */
+ if (TREE_CODE (arg2) != INTEGER_CST)
+ {
+ error ("third arg to `__builtin_prefetch' must be a constant");
+ arg2 = integer_zero_node;
+ }
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ /* Argument 2 must be 0, 1, 2, or 3. */
+ if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
+ {
+ warning ("invalid third arg to __builtin_prefetch; using zero");
+ op2 = const0_rtx;
+ }
+
+#ifdef HAVE_prefetch
+ if (HAVE_prefetch)
+ {
+ if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
+ (op0, Pmode))
+ op0 = force_reg (Pmode, op0);
+ emit_insn (gen_prefetch (op0, op1, op2));
+ }
+ else
+#endif
+ op0 = protect_from_queue (op0, 0);
+ /* Don't do anything with direct references to volatile memory, but
+ generate code to handle other side effects. */
+ if (GET_CODE (op0) != MEM && side_effects_p (op0))
+ emit_insn (op0);
+}
+