Commit Graph

108 Commits

Author SHA1 Message Date
Roland Paterson-Jones
1cb255cb04 Get rid of movins() infra. 2025-03-14 13:07:40 +01:00
Roland Paterson-Jones
c2ff93e75e Global Value Numbering / Global Code Motion
More or less as proposed in its ninth iteration with the
addition of a gcmmove() functionality to restore coherent
local schedules.

Changes since RFC 8:

Features:

 - generalization of phi 1/0 detection
 - collapse linear jmp chains before GVN; simplifies if-graph
     detection used in 0/non-0 value inference and if-elim...
 - infer 0/non-0 values from dominating blk jnz; eliminates
     redundant cmp eq/ne 0 and associated jnz/blocks, for example
     redundant null pointer checks (hare codebase likes this)
 - remove (emergent) empty if-then-else graphlets between GVN and
     GCM; improves GCM instruction placement, particularly cmps.
 - merge %addr =l add %addr1, N sequences - reduces tmp count,
     register pressure.
 - squash consecutive associative ops with constant args, e.g.
     t1 = add t, N ... t2 = add t2, M -> t2 = add t, N+M

Bug Fixes:

 - remove "cmp eq/ne of non-identical RCon's " in copyref().
   RCon's are not guaranteed to be dedup'ed, and symbols can
   alias.

Codebase:

  - moved some stuff into cfg.c including blkmerge()
  - some refactoring in gvn.c
  - simplification of reassoc.c - always reassoc all cmp ops
      and Kl add %t, N. Better on coremark, smaller codebase.
  - minor simplification of movins() - use vins

Testing - standard QBE, cproc, hare, harec, coremark
          [still have Rust build issues with latest roland]

Benchmark
- coremark is ~15%+ faster than master
- hare "HARETEST_INCLUDE='slow' make check" ~8% faster
    (crypto::sha1::sha1_1gb is biggest obvious win - ~25% faster)

Changes since RFC 7:

Bug fixes:

- remove isbad4gcm() in GVN/GCM - it is unsound due to different state
    at GVN vs GCM time; replace with "reassociation" pass after GCM
- fix intra-blk use-before-def after GCM
- prevent GVN from deduping trapping instructions cos GCM will not
    move them
- remove cmp eq/ne identical arg copy detection for floating point, it
    is not valid for NaN
- fix cges/cged flagged as commutative in ops.h instead of cnes/cned
    respectively; just a typo

Minor features:

- copy detection handles cmp le/lt/ge/gt with identical args
- treat (integer) div/rem by non-zero constant as non-trapping
- eliminate add N/sub N pairs in copy detection
- maintain accurate tmp use in GVN; not strictly necessary but enables
    interim global state sanity checking
- "reassociation" of trivial constant offset load/store addresses, and
    cmp ops with point-of-use in pass after GCM
- normalise commutative op arg order - e.g. op con, tmp -> op tmp, con
    to simplify copy detection and GVN instruction dedup

Codebase:

- split out core copy detection and constant folding (back) out into
    copy.c, fold.c respectively; gvn.c was getting monolithic
- generic support for instruction moving in ins.c - used by GCM and
    reassoc
- new reassociation pass in reassoc.c
- other minor clean-up/refactor

Changes since RFC 6:

- More ext elimination in GVN by examination of def and use bit width
- elimination of redundant and mask by bit width examination
- Incorporation of Song's patch

Changes since RFC 5:

- avoidance of "bad" candidates for GVN/GCM - trivial address offset
    calculations, and comparisons
- more copy detection mostly around boolean values
- allow elimination of unused load, alloc, trapping instructions
- detection of trivial boolean v ? 1 : 0 phi patterns
- bug fix for (removal of) "chg" optimisation in ins recreation - it
    was missing removal of unused instructions in some cases

ifelim() between GVN and GCM; deeper nopunused()
2025-03-14 09:58:37 +01:00
Roland Paterson-Jones
9e36cbe4d8 Combine fillrpo() and fillpreds() into fillcfg().
Remove edgedel() calls from fillrpo().

Call new prunephis() from fillpreds().
[Curiously this never seems to do anything even tho edgedel()
is no longer called from fillrpo()]

One remaining fillpreds() call in parse.c typecheck - seems
like it will still work the same.

defensive; fillcfg() combining fillrpo() and fillpreds() - problem after simpljmp() - think it is cos fillrpo() is still doing edgedel() which should now be covered by fillpreds()

comment out edgedel() in fillrpo() - fillcfg() no longer asserts after simpljmp() but seems like prunephis() never triggers???

static fillrpo(); remove edgedel() from fillrpo()

replace fillrpo() and/or fillpreds() with fillcfg()
2025-03-14 09:47:05 +01:00
Roland Paterson-Jones
434cf5fdc4 idup(Ins **, Ins *, ulong) -> idup(Blk *, Ins *, ulong)
Always used this way and factors setting b->nins.
Makes b->ins vector contract more obvious.
2025-03-14 09:47:05 +01:00
Quentin Carbonneaux
626f0b2781 skip preludes for some leaf fns
When rbp is not necessary to compile
a leaf function, we skip saving and
restoring it.
2024-08-23 18:31:53 +02:00
Roland Paterson-Jones
cf9f95f521 Optab-driven copy detection 2024-06-09 22:33:38 +02:00
Quentin Carbonneaux
8ded7a56a2 add common linkage for data 2024-04-12 11:33:58 +02:00
Quentin Carbonneaux
4a809d69b5 fold scaled offsets in addresses 2024-04-11 14:14:53 +02:00
Quentin Carbonneaux
2d046a0ac6 use mgen in amd64/isel.c 2024-04-09 21:47:16 +02:00
Quentin Carbonneaux
a2ad38086c mcf's improved rsval()
It is semantically the same but
does not rely on implementation-
defined behavior.
2024-04-07 22:18:01 +02:00
Nguyễn Gia Phong
b582e84e10 remove duplicated function declarations
References: 12f9d16c7b ("create cfg.c for cfg-related functions")
2024-03-07 16:46:10 +01:00
Drew DeVault
85287081c4 dbgloc: add column argument
dbgloc line [col]

This is implemented in a backwards-compatible manner.
2024-01-02 12:12:05 +01:00
Thomas Bracht Laumann Jespersen
0d929287d7 implement line number info tracking
Support "file" and "loc" directives. "file" takes a string (a file name)
assigns it a number, sets the current file to that number and records
the string for later. "loc" takes a single number and outputs location
information with a reference to the current file.
2023-06-06 18:44:51 +02:00
Alexey Yerin
e493a7f233 Bump NString 2023-05-31 09:25:58 +02:00
Locria Cyber
96f16f958a Fix 1 C UB 2023-04-03 16:08:46 +02:00
Quentin Carbonneaux
5fee3da6ac rename blknew() to newblk()
This is consistent with newtmp()
and newcon().
2023-03-22 11:43:46 +01:00
Quentin Carbonneaux
eb9fcece9e naming nit 2023-03-19 07:38:24 +01:00
Quentin Carbonneaux
011dfc839d silence format warning more reliably 2023-03-16 16:22:11 +01:00
Quentin Carbonneaux
5e9726946d new UNDEF Ref
Crashing loads of uninitialized memory
proved to be a problem when implementing
unions using qbe.  This patch introduces
a new UNDEF Ref to represent data that is
known to be uninitialized.  Optimization
passes can make use of it to eliminate
some code.  In the last compilation stages,
UNDEF is treated as the constant 0xdeaddead.
2022-12-25 16:37:33 +01:00
Quentin Carbonneaux
26c1c30b7d new blit instruction 2022-12-14 23:18:26 +01:00
Quentin Carbonneaux
c0f25aeae3 new rsval() helper for signed Refs
The .val field is signed in RSlot.
Add a new dedicated function to
fetch it as a signed int.
2022-12-12 22:16:33 +01:00
Quentin Carbonneaux
9126afa2da new hlt block terminator
It is handy to express when
the end of a block cannot be
reached. If a hlt terminator
is executed, it traps the
program.

We don't go the llvm way and
specify execution semantics as
undefined behavior.
2022-11-27 21:48:21 +01:00
Quentin Carbonneaux
cbee74bdb4 use a new struct for symbols
Symbols are a useful abstraction
that occurs in both Con and Alias.
In this patch they get their own
struct. This new struct packages
a symbol name and a type; the type
tells us where the symbol name
must be interpreted (currently, in
gobal memory or in thread-local
storage).

The refactor fixed a bug in
addcon(), proving the value of
packaging symbol names with their
type.
2022-11-22 21:56:21 +01:00
Quentin Carbonneaux
04e2640901 rename Tmp.ins to be more descriptive 2022-11-22 21:55:06 +01:00
Quentin Carbonneaux
674901b718 new slot coalescing pass
This pass limits stack usage when
many small aggregates are allocated
on the stack. A fast liveness
analysis figures out which slots
interfere and the pass then fuses
slots that do not interfere. The
pass also kills stack slots that
are only ever assigned.

On the hare stdlib test suite, this
fusion pass managed to reduce the
total eligible slot bytes count
by 84%.

The slots considered for fusion
must not escape and not exceed
64 bytes in size.
2022-11-20 22:14:41 +01:00
Quentin Carbonneaux
f5007126f3 export getalias()
We will be using it in the new
coalesce() pass.
2022-11-20 22:13:44 +01:00
Quentin Carbonneaux
45ab1e5aa3 stored bytes in Alias information
Stack slots may have padding
bytes, and if we want to have
precise liveness information
it's important that we are able
to tell them apart.

This patch extends fillalias()
to remember for every slot
what bytes were ever assigned.
In case the slot address does
not escape we know that only
these bytes matter.

To save space, we only store
this information if the slot
size is less than or equal to
NBit.

The Alias struct was reworked
a bit to save some space. I am
still not very satisfied with
its layout though.
2022-11-20 21:47:11 +01:00
Quentin Carbonneaux
1f696fed0d make Alias.base an int
We had the invariant that it'd
always be a temporary.
2022-11-20 21:44:25 +01:00
Quentin Carbonneaux
0d50ebaed9 fill definition site in filluse() 2022-11-20 21:44:25 +01:00
Quentin Carbonneaux
b03a8970d7 mark apple targets with a boolean
It is more natural to branch on a
flag than have different function
pointers for high-level passes.
2022-10-08 21:48:47 +02:00
Quentin Carbonneaux
4e90b4210e "rel" fields become "reloc" 2022-10-08 21:48:47 +02:00
Quentin Carbonneaux
2e38c86af6 do not drop relocation kind in alias analysis 2022-10-08 21:48:47 +02:00
Quentin Carbonneaux
00a30954ac add support for thread-local storage
The apple targets are not done yet.
2022-10-08 21:48:42 +02:00
Quentin Carbonneaux
70f297bab7 fix case of Pool constants 2022-10-03 10:41:30 +02:00
Quentin Carbonneaux
a9a70e30a8 add new target-specific abi0 pass
The general idea is to give abis a
chance to talk before we've done all
the optimizations. Currently, all
targets eliminate {par,arg,ret}{sb,ub,...}
during this pass. The forthcoming
arm64_apple will, however, insert
proper extensions during abi0.

Moving forward abis can, for example,
lower small-aggregates passing there
so that memory optimizations can
interact better with function calls.
2022-10-03 10:41:03 +02:00
Quentin Carbonneaux
0b26cd4f5e parse sb,ub,sh,uh abi types 2022-10-03 10:41:03 +02:00
Quentin Carbonneaux
8dddb971d9 drop -G flag and add target amd64_apple
apple support is more than assembly syntax
in case of arm64 machines, and apple syntax
is currently useless in all cases but amd64;
rather than having a -G option that only
makes sense with amd64, we add a new target
amd64_apple
2022-08-31 21:42:49 +02:00
Michael Forney
c6b41eb8c8 amd64: restore previous name of amd64_sysv target 2022-03-17 13:24:52 +01:00
Quentin Carbonneaux
2416d29141 new -t? flag to print default target 2022-03-15 22:30:34 +01:00
Quentin Carbonneaux
c5769f62b4 dynamic stack allocs for arm64
I also moved some isel logic
that would have been repeated
a third time in util.c.
2022-03-14 23:14:48 +01:00
Quentin Carbonneaux
6ca9399ed6 output symbol type and size
That is not available on osx
so I tweaked the gas.c api
a little to conditionally
output the two directives.
2022-03-14 15:32:27 +01:00
Quentin Carbonneaux
9060981c10 flag types defined as unions
The risc-v abi needs to know if a
type is defined as a union or not.

We cannot use nunion to obtain this
information because the risc-v abi
made the unfortunate decision of
treating

	union { int i; }

differently from

	int i;

So, instead, I introduce a single
bit flag 'isunion'.
2022-03-08 15:57:06 +01:00
Quentin Carbonneaux
349794f3e4 cosmetics 2022-03-08 15:36:26 +01:00
Michael Forney
4e93eeaa3b add rv64 backend
It is mostly complete, but still has a few ABI bugs when passing
floats in structs, or when structs are passed partly in register,
and partly on stack.
2022-02-17 22:43:12 +01:00
Michael Forney
7aceb24c50 gas: put zero data into .bss by default
This allows frontends to use BSS generically, without knowledge of
platform-dependent details.
2022-02-11 08:49:42 +01:00
Quentin Carbonneaux
2ca6fb25a2 shared linkage logic for func/data 2022-02-02 21:09:37 +01:00
Michael Forney
bf153b359e reuse previous address constants in fold()
parseref() has code to reuse address constants, but this is not
done in other passes such as fold or isel. Introduce a new function
newcon() which takes a Con and returns a Ref for that constant, and
use this whenever creating address constants.

This is necessary to fix folding of address constants when one
operand is already folded. For example, in

	%a =l add $x, 1
	%b =l add %a, 2
	%c =w loadw %b

%a and %b were folded to $x+1 and $x+3 respectively, but then the
second add is visited again since it uses %a. This gets folded to
$x+3 as well, but as a new distinct constant. This results in %b
getting labeled as bottom instead of either constant, disabling the
replacement of %b by a constant in subsequent instructions (such
as the loadw).
2021-11-22 18:07:50 +01:00
Quentin Carbonneaux
49fb63ebac bump NString 2021-11-10 23:23:04 +01:00
Quentin Carbonneaux
fcdef10dae make variadic args explicit
Some abis, like the riscv one, treat
arguments differently depending on
whether they are variadic or not.
To prepare for the upcomming riscv
target, we change the variadic call
syntax and give meaning to the
location of the '...' marker.

  # new syntax
  %ret =w call $f(w %regular, ..., w %variadic)

By nature of their abis, the change
is backwards compatible for existing
targets.
2021-10-22 23:53:25 +02:00
Quentin Carbonneaux
3da3815a67 err when an address contains a sum $a+$b (afl)
Reported by Alessandro Mantovani.
These addresses are likely bogus, but
they triggered an unwarranted assertion
failure. We now raise a civilized error.
2021-07-30 00:14:53 +02:00