[cfe-commits] r143596 - /cfe/trunk/lib/CodeGen/TargetInfo.cpp
Hatanaka, Akira
ahatanaka at mips.com
Mon Nov 7 19:27:35 PST 2011
Just to add to my previous email,
tail call void @callee(i32 3, double %0, i64 %1, i64 %2, i64 %3) nounwind
Without alignment information attached to "double %0", this is how the backend will pass arguments in registers, when the function above is lowered:
i32 3 => 1st integer register
double %0 => 2nd FP register
i64 %1 => 3rd integer register
i64 %2, i64 %3 => 4th and 5th integer register
The correct way to pass arguments is the following:
i32 3 => 1st integer register
double %0 => 3rd FP register
i64 %1 => 4th integer register
i64 %2, i64 %3 => 5th and 6th integer register
________________________________________
From: Hatanaka, Akira
Sent: Monday, November 07, 2011 6:52 PM
To: Eli Friedman
Cc: cfe-commits at cs.uiuc.edu
Subject: RE: [cfe-commits] r143596 - /cfe/trunk/lib/CodeGen/TargetInfo.cpp
One more question.
Suppose I want to compile the following program:
### source program
typedef struct {
double d1;
long double f1;
} S4;
void callee(int, S4);
extern S4 g1;
void foo100() {
callee(3, g1);
}
This is the bitcode clang currently procudes:
// bitcode
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v64:64:64-n32"
target triple = "mips64el-unknown-linux"
%struct.S4 = type { double, fp128 }
@g1 = external global %struct.S4
define void @foo100() nounwind {
entry:
%0 = load double* getelementptr inbounds (%struct.S4* @g1, i64 0, i32 0), align 16
%1 = load i64* getelementptr ({ double, i64, i64, i64 }* bitcast (%struct.S4* @g1 to { double, i64, i64, i64 }*), i64 0, i32 1), align 8
%2 = load i64* bitcast (fp128* getelementptr inbounds (%struct.S4* @g1, i64 0, i32 1) to i64*), align 16
%3 = load i64* getelementptr ({ double, i64, i64, i64 }* bitcast (%struct.S4* @g1 to { double, i64, i64, i64 }*), i64 0, i32 3), align 8
tail call void @callee(i32 3, double %0, i64 %1, i64 %2, i64 %3) nounwind
ret void
}
declare void @callee(i32, double, i64, i64, i64)
### end of bitcode
Since S4 has a long double field, whose alignment is 16, the second argument call to callee (g1) must also be 16-byte aligned, meaning it must be passed in even-odd FP register pairs. How do I convey this information to the backend?
There is nothing in this line that tells "double %0" has to be aligned to a 16-byte boundary.
tail call void @callee(i32 3, double %0, i64 %1, i64 %2, i64 %3) nounwind
I understand you can attach alignment information to byval arguments, but I don't know if it is possible to do that to doubles or i64s. Even if it were possible, it seems that I would still need to override TargetLowering::LowerCallTo to retrieve alignment of arguments that are not byval.
________________________________________
From: Hatanaka, Akira
Sent: Thursday, November 03, 2011 4:15 PM
To: Eli Friedman
Cc: cfe-commits at cs.uiuc.edu
Subject: RE: [cfe-commits] r143596 - /cfe/trunk/lib/CodeGen/TargetInfo.cpp
Thanks for the information, that is a better solution.
________________________________________
From: Eli Friedman [eli.friedman at gmail.com]
Sent: Wednesday, November 02, 2011 6:27 PM
To: Hatanaka, Akira
Cc: cfe-commits at cs.uiuc.edu
Subject: Re: [cfe-commits] r143596 - /cfe/trunk/lib/CodeGen/TargetInfo.cpp
On Wed, Nov 2, 2011 at 6:09 PM, Hatanaka, Akira <ahatanaka at mips.com> wrote:
> Yes, that should be 40-bits.
>
> The structure with sub-doubleword fields was needed to handle packed structures whose size is not a multiple of 64. When I test it with the program below, a full double word load is used to load the last field of struct S4 instead of a byte load. Is this legal? It seems incorrect to me to load from a memory location outside the global g2.
Oh, I see... no, that's not legal (at least, not in the general case).
x86-64 uses a trick to get around this for cases like "struct { char
x[13]; }": the last parameter has the type i40.
-Eli
More information about the cfe-commits
mailing list