summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Sparc/SparcInstr64Bit.td
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2013-04-06 23:57:33 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2013-04-06 23:57:33 +0000
commitedaf66b056f6cb9fe08e43cc6d23f0dadb7060d6 (patch)
treebf2924447f517ebd9abd40c9041da687eabf75ea /llvm/lib/Target/Sparc/SparcInstr64Bit.td
parent03d9f7fda6cde43f88accbe7700f47f5515dfb47 (diff)
downloadbcm5719-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.td9
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,
OpenPOWER on IntegriCloud