IFC 7.1 GenuineIntel check: workaround
From: Mark Mackey (markm_at_chiark.greenend.org.uk)
Date: 07/07/04
- Previous message: Arjen Markus: "Re: What can be done in FORTRAN that cannot be done in C/C++?"
- Next in thread: Steve Lionel: "Re: IFC 7.1 GenuineIntel check: workaround"
- Reply: Steve Lionel: "Re: IFC 7.1 GenuineIntel check: workaround"
- Reply: Herman D. Knoble: "Re: IFC 7.1 GenuineIntel check: workaround"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 07 Jul 2004 12:30:48 +0100 (BST)
Hi all.
I'm still using ifc 7.1 (8.0 doesn't like my code, or vice versa). The
latest version (Linux ia32 7.1.040) has some useful bugfixes from
previous versions but is crippled on non-Intel processors: the
vectorised math library checks for a GenuineIntel chip and disables
SSE/SSE2 code. As a result, code compiled with -axK will run just the
generic (slow) ia32 code on Athlons, while code compiled with -xK will
segfault.
Intel say that this is a bug inadvertently introduced into the math
libraries, and that they have no plans to fix it.
Luckily, it's easy to work around. The attached Perl script (also
available at http://www.swallowtail.org/intel_check_patch.txt in case
word wraps etc bugger up the code below) patches the affected libirc.a
file. The libimf.so file is also affected by this bug, so if you use
-i_dynamic you'll have to patch that file to: it should be pretty simple
to modify this script to do that.
Note: if you got the previous version of this message before I
cancelled it, use this script instead. I'd attached the wrong copy of
the script to the previous one, and it patches libirc so that SSE fails
on _all_ chips, even Intel ones :).
8<---------------------------------------------------------------------
#!/usr/bin/perl
#
# (C) Copyright M. D Mackey 2004. This program may be freely modified and redistributed.
#
# A short program to patch the 'libirc.a' file from the Intel Fortran Compiler
# version 7.1.040 (build 20040309Z). May work on other builds also, but is not
# guaranteed. The patch removes the check for the string "GenuineIntel" in the
# CPUID flags of the processor, thus making SSE/SSE2 code work on AMD chips that
# support it.
#
# Creates a file 'libirc.a.bak' containing the original contents of libirc.a.
#
# If you want to check for a successful patch, do
#
# objdump -d libirc.a.bak > old
# objdump -d libirc.a > new
#
# and examine the differences between 'old' and 'new'. Three lines
# should have changed in __intel_cpu_indicator_init:
#
# 3d 47 65 6e 75 cmp $0x756e6547,%eax
# ...
# 3d 69 6e 65 49 cmp $0x49656e69,%eax
# ...
# 3d 6e 74 65 6c cmp $0x6c65746e,%eax
#
# (these check for "GenuineIntel"). These lines should all be changed to
# a9 00 00 00 00 test $0x00000000,%eax
#
# Note that the "GenuineIntel" check is still present in
# libimf.so, so if you link with the -i_dynamic flag you'll
# have to patch that file yourself.
#
open(LIBIRC,"libirc.a") or help();
my($libirc)=join('',<LIBIRC>);
close(LIBIRC);
# libirc is small, so let's do things the simple way...
#
my($unp)=unpack('H*',$libirc);
my($count);
$count=($unp=~s/3d47656e75/a900000000/);
die("Failure patching 3d 47 65 6e 75: libirc.a has either already been patched or is the wrong version\n") unless ($count==1);
$count=($unp=~s/3d696e6549/a900000000/);
die("Failure patching 3d 69 6e 65 49: libirc.a has either already been patched or is the wrong version\n") unless ($count==1);
$count=($unp=~s/3d6e74656c/a900000000/);
die("Failure patching 3d 6e 74 65 6c: libirc.a has either already been patched or is the wrong version\n") unless ($count==1);
open(OUTPUT,">libirc.a.tmp") or die;
print OUTPUT pack('H*',$unp);
close(OUTPUT);
if (! -f "libirc.a.bak") {
rename("libirc.a","libirc.a.bak") or die("Couldn't rename libirc.a to libirc.a.bak: $!\n");
}
rename("libirc.a.tmp","libirc.a") or die("Couldn't rename libirc.a.tmp to libirc.a: $!\n");
print STDERR "Patch operation on libirc.a successful\n";
exit(0);
sub help {
print STDERR <<EOUSAGE;
Some versions of the Intel Fortran Compiler produce code which checks whether
the CPU is made by Intel or not, and disables MMX/SSE/SSE2 code if it isn't.
This program patches the compiler libraries to remove this check, so that e.g.
programs compiled with -axW will use SSE2 code on Athlon 64 chips.
To run the patch, simply execute this script in the
/opt/intel/compiler70/ia32/lib directory: the file 'libirc.a' will be patched.
A backup copy of libirc.a will be made first, so if it all goes wrong you won't
lose anthing.
This script was tested against ifc version 7.1.040, build 20040309Z, and may
not work on other versions. It shouldn't break anything, however.
EOUSAGE
exit(1);
}
__END__
8<-----------------------------------------------------------------------
-- Mark Mackey "The determined Real Programmer can write Fortran programs in any language." - "Real Programmers don't use Pascal"
- Previous message: Arjen Markus: "Re: What can be done in FORTRAN that cannot be done in C/C++?"
- Next in thread: Steve Lionel: "Re: IFC 7.1 GenuineIntel check: workaround"
- Reply: Steve Lionel: "Re: IFC 7.1 GenuineIntel check: workaround"
- Reply: Herman D. Knoble: "Re: IFC 7.1 GenuineIntel check: workaround"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|