diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-04-06 23:57:33 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-04-06 23:57:33 +0000 |
commit | edaf66b056f6cb9fe08e43cc6d23f0dadb7060d6 (patch) | |
tree | bf2924447f517ebd9abd40c9041da687eabf75ea /llvm/lib/Target/Sparc/SparcInstr64Bit.td | |
parent | 03d9f7fda6cde43f88accbe7700f47f5515dfb47 (diff) | |
download | bcm5719-llvm-edaf66b056f6cb9fe08e43cc6d23f0dadb7060d6.tar.gz bcm5719-llvm-edaf66b056f6cb9fe08e43cc6d23f0dadb7060d6.zip |
Implement LowerReturn_64 for SPARC v9.
Integer return values are sign or zero extended by the callee, and
structs up to 32 bytes in size can be returned in registers.
The CC_Sparc64 CallingConv definition is shared between
LowerFormalArguments_64 and LowerReturn_64. Function arguments and
return values are passed in the same registers.
The inreg flag is also used for return values. This is required to handle
C functions returning structs containing floats and ints:
struct ifp {
int i;
float f;
};
struct ifp f(void);
LLVM IR:
define inreg { i32, float } @f() {
...
ret { i32, float } %retval
}
The ABI requires that %retval.i is returned in the high bits of %i0
while %retval.f goes in %f1.
Without the inreg return value attribute, %retval.i would go in %i0 and
%retval.f would go in %f3 which is a more efficient way of returning
%multiple values, but it is not ABI compliant for returning C structs.
llvm-svn: 178966
Diffstat (limited to 'llvm/lib/Target/Sparc/SparcInstr64Bit.td')
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstr64Bit.td | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index ca1153b3fe8..70e55e638a6 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -40,6 +40,9 @@ let Predicates = [Is64Bit] in { def : Pat<(i64 (zext i32:$val)), (SRLri $val, 0)>; def : Pat<(i64 (sext i32:$val)), (SRAri $val, 0)>; +def : Pat<(i64 (and i64:$val, 0xffffffff)), (SRLri $val, 0)>; +def : Pat<(i64 (sext_inreg i64:$val, i32)), (SRAri $val, 0)>; + defm SLLX : F3_S<"sllx", 0b100101, 1, shl, i64, I64Regs>; defm SRLX : F3_S<"srlx", 0b100110, 1, srl, i64, I64Regs>; defm SRAX : F3_S<"srax", 0b100111, 1, sra, i64, I64Regs>; @@ -203,16 +206,22 @@ def LDXri : F3_2<3, 0b001011, // Extending loads to i64. def : Pat<(i64 (zextloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; def : Pat<(i64 (zextloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; +def : Pat<(i64 (extloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; +def : Pat<(i64 (extloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; def : Pat<(i64 (sextloadi8 ADDRrr:$addr)), (LDSBrr ADDRrr:$addr)>; def : Pat<(i64 (sextloadi8 ADDRri:$addr)), (LDSBri ADDRri:$addr)>; def : Pat<(i64 (zextloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>; def : Pat<(i64 (zextloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>; +def : Pat<(i64 (extloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>; +def : Pat<(i64 (extloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>; def : Pat<(i64 (sextloadi16 ADDRrr:$addr)), (LDSHrr ADDRrr:$addr)>; def : Pat<(i64 (sextloadi16 ADDRri:$addr)), (LDSHri ADDRri:$addr)>; def : Pat<(i64 (zextloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; def : Pat<(i64 (zextloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; +def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; +def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; // Sign-extending load of i32 into i64 is a new SPARC v9 instruction. def LDSWrr : F3_1<3, 0b001011, |