Dr. ERDI Gergo via llvm-dev
2017-May-09 11:51 UTC
[llvm-dev] Instruction selection for 'load' based on static vs. dynamic data
On Mon, 8 May 2017, Krzysztof Parzyszek via llvm-dev wrote:> You can create the differentiation between objects in the data memory and in > the program memory in LowerGlobalAddress (e.g. you can create different ISD > opcodes that generate these addresses) and then use those to select > corresponding instructions.Right, which is how I also understand Zhai Xiang's suggestion with the link to existing AVR target code. This is already done to some extent, since the AVR backend already inserts an AVRISD::WRAPPER node to mark the static data's address. However, what's still missing with that plan is how to propagate that information "upwards". By the time it gets to instruction selection, the `getelementptr` is already expanded into some arithmetic expression of a base address and some arbitrary offset calculations. So for example, with this code: %switch.gep = getelementptr inbounds [15 x i8], [15 x i8]* @switch.table, i16 0, i16 %2 %switch.load = load i8, i8* %switch.gep, align 1 by instrucion selection time, the argument to 'load' is (add (sign_extend (CopyFromReg %vreg2)) (WRAPPER TargetGlobalAddress<@switch.table>)) not a WRAPPER directly.
Krzysztof Parzyszek via llvm-dev
2017-May-09 13:01 UTC
[llvm-dev] Instruction selection for 'load' based on static vs. dynamic data
On 5/9/2017 6:51 AM, Dr. ERDI Gergo wrote:> On Mon, 8 May 2017, Krzysztof Parzyszek via llvm-dev wrote: > > However, what's still missing with that plan is how to propagate that > information "upwards". By the time it gets to instruction selection, the > `getelementptr` is already expanded into some arithmetic expression of a > base address and some arbitrary offset calculations.At this point it's a problem of writing appropriate selection patterns.> So for example, with this code: > [...] > > (add > (sign_extend (CopyFromReg %vreg2)) > (WRAPPER TargetGlobalAddress<@switch.table>)) > > not a WRAPPER directly.Such cases can be treated with conjunction with the load or store instruction, for example: def: Pat<(ld (add (WRAPPER RC:$addr), (sign_extend RC:$offset))), (load_instruction_rr RC:$addr, RC:$offset)>; Where "load_instruction" is a machine load instruction with base address and an offset, both in registers, and RC is the corresponding register class. For cases where the offset is an immediate, you can have def: Pat<(ld (add (WRAPPER RC:$addr), imm:$offset)), (load_instruction_ri RC:$addr, imm:$offset)>; The "imm" is a general predicate for any immediate. If you want to only match a subset of immediates (e.g. those that are within some range), you can define your own PatLeaf and then use it in place of imm: def Test : PatLeaf<(i32 imm), [{ int64_t V = N->getSExtValue(); return V > -17 && V < 12; // Only true for [-16, 11]. }]>; def: Pat<(ld (add (WRAPPER RC:$addr), Test:$offset)), (load_instruction_ri RC:$addr, imm:$offset)>; The "imm" in the second line can remain, it's the first part of the "Pat" that matters, but if you want, you can have "Test" in both. There is also a target hook "isOffsetFoldingLegal" in TargetLowering, which tells the DAG combiner if it can make the immediate offset a part of the global address itself. -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Dr. ERDI Gergo via llvm-dev
2017-May-09 13:16 UTC
[llvm-dev] Instruction selection for 'load' based on static vs. dynamic data
On Tue, 9 May 2017, Krzysztof Parzyszek wrote:> def: Pat<(ld (add (WRAPPER RC:$addr), (sign_extend RC:$offset))), > (load_instruction_rr RC:$addr, RC:$offset)>; > > Where "load_instruction" is a machine load instruction with base address and > an offset, both in registers, and RC is the corresponding register class.Can I also use something more complex than a single machine load instruction here? I.e. can I write something like def: Pat<(ld (add (WRAPPER RC:$addr), (sign_extend RC:$offset))), (load_instruction_rr (special_add RC:$addr, RC:$offset))>; ? Or do I have to go via some pseudo-instruction for that?