[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