Scott Duplichan
2014-10-29 04:59:26 UTC
Optimization is not enabled for x64 builds using gcc 4.4-4.9. For IA32
builds, -Os (optimize for small code size) is used. Why is this? Apparently
it is because variable argument list handling fails when gcc X64 optimization
is enabled. The solution is an improvement to the patch of SVN rev 10440:
http://sourceforge.net/p/edk2/mailman/message/25121111/
The patch in this email only adds gcc X64 optimization for gcc versions 4.8
and newer. This is because testing with older versions of gcc is a lot of
work. On the other hand, the patch could be a lot simpler if it were to
ignore gcc version. The patch is boot tested using Duet with gcc 4.8.2 and
gcc 4.9.1. For these two cases, the print formatting problem is resolved
by the patch.
Should we:
1) Restrict the change to recent gcc versions where testing is easy
(approach of included patch)
2) Apply the change to all gcc versions, and let older versions go
untested?
3) Try to find/build the needed older gcc versions so that the patch
can apply to all versions and be tested too
Thanks,
Scott
--
Enable optimization for gcc x64 builds.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Scott Duplichan <***@notabs.org>
--
Index: BaseTools/Conf/tools_def.template
===================================================================
--- BaseTools/Conf/tools_def.template (revision 16254)
+++ BaseTools/Conf/tools_def.template (working copy)
@@ -3843,7 +3843,7 @@
DEFINE GCC44_ALL_CC_FLAGS = -g -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -c -include AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
DEFINE GCC44_IA32_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m32 -malign-double -fno-stack-protector -D EFI32
-DEFINE GCC44_X64_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -DNO_BUILTIN_VA_FUNCS -mno-red-zone -Wno-address -mcmodel=large
+DEFINE GCC44_X64_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -Wno-address -mcmodel=large
DEFINE GCC44_IA32_X64_DLINK_COMMON = -nostdlib -n -q --gc-sections --script=$(EDK_TOOLS_PATH)/Scripts/gcc4.4-ld-script
DEFINE GCC44_IA32_X64_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_COMMON) --entry ReferenceAcpiTable -u ReferenceAcpiTable
DEFINE GCC44_IA32_X64_DLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_COMMON) --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
@@ -4420,7 +4420,7 @@
*_GCC48_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
*_GCC48_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
*_GCC48_X64_ASM_FLAGS = DEF(GCC48_ASM_FLAGS) -m64
-*_GCC48_X64_CC_FLAGS = DEF(GCC48_X64_CC_FLAGS)
+*_GCC48_X64_CC_FLAGS = DEF(GCC48_X64_CC_FLAGS) -Os
*_GCC48_X64_DLINK_FLAGS = DEF(GCC48_X64_DLINK_FLAGS)
*_GCC48_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
*_GCC48_X64_OBJCOPY_FLAGS =
@@ -4542,7 +4542,7 @@
*_GCC49_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
*_GCC49_X64_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
*_GCC49_X64_ASM_FLAGS = DEF(GCC49_ASM_FLAGS) -m64
-*_GCC49_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS)
+*_GCC49_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS) -Os
*_GCC49_X64_DLINK_FLAGS = DEF(GCC49_X64_DLINK_FLAGS)
*_GCC49_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
*_GCC49_X64_OBJCOPY_FLAGS =
Index: EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h
===================================================================
--- EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h (revision 16254)
+++ EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h (working copy)
@@ -66,6 +66,7 @@
@return The aligned size.
**/
#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+#define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)
#if defined(__CC_ARM)
//
@@ -92,25 +93,37 @@
#define VA_COPY(Dest, Start) __va_copy (Dest, Start)
-#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
+#elif defined(__GNUC__) && !defined(__x86_64__)
//
// Use GCC built-in macros for variable argument lists.
//
///
-/// Variable used to traverse the list of arguments. This type can vary by
-/// implementation and could be an array or structure.
+/// Variable used to traverse the list of arguments. This type can vary by
+/// implementation and could be an array or structure.
///
-typedef __builtin_va_list VA_LIST;
+ typedef __builtin_va_list VA_LIST;
-#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
+ #define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
-#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
-#define VA_END(Marker) __builtin_va_end (Marker)
+ #define VA_END(Marker) __builtin_va_end (Marker)
-#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+ #define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+#elif defined(__GNUC__) && defined(__x86_64__) && (GCC_VERSION >= 48)
+
+ typedef __builtin_ms_va_list VA_LIST;
+
+ #define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter)
+
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+
+ #define VA_END(Marker) __builtin_ms_va_end (Marker)
+
+ #define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start)
+
#else
#ifndef VA_START
Index: MdePkg/Include/Base.h
===================================================================
--- MdePkg/Include/Base.h (revision 16254)
+++ MdePkg/Include/Base.h (working copy)
@@ -441,6 +441,7 @@
@return The aligned size.
**/
#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+#define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)
#if defined(__CC_ARM)
//
@@ -472,7 +473,7 @@
#define VA_COPY(Dest, Start) __va_copy (Dest, Start)
-#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
+#elif defined(__GNUC__) && !defined(__x86_64__)
//
// Use GCC built-in macros for variable argument lists.
//
@@ -481,16 +482,28 @@
/// Variable used to traverse the list of arguments. This type can vary by
/// implementation and could be an array or structure.
///
-typedef __builtin_va_list VA_LIST;
+ typedef __builtin_va_list VA_LIST;
-#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
+ #define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
-#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
-#define VA_END(Marker) __builtin_va_end (Marker)
+ #define VA_END(Marker) __builtin_va_end (Marker)
-#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+ #define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+#elif defined(__GNUC__) && defined(__x86_64__) && (GCC_VERSION >= 48)
+
+ typedef __builtin_ms_va_list VA_LIST;
+
+ #define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter)
+
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+
+ #define VA_END(Marker) __builtin_ms_va_end (Marker)
+
+ #define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start)
+
#else
///
/// Variable used to traverse the list of arguments. This type can vary by
--
builds, -Os (optimize for small code size) is used. Why is this? Apparently
it is because variable argument list handling fails when gcc X64 optimization
is enabled. The solution is an improvement to the patch of SVN rev 10440:
http://sourceforge.net/p/edk2/mailman/message/25121111/
The patch in this email only adds gcc X64 optimization for gcc versions 4.8
and newer. This is because testing with older versions of gcc is a lot of
work. On the other hand, the patch could be a lot simpler if it were to
ignore gcc version. The patch is boot tested using Duet with gcc 4.8.2 and
gcc 4.9.1. For these two cases, the print formatting problem is resolved
by the patch.
Should we:
1) Restrict the change to recent gcc versions where testing is easy
(approach of included patch)
2) Apply the change to all gcc versions, and let older versions go
untested?
3) Try to find/build the needed older gcc versions so that the patch
can apply to all versions and be tested too
Thanks,
Scott
--
Enable optimization for gcc x64 builds.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Scott Duplichan <***@notabs.org>
--
Index: BaseTools/Conf/tools_def.template
===================================================================
--- BaseTools/Conf/tools_def.template (revision 16254)
+++ BaseTools/Conf/tools_def.template (working copy)
@@ -3843,7 +3843,7 @@
DEFINE GCC44_ALL_CC_FLAGS = -g -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -c -include AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
DEFINE GCC44_IA32_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m32 -malign-double -fno-stack-protector -D EFI32
-DEFINE GCC44_X64_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -DNO_BUILTIN_VA_FUNCS -mno-red-zone -Wno-address -mcmodel=large
+DEFINE GCC44_X64_CC_FLAGS = DEF(GCC44_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -Wno-address -mcmodel=large
DEFINE GCC44_IA32_X64_DLINK_COMMON = -nostdlib -n -q --gc-sections --script=$(EDK_TOOLS_PATH)/Scripts/gcc4.4-ld-script
DEFINE GCC44_IA32_X64_ASLDLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_COMMON) --entry ReferenceAcpiTable -u ReferenceAcpiTable
DEFINE GCC44_IA32_X64_DLINK_FLAGS = DEF(GCC44_IA32_X64_DLINK_COMMON) --entry $(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Map $(DEST_DIR_DEBUG)/$(BASE_NAME).map
@@ -4420,7 +4420,7 @@
*_GCC48_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
*_GCC48_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
*_GCC48_X64_ASM_FLAGS = DEF(GCC48_ASM_FLAGS) -m64
-*_GCC48_X64_CC_FLAGS = DEF(GCC48_X64_CC_FLAGS)
+*_GCC48_X64_CC_FLAGS = DEF(GCC48_X64_CC_FLAGS) -Os
*_GCC48_X64_DLINK_FLAGS = DEF(GCC48_X64_DLINK_FLAGS)
*_GCC48_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
*_GCC48_X64_OBJCOPY_FLAGS =
@@ -4542,7 +4542,7 @@
*_GCC49_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
*_GCC49_X64_ASLDLINK_FLAGS = DEF(GCC49_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
*_GCC49_X64_ASM_FLAGS = DEF(GCC49_ASM_FLAGS) -m64
-*_GCC49_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS)
+*_GCC49_X64_CC_FLAGS = DEF(GCC49_X64_CC_FLAGS) -Os
*_GCC49_X64_DLINK_FLAGS = DEF(GCC49_X64_DLINK_FLAGS)
*_GCC49_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
*_GCC49_X64_OBJCOPY_FLAGS =
Index: EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h
===================================================================
--- EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h (revision 16254)
+++ EdkCompatibilityPkg/Foundation/Include/EfiStdArg.h (working copy)
@@ -66,6 +66,7 @@
@return The aligned size.
**/
#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+#define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)
#if defined(__CC_ARM)
//
@@ -92,25 +93,37 @@
#define VA_COPY(Dest, Start) __va_copy (Dest, Start)
-#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
+#elif defined(__GNUC__) && !defined(__x86_64__)
//
// Use GCC built-in macros for variable argument lists.
//
///
-/// Variable used to traverse the list of arguments. This type can vary by
-/// implementation and could be an array or structure.
+/// Variable used to traverse the list of arguments. This type can vary by
+/// implementation and could be an array or structure.
///
-typedef __builtin_va_list VA_LIST;
+ typedef __builtin_va_list VA_LIST;
-#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
+ #define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
-#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
-#define VA_END(Marker) __builtin_va_end (Marker)
+ #define VA_END(Marker) __builtin_va_end (Marker)
-#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+ #define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+#elif defined(__GNUC__) && defined(__x86_64__) && (GCC_VERSION >= 48)
+
+ typedef __builtin_ms_va_list VA_LIST;
+
+ #define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter)
+
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+
+ #define VA_END(Marker) __builtin_ms_va_end (Marker)
+
+ #define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start)
+
#else
#ifndef VA_START
Index: MdePkg/Include/Base.h
===================================================================
--- MdePkg/Include/Base.h (revision 16254)
+++ MdePkg/Include/Base.h (working copy)
@@ -441,6 +441,7 @@
@return The aligned size.
**/
#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
+#define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)
#if defined(__CC_ARM)
//
@@ -472,7 +473,7 @@
#define VA_COPY(Dest, Start) __va_copy (Dest, Start)
-#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
+#elif defined(__GNUC__) && !defined(__x86_64__)
//
// Use GCC built-in macros for variable argument lists.
//
@@ -481,16 +482,28 @@
/// Variable used to traverse the list of arguments. This type can vary by
/// implementation and could be an array or structure.
///
-typedef __builtin_va_list VA_LIST;
+ typedef __builtin_va_list VA_LIST;
-#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
+ #define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter)
-#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
-#define VA_END(Marker) __builtin_va_end (Marker)
+ #define VA_END(Marker) __builtin_va_end (Marker)
-#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+ #define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start)
+#elif defined(__GNUC__) && defined(__x86_64__) && (GCC_VERSION >= 48)
+
+ typedef __builtin_ms_va_list VA_LIST;
+
+ #define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter)
+
+ #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
+
+ #define VA_END(Marker) __builtin_ms_va_end (Marker)
+
+ #define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start)
+
#else
///
/// Variable used to traverse the list of arguments. This type can vary by
--