Commit Graph

18 Commits

Author SHA1 Message Date
Quentin Carbonneaux
c6336557da ifopt simplifications 2026-01-13 18:11:37 +01:00
Roland Paterson-Jones
5c1eb24e2c If-conversion RFC 4 - x86 only (for now), use cmovXX
Replacement of tiny conditional jump graphlets with
conditional move instructions.

Currently enabled only for x86. Arm64 support using cselXX
will be essentially identical.

Adds (internal) frontend sel0/sel1 ops with flag-specific
backend xselXX following jnz implementation pattern.

Testing: standard QBE, cproc, harec, hare, roland
2026-01-13 18:11:30 +01:00
Quentin Carbonneaux
f3ca257737 gvn/gcm review
- Many stylistic nits.
- Removed blkmerge().
- Some minor bug fixes.
- GCM reassoc is now "sink"; a pass that
  moves trivial ops in their target block
  with the same goal of reducing register
  pressure, but starting from instructions
  that benefit from having their inputs
  close.
2025-03-14 13:09:21 +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
cf9f95f521 Optab-driven copy detection 2024-06-09 22:33:38 +02: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
Quentin Carbonneaux
36946a5142 file,loc become dbgfile,dbgloc 2023-08-18 15:12:56 +02: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
Quentin Carbonneaux
26c1c30b7d new blit instruction 2022-12-14 23:18:26 +01:00
Quentin Carbonneaux
0b26cd4f5e parse sb,ub,sh,uh abi types 2022-10-03 10:41:03 +02: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
Bor Grošelj Simić
3964574a83 implement float -> unsigned casts
amd64 lacks instruction for this so it has to be implemented with
float -> signed casts. The approach is borrowed from llvm.
2022-01-28 09:24:15 +01:00
Bor Grošelj Simić
74d022f975 implement unsigned -> float casts
amd64 lacks an instruction for this so it has to be implemented with
signed -> float casts:
 - Word casting is done by zero-extending the word to a long and then doing
   a regular signed cast.
 - Long casting is done by dividing by two with correct rounding if the
   highest bit is set and casting that to float, then adding
   1 to mantissa with integer addition
2022-01-28 09:24:15 +01:00
Eyal Sawady
e91d121581 Add a negation instruction
Necessary for floating-point negation, because
`%result = sub 0, %operand` doesn't give the correct sign for 0/-0.
2022-01-23 11:43:59 +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
138b09af87 minor changes for env parameter
Since the environment can only be of type `l`, do
not require to write it down.

I also tightened the type information of the `pare`
and `arge` instructions.
2017-04-16 14:50:13 -04:00
Quentin Carbonneaux
61090c758d new arm64 backend, yeepee 2017-04-08 22:09:55 -04:00
Quentin Carbonneaux
49a4593c33 prepare for multi-target
This big diff does multiple changes to allow
the addition of new targets to qbe.  The
changes are listed below in decreasing order
of impact.

1. Add a new Target structure.

To add support for a given target, one has to
implement all the members of the Target
structure.  All the source files where changed
to use this interface where needed.

2. Single out amd64-specific code.

In this commit, the amd64 target T_amd64_sysv
is the only target available, it is implemented
in the amd64/ directory.  All the non-static
items in this directory are prefixed with either
amd64_ or amd64_sysv (for items that are
specific to the System V ABI).

3. Centralize Ops information.

There is now a file 'ops.h' that must be used to
store all the available operations together with
their metadata.  The various targets will only
select what they need; but it is beneficial that
there is only *one* place to change to add a new
instruction.

One good side effect of this change is that any
operation 'xyz' in the IL now as a corresponding
'Oxyz' in the code.

4. Misc fixes.

One notable change is that instruction selection
now generates generic comparison operations and
the lowering to the target's comparisons is done
in the emitter.

GAS directives for data are the same for many
targets, so data emission was extracted in a
file 'gas.c'.

5. Modularize the Makefile.

The Makefile now has a list of C files that
are target-independent (SRC), and one list
of C files per target.  Each target can also
use its own 'all.h' header (for example to
define registers).
2017-04-08 21:56:20 -04:00