Override getTypeForExtReturn so that functions returning an i32 typed value have it sign extended on MIPS64.
Also provide patterns to get rid of unneeded sign extensions for arithmetic instructions which implicitly sign extend their results.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
Forgot to mark this explicitly as still being WIP, since we are missing sign extensions at some places.
test/CodeGen/Mips/llvm-ir/or.ll | ||
---|---|---|
111 ↗ | (On Diff #152100) | For example here. Likewise for the xor.ll test. |
Added target hooks to replace the sign_extend with the sign_extend_inreg node which will get pattern matched with the SLL64_64 thus providing the needed sign extension.
The second target hook is introduced to keep the sign_extend_inreg node from being combined away.
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | Is this required for correctness? If it is, then the MIPS target is lying to DAGCombine somehow, and this fix is just papering over the bug. Otherwise, I can't see how keeping around a redundant SIGN_EXTEND_INREG would make the generated code more efficient. |
test/CodeGen/Mips/llvm-ir/or.ll | ||
---|---|---|
111 ↗ | (On Diff #152100) | The sign extension here is redundant, I think: if x and y both have N sign bits, x | y also has N sign bits. |
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | The sole purpose of that function, and keeping the SIGN_EXTEND_INREG node alive, is so that it could be later matched with this pattern: def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), (SLL64_64 GPR64:$src)>; As an example, SelectionDAG for the or_i32 function which resides in the or.ll test file: t0: ch = EntryToken t2: i64,ch = CopyFromReg t0, Register:i64 %0 t4: i64 = AssertSext t2, ValueType:ch:i32 t5: i32 = truncate t4 t7: i64,ch = CopyFromReg t0, Register:i64 %1 t8: i64 = AssertSext t7, ValueType:ch:i32 t9: i32 = truncate t8 t10: i32 = or t5, t9 t11: i64 = sign_extend t10 t13: ch,glue = CopyToReg t0, Register:i64 $v0_64, t11 t14: ch = MipsISD::Ret t13, Register:i64 $v0_64, t13:1 gets eventually transformed to this (including the sign_extend_inreg node incorporated by this patch): t0: ch = EntryToken t2: i64,ch = CopyFromReg t0, Register:i64 %0 t4: i64 = AssertSext t2, ValueType:ch:i32 t7: i64,ch = CopyFromReg t0, Register:i64 %1 t8: i64 = AssertSext t7, ValueType:ch:i32 t15: i64 = or t4, t8 t17: i64 = sign_extend_inreg t15, ValueType:ch:i32 t13: ch,glue = CopyToReg t0, Register:i64 $v0_64, t17 t14: ch = MipsISD::Ret t13, Register:i64 $v0_64, t13:1 In place of sign_extend_inreg node would be the sign_extend node, which would be removed the same way the sign_extend_inreg would. |
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | I don't understand: why do you want to generate a redundant "sll" instruction? |
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | Its purpose in this case is to sign extend the return value of a function, specifically i32 on MIPS64. At the moment that is not the case, even if the i32 return value is marked with the signext attribute. |
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | I don't mean "why do you want to generate an sll instruction in general"; I follow that part. I mean, "why do you want to generate a redundant sll instruction in your example"? "i64 = or t4, t8" is already appropriately sign-extended. |
include/llvm/CodeGen/TargetLowering.h | ||
---|---|---|
2140 ↗ | (On Diff #155342) | Ah, I see, there was a misunderstanding on my part. |
Not anymore, I'd like to have it reviewed.
I rolled it back to the version similar to the one you reviewed initially.