diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index 09217d6041e..5ab7b1f8837 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -45,3 +45,91 @@ defm SRLX : F3_S<"srlx", 0b100110, 1, srl, i64, I64Regs>; defm SRAX : F3_S<"srax", 0b100111, 1, sra, i64, I64Regs>; } // Predicates = [Is64Bit] + + +//===----------------------------------------------------------------------===// +// 64-bit Immediates. +//===----------------------------------------------------------------------===// +// +// All 32-bit immediates can be materialized with sethi+or, but 64-bit +// immediates may require more code. There may be a point where it is +// preferable to use a constant pool load instead, depending on the +// microarchitecture. + +// The %g0 register is constant 0. +// This is useful for stx %g0, [...], for example. +def : Pat<(i64 0), (i64 G0)>, Requires<[Is64Bit]>; + +// Single-instruction patterns. + +// The ALU instructions want their simm13 operands as i32 immediates. +def as_i32imm : SDNodeXFormgetTargetConstant(N->getSExtValue(), MVT::i32); +}]>; +def : Pat<(i64 simm13:$val), (ORri (i64 G0), (as_i32imm $val))>; +def : Pat<(i64 SETHIimm:$val), (SETHIi (HI22 $val))>; + +// Double-instruction patterns. + +// All unsigned i32 immediates can be handled by sethi+or. +def uimm32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>; +def : Pat<(i64 uimm32:$val), (ORri (SETHIi (HI22 $val)), (LO10 $val))>, + Requires<[Is64Bit]>; + +// All negative i33 immediates can be handled by sethi+xor. +def nimm33 : PatLeaf<(imm), [{ + int64_t Imm = N->getSExtValue(); + return Imm < 0 && isInt<33>(Imm); +}]>; +// Bits 10-31 inverted. Same as assembler's %hix. +def HIX22 : SDNodeXFormgetZExtValue() >> 10) & ((1u << 22) - 1); + return CurDAG->getTargetConstant(Val, MVT::i32); +}]>; +// Bits 0-9 with ones in bits 10-31. Same as assembler's %lox. +def LOX10 : SDNodeXFormgetTargetConstant(~(~N->getZExtValue() & 0x3ff), MVT::i32); +}]>; +def : Pat<(i64 nimm33:$val), (XORri (SETHIi (HIX22 $val)), (LOX10 $val))>, + Requires<[Is64Bit]>; + +// More possible patterns: +// +// (sllx sethi, n) +// (sllx simm13, n) +// +// 3 instrs: +// +// (xor (sllx sethi), simm13) +// (sllx (xor sethi, simm13)) +// +// 4 instrs: +// +// (or sethi, (sllx sethi)) +// (xnor sethi, (sllx sethi)) +// +// 5 instrs: +// +// (or (sllx sethi), (or sethi, simm13)) +// (xnor (sllx sethi), (or sethi, simm13)) +// (or (sllx sethi), (sllx sethi)) +// (xnor (sllx sethi), (sllx sethi)) +// +// Worst case is 6 instrs: +// +// (or (sllx (or sethi, simmm13)), (or sethi, simm13)) + +// Bits 42-63, same as assembler's %hh. +def HH22 : SDNodeXFormgetZExtValue() >> 42) & ((1u << 22) - 1); + return CurDAG->getTargetConstant(Val, MVT::i32); +}]>; +// Bits 32-41, same as assembler's %hm. +def HM10 : SDNodeXFormgetZExtValue() >> 32) & ((1u << 10) - 1); + return CurDAG->getTargetConstant(Val, MVT::i32); +}]>; +def : Pat<(i64 imm:$val), + (ORrr (SLLXri (ORri (SETHIi (HH22 $val)), (HM10 $val)), (i64 32)), + (ORri (SETHIi (HI22 $val)), (LO10 $val)))>, + Requires<[Is64Bit]>; diff --git a/test/CodeGen/SPARC/64bit.ll b/test/CodeGen/SPARC/64bit.ll index 6387e004278..b0c9852ef25 100644 --- a/test/CodeGen/SPARC/64bit.ll +++ b/test/CodeGen/SPARC/64bit.ll @@ -19,3 +19,49 @@ define i64 @sra_reg(i64 %a, i64 %b) { %x = ashr i64 %a, %b ret i64 %x } + +; Immediate materialization. Many of these patterns could actually be merged +; into the restore instruction: +; +; restore %g0, %g0, %o0 +; +; CHECK: ret_imm0 +; CHECK: or %g0, %g0, %i0 +define i64 @ret_imm0() { + ret i64 0 +} + +; CHECK: ret_simm13 +; CHECK: or %g0, -4096, %i0 +define i64 @ret_simm13() { + ret i64 -4096 +} + +; CHECK: ret_sethi +; CHECK: sethi 4, %i0 +; CHECK-NOT: or +; CHECK: restore +define i64 @ret_sethi() { + ret i64 4096 +} + +; CHECK: ret_sethi +; CHECK: sethi 4, [[R:%[goli][0-7]]] +; CHECK: or [[R]], 1, %i0 +define i64 @ret_sethi_or() { + ret i64 4097 +} + +; CHECK: ret_nimm33 +; CHECK: sethi 4, [[R:%[goli][0-7]]] +; CHECK: xor [[R]], -4, %i0 +define i64 @ret_nimm33() { + ret i64 -4100 +} + +; CHECK: ret_bigimm +; CHECK: sethi +; CHECK: sethi +define i64 @ret_bigimm() { + ret i64 6800754272627607872 +}