Christopher Lamb
2007-Feb-12 09:41 UTC
[LLVMdev] bitconvert for multi-typed RegisterClasses
Hi All, I'm working on a back end for an architecture that makes use of multi- typed register classes. def MR: RegisterClass<"namespace", [type1, type2, ... ], ... > When running some preliminary tests I found that the instruction selector refused to select certain ops (specifically stores) for some instructions when the operand type wasn't the first type for the register class. After some digging around I seem to have solved the problem by creating bitconvert patterns between the types in the register class like the following: def : Pat<(type1 (bitconvert (type2 MR:$src))), (type1 MR:$src)>; def : Pat<(type2 (bitconvert (type1 MR:$src))), (type2 MR:$src)>; ... Adding these patterns appeared to allow the instruction selector to select/legalize the store operations. So I have two questions: 1) Is relying on these patterns for instruction selection/ legalization the correct way to implement multi-typed RegisterClasses? I like having TableGen do the pattern work for me rather than writing custom selection code... 2) I'd think that when a multi-typed RegisterClass is declared that these bitconvert patterns between types in that class automatically become legal. Is there a reason that TableGen shouldn't automatically generate these patterns when a multi-typed register class is created? Thanks -- Christopher Lamb
On Feb 12, 2007, at 1:41 AM, Christopher Lamb wrote:> > selector refused to select certain ops (specifically stores) for some > instructions when the operand type wasn't the first type for the > register class. After some digging around I seem to have solved the > problem by creating bitconvert patterns between the types in the > register class like the following: > > def : Pat<(type1 (bitconvert (type2 MR:$src))), (type1 MR:$src)>; > def : Pat<(type2 (bitconvert (type1 MR:$src))), (type2 MR:$src)>; > ... > > Adding these patterns appeared to allow the instruction selector to > select/legalize the store operations. So I have two questions: > > 1) Is relying on these patterns for instruction selection/ > legalization the correct way to implement multi-typed > RegisterClasses? I like having TableGen do the pattern work for me > rather than writing custom selection code... > > 2) I'd think that when a multi-typed RegisterClass is declared that > these bitconvert patterns between types in that class automatically > become legal. Is there a reason that TableGen shouldn't automatically > generate these patterns when a multi-typed register class is created?X86 backend has the VR64 and VR128 register classes which are exactly like this. Rather than adding a whole bunch of instruction selection rules to match all the possibilities. We've decided to ask the legalizer to normalize the target-independent nodes to one particular type. See X86ISelLowering.cpp: // Promote v16i8, v8i16, v4i32 load, select, and, or, xor to v2i64. for (unsigned VT = (unsigned)MVT::v16i8; VT != (unsigned) MVT::v2i64; VT++) { setOperationAction(ISD::AND, (MVT::ValueType)VT, Promote); AddPromotedToType (ISD::AND, (MVT::ValueType)VT, MVT::v2i64); ... Evan> > Thanks > -- > Christopher Lamb > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Christopher Lamb
2007-Feb-12 19:56 UTC
[LLVMdev] bitconvert for multi-typed RegisterClasses
On Feb 12, 2007, at 12:58 PM, Evan Cheng wrote:> > On Feb 12, 2007, at 1:41 AM, Christopher Lamb wrote: > >> >> selector refused to select certain ops (specifically stores) for some >> instructions when the operand type wasn't the first type for the >> register class. After some digging around I seem to have solved the >> problem by creating bitconvert patterns between the types in the >> register class like the following: >> >> def : Pat<(type1 (bitconvert (type2 MR:$src))), (type1 MR:$src)>; >> def : Pat<(type2 (bitconvert (type1 MR:$src))), (type2 MR:$src)>; >> ... >> >> Adding these patterns appeared to allow the instruction selector to >> select/legalize the store operations. So I have two questions: >> >> 1) Is relying on these patterns for instruction selection/ >> legalization the correct way to implement multi-typed >> RegisterClasses? I like having TableGen do the pattern work for me >> rather than writing custom selection code... >> >> 2) I'd think that when a multi-typed RegisterClass is declared that >> these bitconvert patterns between types in that class automatically >> become legal. Is there a reason that TableGen shouldn't automatically >> generate these patterns when a multi-typed register class is created? > > X86 backend has the VR64 and VR128 register classes which are exactly > like this. Rather than adding a whole bunch of instruction selection > rules to match all the possibilities. We've decided to ask the > legalizer to normalize the target-independent nodes to one particular > type. See X86ISelLowering.cpp: > > // Promote v16i8, v8i16, v4i32 load, select, and, or, xor to > v2i64. > for (unsigned VT = (unsigned)MVT::v16i8; VT != (unsigned) > MVT::v2i64; VT++) { > setOperationAction(ISD::AND, (MVT::ValueType)VT, Promote); > AddPromotedToType (ISD::AND, (MVT::ValueType)VT, > MVT::v2i64); > ... > > EvanThanks Evan, I had tried something like this, but ran into some problems. llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1478: failed assertion `MVT::isVector(VT) && "Cannot promote this load!"' and llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1766: failed assertion `MVT::isVector(VT) && "Unknown legal promote case!"' it appears that for load/store only vector types of equivalent bit- widths can be promoted in this way, but one cannot promote an f32 to an i32. Also, I was incorrect in thinking that the bitconvert patterns I mentioned in the original post had solved my problems. I ended up having to explicitly add patterns for the f32 types to the InstrInfo.td. And then, it only seems to work if I add a pseudo instruction with the following selection pattern (store (f32 Regs: $src), ADDRri:$addr), rather than adding a pattern such as the following: def : Pat<(store (f32 Regs:$src), ADDRri:$addr), (ST32 Regs:$src, ADDRri:$addr)>; The above pattern produced the following error because the TargetOperandInfo for the 1 operand of the store had a NULL register class. llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:304: failed assertion `RC && "Don't have operand info for this instruction!"' Why the pseudo-op doesn't have this problem, I'm not clear. Thanks -- Christopher Lamb> >> >> Thanks >> -- >> Christopher Lamb >> >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev