[LLVMbugs] [Bug 668] NEW: PPC: or with disjoint bit pattern followed by load not turned into lwxz

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Thu Nov 17 17:47:04 PST 2005


http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=668

           Summary: PPC: or with disjoint bit pattern followed by load not
                    turned into lwxz
           Product: libraries
           Version: trunk
          Platform: Macintosh
        OS/Version: MacOS X
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Backend: PowerPC
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: ggreif at gmail.com


gabor: this should be C:
gabor: inline const void* RawObj2Meta(const void* obj)
gabor: {
gabor: #define PAGE 12
gabor: #define CLUSTER 4
gabor: #define SCALE 5
gabor: #define GRAN 3
gabor: #define            pat ((1 << PAGE + CLUSTER) - 1)
gabor: #define            mask (~((1 << GRAN) - 1))
gabor:     typedef unsigned long sptr_t;
gabor:     register sptr_t o = (sptr_t)(obj);
gabor:     enum
gabor:         {
gabor:         };
gabor:        
gabor:     register sptr_t b = o & ~(sptr_t)(pat); // base
gabor:     register sptr_t d = o & (sptr_t)(pat);  // displacement
gabor:     return (void*)(b + ((d >> SCALE) & mask));
gabor: }
gabor:
gabor: sorry, never programmed in C
sabre: j/s
sabre: the code above compiles to:
sabre: _RawObj2Meta:
sabre:         rlwinm r2, r3, 0, 0, 15
sabre:         rlwimi r2, r3, 27, 21, 28
sabre:         or r3, r2, r2
sabre:         blr
sabre: lemme try with |
sabre: same code with |
gabor: ah, call it and immediately dereference!
sabre: it will canonicalize both to |
sabre: not +
gabor: i.e.  *(int*)RawObj2Meta(obj)
sabre: it will leave it |
sabre: not an indexed load
gabor: if this gets inlined, gcc makes a (rlwinm, rlwinm, lwxz)
gabor: you probably make (rlwinm, rlwinm, or, lwz)
sabre: entirely possible
sabre: Can you file an llvm bugzilla?
gabor: it is 2:29 here 
sabre: tomorrow then? 
gabor: enough if I paste this discussion?
sabre: sure
sabre: try to edit it a little tho 
gabor: okay, done deal


here is the code:

inline const void* RawObj2Meta(const void* obj)
{
#define PAGE 12
#define CLUSTER 4
#define SCALE 5
#define GRAN 3
#define            pat ((1 << PAGE + CLUSTER) - 1)
#define            mask (~((1 << GRAN) - 1))

    typedef unsigned long sptr_t;
    register sptr_t o = (sptr_t)(obj);
    enum
        {
        };
       
    register sptr_t b = o & ~(sptr_t)(pat);
    register sptr_t d = o & (sptr_t)(pat);
    return (void*)(b | ((d >> SCALE) & mask));        /* when inlined below, LLVM: (rlwinm, rlwinm, or, lwz), 
GCC: (rlwinm, rlwinm, or, lwz) */
    /* return (void*)(b + ((d >> SCALE) & mask)); */  /* when inlined below, LLVM: (rlwinm, rlwinm, or, 
lwz), GCC: (rlwinm, rlwinm, lwxz) */
}


int main(argv char* v[], int argc)
{
    return *(int*)RawObj2Meta(v);
}


Looks like LLVM is smart enough to see the disjointness of bit patterns,
so it turns + to |. But in this case both expressions should be turned into
a (rlwinm, rlwinm, lwxz) instruction sequence!

Essentially what to be proven is that no carry can ripple up.

Cheers,

    Gabor



------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.




More information about the llvm-bugs mailing list