aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.h
AgeCommit message (Collapse)AuthorFilesLines
2021-04-20Merge branches misc, cmp-pow2, optim-and-cmp, cmp-and-or and optim-cast-eval ↵Luc Van Oostenryck1-0/+5
into next * no needs to use MARK_CURRENT_DELETED() for multi-jumps * canonicalize ((x & M) == M) --> ((x & M) != 0) when M is a power-of-2 * simplify AND(x >= 0, x < C) --> (unsigned)x < C * simplify TRUNC(x) {==,!=} C --> AND(x,M) {==,!=} C * remove early simplification of casts during evaluation * but this back as simplificaion of TRUNC(NOT(x)) --> NOT(TRUNC(x))
2021-04-18add helper is_positive()Luc Van Oostenryck1-0/+5
Add a small helper to test if a pseudo is a positive (= non-negative) constant (for a given bitsize). It's meant to make some conditions more readable. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18Merge branches 'fix-phisrc' and 'insert-last-insn' into memops-prepLuc Van Oostenryck1-1/+8
* fix and improve the check that protects try_to_simplify_bb() * fix remove_merging_phisrc() with duplicated CFG edges.
2021-03-21add insert_last_instruction()Luc Van Oostenryck1-0/+8
It's relatively common to have to add an instruction at the end of a BB. More exactly, at the end but just before the terminator instruction. What is done for this is: 1) remove the terminator 2) add the new instruction 3) add the terminator back This is a bit tedious, need to declare a temporary variable for the terminator and, more generally, it's low-level details. So, add an helper for doing this: insert_last_instruction(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19move insert_branch() to flow.cLuc Van Oostenryck1-1/+0
Now that insert_branch() doesn't need to allocate a new instruction, there is no more reasons to have it defined in linearize.c So move it to flow.c which is more concerned with CFG changes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19remove insert_branch() redundant argLuc Van Oostenryck1-1/+1
insert_branch()'s first argument must be the BB of the instruction given in the second argument. So, remove it from the argument and simply use insn->bb instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: fix conversion with mismatched size or offsetLuc Van Oostenryck1-1/+1
The SSA conversion works under the assumption that all the memory operations on a given symbol always refer to the same object. So, exclude the conversion of variables where: * memory operations do not always match in size or offset * there is an implicit integer/float conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-08Merge branch 'uniq-phinode'Luc Van Oostenryck1-1/+7
* phi-sources can only have a single user (or none)
2021-03-08phi-sources can only have a single user (or none)Luc Van Oostenryck1-1/+7
Currently, OP_PHISOURCES have a list as member, 'phi_users', that should link to all phi-nodes using them but: *) phi-sources are never shared between phi-nodes *) this list is useless because it's only created during liveness and not used after. So, replace the list by a simple pointer to hold the unique phi-node using it and keep this link updated during all its lifetime. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
2021-03-05Merge branch 'slice'Luc Van Oostenryck1-4/+1
* slice: small reorg of OP_SLICE in preparation for some incoming changes
2021-02-28slice: OP_SLICE needs the source's type: make it a kind of unopLuc Van Oostenryck1-4/+1
OP_SLICE's source's type is needed for some simplifications. For example, in some cases it can be simplified into OP_TRUNC. So, merge its representation with the one for unops which also need the source's type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28slice: remove unneeded len from OP_SLICELuc Van Oostenryck1-1/+1
OP_SLICE::len is necessarily equal to the result size. So remove this redundancy. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28linearize.h: fix some 'selfcheck' warningsRamsay Jones1-2/+2
Commits 34c57a7f ("asm-mem: does it clobber memory?", 2021-02-20) and d6721b38 ("asm-mem: does it output to memory?", 2021-02-20) both add a single bit bitfield to the 'struct asm' part of the union contained within the 'struct instruction'. This causes the 'selfcheck' target to issue several 'dubious one-bit signed bitfield' errors. In order to suppress these errors, change the type of the bitfields to an unsigned type. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: does it output to memory?Luc Van Oostenryck1-0/+1
If an asm statement have a memory output operand, it modifies memory. Since this information is needed during memops simplification, add this info directly in the corresponding instruction, avoiding the need to scan the output operands list each time. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: does it clobber memory?Luc Van Oostenryck1-0/+1
An asm statement can specify that it clobbers memory. Add this info directly in the corresponding instruction, avoiding the need to scan the clobber list each time. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-31Merge branches 'fix-rem-usage', 'ptrlist-no-mix' and 'diet-bb' into nextLuc Van Oostenryck1-7/+5
* fix rem_usage() when the pseudo has a use list but is not PSEUDO_REG * ptrlist: avoid mixing reverse and non-reverse macros * shrink struct basic_block
2020-12-29add helper has_definition()Luc Van Oostenryck1-0/+5
Add the helper has_definition() to check if the pseudo belong to one of the pseudo types having a definition: PSEUDO_REG & PSEUDO_PHI. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-27shrink struct BBLuc Van Oostenryck1-7/+5
Reorganize the members of struct BB, avoiding padding and making better use of the union, to shrink its size from 104 to 96 bytes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-22canon: simplify calculation of canonical orderLuc Van Oostenryck1-2/+2
The calculation of the canonical order is currently somehow complicated. Fix this by reordering the definition of the different type of pseudos so that they are already in canonical order and just comparing the types to determine the order. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-12linearize: fix a couple of 'selfcheck' warningsRamsay Jones1-0/+2
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-11-01eval_insn: give an explicit type to compare's operandsLuc Van Oostenryck1-0/+4
The return type of IR instructions is stored in the field ::type of struct instruction and this struct has no space to hold the type of the operand(s). This is not a problem for most instructions because there is an easy way to get the operands' type. For example, for binops both types must be the same so they are used interchangeably. However, for compare instructions both types can be different and there is no easy way to get the type of the operands. Currently, this is ignored and creates some errors. It also blocks simplifications that need this type information. But compares instructions need only 2 operands, there is thus one 'slot' left. So, use this slot for the operands' type. This solves the current errors, allows new simplifications and has very little impact on existing code. Of course, this type information needs now to be tracked and adjusted whenever the operands change or an instruction is changed into a compare. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-27Merge branch 'one_use'Luc Van Oostenryck1-2/+2
* replace nbr_users() & multi_users() by one_use()
2020-10-27replace nbr_users() & multi_users() by one_use()Luc Van Oostenryck1-2/+2
During simplification, we're only interested to know if a pseudo is used only once or more than once. This can be checked quicker than getting the exact number of users. So, replace the last call to nbr_users() and the calls to multi_users() by a call to one_use() which has a slightly clearer name. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-10-22memops need long offsetsLuc Van Oostenryck1-1/+1
These days, declaring arrays bigger than 2GB or doing pointer arithmetic with an offset larger than 2^31 is maybe not usual but certainly not outrageous. However, currently Sparse silently truncates 32 bits the offsets of memory accesses. So, fix this by using 64-bit offsets for memory accesses. Also, use a signed type since these offsets can be negative. Note: I had a really nice (real) example for this but the margin of this patch is too small for it (and now I've lost it). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2019-09-27asm: fix liveness memory operandLuc Van Oostenryck1-0/+1
Since memory operands are only some kind of reference, the pseudo in an output operand is not defined by the statement, the reference is only used. Fix the liveness processing accordingly. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-09-06Merge branch 'rem-trivial-phi' into tipLuc Van Oostenryck1-0/+8
* remove more complex phi-nodes
2018-09-01Merge branch 'dead-switch' into tipLuc Van Oostenryck1-0/+6
* fix linearization of unreachable switch + label
2018-09-01move DEF_OPCODE() to header fileLuc Van Oostenryck1-0/+8
as it will be needed before it was defined in simplify.c and can be useful in other files too. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-09-01ir-validate: add validation branch to dead BBLuc Van Oostenryck1-0/+6
All branches must target an existing BB. Validate that it is the case for BR, CBR & SWITCH (COMPUTEDGOTO is left aside for the moment). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-31Merge branch 'opcode' into tipLuc Van Oostenryck1-119/+0
* consolidate instruction's properties into an opcode table
2018-08-26opcode: centralize opcode definitionLuc Van Oostenryck1-116/+0
Opcodes are defined in linearize.c:enum opcode. The file opcode.c also contains a table with opcodes properties. Centralize these definitions into a single file: opcode.def that will then be reused for enum opcode & the table. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-25add a flag for volatile memopsLuc Van Oostenryck1-0/+1
When simplifying memops, it's needed to check if the memops is a volatile access or not. This is currently done by checking insn->type->ctype.modifiers & MOD_VOLATILE which is rather long but also incorrect for bitfields. Prepare to fix this by adding a flag to struct instruction directly telling if the access is volatile. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-25split memops from unopsLuc Van Oostenryck1-1/+4
The field 'orig_type' is only used for casts while 'offset' is only used for memops. Split this in two separated sub-structures so that we can add an additional field for memops without increasing the total size. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-25symaddr: s/insn->symbol/insn->src/Luc Van Oostenryck1-3/+0
OP_SYMADDR take a single operand 'symbol' but this instruction is very much like other unops and using the same operand's name allow to avoid some special cases. So, s/symbol/src/ for OP_SYMADDRs. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-25Merge branch 'ssa' into tipLuc Van Oostenryck1-2/+19
* do 'classical' SSA conversion (via the iterated dominance frontier). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-08-04Merge branch 'list-optims' (early part) into tipLuc Van Oostenryck1-1/+16
* add optimized version of some list operations Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-25add lookup_ptr_list_entry()Luc Van Oostenryck1-0/+5
For liveness analysis, the ptrlists need to be used as sets. IOW, before adding a new element, it's needed to check if it doesn't already belong to the list. This check is currently done, specifically for pseudos, using the list walking macros FOR_EACH_PTR/END_FOR_EACH_PTR. Add a new generic ptrlist function: lookup_ptr_list_entry() which test if a given pointer already belong to the list. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-25add ptr_list_multiple()Luc Van Oostenryck1-0/+5
When doing IR simplification, to know if an instruction can be destructively modified, it's needed to know if the pseudo it defines is used by a single instruction or not. Currently this is done using ptr_list_size() which needs to walk the whole list. This walk is relatively costly when the list is long but knowing if the list contains more than 1 element can often be answered more cheaply since an answer can be returned as soon as it's known that the list contains at least 2 elements. Add the helpers ptr_list_multiple() and multi_users(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-25add ptr_list_empty()Luc Van Oostenryck1-1/+6
Sometimes we need to know if a list is empty, for example, in order to determine if a pseudo has some users or not. Currently, this is done using ptr_list_size(), which always walks the whole list but the needed answer can be returned as soon as it's known that the list contains at least one element. Add the helper ptr_list_empty() and use it for has_users(). This gives a speedup up to 18% on some pathological workloads. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-23extract nbr_users() from unssa.cLuc Van Oostenryck1-0/+5
This small helper was used in unssa.c but is useful elsewhere too. Move it as an inline function to linearize.h and rename it to 'nbr_users()' since it is close to the existing 'has_users()'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01ssa: phi worklistLuc Van Oostenryck1-0/+1
This patch optimize the very simple implementation of the phi-node renaming at the end of the SSA conversion. It avoids the need to rescan the whole function to find the phi-nodes by using a worklist to put the phi-nodes during the renaming of non-phi nodes instructions. This optimization avoids O(n^2) behaviour in some pathological cases. Note: A lot of optimizations can be done for the renaming. For the moment, things are kept as simplest as possible, the goal being to have correctness first. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01ssa: phase 1: phi-nodes placementLuc Van Oostenryck1-0/+4
This implement the first phase of classical SSA conversion: the placement of phi-nodes at the dominance frontier. The implementation is rather straight-forward: * for each pseudo used to make an access do: * reject cases that can't be converted: - volatile accesses - symbols externally visible - complex types that should not be converted * scan the concerned instructions and BBs * if there is only 1 store the loads may be directly converted (if dominated by the store!) * if all accesses are in a single BB, then no phi-nodes are needed and the accesses can be rewritten easily * otherwise we compute the iterated dominance frontier of the BBs just scanned and insert the phi-nodes there. * finally, some cleanup is done on dead stores Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01add insert_phi_node()Luc Van Oostenryck1-0/+3
This helper is used later during the SSA construction and is, as its name suggest, used to insert phi-nodes in the instruction stream. More exactly, the phi-node will be put at the begining of the specified BB, just after the others phi-nodes but before any other instructions, as required for their semantics (although, it's less important for sparse since each operand correspond first to a phi-source, so no phi-node directly depending on themselves in sparse). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01add PSEUDO_UNDEF & undef_pseudo()Luc Van Oostenryck1-1/+3
Processing in the middle-end are much easier if undefined values have been clearly identified. Once done, we can then make choices like: - give some warnings about uninitialized variables - always initialize them to zero - allow arbitraly simplification - ... Prepare this by declaring a new type of pseudo: PSEUDO_UNDEF somewhat similar to PSEUDO_VOID. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01dom: calculate the dominance treeLuc Van Oostenryck1-0/+4
Build the CFG's dominance tree and for each BB record: - the immediate dominator as bb->idom (is null for entry BB). - the list of immediately dominated BB as bb->doms. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-07-01graph: build the CFG reverse postorder traversalLuc Van Oostenryck1-1/+4
Do a DFS on the CFG and record the (reverse) postorder. Use this order for the normal BB traversal (ep->bbs). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-28bool: remove OP_{AND,OR}_BOOL instructionsLuc Van Oostenryck1-3/+1
Now that these instructions are not generated anymore, we can remove all related code, defines and doc. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23cast: specialize integer castsLuc Van Oostenryck1-2/+2
Casts to integer used to be done with only 2 instructions: OP_CAST & OP_SCAST. Those are not very convenient as they don't reflect the real operations that need to be done. This patch specialize these instructions in: - OP_TRUNC, for casts to a smaller type - OP_ZEXT, for casts that need a zero extension - OP_SEXT, for casts that need a sign extension - Integer-to-integer casts of the same size are considered as a NOPs and are, in fact, never emitted. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23cast: specialize cast from pointersLuc Van Oostenryck1-0/+1
Currently all casts to pointers are processed alike. This is simple but rather unconvenient in later phases as this correspond to different operations that obeys to different rules and which later need extra checks. Change this by using a specific instructions (OP_UTPTR) for [unsigned] integer to pointers. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23cast: specialize casts from unsigned to pointersLuc Van Oostenryck1-0/+1
Currently all casts to pointers are processed alike. This is simple but rather unconvenient as it correspond to different operations that obeys to different rules and which later need extra checks. Change this by using a specific instructions (OP_UTPTR) for unsigned integer to pointers. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23cast: specialize floats to integer conversionLuc Van Oostenryck1-0/+1
Currently, casts from floats to integers are processed like integers (or any other type) to integers. This is simple but rather unconvenient as it correspond to different operations that obeys to different rules and which later need extra checks. Change this by directly using specific instructions: - FCVTU for floats to unsigned integers - FCVTS for floats to signed integers Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23cast: specialize FPCAST into [USF]CVTFLuc Van Oostenryck1-1/+2
Currently, all casts to a floating point type use OP_FPCAST. This is maybe simple but rather uncovenient as it correspond to several quite different operations that later need extra checks. Change this by directly using different instructions for the different cases: - FCVTF for float-float conversions - UCVTF for unsigned integer to floats - SCVTF for signed integer to floats and reject attempts to cast a pointer to a float. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-06-23ir: define an OP_... range for unopsLuc Van Oostenryck1-5/+9
Some operations are exactly the same for all unops, including casts. To make things more readable and decrease the amount of churn, create a range OP_UNOP - OP_UNOP_END like already done for binops. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-05-06OP_SYMADDR is simply an unopLuc Van Oostenryck1-1/+3
Currently OP_SYMADDR are defined the same as OP_SETVAL. However, OP_SYMADDRs don't need the field 'struct expression *val' and OP_SETVALs don't need the field 'pseudo_t symbol' which suggest that those two should be splitted. In fact, OP_SYMADDR, having just one pseudo as operand and producing one pseudo, is simply an unary op like OP_NOT, OP_NEG, ... Change this by letting OP_SYMADDRs use the field 'src' as the others unops do. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-18extract alloc_phisrc() from alloc_phi()Luc Van Oostenryck1-0/+2
This give us: - a clearer name (than alloc_phi()) - more flexibility when we need the instruction and not the pseudo. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-18show_label: add (and use) show_label()Luc Van Oostenryck1-0/+1
Add an helper to display labels. This allow us to: *) abstract away the details of how to display them *) gracefully handle abnormal cases of a null label. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-17add an helper to test the value of a pseudo against zeroLuc Van Oostenryck1-0/+11
Testing the value of a pseudo against zero is relatively common but it needs to test the type of the pseudo before testing the value itself. Add 2 small helpers for this: is_zero() & is_nonzero(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-11add a field 'tainted' to struct instructionLuc Van Oostenryck1-1/+2
During the processing, some verification are done and if the check fails, a warning is normally issued. But some checks are done at several steps and so the same warning can be give several time, which is annoying. Add to instructions a field '.tainted' which will allow to mark instructions which fail some checks and have already warned about. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-01IR: let .cond unionize with .src and not .targetLuc Van Oostenryck1-4/+3
In struct instruction, .target is normally used to hold the result. Its value is thus produced/defined by instructions. On the contrary, .cond is used as an input value and is thus used by instructions. However, these two fields belong to the same union. This creates slight complications for code, like liveness analysis which care about which fields are used and which are defined by the instructions. Change this by unionizing .cond with .src, .src1 & friends instead of with .target. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-01IR: remove never-generated instructionsLuc Van Oostenryck1-9/+1
Some of the IR instructions have been defined but are never generated. Remove them as they have no purposes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-03-01IR: remove now unused OP_LNOP & OP_SNOPLuc Van Oostenryck1-2/+0
No instructions have an opcode set to OP_[LS]NOP anymore so we can now remove all remaining traces of these opcode. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-02-20no need for signed & unsigned multiplicationLuc Van Oostenryck1-1/+1
Currently, we have OP_MULS & OP_MULU but unless it's full, widening multiplication both must give exactly the same result (the world run on 2's complement CPUs now, right?). Also, the IR doesn't have widening multiplication but only instruction where both operands and the result have the same size. So, since theer is no reasons to keep 2 instructions, merge OP_MULS & OP_MULU into a single one: OP_MUL. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-02-16cleanup: remove unused 'struct pseudo_ptr_list'Luc Van Oostenryck1-6/+0
'struct pseudo_ptr_list' was used to store pseudo usage but this structure is not used since commit e7fb6e092 (Add instruction to pseudo user tracking). Remove the leftovers. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-02-13add helper: has_users()Luc Van Oostenryck1-0/+5
This is a wrapper around pseudo_user_list_size() which can directly be used on a pseudo. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-02-13add helper for pseudo's user-list's sizeLuc Van Oostenryck1-0/+5
Add pseudo_user_list_size() instead of having to use ptr_list_size() with an ugly cast. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2018-01-08add OP_SETFVALLuc Van Oostenryck1-0/+4
OP_SETVAL is used to create floating-point and string as well as labels-as-values. This multi-purpose aspect sometimes make things a bit more complicated. Change this by using a new instruction for the direct creation of floating-point literals without needing to have an intermediate EXPR_FVALUE. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-18add support of floating-point specific arithmetic opsLuc Van Oostenryck1-0/+7
Floating-point arithmetic is quite different from the arithmetic on integers or the one of real numbers. In particular, most transformations, simplifications that can be done on integers are invalid when done on floats. For example: - associativity doesn't hold - distributivity doesn't hold - comparison is tricky & complex This is because (among others things): - limited precision, rounding everywhere - presence of signed zeroes - presence of infinities - presence of NaNs (signaling or quiet) - presence of numbers without inverse - several kind of exceptions. Since they don't follow the same rules as their integer counterpart, better to give them a specific opcode instead of having to test the type of the operands at each manipulation. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-18fix support of floating-point compareLuc Van Oostenryck1-0/+18
Comparision of floating-point values can't be done like for integral values because of the possibility to have NaNs which can't be ordered with normal values or even between themselves. The real difference appears once there is any "reasoning" done with the result of the comparison. For example, once NaNs are taken in account: "!(a < b)" and "(a >= b)" are not the same. In fact the usual comparison operators must be reinterpreted as implicitely first testing if any of the operand is a Nan and return 'false' if it is the case. Thus "a < b" becomes "!isnan(a) && !isnan(b) && (a < b)". If we need to negate the comparison we get "!(a < b)" which naturally becomes "isnan(a) || isnan(b) || (a >= b)". We thus need two sets of operators for comparison of floats: one for the "ordered" values (only true if neither operand is a Nan) and one for the "values" (also true if either operand is a NaN). A negation of the comparison switch from one of the set to the other. So, introduce another set of instructions for the comparison of floats. Note: the C standard requires that: *) "x == x" is false if x is a NaN, *) "x != x" is true if x is a NaN, and this is coherent with "x != x" <-> "!(x == x)". Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-17add support for wider type in switch-caseLuc Van Oostenryck1-1/+1
Currently the different cases of a switch-statement, or more exactly the 'struct multijmp' that hold the value of these cases excepted only value of 'int' type. Trying to use a wider value results in the value being truncated but any integer value should be valid. Fix this by unsigned 'long long' to hold these values. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-16give a type to OP_PHISOURCEsLuc Van Oostenryck1-1/+1
Currently, OP_PHISOURCEs are given a size but not a type. For consistency and for sparse-LLVM which need it, give them a type too. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-16give a type to all function argumentsLuc Van Oostenryck1-1/+1
The linearized code, sparse's IR, have no use of C's complex type system. Those types are checked in previous phases and the pseudos doesn't have a type directly attached to them as all the needed typing info info are conveyed by the instructions. In particular, PSEUDO_VAL (used for integer and address constants) are completely typeless. There is a problem with this when calling a variadic function with a constant argument as in this case there is no type in the function prototype (for the variadic part, of course) and there is no defining instructions holding the type of the argument. Possible but rejected solutions are: * give a full type to all pseudos This is silly as, for example 'int 0' and 'unsigned int 0' are, really, the same constants. * give simply a size to all pseudos This seems to be simple enough but *currently* it negatively impacts CSE (maybe because of some others deficiencies in the type system, especially for casts). * give a type to all function arguments via a new instruction that would mimic argument passing (OP_ARG or OP_PUSH). This solution is interesting, especially as it gives a placeholder for real argument passing at code generation time, but: 0) they can be added, if needed, when some code generation will be done. 1) it creates a superfluous instruction for every argument of every function call 2) these instructions are essentially copy instructions in disguise. So, since the problem only exist for constants used in variadic arguments (and currently, it's only a problem for sparse-llvm), the solution selected is to add to OP_CALLs a list holding the type of all arguments. More exactly, it reuses the field .fntype which was used to store the type of the function, and changes it to a list holding the function type *and* the type of all effective arguments. Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-16add table to "negate" some opcodeLuc Van Oostenryck1-0/+3
Some optimizations transform an instruction opcode into another. For example, it may be needed to know the opcode corresponding to the negation of a comparison. This patch make this easy and flexible by adding a table for the relation between opcodes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-11-11fix description setval & symaddrLuc Van Oostenryck1-1/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2017-03-06remove unused helper is_branch_goto()Luc Van Oostenryck1-4/+0
This helper is also made unneeded since the introduction of OP_CBR. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Christopher Li <sparse@chrisli.org>
2017-03-06split OP_BR between unconditional & conditional: OP_CBRLuc Van Oostenryck1-0/+1
OP_BR instructions exist in two flavours, relatively much differentiated: conditional & non-conditional. One has an operand (and thus its usage need to be cared for, must be handled in liveness analysis, ..) the other has not; one has two BB target, the other only one. There is essentially no places in the code where both flavours are handled the same. Sometimes they both must be handled but each with their specificities but in most cases only one of them is concerned and we need to filter out the other one. In both cases it means that we need to check what kind we're dealing with. There is already a problem with this because there is several ways to test which kind an OP_BR is and they are not exactly equivalent: 1) testing if insn->cond is NULL 2) testing if one of insn->bb_true or ->bb_false is NULL. There exist also an helper (is_branch_goto()) which does the second tests but which is never used. It appears that the first test should not be used because in some cases an conditional OP_BR is changed into a non-conditional one by (amongst others things) setting it's ->cond to VOID. We should thus always use the seconds test (which need two compares with NULL). This could be corrected in several ways (like changing all the places wheer the first test is used, use the helper everywhere or never set ->cond to VOID) but the simplest is to simply split them in two separated instructions: OP_BR & OP_CBR, especailly given the fact that in most cases the OP_BR was first selected by a switch (opcode). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Christopher Li <sparse@chrisli.org>
2017-02-13remove unused field 'multijump' in struct instructionLuc Van Oostenryck1-3/+0
This field was introduced (I think) for OP_SWITCH but is not needed anymore as OP_SWITCH has its own entry with a field fOr multijump list. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Christopher Li <sparse@chrisli.org>
2017-02-13give comparable label's names to basic blocksLuc Van Oostenryck1-1/+4
test-linearize displays basic block's labels by using '.L0x' plus the address of the bb struct. This is certainly convenient as an UID but it has the disadvantage that these names change at each run and are thus not comparable. This complicate testing quite a bit. Let change this by giving a simple sequential number to each bb and simply display them as: '.L1', '.L2', ... Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Christopher Li <sparse@chrisli.org>
2012-02-04sparse, llvm: Make function declaration accessible to backendLinus Torvalds1-0/+1
On Tue, Aug 30, 2011 at 10:43 AM, Jeff Garzik <jeff@garzik.org> wrote: > * if someone knows how to access a function declaration, I can solve the > varargs problem Hmm. Right now we do not have access to the function declaration at linearize time. We've checked that the arguments match, and we've cast the arguments to the right types (evaluate.c), so the thinking was that you just use the arguments as-is. But if llvm needs the declaration of a function, we'd need to squirrel it away. Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Christopher Li <sparse@chrisli.org> Cc: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> [ penberg@kernel.org: Fix validation/context.c breakage. ] Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-27sparse, llvm: if-else code generationJeff Garzik1-0/+1
It gets the code a bit farther, with the following test case: int foo(int x) { if (x > 0xffff) x++; else x--; return x; } * run with ./sparse-llvm hello.c | llvm-dis for an IMO more useful disassembly than via 'llc' * add 'priv' to struct basic_block * run a first pass through the BB's, creating LLVMBasicBlockRef's and assigning them to bb->priv * comment out unssa() call, and implement OP_PHI and OP_PHISOURCE, which LLVM directly supports. * remove '%' prefix from PSEUDO_REG names, as it was redundant and made llvm-dis output ugly * implement support for conditional and unconditional branches (OP_BR) * implement OP_COPY. a possibly better implementation would be a single-source LLVMBuildPhi [ penberg@kernel.org: minor cleanups ] Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-08-25sparse, llvm: Implement OP_ADDPekka Enberg1-0/+1
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2009-07-29linearize.h: sanitize headerKamil Dudka1-1/+1
It's unfortunate to use 'true' and 'false' as identifiers in a system header. It clashes with corresponding macros from <stdbool.h> when included before <sparse/linearize.h>. Signed-off-by: Kamil Dudka <kdudka@redhat.com> Acked-by: Hannes Eder <hannes@hanneseder.net> Signed-off-by: Christopher Li <sparse@chrisli.org>
2008-12-24Revert the context tracking codeJohannes Berg1-4/+3
> Do you want to resend your change which revert the context changes? > Make it base on Josh's git's tree and I will merge your changes in my > branch. Below. Or I can give it to you in git if you prefer. I still think we should redo this in some form so that annotations with different contexts can work properly, but I don't have time to take care of it right now. johannes >From ca95b62edf1600a2b55ed9ca0515d049807a84fc Mon Sep 17 00:00:00 2001 From: Johannes Berg <johannes@sipsolutions.net> Date: Tue, 23 Dec 2008 10:53:19 +0100 Subject: [PATCH] Revert context tracking code
2008-12-18Add type information to struct instruction.David Given1-0/+1
Currently there is no generic way to derive phy type information from the instruction flow. Signed-off-by: David Given <dg@cowlark.com>
2008-04-24fix bug in context tracking codeJohannes Berg1-1/+3
My optimisation to avoid recursion into BBs when checking contexts lead to a failure in a case like this: static int warn_conditional(void) { if (condition) return 0; a(); if (condition == 0) return 1; r(); return 0; } because some blocks are called with different contexts and thus need to be checked multiple times. The obvious fix would be to decrease the recursion depth at the end of the BB check function, but that, while correct, leads to extremely long sparse runtimes on somewhat complex functions. Thus, this patch also makes sparse cache which contexts it has checked a block in and avoid the re-checking in that case. Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
2008-04-21sparse: simple conditional context trackingJohannes Berg1-2/+1
This patch enables a very simple form of conditional context tracking, namely something like if (spin_trylock(...)) { [...] spin_unlock(...); } Note that __ret = spin_trylock(...); if (__ret) { [...] spin_unlock(...); } does /not/ work since that would require tracking the variable and doing extra checks to ensure the variable isn't globally accessible or similar which could lead to race conditions. To declare a trylock, one uses: int spin_trylock(...) __attribute__((conditional_context(spinlock,0,1,0))) {...} Note that doing this currently excludes that function itself from context checking completely. Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
2008-04-21make sparse keep its promise about context trackingJohannes Berg1-1/+1
The sparse man page promises that it will check this: Functions with the extended attribute __attribute__((context(expression,in_context,out_context)) require the context expression (for instance, a lock) to have the value in_context (a constant nonnegative integer) when called, and return with the value out_context (a constant nonnegative integer). It doesn't keep that promise though, nor can it, especially with contexts that can be acquired recursively (like RCU in the kernel.) This patch makes sparse track different contexts, and also follows up on that promise, but with slightly different semantics: * the "require the context to have the value" is changed to require it to have /at least/ the value if 'in_context', * an exact_context(...) attribute is introduced with the previously described semantics (to be used for non-recursive contexts), * the __context__ statement is extended to also include a required context argument (same at least semantics), Unfortunately, I wasn't able to keep the same output, so now you'll see different messages from sparse, especially when trying to unlock a lock that isn't locked you'll see a message pointing to the unlock function rather than complaining about the basic block, you can see that in the test suite changes. This patch also contains test updates and a lot of new tests for the new functionality. Except for the changed messages, old functionality should not be affected. However, the kernel use of __attribute__((context(...)) is actually wrong, the kernel often does things like: static void *dev_mc_seq_start(struct seq_file *seq, loff_t * pos) __acquires(dev_base_lock) { [...] read_lock(&dev_base_lock); [...] } rather than static void *dev_mc_seq_start(struct seq_file *seq, loff_t * pos) __acquires(dev_base_lock) { [...] __acquire__(dev_base_lock); read_lock(&dev_base_lock); [...] } (and possibly more when read_lock() is annotated appropriately, such as dropping whatever context read_lock() returns to convert the context to the dev_base_lock one.) Currently, sparse doesn't care, but if it's going to check the context of functions contained within another function then we need to put the actual __acquire__ together with acquiring the context. The great benefit of this patch is that you can now document at least some locking assumptions in a machine-readable way: before: /* requires mylock held */ static void myfunc(void) {...} after: static void myfunc(void) __requires(mylock) {...} where, for sparse, #define __requires(x) __attribute__((context(x,1,1))) Doing so may result in lots of other functions that need to be annoated along with it because they also have the same locking requirements, but ultimately sparse can check a lot of locking assumptions that way. I have already used this patch and identify a number of kernel bugs by marking things to require certain locks or RCU-protection and checking sparse output. To do that, you need a few kernel patches which I'll send separately. Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
2007-04-20linearize: DECLARE_ALLOCATOR for asm_constraint and asm_rulesJosh Triplett1-0/+3
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-03-02Add annotation for inline function call.Christopher Li1-0/+1
For inline functions, Sparse inlines the function body at evaluation. It is very hard to find out the original function call. This change preserves the original call as an annotation. Signed-Off-By: Christopher Li <sparse@chrisli.org>
2007-01-27Add missing #include "allocate.h" in linearize.h for DECLARE_ALLOCATOR.Josh Triplett1-0/+1
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-01-27Coding style fix: in a pointer type, * goes with the name, not the type.Josh Triplett1-1/+1
Signed-off-by: Josh Triplett <josh@freedesktop.org>
2007-01-16Add instruction to pseudo user tracking.Christopher Li1-3/+25
The current way of tracking pseudo register user is by keeping a list of the address of the pseudo_t member. This address can be in part of the instruction member, the worse case is in the argument list of the call instruction. As the comment for address_taken() said, using the container to get instruction pointer is wrong. It use to work with instruction that relate to symbol address. But that is not true any more. Even worse, it is very hard to track the pseudo usage other than symbol address. The only reason symbol address used to works for call instruction is because call instruction did not directly use the symbol address. I bit the bullet and just add the instruction pointer to pair with the pseudo user pointer. So it will work with the case that the user instruction is call as well. Testing: I compare the linearize result with/without the patch on a few sparse source file it self. The linearize generate exactly the same result except the symbol address changes. Which is predictable different because the pseudo user structure allocate memory. Singed-Off-By: Christopher Li <sparse@chrisli.org>
2007-01-16Change the symbol access list to a pseudo listChristopher Li1-1/+1
A pseudo list contains more information. It can get to the symbol as well as the usage information. Now it is much easier to answer questions like "What functions does this function call?". Signed-Off-By: Christopher Li <sparse@chrisli.org>
2006-09-14bb_terminated: Use boundary values rather than specific opcodesJosh Triplett1-1/+2
The opcode enum defines the boundary values OP_TERMINATOR and OP_TERMINATOR_END for terminator instructions; use those in bb_terminated rather than the specific values they currently equal. Signed-off-by: Josh Triplett <josh@freedesktop.org>
2006-08-30[PATCH] Parse and track multiple contexts by expressionJosh Triplett1-0/+1
sparse currently only tracks one global context for __context__ and __attribute__((context)). This adds support for parsing an additional argument to each of these which gives a context expression. For __attribute__((context)), store each context attribute as a separate context structure containing the expression, the entry context, and the exit context, and keep a list of these structures in the ctype. For __context__, store the context expression in the context instruction. Modify the various frontends to adapt to this change, without changing functionality. This change should not affect parsing of programs which worked with previous versions of sparse, unless those programs use comma expressions as arguments to __context__ or __attribute__((context)), which seems highly dubious and unlikely. sparse with -Wcontext generates identical output with or without this change on Linux 2.6.18-rc4. Signed-off-by: Josh Triplett <josh@freedesktop.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-08Fix dropped type information in "add_pseudo()".Linus Torvalds1-1/+1
We return a well-defined type (a pointer to the pseudo_t we added), so don't cast it to "void *" unnecessarily. Type safety is good. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-11-21[PATCH] Add a function to translate the SSA form back to normal form.Luc Van Oostenryck1-0/+1
For now, it use a simple method but which introduces a lot more copies than necessary. Can be fixed later. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@looxix.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-11-21[PATCH] Add a new opcode: OP_COPY.Luc Van Oostenryck1-0/+3
This is needed to translate SSA back to normal form. Maybe we should split this in two distinct ops: The first ones correspond to the old OP_PHISOURCE (but if the same phisrc feed several phi-nodes, we need sevarel distinct copy instruction); at this stage they are the only instruction that can define a pseudo in multiple places. The other ones being the "normal" copies. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@looxix.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-04-07Add support for context checking functions.Linus Torvalds1-0/+1
You can mark a function as requiring a lock, or requiring being called without a lock.
2005-04-07Make each instruction have a position of its own.Linus Torvalds1-0/+1
Rather than tying everything to the beginning basic block position. This should be able to pinpoint instruction issues much more exactly and readably.
2005-04-07Add compile-time "range-check" infrastructure to sparseLinus Torvalds1-0/+1
2005-04-07Split OP_CAST into signed, unsigned and FP casts.Linus Torvalds1-0/+2
Otherwise we lose the information what the target type is (we only have the bit-size of the target).
2005-04-07Split the binops where signedness matters into unsigned and signed.Linus Torvalds1-4/+4
This is OP_MUL/OP_DIV/OP_MOD/OP_SHR. We actually do the constant simplifications still wrong, but now the information is all there.
2005-04-07Split OP_SETVAL into OP_SETVAL (fp expressions and labels) and OP_SYMADDRLinus Torvalds1-0/+1
(symbol addresses). They are pretty different. Symbol addresses have special meaning during various phases, from symbol simplification to CSE.
2005-04-07Save off the asm parameter name too.Linus Torvalds1-0/+1
The asm_inputs/outputs "expression list" is not really an expression list any more: it is a list of "triples", where the first entry is the identifier name, the second one is the constraint string, and the third one is the expression.
2005-04-07Make asm linearization not drop the constraints.Linus Torvalds1-2/+14
This also makes the OP_ASM data structures a bit more structured in order to contain all the required information.
2005-04-07Add the argument pseudos to the "enter" instructionLinus Torvalds1-0/+3
Not only does it make sense, but the back-end needs to know what pseudos got allocated ;)
2005-04-07Make "remove_pseudo()" return whether it removed a pseudo fromLinus Torvalds1-2/+2
the list or not.
2005-04-07Make pretty helper functions for showing individual instructionsLinus Torvalds1-1/+1
and labels. And comments, for that matter. This eventually allows us to buffer them up, rather than print them out directly. Which we'll need to do if we want to fix up frame offsets etc (for register save areas). And other post- processing. Also, for comments, make "show_instruction()" return the string rather than print it out.
2005-04-07Move remove_pseudo() to linearize.hLinus Torvalds1-0/+4
2005-04-07Expose "show_instruction()" for debugging.Linus Torvalds1-0/+1
We already did this, we just didn't have a visible prototype.
2005-04-07Expose "show_bb()" for debugging, and make it do more appropriateLinus Torvalds1-0/+1
white-space.
2005-04-07Make OP_PHISOURCE track the OP_PHI instructions that it defines.Linus Torvalds1-0/+4
This allows us to always see which pseudos are nonlocally affected by the phi source. We can only do this after the instruction flow is fixed, together with the OP_DEATHNOTE phase.
2005-04-07Linearize inline asm statementsLinus Torvalds1-0/+6
This doesn't actually save the register class information, so you can't do proper register allocation, but it does all the input reading and store to outputs. Still need to teach the liveness analysis about the _usage_ rules.
2005-04-07Make the "entrypoint" be a special OP_ENTRY instruction instead ofLinus Torvalds1-1/+5
a special basic block. This removes a lot of special cases, since now flow doesn't have any special BB to worry about. It also gives a clear definition point for argument pseudos, and thus makes liveness tracking lose a special case.
2005-04-07Expose "show_pseudo()" to the world.Linus Torvalds1-0/+1
We want to use it in almost any debugging schenario, so why not just admit that.
2005-04-07Add pseudo death-note tracking.Linus Torvalds1-0/+1
Now that we have full pseudo usage lists, we can also add deathnotes to pseudos in the instruction stream. NOTE! We add the deathnote to _before_ the last instruction that uses that pseudo. That looks a bit strange, but it's actually what you want: when we traverse the instuctions, we want to know that the inputs are dead.
2005-04-07Remove OP_SETCC, make OP_SEL bigger instead.Linus Torvalds1-4/+3
This was originally done so that "struct instruction" would be smaller, but it has since grown anyway (for the memops), so splitting OP_SEL into two instructions no longer makes sense, and makes it harder on CSE.
2005-04-07Simplify trivial casts (and handle pointers specially).Linus Torvalds1-0/+1
This does trivial simplification of casting to the same typesize. HOWEVER. We split casts up into whether they cast to a dereferencable pointer type or not, and we don't simplify pointer casts. This should mean that if we ever want to do type-based alias analysis, we can still avoid casted accesses. (If we do type-based alias analysis, we'll also need to make a union access do a cast. Which we probably should do anyway).
2005-04-07Associate pseudos with the symbol name whose value they got.Linus Torvalds1-0/+1
This is purely for debugging. It's only used to show what symbol a pseudo might be (and I stress "might", since CSE can and does screw it up) associated with. Also print out the def list for a basic block when verbose. It all makes it a bit easier to guess what's up.
2005-04-07Start tracking cross-basic-block pseudo usage.Linus Torvalds1-2/+1
This should basically allow us to do register allocation. Or maybe it's too broken. But the results look reasonable from a quick manual peek.
2005-04-07Start using instruction sizes properly.Linus Torvalds1-3/+3
We should drop symbol types by now, and base things on just raw sizes. Anything else just doesn't work from a CSE standpoint. Some things may care about actual types later, notably the type- based alias analysis. Those types still exist in the cast nodes. Also, make the printout be more readable.
2005-04-07Add entrypoint pointer to each bb.Linus Torvalds1-0/+1
Very useful for debugging, since otherwise it's often impossible to find all the other basic blocks.
2005-04-07Make list-ptr remove/replace take a count.Linus Torvalds1-5/+5
It will assrt if it can't find that many entries. Zero means "all the ones you can find", aka old behaviour.
2005-04-07Be a lot more careful when re-writing branches.Linus Torvalds1-0/+6
Besides, the code is cleaner now - we can use our helper functions.
2005-04-07Kill long-dead pseudo-reuse code.Linus Torvalds1-2/+1
We don't have usage counters, we have usage lists these days.
2005-04-07Add a final pseudo usage tracking phase, which keepsLinus Torvalds1-0/+2
track of which instructions use which pseudos. It also verifies the usage, which shows a few bugs in structure handling.
2005-04-07Who says you can't do type-safe function-overloading in C?Linus Torvalds1-5/+5
You just have to be a bit crazy (*), and use "__typeof__" in creative ways. (*) Ok, a _lot_ crazy. But dammit, I want type-safety _and_ convenience, and I'm willing to do a few crazy macros to get it.
2005-04-07Add some type-safety features to the list pointer operations.Linus Torvalds1-1/+1
The list pointer traversal macros are very easy to use, but you can also mis-use them by passing in the wrong pointer type without the macros having any chance to warn you about it. Until now.
2005-04-07Clean up the tests for "pseudo has use list", since add/removeLinus Torvalds1-1/+6
has to agree on it or bad things happen.
2005-04-07Do early CSE before even doing the symbol simplification.Linus Torvalds1-2/+2
This allows us to notice when a symbol address usage is trivially dead, and optimize such a symbol better since we don't have to worry about the address being used to access it.
2005-04-07Use cleaned-up ptr list removal for removing basic blocksLinus Torvalds1-0/+5
from child and parent lists.
2005-04-07Simplify constant "conditional" branches and OP_SETCC/OP_SEL instructions.Linus Torvalds1-1/+1
Also, remove OP_SEL from the "binop" list - it really really isn't, since it has a third implied input in the OP_SETCC.
2005-04-07Clean up rewriting a switch into a branch.Linus Torvalds1-1/+1
And make sure to set the bb on the branch we create.
2005-04-07Make phi pseudos be a type of their own.Linus Torvalds1-0/+1
This makes it easier to verify that they are used only in phi-nodes, not anywhere else.
2005-04-07Fix up various pseudo usage list issues:Linus Torvalds1-2/+3
- value pseudos - clear the list on usage transfer - don't re-use OP_SWITCH as OP_BR when simplifying.
2005-04-07Oops. Forgot to add usage of a dominator list pseudo.Linus Torvalds1-0/+12
This made the phi-source CSE generate garbage, since the information wasn't updated in the phi list of the user. Move use_pseudo() to header file, since flow wants to use it too now.
2005-04-07Remove "struct phi", replace with instruction that generates a pseudo.Linus Torvalds1-13/+3
The instruction contains everything "struct phi" had, namely source bb and pseudo. And generating a new pseudo means that we not only have the pointer to the instruction that defines the phi-node (in pseudo->def), we also end up with automatic phi-node usage tracking (pseudo->users). The changes may look large, but almost all of this is just direct search-and-replace of the old phi-node usage.
2005-04-07Do if-conversion.Linus Torvalds1-0/+1
We can turn trivial phi-nodes into OP_SEL instructions instead, and generally improve code flow. This doesn't remove the empty blocks this results in yet, so it's not quite as dramatic as it could be, but it does the hard work. Empty block removal is trivial.
2005-04-07Make CSE convert instructions to OP_NOPLinus Torvalds1-0/+1
Instead of using the "convert_load_insn()" that converts them to OP_LNOP's, which ends up confusing instruction printout horribly.
2005-04-07Move flow analysis out of "linearize.c" and into new "flow.c"Linus Torvalds1-0/+4
Small files are good. Now "linearize" really just contains the code that does a straightforward linearization of the tree, and flow.c contains the stuff that tries to analyse the result.
2005-04-07Simplify switches on compile-time constant values.Linus Torvalds1-0/+1
It happens. Deal with it gracefully, and turn it into the proper jump.
2005-04-07Do some initial basic block packing and remove BB_REACHABLE flag.Linus Torvalds1-9/+1
Trivial basic block merging. I should do switch and branch following too. Maybe next.
2005-04-07Remove OP_MOV and copy_pseudo.Linus Torvalds1-1/+0
They only made sense with the original (broken) pseudo liveness analysis.
2005-04-07Clean up pseudo and bb usage handling.Linus Torvalds1-2/+1
We really don't care about all bb usage, only about the phi-nodes that use bb's. All the other usage is pretty obvious from the flow graph, no need to add them to the list (and if we _only_ add phi-nodes, then it becomes easier to check whether a bb needs to be saved due to phi-node issues). The pseudo usage has nothing to do with an instruction, so don't mix in the instruction into it.
2005-04-07Do symbol dominance checks for all used symbols.Linus Torvalds1-0/+1
Non-local symbols need more care. Function calls and pointer accesses can obviously clash with them, so we're less likely to find good domination. But every little piece helps.
2005-04-07Add basic block usage list to bb.Linus Torvalds1-0/+2
We'll need this to efficiently rewrite bb's.
2005-04-07Remove the horrid iterators.Linus Torvalds1-0/+1
Instead of having magic iterators over the last instruction of a basic block, we just add a list of "children" to each basic block. This removes all the packing logic, because it needs to be totally rewritten to work with the new iterators.
2005-04-07Undo braindamage.Linus Torvalds1-1/+2
Duh. They really were different types. One was a list of pointers to pseudos, the other is just a list of pseudos. Cset exclude: torvalds@ppc970.osdl.org|ChangeSet|20041112172911|52083
2005-04-07Duplicate type removal..Linus Torvalds1-2/+1
Use "pseudo_list" rather than "pseudo_ptr_list" type.
2005-04-07Do a first pass at making symbols into pseudos.Linus Torvalds1-0/+1
This looks for dominating stores and the whole enchilada. It's likely buggy as hell.
2005-04-07Do some very rough (stupid) symbol access optimizations.Linus Torvalds1-0/+1
We just look when a store dominates a load, and replace the load with the source of the dominating store. It would even be useful, but we give up at basic block borders. Retard, I tell you.
2005-04-07Replace OP_LOAD/OP_STORE with OP_LNOP/OP_SNOP when making them irrelevant.Linus Torvalds1-0/+2
This shows an interesting (?) bug with uninlining, where we seem to go through the same symbol twice, resulting in complaints about symbols used in strange ways (because we see an instruction that we have already NOP'ped out, using a symbol). I'm not convinced this is a bug yet - it might just be that we really _can_ reach the same symbol twice. But I _think_ it means our uninliner may have problems.
2005-04-07Remove deathnotesLinus Torvalds1-1/+0
They don't really buy us anything, and while generating them is easy, keeping them up-to-date is not. Also, don't print out the killed OP_LOAD/OP_STORE instructions that we voided by making the target be VOID.
2005-04-07Make the pseudo usage list be a list of pointers toLinus Torvalds1-3/+4
the pseudos, not the instructions that use them. That makes replacing a pseudo trivial: just walk the list, and overwrite the thing we have a pointer to. We also take advantage of the fact that symbol pseudos only exist in the "address" part of memory load, so if we know the pointer to the pseudo, we can calculate the pointer to the instruction. This makes the symbol pseudo replacement a lot more effective.
2005-04-07Add "argument pseudo" for incoming arguments to a function.Linus Torvalds1-0/+1
This still leaves varargs wrong, but we'll get to that eventually.
2005-04-07Show usage notes for symbols.Linus Torvalds1-2/+0
We add a per-symbol pseudo, and just track them that way.
2005-04-07Each pseudo has its "def" pointer, they now also have "use" pointers.Linus Torvalds1-0/+1
Well, at least part of the use pointers. I probably missed some uses.
2005-04-07Introduce "value pseudos" and implicit deathnotes.Linus Torvalds1-4/+14
A "value pseudo" is a pseudo that just has a constant value at any particular time. Instead of allocating a real pseudo for it, and associating the pseudo with an expression, the pseudo itself is directly associated with the value. Also remove a few explicit death-notes: branches and calls always kill their arguments, so make that implicit rather than waste time addign explicit notes.
2005-04-07Allow "pseudo-pseudos", which are a temporary symbol reference.Linus Torvalds1-0/+1
This simplifies stuff that wants to allow either a calculated expression pseudo, or a symbol. Use one of the pseudo-pseudos for the symbol, and pass that one around. First use: the address.
2005-04-07Add usage refcounting to pseudos to make deathnotes come out right.Linus Torvalds1-0/+1
The memory access initialization would keep a cache of "original value of the memory access" which means that we only do one read of a field even if it's an update of a bitfield. But that means that the usage of the pseudo in question needs refcounting.
2005-04-07Re-do memory access linearization.Linus Torvalds1-0/+1
This generates a "struct access_data" structure, which contains all the offsetting/symbol information for the access, and which makes things like bitfields and read-modify-writes all use the same basic information.
2005-04-07Do silly phi-node "expansion" as the last phase of theLinus Torvalds1-0/+1
linearized tree. This just copies all the phi node information into the source of the phi node, so that the linearized thing looks a bit more like "real" assembly language. It's likely bogus in many ways, but I want to make a pretty-printer for the linearized output, and this will make it much much easier to do.
2005-04-07Add deathnotes for the pseudo's we use.Linus Torvalds1-0/+1
It's a hell of a lot easier to add them when generating the linearized output than it is to go back and analyse them later. We know when we throw values away, so just note it. NOTE NOTE NOTE! This is only a rough first draft. Not complete.
2005-04-07Start "linearizing" initializers.Linus Torvalds1-0/+1
It's really pretty fake, but we used to ignore initializers completely, so this is certainly better than that. Now we at least linearize all the sub-expressions, and we do a kind of fake assignment.
2005-04-07Associate each pseudo with the instruction that defines it.Linus Torvalds1-0/+3
This allows us to get rid of the loop that searches for the def of a pseudo when simplifying <phi+br> blocks.
2005-04-07Add "struct position" to basic blocks, and give it someLinus Torvalds1-0/+1
half-way sane value. This makes it easier to tell people where a linearizer event happened. It won't be exact, but at least it will be _somewhere_ closer than just saying "it was in this function".
2005-04-07Add an internal sparse "context" statement type.Linus Torvalds1-0/+7
It just ends up propagating the expression to the linearizer, which creates an internal "context" instruction for it.
2005-04-07Mark the "entry" point in a function, and update it whenLinus Torvalds1-0/+1
packing blocks. The entrypoint doesn't necessarily end up being the first basic block in the list of blocks after we have packed them.
2005-04-07[PATCH] handling of non-lvalue compound objectsAlexander Viro1-0/+5
Handling of non-lvalue compound objects: We introduce a new primitive - EXPR_SLICE. Meaning is "that many bits from that offset in that non-lvalue struct or union". It is used when we try to get a member out of a non-lvalue struct or union (subsequent .<field> just narrow the slice). And as far as scalar, struct and union fields count, that's it. The only subtle point is handling of array fields. And there I'm doing what C99 requires - they *do* decay to real, honest pointers, causing a copy of object to memory if needed. We get an anonymous object that lives until the next sequence point; optimizer is certainly free to get rid of it completely if it can make do with the value we'd copied there. Note that you _are_ allowed to say foo().a[1] = 0; It doesn't make sense, since the value you've assigned will be immediately lost (and any optimizer will turn that into f()), but it is legitimate and it avoids a *lot* of PITA in describing semantics. It covers only array decay - any other member of non-lvalue struct or union is *not* an lvalue and in struct foo {int x; int y[2];}; struct foo a(void); ... a().x = 0; /* not allowed, non-lvalue */ a().y[0] = 1; /* allowed, but pointless */ you will get an error from the first assignment, but not from the second one. Signed-off-by: Al Viro <viro@parcelfarce.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-04-07Create a valid linearization of EXPR_SELECT.Linus Torvalds1-0/+3
Since the "struct instruction" format doesn't allow for all the data a select needs, we create two pseudo-instructions instead, and generate a select as a combination of the two: OP_SETCC + OP_SEL. We should possibly do the same thing for conditional branches.
2005-04-07EXPR_SAFELOGICAL is unnecessary. It ends up being the same as EXPR_BINOP.Linus Torvalds1-4/+4
Make linearize.h show the right ops for the logical (as opposed to binary) and/or EXPR_BINOP.
2005-04-07Make expression expansion calculate the "cost" of theLinus Torvalds1-0/+1
expression. This is just a very high-level cost, mainly distinguishing between "safe" and "unsafe" operations, so that we can determine if we can turn a C conditional into a select statement, or a logical op into one without short-ciruiting.
2005-04-07Teach linearizer about computed goto's.Linus Torvalds1-0/+1
We need to emit an OP_COMPUTEDGOTO instruction with a full list of potential targets.
2005-04-07[PATCH] comparison operations fixAlexander Viro1-1/+5
simplify_int_binop() was completely broken for comparisons - there the signedness of (converted) arguments can not be obtained from type of result. IOW, we had all comparisons in constant expressions done as signed ones. Fixed by introducing new primitives for unsigned versions of comparions (SPECIAL_UNSIGNED_LT, etc.) and remapping in evaluate_compare() once we know the types. That also fixes similar mess in compile-i386 and linearize.
2005-04-07Generalize linearize_symbol()Jeff Garzik1-1/+2
Allow it to be used by multiple callers.
2005-04-07[PATCH] Fix "return" target handlingChristopher Li1-1/+3
This fixes the linearization of "return", to use the proper symbol target that the front end has already set up for it: - linearize_statement(), case "STMT_COMPOUND" needs to create a label at the _end_ (aftre doing the linearization of all the other stuff) if "stmt->ret" is non-NULL. - STMT_RETURN needs to move the return expression to the return variable, and goto the return label.
2005-04-07[PATCH] More linearizion funChristopher Li1-22/+22
- add pre/post op and assign add etc. - change the call instruction have a list of arguments. - change the pseudo_t to be struct pseudo_t *, prepare for adding stuff to pseudo_t.
2005-04-07[PATCH] more op-codesChristopher Li1-8/+17
This is another small step. It adds binary ops, compare ops and ret. The classic recursive Fibonacci numbers function should be working.
2005-04-07[PATCH] condition branch simplificationChristopher Li1-13/+97
Here is the updated version of the patch. I tried to do as well on the iterator flattening as the old code, but then realized that the end result will be about as complex as what was there from before. So instead I wrote a simple pass to stitch the basic blocks together. It does two things: ff it is an empty block with a goto, it transfers the outgoing edge directly to the target. And if the only parent ends with a goto, it combines the block with the parent. There is also dead code elimination. So I removed the previous entry point hack for while loops. There is no need for that any more, and the end result is that we generate very compact basic blocks, often better than the previous approach did. The extra pass can almost certainly be reused for other back end passes. I also did: - add some lib functions to delete a point from the ptr_list while iterating. - Ignore labels which are not used - some minor bug fixing to the previous patch Know problem: - it doesn't deal with phi correctly, I need to redo the phi base on Tommy's suggestion.
2005-04-07[PATCH] PATCH: remove dead while loopChristopher Li1-0/+3
This improves the dead code eliminate for iterators that begin in an unreachable section (eg a "while" statement inside a "if (0)"). The idea is that have a decoy entrypoint for those while loops. On copy the basic block back only if there is C level label was found inside the block. It is tempting that left the dead code elimination and constant propagation to the some back end pass.
2005-04-07Linearize post-ops and casts.Linus Torvalds1-1/+6
And add a "OP_BADOP" linearization for expressions that we don't do yet, so that it's easier to see what is missing..
2005-04-07Linearize function calls. Kind-of.Linus Torvalds1-0/+3
(Btw - a number of the linearizations are pretty spotty, and not doing the right thing in the details. It's more concept thing).
2005-04-07Linearize logical ops.Linus Torvalds1-0/+1
2005-04-07Add new IL for expression linearization.Linus Torvalds1-1/+52
Linearize some simple expressions, the rest we just ignore for now. This is crapola. I'm really not sure this is the right way at all, but I don't see any good alternatives.
2005-04-07Clean up linearization, and make the basic blocks beLinus Torvalds1-0/+8
true basic blocks (with all exits at the bottom). This will simplify some of the analysis.
2005-04-07Clean up "linearize()" calling convention even more.Linus Torvalds1-0/+1
It's almost understandable now.
2005-04-07Add basic block "ownership", ie each basic block has aLinus Torvalds1-2/+3
symbol that "owns" it (unless it is entirely statically unreachable). Use this to do trivial constant conditional folding.
2005-04-07Add "goto/label" support for linearization.Linus Torvalds1-1/+1
This required making the inter-BB trampoline to be done using indirection through a symbol, rather than as direct pointers from one BB to another. Fix up code to match. Avoid a few warnings by handling GOTO_BB in the case statements.
2005-04-07Add real flow control to the basic-block handling.Linus Torvalds1-0/+1
Right now we only really do trivial if-statements, but the ideas are all there now.
2005-04-07Oops. Fix name clash by renaming the new "copy_ptr_list" to beLinus Torvalds1-0/+2
"concat_ptr_list" (which also is more accurate). Declare linearize_symbol().
2005-04-07This add a linearization phase. It's not even close to doneLinus Torvalds1-0/+27
yet, but the framework is there. When we linearize the tree we just generate a list of basic blocks of statement expressions (and branches between them, although that "small details" isn't actually done yet ;).