I think we should keep GEP essentially the same, but disassociate the type being GEPd over from the type of the operands. So, assuming the new ptr type is spelled "ptr", we could use this syntax: %inner.ptr = getelementptr ptr, ptr %x, i32 1 Or if I was adding 1 to a "struct A*" value in C: %next_elt = getelementptr %struct.A, ptr %x, i32 1 Ditto for all other instructions that care about pointee types, like load and store: %v = load i32, ptr %p ; loads already know (and store!) their loaded type internally store i32 %v, ptr %p ; no need to duplicate that %p points to, we have the type on %v I don't think this can be incremental, I think it all goes at once. I think you might need to add a new GEP bitcode opcode, since that instruction grows a new type operand that doesn't come from an operand type or result type. It also wouldn't be too hard to accept the old .ll syntax, since the upgrade path mostly discards information. On Fri, Feb 6, 2015 at 4:12 PM, Sanjoy Das <sanjoy at playingwithpointers.com> wrote:> How would GEP's look like in this scheme? Concretely, what would be > the equivalent of > > %inner.ptr = getelementptr i8** %x, i32 1 > > assuming we're doing target independent optimizations and do not know > the size of a pointer? > > -- Sanjoy > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150206/dd1f9b84/attachment.html>
On Fri, Feb 6, 2015 at 6:09 PM, Reid Kleckner <rnk at google.com> wrote:> I think we should keep GEP essentially the same, but disassociate the type > being GEPd over from the type of the operands. So, assuming the new ptr > type is spelled "ptr", we could use this syntax: > %inner.ptr = getelementptr ptr, ptr %x, i32 1 > > Or if I was adding 1 to a "struct A*" value in C: > %next_elt = getelementptr %struct.A, ptr %x, i32 1 > > Ditto for all other instructions that care about pointee types, like load > and store: > %v = load i32, ptr %p ; loads already know (and store!) their loaded type > internally > store i32 %v, ptr %p ; no need to duplicate that %p points to, we have the > type on %v >Emphatically agree. No instruction should really change semantics here. GEPs should keep working the exact same way, the type involved should just be separate from the pointer's type.> > I don't think this can be incremental, I think it all goes at once. >I have some ideas of how to make it incremental:> I think you might need to add a new GEP bitcode opcode, since that > instruction grows a new type operand that doesn't come from an operand type > or result type. >Yep. And you can add this first, defining the semantics to be as-if the pointer operand was bit casted to a pointer to the new type. Then we could (in theory, not in practice!) even use and test it with the current IR, passing an i8* or any other pointer type operand. Same goes for the load instruction. We could support the new syntax first. Next, I think you might be able to introduce a generic pointer type, spelled as 'ptr' which would verifier fail if used with the old load or gep instructions. You might have to synthesize an unnamable pointee type to use for the in-memory representation, but that seems not beyond reason. Then you can wire up all the asm parsing and printing and bitcode stuff incrementally without any disruption. The remaining parts are more interesting and maybe harder to do incrementally, but still seem at least somewhat decomposable: - switching all of the LLVM optimizer and all of Clang to produce the new forms of GEP and load rather than the old forms - switching all of the optimizer and clang to use the new boring pointer type now that they never form old gep and load instructions - switching all the auto-upgrade functionality on - removing the in-memory support for the old forms - simplifying a ton of the in-memory support and the optimizer now that the old forms can't show up Also: It also wouldn't be too hard to accept the old .ll syntax, since the> upgrade path mostly discards information. >I agree here. If only because of th eregression test suite, and the *incredible* tediousness of updating the pointers. The auto-upgrade for this kind of thing is essentially perfect. -Chandler -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150206/9678b69d/attachment.html>
On Fri, Feb 6, 2015 at 6:40 PM, Chandler Carruth <chandlerc at google.com> wrote:> > It also wouldn't be too hard to accept the old .ll syntax, since the >> upgrade path mostly discards information. >> > > I agree here. If only because of th eregression test suite, and the > *incredible* tediousness of updating the pointers. The auto-upgrade for > this kind of thing is essentially perfect. >I think we should definitely script an update of the test suite if we do this. I really don't want to deal with reading old style IR in 98% of existing tests. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150206/abdd0f81/attachment.html>
> On Feb 6, 2015, at 6:40 PM, Chandler Carruth <chandlerc at google.com> wrote: > > On Fri, Feb 6, 2015 at 6:09 PM, Reid Kleckner <rnk at google.com <mailto:rnk at google.com>> wrote: > I think we should keep GEP essentially the same, but disassociate the type being GEPd over from the type of the operands. So, assuming the new ptr type is spelled "ptr", we could use this syntax: > %inner.ptr = getelementptr ptr, ptr %x, i32 1 > > Or if I was adding 1 to a "struct A*" value in C: > %next_elt = getelementptr %struct.A, ptr %x, i32 1 > > Ditto for all other instructions that care about pointee types, like load and store: > %v = load i32, ptr %p ; loads already know (and store!) their loaded type internally > store i32 %v, ptr %p ; no need to duplicate that %p points to, we have the type on %v > > Emphatically agree. No instruction should really change semantics here. GEPs should keep working the exact same way, the type involved should just be separate from the pointer's type. > > > I don't think this can be incremental, I think it all goes at once. > > I have some ideas of how to make it incremental: > > I think you might need to add a new GEP bitcode opcode, since that instruction grows a new type operand that doesn't come from an operand type or result type. > > Yep. And you can add this first, defining the semantics to be as-if the pointer operand was bit casted to a pointer to the new type. Then we could (in theory, not in practice!) even use and test it with the current IR, passing an i8* or any other pointer type operand.I’m not sure we need the new instructions at all. Really what we want is for Load and GEP to carry around a Type* alongside all their operands. This can be added now to the existing Load and GEP insts, and to their constructors/create methods. Going through all of the codebase to ensure we pass in the Type* in all the right places was going to have to be done anyway for a new instruction, but now can be done on the existing instructions. You can also assert (temporarily) to ensure that the type passed in matches the pointer operand type. I do agree the actual final switch could be tricky, but I think we should do what I’ve suggested here first, then see what happens if we just make the switch (which if we get everything in place really just means turning off a bunch of asserts and parser error checks). Personally I think this is far less work and less disruptive to out of tree targets, which are otherwise going to have to find all their own uses of the old style GEP instruction and add another GEP instruction to switches, etc. ...> > Same goes for the load instruction. We could support the new syntax first. > > > Next, I think you might be able to introduce a generic pointer type, spelled as 'ptr' which would verifier fail if used with the old load or gep instructions. You might have to synthesize an unnamable pointee type to use for the in-memory representation, but that seems not beyond reason. Then you can wire up all the asm parsing and printing and bitcode stuff incrementally without any disruption. > > The remaining parts are more interesting and maybe harder to do incrementally, but still seem at least somewhat decomposable: > > - switching all of the LLVM optimizer and all of Clang to produce the new forms of GEP and load rather than the old forms > - switching all of the optimizer and clang to use the new boring pointer type now that they never form old gep and load instructions > - switching all the auto-upgrade functionality on > - removing the in-memory support for the old forms > - simplifying a ton of the in-memory support and the optimizer now that the old forms can't show up > > > Also: > > It also wouldn't be too hard to accept the old .ll syntax, since the upgrade path mostly discards information. > > I agree here. If only because of th eregression test suite, and the *incredible* tediousness of updating the pointers. The auto-upgrade for this kind of thing is essentially perfect.I agree in principle, but I think the precedent here is dangerous. Thanks, Pete> > > -Chandler > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150209/275fe6b0/attachment.html>