diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td new file mode 100644 index 00000000000..09217d6041e --- /dev/null +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -0,0 +1,47 @@ +//===-- SparcInstr64Bit.td - 64-bit instructions for Sparc Target ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains instruction definitions and patterns needed for 64-bit +// code generation on SPARC v9. +// +// Some SPARC v9 instructions are defined in SparcInstrInfo.td because they can +// also be used in 32-bit code running on a SPARC v9 CPU. +// +//===----------------------------------------------------------------------===// + +let Predicates = [Is64Bit] in { +// The same integer registers are used for i32 and i64 values. +// When registers hold i32 values, the high bits are don't care. +// This give us free trunc and anyext. +def : Pat<(i64 (anyext i32:$val)), (COPY $val)>; +def : Pat<(i32 (trunc i64:$val)), (COPY $val)>; + +} // Predicates = [Is64Bit] + + +//===----------------------------------------------------------------------===// +// 64-bit Shift Instructions. +//===----------------------------------------------------------------------===// +// +// The 32-bit shift instructions are still available. The left shift srl +// instructions shift all 64 bits, but it only accepts a 5-bit shift amount. +// +// The srl instructions only shift the low 32 bits and clear the high 32 bits. +// Finally, sra shifts the low 32 bits and sign-extends to 64 bits. + +let Predicates = [Is64Bit] in { + +def : Pat<(i64 (zext i32:$val)), (SRLri $val, 0)>; +def : Pat<(i64 (sext i32:$val)), (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>; + +} // Predicates = [Is64Bit] diff --git a/lib/Target/Sparc/SparcInstrFormats.td b/lib/Target/Sparc/SparcInstrFormats.td index dce331228b8..f1018569153 100644 --- a/lib/Target/Sparc/SparcInstrFormats.td +++ b/lib/Target/Sparc/SparcInstrFormats.td @@ -111,4 +111,41 @@ class F3_3 opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins, let Inst{4-0} = rs2; } +// Shift by register rs2. +class F3_Sr opVal, bits<6> op3val, bit xVal, dag outs, dag ins, + string asmstr, list pattern> : F3 { + bit x = xVal; // 1 for 64-bit shifts. + bits<5> rs2; + let op = opVal; + let op3 = op3val; + + let Inst{13} = 0; // i field = 0 + let Inst{12} = x; // extended registers. + let Inst{4-0} = rs2; +} + +// Shift by immediate. +class F3_Si opVal, bits<6> op3val, bit xVal, dag outs, dag ins, + string asmstr, list pattern> : F3 { + bit x = xVal; // 1 for 64-bit shifts. + bits<6> shcnt; // shcnt32 / shcnt64. + + let op = opVal; + let op3 = op3val; + + let Inst{13} = 1; // i field = 1 + let Inst{12} = x; // extended registers. + let Inst{5-0} = shcnt; +} + +// Define rr and ri shift instructions with patterns. +multiclass F3_S Op3Val, bit XVal, SDNode OpNode, + ValueType VT, RegisterClass RC> { + def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, RC:$rs2), + !strconcat(OpcStr, " $rs, $rs2, $rd"), + [(set VT:$rd, (OpNode VT:$rs, VT:$rs2))]>; + def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, unknown:$shcnt), + !strconcat(OpcStr, " $rs, $shcnt, $rd"), + [(set VT:$rd, (OpNode VT:$rs, (VT imm:$shcnt)))]>; +} diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 1c1bb9826cb..b5a02780fb8 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -816,3 +816,5 @@ def : Pat<(i32 (extloadi16 ADDRri:$src)), (LDUHri ADDRri:$src)>; // zextload bool -> zextload byte def : Pat<(i32 (zextloadi1 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>; def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>; + +include "SparcInstr64Bit.td" diff --git a/test/CodeGen/SPARC/64bit.ll b/test/CodeGen/SPARC/64bit.ll index 1efbc15af64..6387e004278 100644 --- a/test/CodeGen/SPARC/64bit.ll +++ b/test/CodeGen/SPARC/64bit.ll @@ -5,3 +5,17 @@ define i64 @ret2(i64 %a, i64 %b) { ret i64 %b } + +; CHECK: shl_imm +; CHECK: sllx %i0, 7, %i0 +define i64 @shl_imm(i64 %a) { + %x = shl i64 %a, 7 + ret i64 %x +} + +; CHECK: sra_reg +; CHECK: srax %i0, %i1, %i0 +define i64 @sra_reg(i64 %a, i64 %b) { + %x = ashr i64 %a, %b + ret i64 %x +}