[llvm-bugs] [Bug 51958] New: [MIPS] miscompilation of passing 32 bits from 64 bit struct from input register

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Sep 24 09:05:07 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=51958

            Bug ID: 51958
           Summary: [MIPS] miscompilation of passing 32 bits from 64 bit
                    struct from input register
           Product: new-bugs
           Version: 12.0
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: vladimir at pobox.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

Created attachment 25290
  --> https://bugs.llvm.org/attachment.cgi?id=25290&action=edit
testcase

The attached .ll testcase shows what looks like an error in translating down to
native code for mips.  I've annotated the testcase with info & the generated
instructions; it's self-contained and can be compiled to an executable that
should print "hello".

Note the .ll specifies mips/irix (which is mips3/n32), but I've verified the
miscompilation happens with stock LLVM 12 targeting mips64-unknown-unknown and
mips64r3/n32.

The problem is in the `doit` function:

;; %path.coerce is struct StringRef { char *data; int len; }

define void @doit(i8* nonnull align 1 %dst, i64 inreg %path.coerce)
local_unnamed_addr #0 {                                                         
  %path = alloca i64, align 8                                                   
  store i64 %path.coerce, i64* %path, align 8
  %copyload = load i64, i64* %path, align 8, !tbaa.struct !32
  %struct_ptr_pre_trunc = lshr i64 %copyload, 32
  %struct_ptr_int = trunc i64 %struct_ptr_pre_trunc to i32
  %struct_ptr = inttoptr i32 %struct_ptr_int to i8*

  ;; this trunc is not actually happening; the result
  %struct_len = trunc i64 %copyload to i32

  ;; at this point
  ;; a0 = dst, same as input register
  ;; a1 = a2 >> (32+0)
  ;; a2 = ^^^ full 64-bit value from original load -- no trunc!

  call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 %dst, i8* align 1
%struct_ptr, i32 %struct_len, i1 false) #1


There's a missing `sll a2,a2,0` that I believe should be emitted for the trunc
but is not happening.  If I insert a i32 store of %struct_len to the stack, and
then load it back, the sll is emitted properly and the function works
correctly.

Random observation -- the non-truncated value is already in register a2, which
is where it needs to go for the memcpy; could be something trying to take
advantage of that, but doing so incorrectly?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210924/1cad72f4/attachment.html>


More information about the llvm-bugs mailing list