rtx_code_label *L_loop_long = gen_label_rtx ();
rtx_code_label *L_end_loop_long = gen_label_rtx ();
- int align = INTVAL (operands[3]);
-
- emit_move_insn (tmp0, const0_rtx);
+ const unsigned int addr1_alignment = MEM_ALIGN (operands[1]) / BITS_PER_UNIT;
+ const unsigned int addr2_alignment = MEM_ALIGN (operands[2]) / BITS_PER_UNIT;
- if (align < 4)
+ if (addr1_alignment < 4 && addr2_alignment < 4)
{
emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
emit_insn (gen_tstsi_t (tmp1, GEN_INT (3)));
jump = emit_jump_insn (gen_branch_false (L_loop_byte));
add_int_reg_note (jump, REG_BR_PROB, prob_likely);
}
+ else if (addr1_alignment < 4 && addr2_alignment >= 4)
+ {
+ emit_insn (gen_tstsi_t (s1_addr, GEN_INT (3)));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+ else if (addr1_alignment >= 4 && addr2_alignment < 4)
+ {
+ emit_insn (gen_tstsi_t (s2_addr, GEN_INT (3)));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
rtx len = force_reg (SImode, operands[3]);
int constp = CONST_INT_P (operands[3]);
+ const unsigned int addr1_alignment = MEM_ALIGN (operands[1]) / BITS_PER_UNIT;
+ const unsigned int addr2_alignment = MEM_ALIGN (operands[2]) / BITS_PER_UNIT;
+
/* Loop on a register count. */
if (constp)
{
rtx_code_label *L_loop_long = gen_label_rtx ();
rtx_code_label *L_end_loop_long = gen_label_rtx ();
- int align = INTVAL (operands[4]);
int bytes = INTVAL (operands[3]);
int witers = bytes / 4;
emit_move_insn (tmp0, const0_rtx);
- if (align < 4)
+ if (addr1_alignment < 4 && addr2_alignment < 4)
{
emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
emit_insn (gen_tstsi_t (tmp1, GEN_INT (3)));
jump = emit_jump_insn (gen_branch_false (L_loop_byte));
add_int_reg_note (jump, REG_BR_PROB, prob_likely);
}
+ else if (addr1_alignment < 4 && addr2_alignment >= 4)
+ {
+ emit_insn (gen_tstsi_t (s1_addr, GEN_INT (3)));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+ else if (addr1_alignment >= 4 && addr2_alignment < 4)
+ {
+ emit_insn (gen_tstsi_t (s2_addr, GEN_INT (3)));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
/* word count. Do we have iterations ? */
emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
--- /dev/null
+/* Check that run time alignment tests are generated only for inputs of
+ unknown alignment. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "jmp|bsr|jsr" } } */
+/* { dg-final { scan-assembler-times {tst #3,r0} 6 } } */
+/* { dg-final { scan-assembler-times {or r[0-9],r[0-9]} 1 } } */
+
+int
+test_00 (const char* x, const char* y)
+{
+ /* 1x or reg,reg, 1x tst #3,r0 */
+ return __builtin_strcmp (x, y);
+}
+
+int
+test_01 (const char* x, const char* y)
+{
+ /* 1x tst #3,r0 */
+ return __builtin_strcmp (__builtin_assume_aligned (x, 4), y);
+}
+
+int
+test_02 (const char* x, const char* y)
+{
+ /* 1x tst #3,r0 */
+ return __builtin_strcmp (x, __builtin_assume_aligned (y, 4));
+}
+
+int
+test_03 (const char* x, const char* y)
+{
+ return __builtin_strcmp (__builtin_assume_aligned (x, 4),
+ __builtin_assume_aligned (y, 4));
+}
+
+int
+test_04 (const char* x, const char* y)
+{
+ /* 1x tst #3,r0 */
+ return __builtin_strcmp (x, "1234567");
+}
+
+int
+test_05 (const char* x, const char* y)
+{
+ /* 1x tst #3,r0 */
+ return __builtin_strcmp ("1234567", y);
+}
+
+int
+test_06 (const char* s1)
+{
+ /* 1x tst #3,r0 */
+ return __builtin_strncmp (s1, "abcdabcd", 8);
+}
+
+int
+test_07 (const char* s1)
+{
+ return __builtin_strncmp (__builtin_assume_aligned (s1, 4), "abcdabcd", 8);
+}