Hello, I'm John Crawford, here today
to give you an overview of Intel's Pentium microprocessor.
The Pentium processor is the fifth generation
of Intel's line of PC-compatible microprocessors.
I co-managed the chip design of the Pentium processor,
starting back in 1989.
I will start out with a historical perspective
of Intel's microprocessors from the 386 up through the Pentium
processor and back that up with the underlying historical
trends in the semiconductor technology from 1970
through the present.
Then, I will spend a few minutes describing
a few key aspects of the design methodology we used.
The bulk of this video is devoted
to describing the microarchitecture
of the Pentium processor and how the different hardware
techniques we chose to include contribute to its performance.
After working through this large amount of material,
I'll briefly describe the data integrity or error
checking features we included.
In the last section, we'll describe
the compiler technology co-developed with the Pentium
processor and the results delivered
on industry-standard SPEC benchmarks
that we achieved with the combination of the hardware
techniques and compiler optimizations.
Let me start with a brief overview of Intel's
microprocessor strategy.
We've kept three main goals in mind.
First of all, to maintain compatibility--
that is, each generation must be compatible with the last
in order to carry forward a very large software
base and the momentum that comes with that in the market.
A second key aspect of the strategy
is to maintain a very aggressive performance
ramp of doubling the performance every 18 months.
The third aspect of the strategy is
to continuously add new functions to enter new markets.
We've done this in two directions.
First of all, we've added functions
to move upward from the PC market
into the workstation, minicomputer,
and mainframe marketplaces, also known as the server market.
In the other directions, we've added features
to move downward into the laptop, notebook, and handheld,
or generally known as the mobile marketplace.
So given this is the overall strategy, let's delve
into this in more detail.
First of all, let's look at the performance growth from the 386
up through the Pentium processor.
Spanning a period from 1986 up until the 1993 timeframe,
I've highlighted three different generations of processors.
You can see four points of the 386 line
where we offer different frequencies of that product.
You can again see four of the points of the 486 product line
in the first point on the Pentium processor line.
Now, each of these is plotted in terms of the integer SPEC
performance on the y-axis against general system
availability date on the x-axis.
It's important to note that this is the date when systems are
available from our customers-- that is,
after they've announced the products
and started shipping to their customers
through their channels.
So you can see here a very nice performance growth rate.
And I've had a spreadsheet program plot the regression
line on a semi-log chart where it computes
the compound annual growth rate somewhere close to 1.6
every year, which corresponds to a doubling of performance
about every 18 months.
That's a very interesting growth rate.
I thought I'd try to relate that growth rate to some real world
examples.
We get a little blase in the computer industry
about the performance going up and up every year,
whereas if the same growth rate occurred in other areas
it would be truly astounding.
For example given the same growth
rate of doubling every 18 months over a decade,
you come up with a factor of approximately
a 200-fold increase.
With the same improvement were applied to automobiles,
we'd be traveling around in our cars
at about 11,000 miles an hour or potentially getting
about 4,000 miles to the gallon.
A point that's maybe a little easier
to visualize or to comprehend would be a flight
from Los Angeles to New York would
take 90 seconds rather than the five hours
or so that it takes currently.
A different way of looking at it might
be in the agricultural field where wheat yields would
have gone from about 35 bushels per acre
up to about 7,000 bushels an acre.
So this is really quite a remarkable growth rate.
Now, where did this performance come from?
I believe that we've really developed the performance
along three dimensions.
Let me go into each of these in a little more detail.
Along one dimension, we have silicon technology.
And here with a Pentium processor,
we've applied 0.8 micron BiCMOS technology as our latest
and greatest process.
A second dimension is an architecture technology
in terms of structuring the computers to extract more
parallelism by executing more and more instructions
in parallel, using techniques such as superscalar
execution, branch prediction, and some more
straightforward aspects such as just larger caches on board
and wider buses.
A third dimension is software technology.
And here, improved compilers are key to providing
improved performance from maximizing
the parallelism that's made available to the hardware.
Let's take a closer look at the semiconductor technology
dimension.
It really is a key aspect that's driving the performance
forward.
And here, we have technology scaling as the main driver,
and there are really two aspects of this.
One is that the die size grows as we improve our manufacturing
processes, and we're able to process larger wafers.
We can economically produce larger and larger die sizes.
The second aspect is that circuit dimensions shrink,
so that each generation we have smaller devices
and we're able to print thinner wires and more
compact transistors.
Fortunately, the smaller transistors run faster
and the extra devices also provide the raw material
for integrating performance structures such as caches,
extra execution pipelines, and in general more
parallel performance structures.
The third category is that new capabilities can also
be added using the extra devices that the technology makes
available to us.
I have here a few charts showing our technology growth from 1970
through the present where I've charted
certain key aspects of our semiconductor technology used
in our microprocessors from the 4,004
in 1971 up through the Pentium processor in 1993.
Here charting the die size, you can
see a nice compound annual growth rate of the die size
with a nice regression line, which I've plotted only
against the lead CPUs.
Coming way below the line at much smaller die sizes,
you can see what we call our compaction
products, such as the 386 compaction and the 486
compaction.
These designs have taken a processor
such as the 386 produced on one technology
and compacted it to the next generation
so we get a much smaller size to take into volume manufacturing.
If you rule these out and plot just the lead CPUs,
we get a very nice compound annual growth rate
on the die size that's fairly constant over time.
This chart shows the shrinking of the transistor dimensions.
And here, I have a semi-log plot of the squares microns
per transistor on the y-axis, turning down over time
very nicely.
The larger die sizes compounded with the smaller dimensions
for each transistor combine to produce a very nice growth
rate in the transistors per microprocessor.
And here, you can see a very nice compound annual growth
rate of the number of transistors per microprocessor.
And here again, we can see the compaction devices
a little below the line for the same reasons discussed earlier.
Again, let's come back to reality
and try to relate these growth curves to some real world
examples.
The transistor count per die is doubling every 24 months
and has been doing so since 1970.
That gives us about a 3,000 fold increase over that timeframe.
Coming back to the real world examples,
perhaps the best analogy is the one of the wheat yields.
Again, back in 1970, the typical yield
was about 33 bushels per acre.
If we had a 3,000 fold increase, that
would give us about 100,000 bushels per acre,
and that would be about three feet
of wheat piled up on that acre.
Perhaps the only real world example
that's come even close to this growth rate
is the growth in our national debt,
but I haven't had the courage to work out
the figures on that one.
Let me shift gears now back to the present
and bring you to the Pentium processor.
First of all, I'd like to cover two key aspects of the design
methodology used in developing this processor of the many
that were involved.
One is that we could develop software with the hardware
so that they would complement each other to deliver
maximum performance.
In order to do this, we had a big focus
on compiler technology.
We staffed and funded a very professional compiler team
internally so that the compiler developers
could work hand in hand with the hardware developers.
We also wanted to ensure that this compiler technology was
propagated out to our large community of applications
developers, so it was very important to make
this technology broadly available
and not hold it close to our vest.
Consequently, we had a big focus on working
with external compiler vendors to deliver this technology out
through their channels.
Later on, we'll hear from the manager
of our internal compiler effort, Beatrice Fu, who
will describe this compiler technology and the results
that we achieved.
We also worked closely with key operating system vendors
to make sure that the system aspects of the processor
would result in good delivered performance
from these operating systems.
A second aspect of the design methodology
was quantifying the design decisions.
And the focus here was to quantify
decisions on the architecture features to include--
that is, what new features to add to the instruction set--
and to quantify decisions on the microarchitecture-- that
is, the internal structure of the processor
and the compiler techniques, the internal structure
of the compiler if you will.
We wanted to base decisions in these areas
on as much quantitative data as possible.
One technique we used was system measurement,
where we could measure programs executing on 386 and 486
systems and project forward to the Pentium processor
from the system measurements.
At a more detailed level, we developed
a very flexible and detailed performance simulator
that would very accurately estimate
the performance of different software running on the Pentium
processor long before it was realized in silicon.
In order to drive the simulator, we collected a number of traces
across a broad spectrum of application areas
and used these traces to drive the performance simulator.
The results of this trace-driven simulation
gave us some quantitative feedback
on the value of the different aspects of the hardware
and software.
We even carried this quantitative computer
architecture into the hardware itself
by providing a number of facilities
within the processor to support measurement of running systems
so that we have a very nice event monitoring facility that
can count both discrete events, such as cache misses,
as well as some duration events, such as bus stalls.
Later on, we'll see how we use these performance monitors
to measure the effectiveness of some key microarchitecture
techniques included in the Pentium processor
and how they performed when executing the SPEC benchmark
suite.
But first, let's hear from Dan Alpert, chief architect
of the Pentium processor who will describe key features
of its micro architecture.
Thanks, John.
When we started the design of the Pentium processor,
we knew there'd be a number of very important challenges
in trying to stay on the performance treadmill
while maintaining compatibility with the previous generation
of Intel microprocessors.
What I'll be describing here is a number
of the microarchitecture techniques
that we developed in designing the Pentium processor.
The topics I will cover are the bus interface,
superscalar integer pipelines, cache organization,
branch prediction, and pipeline floating point unit.
Let's start with the bus interface.
We needed a high performance bus to satisfy the Pentium
processors demand for instructions and data
from external cache and memory.
The data bus is 64 bits wide and operates
at the full 66 megahertz speed of the processor core.
In contrast, the bus of our previous generation processor,
the Intel 486 model DX2, has a 32-bit data path
and it runs at 33 megahertz.
So the Pentium processor's bus has four times the bandwidth
with a peak rate of over half a gigabyte per second.
Now moving on to the integer execution units,
we started with the five-stage pipeline
based on that of the Intel 486 processor.
The first stage reads instructions from the cache
into a prefetch buffer and aligns them for decoding.
The first decode stage generates a control word for execution
by the pipeline.
The second code stage decodes the control word
and generates addresses for memory references.
The E stage is used either to calculate a result in the ALU
or to access data in the cache.
The final stage is used to write results back
to the register file.
In the Pentium processor, we have improved performance
by decoding two instructions in parallel
and replicating the address generation hardware and ALU.
You can think of this as being similar to placing
two of the 486's integer pipelines on the same chip.
We call the two pipelines U and V.
One final point is that complex instructions, such as string
operations, are executed by generating
a sequence of microcode words in the D1 stage.
The microcode is written to take advantage
of the hardware that's available in both pipelines.
Let's look at more detail at the instruction-decode stage.
Logic in the D1 stage is used to check for dependencies
between instructions, and we only
issue instructions in parallel to the two pipelines
if they are independent.
The types of dependency that we check for
are resource, control, and data.
First of all, we check that both of the instructions
are from a class we call--
and this is in quotes-- "simple."
The so-called simple instructions
include ALU operations, jumps, loads, and stores.
Our definition of simple even includes
instructions that perform operations from memory
to registers.
We find that about 90% to 95% of instructions executed
are simple.
By issuing only a subset of the instructions in parallel,
we are able to handle resource dependencies.
For example, there's only a single shifter in the U pipe,
so all of the shift instructions are issued to the U pipe.
Control dependencies occur when the result of one instruction
determines whether another instruction will be executed.
We handle this by checking whether the first instruction
is the jump instruction.
If it is, then we don't issue an instruction in parallel.
Data dependencies occur when the result if one instruction
is used or modified by another instruction.
We handle this by checking that the destination
register of the first instruction
is neither the source nor destination register
of the second instruction.
We have included logic to improve performance
by handling some common cases of dependencies,
thereby allowing more instructions
to be executed in parallel.
First of all are flags.
In the Intel architecture, most of the instructions
modify the flags so that without special handling,
it would be difficult to pair many instructions.
So we do handle the case of parallel instructions
that modify the flags, and we update the flags
the same as if the instructions were executed sequentially.
We also have special logic that handles
the case for conditional branch instructions executed
in parallel with an instruction that sets the flags.
This occurs quite commonly, especially
for compare-branch combinations.
A second special case was the logic
on the stack pointer that allows pushes and pops
to be executed in parallel.
For example, when passing parameters for a procedure
call, there will often be a sequence of pushes.
The logic adjusts the stack pointer
appropriately for parallel execution.
One final point about the decoder
is that we prefetch a complete cache line of 256 bits
to keep the decoder busy.
So the question comes up, just how effective
is the instruction pairing?
Here's a chart showing how the pipelines are
utilized on the SPECint 92 or integer SPEC benchmark suite.
What I've plotted here is for each of the SPEC benchmarks
the percentage of instructions that
go in the U pipe, which is the primary pipeline,
and then the percentage of instructions
that go through the V pipe, which
is the secondary pipeline.
You can see that the pairing ranges roughly around 30%
to 40%, with one benchmark [INAUDIBLE]
hitting above 40% of the instructions
going into the V pipe.
You can see on this particular set of applications
that the pairing is quite effective.
I would like to point out again that these measurements are
taken from an actual running system using
the performance monitoring counters
that John described earlier.
At this point, let's take a look at the cache organization.
We have separate code and data caches.
This was done to eliminate the conflicts between prefetch
access's and data access's.
This was important because we knew the branch predictor was
going to drive a lot more references into the code cache
and because the superscalar pipelines would generate two
data references in parallel.
A consequence of splitting the caches
is that we have to add extra logic to handle
self-modifying code compatibly.
This affected a couple of key areas.
One is that each cache has to snoop the other caches
misses so there would never be inconsistent
data in the two caches.
It turns out that the logic that handles consistency
between external memory and the on-chip caches
was able to handle consistency between the on-chip caches
as well.
The other aspect is that we had to snoop the prefetch buffers
also so that if, for example, we wrote to an area of memory that
happened to be in a prefetch buffer,
we would need to invalidate the prefetch.
Now we can look at some of the vital statistics
about the caches.
Each of them is 8K bytes in size.
They both use 32-byte lines and are two way associative.
The data cache uses a write-back protocol to minimize the bus
traffic, and we use a MESI--
that's M, E, S, I-- for state protocol
to keep the data cache consistent with the code cache
as well as the rest of the system, including
multilevel caches, off-chip, and the memory.
Once we separated the code and data caches,
it became effective to separate the TLBs as well.
The TLBs support two page sizes, a 4 kilobyte page
and a 4 megabyte page.
The larger page is useful for mapping large, resonate data
structures with a single TLB entry.
For example, it can be used to map a graphics frame
buffer or the memory resident portions, either code or data,
of the operating system.
The data TLB has 64 entries for 4K byte pages
and 8 entries for 4 megabyte pages.
The co-TLB has 32 entries for 4K byte pages.
The effectiveness of the caches is
shown on the following charts for the SPEC benchmark suite.
Please remember that this data is taken from an actual running
system using the performance monitoring hardware that we
included on-chip.
The first chart shows the hit rate for instructions.
It varies from about 90% to a little over 95%.
What we are showing is the hit rate
for prefetches of 32 byte lines coming out
of the instruction cache.
This is often reported in terms of hits per instruction
instead.
And if we looked at it in this way,
the rate would even have been higher.
The next chart shows the data cache
hit rate based on the hits per read
or write reference to memory.
You can see that here, the data cache
hit rate varies from just below 90% to about 95%.
One of the most interesting aspects of the data cache's
design is its support for dual accesses by the two pipelines.
The Intel architecture has a limited number of registers.
There are only eight, and that results in more data memory
references for instruction than we would see in architectures
that have more registers.
For example, for optimized 32-bit code,
we see about 0.6 data references per instruction.
In contrast, many of the risk architectures
that have 32 registers would see only about half that number
of memory references per instruction.
Now, even a small cache can capture the locality
of the additional references.
We see that the compiler for the risk processors
can capture all those references in the 32-register file.
But it does lead to a requirement
for additional bandwidth in the Pentium processor.
We have implemented the cache using dual ported tags in TLB
with a single ported interleaved data array.
Making the data array, which is the bulk of storage
in the cache single ported, turned out
to be the most efficient use of area.
If we had also made it dual ported,
we would have had a smaller cache
and consequently higher miss rate.
The effect of increased misses was more
than the impact of bank conflicts,
so we went with the interleaved approach.
There's logic to detect when parallel references go
to the same bank.
When they do, the U pipe reference is completed
and the V pipe is forced to stall for one clock.
The same logic also handles the case
of data dependencies between parallel references
because, of course, if two references are
to the same location in memory, they will necessarily
be to the same bank.
One final point about the data cache
is that the two 32-bit paths are combined together
to form a 64-bit path for double precision floating point
operands.
The next chart shows some measurements
taken from the SPEC integer benchmarks suite,
demonstrating the effectiveness of dual memory reference
support.
The chart shows the frequency of references
that are actually paired.
You can see here that except for [INAUDIBLE],, about 20% to 25%
of the memory references are V pipe references paired
with U pipe references and the rate of bank conflicts is low.
[INAUDIBLE] shows 40% of references executed in parallel
in the V pipe, but about one out of eight references
is a conflict.
One of the most important performance enhancements
of the Pentium processor is dynamic branch prediction.
The Intel 486 processor flushes its pipeline
for every taken branch at a cost of 2 clocks delay.
Taken branches amount to 15% to 20% of instructions
executed, representing an opportunity
for substantial improvement.
In the Pentium processor, we cache information
about previous branches and use this
to predict future branches.
The prediction is made in an early stage of the pipeline,
and when the prediction is correct,
we can execute branches with no delay.
All of the branch predictions are verified
at the end of the pipeline.
If the prediction was incorrect, the pipelines
are flushed at a cost of 3 or 4 clocks.
The techniques are similar to those
used in mainframe architectures with adaptation
to the Intel architecture and to superscalar execution.
The memory structures that are used in the branch prediction
hardware make for very efficient VLSI implementation.
The heart of the branch prediction hardware
is an associate of memory called a branch target buffer, or BTB.
The BTB has 256 entries, and it is 4-way associative.
The tags used to access the BTB is the address
of the branch instruction.
The data portion of the BTB includes the branch destination
address and 2 bits of history used to predict whether or not
the branch will be taken.
Using 2 bits of history helps in cases
where a branch is consistently taken for a while then
occasionally not taken.
Only when the prediction is wrong twice in a row
will the prediction be changed.
We have some measurements of the branch prediction
accuracy taken with a built-in performance monitoring
hardware.
As you can see, the branch prediction accuracy
is generally 80% to 85% with the exception of the gcc
benchmark, which is only 73%.
The transistor budget available in the Pentium processor
allowed for dramatic improvements
in the floating point performance.
In the Intel 486 microprocessor, the floating point unit
wasn't pipelined and it typically took 10 to 14 clocks
for most operations.
The faster hardware algorithms in the Pentium processor
allow the operations to be executed
by a factor of 3 or more faster.
The execution units are also pipelined
to deliver one floating point result per clock.
The floating point pipeline was closely integrated
with the integer pipeline.
This was important in optimizing from memory
to register operations to deliver 164-bit memory
reference per clock in parallel with one floating
point operation.
The floating point execution units
support the 80-bit IEEE extended format with short latencies.
The multiplier and adder have latencies
of 3 clocks for all formats.
The divider has a latency of 18 to 38 clocks for precisions
from single to extended.
Along with the hardware to improve performance
of the basic arithmetic functions,
we also reimplemented the transcendental instructions--
sine, cosine, logarithm, and exponential--
that are part of our instruction set.
The new algorithms use polynomial approximations
to take advantage of the fast multiplier and adder.
This provides improvements both in performance and accuracy
over the Intel 486 microprocessor.
A key aspect of the floating point performance
was co-developing the compiler with the hardware
in order to ensure that this pipeline structure would
be very effectively used.
So that completes my portion of the presentation.
I hope that it helped you in your understanding
of the Pentium microprocessor.
Some of the new capabilities we included on the Pentium
processor were increased error detection
and a functional redundancy check mode of operation.
These were included at the request of our customers
at the high end of the computer market,
those involved in delivering solutions
to mission-critical server applications.
In these areas, even extremely rare errors
must be detected and handled appropriately,
so we included these features to satisfy those requirements.
The most important thing is to handle external errors.
And here, we've carried forward the data bus parity generation
and checking logic that was on the 486
and extended that to our 64-bit data bus.
Also, we added a parity bit on the address bus
so that we also can cover the second wide bus going off-chip
with parity generation and checking.
In addition to this external error detection capability,
within the chip we've included parity bits
on all the major arrays.
This includes the code and data cache arrays, cache tag arrays,
the TLBs, and even the microcode ROM.
All of these have parity bits included
so that any internal errors are detected and reported via pin.
This internal parity checking covers about half the devices
on the chip and so provides a very nice basic level
of coverage.
Beyond that, in order to offer an option
for the ultimate in error detection,
we have an FRC, or functional redundancy check,
mode on the chip where you can configure two processors
in a master checker configuration
where the master is operating normally
and the checker, rather than driving its output pins,
turns them inside out and checks the values driven by the master
and pulls a pin only if a mismatch occurs.
So this increased error detection level
provides a nice capability for some new application
areas where the ultimate in error detection is required.
And now, let's go with Beatrice Fu to our performance lab
where she will describe the compiler
technology we developed with the Pentium processor.
Thanks, John.
How compiler technology enhances the performance of the Pentium
processor is best illustrated with a simple example.
Here, we have a simple synthetic program
compiled by tool compilers.
The code on the left-hand side is generated by a typical 486
compiler, and the code on the right-hand side
is generated by the new compiler technology optimized
for the Pentium CPU.
The two code sequences are quite different,
even though they are both correct representations
of the original program.
This demonstration shows how the two code sequences proceed
through the Pentium processor.
The graphical block diagram represents the instruction
cache, the data cache, the two execution pipelines as well as
the floating point unit.
While executing, the active instructions
are color coded so that we can follow the journeys
through the Pentium processor.
As can be seen, the Pentium processor
has many idle resources on the left-hand side when
executing the traditional code sequence,
whereas the new code sequence utilizes the dual execution
pipelines more effectively on the right-hand side.
As a result, the time taken to run the new code sequence
is much less than the traditional code.
As can be seen, the right-hand side
is finished whereas the left-hand side is still
chugging along.
The advancement of CPU microarchitecture
requires advanced compiler technology
to exploit the on-chip parallelism,
such that features like pipeline and superscalar
can be made more effective to deliver the final performance
as illustrated in the previous demonstration.
The role of a compiler has always
been translating high-level language into low-level machine
code so as to hide the machine details from many programmers.
The role of an optimizing compiler
is to generate machine code that runs efficiently on the target
processor.
In the simple example here, a traditional compiler
will generate code to increment the array index
and compare the loop bond and end up with a three-cycle loop
body.
Using the same example, our optimizing compiler
displaces the loop count to eliminate
the compare instruction and take advantage
of the zero-flex setting of the increment instruction, which
improves the loop cycle count from 3 down to 2.
We are again using the same example.
Our new compiler technology further unrolls the loop
and overlaps the instructions from two different iterations
to take full advantage of the superscalar core.
This gives a two-cycle loop count for every two iterations
or effectively one cycle per iteration.
This is one example of how our compiler technology maximizes
the usage of the dual pipelines of the Pentium processor.
In the last decade, the CPU speed has increased more than
10 times , but the speed of memory components has not kept
up.
As caches are introduced into the memory subsystem
to meet the CPU demand, cooperation from compilers
is sometimes needed to ensure efficient use of the memory
bandwidth.
In this example, with j being the index
of the innermost loop, the array elements
are not accessed from contiguous memory locations.
In other words, even though several elements
are brought into one cache line, only the first element
will be used.
The rest will be discarded and brought
in again and again as we cycle through the outer loop.
Our compiler technology remedies this by interchanging i
and j making the memory accesses contiguous.
Just now, I illustrated a few techniques
of optimizing compiler.
Our 32-bit compiler has extensive optimization
to ensure the maximum performance of the Pentium
processor.
We have state of the art classical optimizations,
light register variable detection, loop invariant
co-motion, and others listed here.
We also pay specific attention to the X86 architecture
as well as our CPU implementation
in terms of selecting effective addressing modes
and co-sequences and rearranging instructions to take advantage
of the superscalar core.
In the earlier example, I illustrated
how loop interchange can result in more effective use
of the memory bandwidth.
Loop interchange is only one of the memory optimization
techniques.
Our compiler technology can also perform loop distribution
to promote parallelism, blocking to maximize memory reuse once
loaded into the cache, strip mining
to adjust the problem size to the size of the cache
in order to minimize trashing, and cache preloading
to hide the memory latency.
The next chart shows the result of our compiler efforts.
We are comparing the performance of the 66 megahertz Pentium
processor running the SPEC benchmark suites compiled
by three different compilers.
The compiler technology I just described is shown here.
Compiler A is the best available 486 compiler,
and compiler B was an average compiler in 1990 when
we started the compiler effort.
On the integer side, we were able to go from a performance
level of 41 using the average compiler up to a level a 64.6
using our new compiler technology.
When compared to the level of 57.6
from the best available 486 compiler,
the difference between the best 486 compiler and a new compiler
is on the order of 10% to 15%, obviously
a very substantial improvement over the average compiler
from the 1990 vintage.
On the floating point side, the results are even more dramatic.
From the new compiler technology,
we are able to achieve a SPEC floating point 59.7 compared
to much lower numbers in the 30s using the other compilers.
Throughout the development of the new compiler technology,
we emphasize that we could not optimize performance
of the Pentium processor at the expense of the Intel 486
or even the Intel 386 processors.
So we were very careful in implementing our optimization
techniques, and we constantly measured the performance
of the generator code on the older generation processors.
The efforts really paid off.
This chart shows that instead of optimizing for the Pentium
processor at the expense of the older parts,
we were in fact, able to improve the performance on the older
parts while optimizing for the Pentium processor.
We are again comparing the same benchmark suites
with using the same three compilers
but running the code on the Intel 486 processor.
You can see that our new compiler technology
is providing a nice performance boost,
not only over the average compiler that we had in 1990
but also over the best available 486 compiler.
Now, I hope you can see the importance of compiler
technology to the overall performance.
This concludes our talk on the Pentium microprocessor.
I hope that you'll take away from this talk
some understanding of the key microarchitecture features
inside the processor as well as some of the key techniques
we've developed with compiler technology.
In combination, these two producing a new level
of performance within our line of PC
compatible microprocessors.
Thank you.