summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/util/gcc-opt-x86.pl
blob: 9009a0a71a1dcf5938cab9283ad753f61b477a4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env perl
#
# GCC optimization flag generator
#

use strict;
use warnings;

my $gcc = $ARGV[0];
my $cpuinfo = $ARGV[1];

if ( ! $gcc ) {
	die "Can't generate optimization flags (no compiler specified)\n";
}

if ( ! `which $gcc 2> /dev/null` ) {
	die "Can't generate optimization flags ($gcc is missing?)\n";
}

#
# We allow people to provide their own cpuinfo-compatible
# descriptor. This may be useful later if we want to have
# specific architecture-specific optimizations for release
# builds or something.
#
if ( ! $cpuinfo ) {
	$cpuinfo = "/proc/cpuinfo";
}

my %features;
my ($family, $model);
my $uname_M = `uname -m`;
my $uname_P = `uname -p`;
my $uname_S = `uname -s`;

#
# Collect CPU feature list
#

# The Linux way
if ( -e $cpuinfo ) {
	open(FH, "< $cpuinfo");
	my @cpuinfo = <FH>;
	close FH;

	my @line = grep(/^cpu family/, @cpuinfo);
	$line[0] =~ /([0-9]*)$/;
	$family = $1;

	@line = grep(/^model/, @cpuinfo);
	$line[0] =~ /([0-9]*)$/;
	$model = $1;

	my @flags = grep(/^flags/, @cpuinfo);
	$flags[0] =~ s/^flags[ \t]*[:][ \t]*//;
	@flags = split(' ',$flags[0]);
	foreach (@flags) {
		$features{$_} = 1;
	}
}

# The Mac OS X way
if ( $uname_S =~ /^Darwin/ ) {
	# All released Intel macs have CMOV, and
	# sysctl doesn't provide this one.
	$features{"cmov"} = 1;

	$features{"mmx"} = `sysctl -n hw.optional.mmx`;
	$features{"sse"} = `sysctl -n hw.optional.sse`;
	$features{"sse2"} = `sysctl -n hw.optional.sse2`;
	$features{"pni"} = `sysctl -n hw.optional.sse3`;
	$features{"ssse3"} = `sysctl -n hw.optional.supplementalsse3`;
}

# TODO architectures:
# * athlon-4, athlon-xp, athlon-mp
# * k8, opteron, athlon64, athlon-fx
# * k8-sse3, opteron-sse3, athlon64-sse3
# * winchip-c6, winchip2

my $gcc_gte_4_2_0 = `util/gcc-gte.pl $gcc 4.2.0`;
my $gcc_gte_4_3_0 = `util/gcc-gte.pl $gcc 4.2.0`;
my $gcc_gte_4_5_0 = `util/gcc-gte.pl $gcc 4.5.0`;

#
# Check the minimum march/mtune value
#
my $march = "i386";
my $fpmath;

if ($uname_M eq "i586" || $uname_M eq "i686")
{
	# Pentium and PentiumPro
	$march = $uname_M;
}
if ( $uname_M eq "i586" && $features{"mmx"} )
{
	$march = "pentium-mmx";
}
if ( $features{"cmov"} && $features{"mmx"} ) {
	$march = "pentium2";
}
if ( $features{"sse"} ) {
	$march = "pentium3";
	$fpmath = "sse"
}
if ( $features{"sse2"} ) {
	$march = "pentium-m";
}
if ( $features{"pni"} ) { # a.k.a. SSE3
	$march = "prescott";
}
if ( $features{"ssse3"} ) {
	if ( $gcc_gte_4_3_0 ) {
		$march = "core2";
	} else {
		$march = "nocona";
	}
}
if ( $gcc_gte_4_5_0 && $features{"movbe"} ) {
	$march = "atom";
}
if ( $uname_P =~ /Athlon/ )
{
	$march = "athlon";

	if ( $features{"abm"} && $features{"sse4a"} )
	{
		$march = "amdfam10";
	}
}

# It's important to specify 'march=pentium4' for the
# Pentium 4, because it has vastly different optimization
# rules than other x86 processors. What's optimal for the
# Pentium 3 is extremely sub-optimal for the Pentium 4.
if ( $family == 15 ) {
	$march = "pentium4";
}

print "-march=$march -mtune=$march";
if ( $fpmath ) {
	print " -mfpmath=$fpmath";
}

print "\n";

exit 0