[llvm-commits] [llvm] r61297 - in /llvm/trunk: lib/Transforms/Scalar/SimplifyLibCalls.cpp test/Transforms/SimplifyLibCalls/2008-12-20-StrcmpMemcmp.ll
Török Edwin
edwintorok at gmail.com
Tue Dec 23 04:19:33 PST 2008
On 2008-12-23 14:17, Török Edwin wrote:
> On 2008-12-23 02:56, Chris Lattner wrote:
>
>> On Dec 22, 2008, at 7:15 AM, Török Edwin wrote:
>>
>>
>>>>> You need to check the alignment.
>>>>>
>>>>>
>>>> I think something like:
>>>> MinAlignStr = Minimum Alignment of Str1P, Str2P (max 16)
>>>> MinLen = Minimum length of Str1P and Str2P
>>>> AlignMinLen = AlignOf(MinLen) (max 16)
>>>> If (MinAlignStr >= AlingMinLen) -> transform is safe
>>>>
>>>>
>>>>
>>> But try this with llvm-gcc:
>>> #include <string.h>
>>> int foo(const char *s)
>>> {
>>> return !memcmp(s,"x",2);
>>> }
>>>
>>> It produces:
>>> foo:
>>> .Leh_func_begin1:
>>> .Llabel1:
>>> cmpw $120, (%rdi)
>>> sete %al
>>> movzbl %al, %eax
>>> ret
>>>
>>> So is it a bug in MemCmp optimization?
>>>
>>>
>> hi Edwin,
>>
>> This is a really important question that I don't know the answer to.
>> My understanding is that memcmp only touches the bytes necessary to
>> make a decision: it is not allowed to touch the full size if
>> unneeded. However, I don't really *know* that, and nothing I find
>> online in a quick scan comes up with an obvious answer.
>>
>> Can you try asking on comp.lang.c or something like that?
>>
>
> I found 2 messages on comp.lang.c about this:
> http://groups.google.com/group/comp.lang.c/msg/28fcc4a0e29e5339
> http://groups.google.com/group/comp.lang.c/msg/786c9f1cb2e9b085
>
> " /* or can probably use memcmp since in practice it will safely
> stop on or near null != nonnull and return nonmatch, but not
> AFAICT guaranteed, and being not str* may alarm some */
>
> You seem to be correct - "7.21.4.1 The memcmp function" doesn't require it
> to stop as long as it ultimately returns the correct result - but it's in
> the implementation's interests to make it as efficient as possible."
>
>
>> It would
>> also be interesting to look at the source for various memcmp
>> implementations
>>
>
> glibc:
> /* The strategy of this memcmp is:
>
> 1. Compare bytes until one of the block pointers is aligned.
>
> 2. Compare using memcmp_common_alignment or
> memcmp_not_common_alignment, regarding the alignment of the other
> block after the initial byte operations. The maximum number of
> full words (of type op_t) are compared in this way.
>
> 3. Compare the few remaining bytes. */
>
> However in memcmp_not_common_alignment:
> /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
> `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory
> operations on `op_t', but SRCP1 *should be unaligned*. */
> switch (len % 4) {
> case 2:
> a1 = ((op_t *) srcp1)[0];
> a2 = ((op_t *) srcp1)[1];
> ...
> }
>
> It does a 2-byte read on srcp1, which is unaligned, so I think it may
> cross a page boundary if we aren't allowed to do 2-byte reads on all the
> region we pass to memcmp.
>
>
>
>> to decide if they are safe on commonly available
>> systems (worst-case this becomes a target-specific optimization).
>>
>>
>
> How about using the alignment and length of the string to determine that
> memcmp won't cross a page boundary, even
> with an implementation that does 8-byte reads always?
> Alternatively we may align the operands with some extra code inserted.
>
> I remember seeing valgrind warnings with older versions about strcmp,
> and valgrind has --partial-loads-ok, so
> I guess strcmp already does loads that cross the boundary of one of its
> arguments, if it knows that it is safe to do so (i.e. it won't cross
> page boundaries).
[sorry, hit Send button too soon]
We should also add a testcase to test/ or in test-suite/ that
specifically tests these corner cases.
We can allocate a single page with mmap, so that the OS will kill the
program if it crosses page boundary.
Best regards,
--Edwin
More information about the llvm-commits
mailing list