Commit Graph

1427 Commits

Author SHA1 Message Date
Quentin Carbonneaux
4f9b94a9b3 formatting fixes in tests 2026-02-12 09:23:13 +01:00
Quentin Carbonneaux
5f40188f9e cosmetics in emit.c 2026-02-12 09:21:15 +01:00
Scott Graham
01102ad63b winabi: fix isel of large consts
ABI lowering for winabi was incorrectly using a Kl cls when emitting
Ostorel, which in turn was causing isel to fail to lower large constants
in to temporaries ( https://c9x.me/git/qbe.git/tree/amd64/isel.c#n107 )
when necessary.

(This should be applied on the 'winabi' branch.)
2026-02-12 09:17:17 +01:00
Scott Graham
d5f02dc67c winabi: fix allocation of parameters to regs with hidden arg
In the presence of the hidden arg for return-by-value, the
registers used for natural arguments were incorrect.

(This should be applied on the 'winabi' branch.)
2026-02-12 09:17:17 +01:00
Scott Graham
d166a61141 Implementation of Windows amd64_win target
This is an implementation of the Windows ABI. It supports most features
(struct passing/returning, varargs, env). TLS is not yet supported.

This patch does not actually port QBE to Windows, it only allows QBE to
generate correct asm to target Windows. As a result, testing is
accomplished on a Linux host, by using a cross-compiling toolchain, and
running the resulting binaries by using wine. See:

	TARGET=amd64_win tools/test.sh all

A few cross-platform tests were changed from 'long' to 'long long' in
driver code because long in C does not match the size of a QBE 'l' on
Windows.
2026-02-12 09:17:17 +01:00
Richard McCormack
cf06ce159d Modify amd64 fixarg to fix calling constant addresses
On x86_64, direct calls are always PC-relative. This means that
in order to call an absolute address, the call must be indirect.

To accomplish this, update fixarg to introduce a temporary before
emitting.
2026-01-13 21:24:31 +01:00
Quentin Carbonneaux
640c78d0da fix typo in simplcfg 2026-01-13 20:36:23 +01:00
Quentin Carbonneaux
afd5d2e518 drop dead preds in fixphis
It is possible that GVN removes
some dead blocks, this could lead
to odd - but probably harmless -
phi args appearing in the IL.
This patch cleans things up during
fillcfg().
2026-01-13 18:27:50 +01:00
Quentin Carbonneaux
e8365dd0a2 new simplcfg pass
Useful for ifopt to match more
often. Empty blocks are fused
and conditional jumps on empty
blocks with the same successor
(and no phis in the successor)
are collapsed.
2026-01-13 18:17:35 +01:00
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
7201079137 update copyright years 2026-01-13 17:09:41 +01:00
Quentin Carbonneaux
112cc1b824 rv64: handle slots in jnz 2026-01-13 17:09:41 +01:00
Quentin Carbonneaux
6a2dca8b99 fix jmp arg spilling
In case we need to spill to accomodate
for the jump argument, piggyback the
reloads from slots to regalloc so that
they can be correctly inserted on edges.
2026-01-13 17:09:41 +01:00
Quentin Carbonneaux
e0ded59639 please as with truncated constants
Apple's assembler actually hard
crashed on overflows.
2026-01-06 20:43:42 +01:00
Quentin Carbonneaux
0f6bbb1c7c arm64_apple: fix argxbh support 2026-01-06 20:43:42 +01:00
Quentin Carbonneaux
73f0accb45 arm64: prevent bogus IP1 clobbers 2026-01-06 20:43:38 +01:00
Quentin Carbonneaux
03da40271f rv64: fix invalid float immediates
Thanks to Luke Graham for reporting
and fixing this issue.
2026-01-05 22:19:53 +01:00
Quentin Carbonneaux
120f316162 skip deleted phis in use width scan 2025-05-30 17:40:17 +02:00
Quentin Carbonneaux
8d5b86ac4c fix fp constants on big endian hosts 2025-04-16 10:29:00 +02:00
Horst H. von Brand
348f2eac90 minic: C23 doesn't allow bool as identifier
Signed-off-by: Horst H. von Brand <vonbrand@inf.utfsm.cl>
2025-03-16 11:27:49 +01:00
Antonio Terceiro
903610de4f tools/test.sh: test the native architecture without QEMU
While at it, extract most duplicated code across targets into a
function.
2025-03-15 14:43:33 +01:00
Antonio Terceiro
f7ab20680b tools/test.sh: allow running against installed package
If $bin is set in the environment, use it instead of using `qbe` from
the source tree. The same for $binref. This supports the following use
cases:

- I have a qbe package installed, and I want to test my local changes
  with the installed packages as a reference:

  $ binref=/usr/bin/qbe ./tools/test.sh all

- I want to test the installed qbe against new tests that I have
  written, to reproduce a bug:

  $ bin=/usr/bin/qbe ./tools/test.sh test/newtest.ssa

In Debian, we also run tests against the installed package when
dependencies change, etc. We will also run on several architectures
where the necessary cross compilers might not be available. So make
tests that cannot be run because of a missing compiler exit with 77,
signaling to Debian's autopkgtest that the test is skipped.
2025-03-15 14:43:00 +01:00
Antonio Terceiro
789e38fdb2 Makefile: add explicit target to test the x86_64 backend
When developing on an arm64 machine, it's useful to be able to test the
x86_64 target.
2025-03-15 14:40:55 +01:00
Quentin Carbonneaux
86d13b93e8 arm64: use IP1 as scratch register
On Apple platforms x18 is not guaranteed
to be preserved across context switches.
So we now use IP1 as scratch register.

En passant, one dubious use of IP0 in
arm64/emit.c fixarg() was transitioned
to IP1. I believe the previous code could
clobber a user value if IP0 was live.
2025-03-15 14:27:34 +01:00
Quentin Carbonneaux
ec5502645f 10 years of qbe! 2025-03-14 13:09:42 +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
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
ecfdac4f00 Simplify fillpreds()
Now that b->pred is a vector we do can remove the counting pass.
2025-03-14 09:47:05 +01:00
Roland Paterson-Jones
1c769584ac Simplify fillrpo()
Essentially use post-order as id, then reverse to rpo.
Avoids needing f->nblk initially; slightly simpler logic.
2025-03-14 09:47:05 +01:00
Roland Paterson-Jones
0ce9966c23 Re-use (vgrow) b->ins vector in backend xxx_abi() fn's.
Removes last re-allocation of b->ins.
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
Roland Paterson-Jones
ca928f6f8d Blk::ins is a vector
Scratching an itch - avoid unnecesary re-allocation in idup()
which is called often in the optimisation chain.

Blk::ins is reallocated in xxx_abi() - needs further fiddling.
2025-03-14 09:47:05 +01:00
Roland Paterson-Jones
024dffac8b Blk::pred is a vector
Scratching an itch - avoid unnecesary re-allocation in fillpred()
which is called often in the optimisation chain.
2025-03-14 09:47:05 +01:00
Roland Paterson-Jones
c16f7eafca Fn::rpo is a vector
Scratching an itch - avoid unnecesary re-allocation in fillrpo()
which is called multiple times in the optimisation chain.
2025-03-14 09:47:05 +01:00
Quentin Carbonneaux
327736b3a6 handle large hfas correctly on arm64 2024-12-19 15:27:16 +01:00
Quentin Carbonneaux
90050202f5 fix various codegen bugs on arm64
- dynamic allocations could generate
  bad 'and' instructions (for the
  and with -16 in salloc()).
- symbols used in w context would
  generate adrp and add instructions
  on wN registers while they seem to
  only work on xN registers.

Thanks to Rosie for reporting them.
2024-10-01 19:42:50 +02: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
Alexey Yerin
bb8de8c633 arm64/isel: Avoid signed overflow when handling immediates
Clang incorrectly optimizes this negation with -O2 and causes QBE to
emit 0 in place of INT64_MIN.
2024-08-15 23:21:05 +02:00
Quentin Carbonneaux
efcb5465e5 align emitted code
Functions are now aligned on 16-byte
boundaries. This mimics gcc and should
help reduce the maximum perf impact of
cosmetic code changes. Previously, any
change in the output of qbe could have
far reaching implications on alignment.

Thanks to Roland Paterson-Jones for
pointing out the variability issue.
2024-08-15 23:11:41 +02:00
Quentin Carbonneaux
e8fa27bcdb drop imul rewriting
This was cute to do, but it is
largely inconsequential, as shown
by the rough timings below:

    benchmarking mul8_lea
      3.9 ticks ± 0.88 (min: 3)
    benchmarking mul8_imul
      3.3 ticks ± 0.27 (min: 3)
    benchmarking div8_udiv
      6.5 ticks ± 0.52 (min: 6)
    benchmarking div8_shr
      3.3 ticks ± 0.34 (min: 3)
2024-06-19 12:39:26 +02:00
Quentin Carbonneaux
7de34d3454 no mul->shl as it confuses address matching
Additionally, the strength-reduction
for small powers of two is handled
by amd64/emit.c now.
2024-06-19 10:58:17 +02:00
Quentin Carbonneaux
6dab93b4b2 cheaper mul by small constants on amd64 2024-06-18 17:06:56 +02:00
Quentin Carbonneaux
96f18be71d simplify 8*x as well as x*8 2024-06-18 16:59:42 +02:00
Quentin Carbonneaux
0631bc4fec prevent bogus simplifications 2024-06-17 13:24:22 +02:00
Quentin Carbonneaux
e7ebdc8fb6 qbe has its own magic 2024-06-17 13:17:39 +02:00
Quentin Carbonneaux
b5be429091 fix unintended assignment 2024-06-16 22:31:38 +02:00
Quentin Carbonneaux
ddf5ced4a7 revert 4bc4c958
Hopefully the right time now!
2024-06-16 22:26:51 +02:00