summaryrefslogtreecommitdiff
path: root/fpcsrc/tests/test/opt/tcse2.pp
blob: 57ccb73cd8892a4750a74a1754b422ab1f4a23aa (plain)
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
{ %OPT=-OG2}
{$r+}

type
  tsubr = 1..100000;
  tarr = array[1..100000] of longint;

function test(b: tsubr): longint;
begin
 test := b;
end;

var
  p: ^longint;
  l: longint;
  a, a2: tarr;

begin
  getmem(p,4);
  p^ := 100000;
  l := 5;
  { clear the optimizer state }
  asm
  end;
{$r-}
  { get p^ in eax, the following statement generates the code }
  {   movl A,%eax                                             }
  {   movl (%eax),%eax                                        }
  a[p^] := l;
{$r+}
  { now, p^ gets rangechecked, this generates the code                  }
  {   movl A,%eax        (1)                                            }
  {   movl (%eax),%ecx   (1)                                            }
  {   ...                                                               }
  {   call rangecheck_procedure                                         }
  {   pushl (%eax)                                                      }
  {                                                                     }
  { With the bug in the optimizer, the instructions marked with (1) are }
  { replaced by                                                         }
  {   movl %eax,%ecx                                                    }
  {                                                                     }
  { and as such the "pushl (%eax)" pushes a wrong value afterwards      }
  l := test(p^);
  if l <> 100000 then
    begin
      writeln('Problem 1!');
      halt(1);
    end;
  p^ := 5;
  l := 5;
  { clear the optimizer state }
  asm
  end;
{$r-}
  { the following moves p^ in %edx }
  a2[l] := a[p^];
{$r+}
  { same test as before, but now the original value comes from edx }
  { instead of that it is already in eax (so check that it doesn't }
  { replace the                                                    }
  {   movl P,%eax                                                  }
  {   movl (%eax),%ecx                                             }
  { with                                                           }
  {   movl %edx,%ecx                                               }
  l := test(p^);
  if l <> 5 then
    begin
      writeln('Problem 2!');
      halt(1);
    end;
  freemem(p,4);
end.