Skip to content

Commit

Permalink
[SystemZ] Support floating-point control register instructions
Browse files Browse the repository at this point in the history
Add assembler support for instructions manipulating the FPC.

Also add codegen support via the GCC compatibility builtins:
  __builtin_s390_sfpc
  __builtin_s390_efpc



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288525 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
uweigand committed Dec 2, 2016
1 parent 1f697f4 commit 4b7476c
Show file tree
Hide file tree
Showing 14 changed files with 480 additions and 11 deletions.
5 changes: 5 additions & 0 deletions include/llvm/IR/IntrinsicsSystemZ.td
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,11 @@ let TargetPrefix = "s390" in {
//===----------------------------------------------------------------------===//

let TargetPrefix = "s390" in {
def int_s390_sfpc : GCCBuiltin<"__builtin_s390_sfpc">,
Intrinsic<[], [llvm_i32_ty], []>;
def int_s390_efpc : GCCBuiltin<"__builtin_s390_efpc">,
Intrinsic<[llvm_i32_ty], [], []>;

def int_s390_tdc : Intrinsic<[llvm_i32_ty], [llvm_anyfloat_ty, llvm_i64_ty],
[IntrNoMem]>;
}
20 changes: 20 additions & 0 deletions lib/Target/SystemZ/SystemZInstrFP.td
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,26 @@ let Defs = [CC], CCValues = 0xC in {
def TCXB : TestRXE<"tcxb", 0xED12, z_tdc, FP128>;
}

//===----------------------------------------------------------------------===//
// Floating-point control register instructions
//===----------------------------------------------------------------------===//

let hasSideEffects = 1 in {
def EFPC : InherentRRE<"efpc", 0xB38C, GR32, int_s390_efpc>;
def STFPC : StoreInherentS<"stfpc", 0xB29C, storei<int_s390_efpc>, 4>;

def SFPC : SideEffectUnaryRRE<"sfpc", 0xB384, GR32, int_s390_sfpc>;
def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu<int_s390_sfpc>, 4>;

def SFASR : SideEffectUnaryRRE<"sfasr", 0xB385, GR32, null_frag>;
def LFAS : SideEffectUnaryS<"lfas", 0xB2BD, null_frag, 4>;

def SRNMB : SideEffectAddressS<"srnmb", 0xB2B8, null_frag, shift12only>,
Requires<[FeatureFPExtension]>;
def SRNM : SideEffectAddressS<"srnm", 0xB299, null_frag, shift12only>;
def SRNMT : SideEffectAddressS<"srnmt", 0xB2B9, null_frag, shift12only>;
}

//===----------------------------------------------------------------------===//
// Peepholes
//===----------------------------------------------------------------------===//
Expand Down
32 changes: 27 additions & 5 deletions lib/Target/SystemZ/SystemZInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,9 @@ class ICV<string name>
// LoadAddress:
// One register output operand and one address operand.
//
// SideEffectAddress:
// One address operand. No output operands, but causes some side effect.
//
// Unary:
// One register output operand and one input operand.
//
Expand Down Expand Up @@ -1677,10 +1680,12 @@ class InherentVRIa<string mnemonic, bits<16> opcode, bits<16> value>
let M3 = 0;
}

class StoreInherentS<string mnemonic, bits<16> opcode>
class StoreInherentS<string mnemonic, bits<16> opcode,
SDPatternOperator operator, bits<5> bytes>
: InstS<opcode, (outs), (ins bdaddr12only:$BD2),
mnemonic#"\t$BD2", []> {
mnemonic#"\t$BD2", [(operator bdaddr12only:$BD2)]> {
let mayStore = 1;
let AccessBytes = bytes;
}

class SideEffectInherentE<string mnemonic, bits<16>opcode>
Expand Down Expand Up @@ -2265,10 +2270,27 @@ class SideEffectUnaryRR<string mnemonic, bits<8>opcode, RegisterOperand cls>
let R2 = 0;
}

class SideEffectUnaryRRE<string mnemonic, bits<16> opcode, RegisterOperand cls,
SDPatternOperator operator>
: InstRRE<opcode, (outs), (ins cls:$R1),
mnemonic#"\t$R1", [(operator cls:$R1)]> {
let R2 = 0;
}

class SideEffectUnaryS<string mnemonic, bits<16> opcode,
SDPatternOperator operator>
: InstS<opcode, (outs), (ins bdaddr12only:$BD2),
mnemonic#"\t$BD2", [(operator bdaddr12only:$BD2)]>;
SDPatternOperator operator, bits<5> bytes,
AddressingMode mode = bdaddr12only>
: InstS<opcode, (outs), (ins mode:$BD2),
mnemonic#"\t$BD2", [(operator mode:$BD2)]> {
let mayLoad = 1;
let AccessBytes = bytes;
}

class SideEffectAddressS<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
AddressingMode mode = bdaddr12only>
: InstS<opcode, (outs), (ins mode:$BD2),
mnemonic#"\t$BD2", [(operator mode:$BD2)]>;

class LoadAddressRX<string mnemonic, bits<8> opcode,
SDPatternOperator operator, AddressingMode mode>
Expand Down
12 changes: 6 additions & 6 deletions lib/Target/SystemZ/SystemZInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@ let hasSideEffects = 1, Predicates = [FeatureTransactionalExecution] in {

// Transaction Abort
let isTerminator = 1, isBarrier = 1 in
def TABORT : SideEffectUnaryS<"tabort", 0xB2FC, int_s390_tabort>;
def TABORT : SideEffectAddressS<"tabort", 0xB2FC, int_s390_tabort>;

// Nontransactional Store
def NTSTG : StoreRXY<"ntstg", 0xE325, int_s390_ntstg, GR64, 8>;
Expand Down Expand Up @@ -1691,14 +1691,14 @@ let hasSideEffects = 1, isCall = 1, Defs = [CC] in

// Store clock.
let hasSideEffects = 1, Defs = [CC] in {
def STCK : StoreInherentS<"stck", 0xB205>;
def STCKF : StoreInherentS<"stckf", 0xB27C>;
def STCKE : StoreInherentS<"stcke", 0xB278>;
def STCK : StoreInherentS<"stck", 0xB205, null_frag, 8>;
def STCKF : StoreInherentS<"stckf", 0xB27C, null_frag, 8>;
def STCKE : StoreInherentS<"stcke", 0xB278, null_frag, 16>;
}

// Store facility list.
let hasSideEffects = 1, Defs = [CC] in
def STFLE : StoreInherentS<"stfle", 0xB2B0>;
let hasSideEffects = 1, Uses = [R0D], Defs = [R0D, CC] in
def STFLE : StoreInherentS<"stfle", 0xB2B0, null_frag, 0>;

// Extract CPU time.
let Defs = [R0D, R1D], hasSideEffects = 1, mayLoad = 1 in
Expand Down
6 changes: 6 additions & 0 deletions lib/Target/SystemZ/SystemZOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,12 @@ class storeu<SDPatternOperator operator, SDPatternOperator store = store>
: PatFrag<(ops node:$value, node:$addr),
(store (operator node:$value), node:$addr)>;

// Create a store operator that performs the given inherent operation
// and stores the resulting value.
class storei<SDPatternOperator operator, SDPatternOperator store = store>
: PatFrag<(ops node:$addr),
(store (operator), node:$addr)>;

// Vector representation of all-zeros and all-ones.
def z_vzero : PatFrag<(ops), (bitconvert (v16i8 (z_byte_mask (i32 0))))>;
def z_vones : PatFrag<(ops), (bitconvert (v16i8 (z_byte_mask (i32 65535))))>;
Expand Down
11 changes: 11 additions & 0 deletions lib/Target/SystemZ/SystemZScheduleZ13.td
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,17 @@ def : InstRW<[VecDF, VecDF, Lat20, GroupAlone], (instregex "CXBR$")>;
def : InstRW<[LSU, VecXsPm, Lat9], (instregex "TC(E|D)B$")>;
def : InstRW<[LSU, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "TCXB$")>;

//===----------------------------------------------------------------------===//
// FP: Floating-point control register instructions
//===----------------------------------------------------------------------===//

def : InstRW<[FXa, LSU, Lat4, GroupAlone], (instregex "EFPC$")>;
def : InstRW<[FXb, LSU, Lat5, GroupAlone], (instregex "STFPC$")>;
def : InstRW<[LSU, Lat3, GroupAlone], (instregex "SFPC$")>;
def : InstRW<[LSU, LSU, Lat6, GroupAlone], (instregex "LFPC$")>;
def : InstRW<[FXa, Lat30, GroupAlone], (instregex "SFASR$")>;
def : InstRW<[FXa, LSU, Lat30, GroupAlone], (instregex "LFAS$")>;
def : InstRW<[FXb, Lat3, GroupAlone], (instregex "SRNM(B|T)?$")>;

// --------------------------------- Vector --------------------------------- //

Expand Down
12 changes: 12 additions & 0 deletions lib/Target/SystemZ/SystemZScheduleZ196.td
Original file line number Diff line number Diff line change
Expand Up @@ -731,5 +731,17 @@ def : InstRW<[FPU, FPU, Lat30], (instregex "CXBR$")>;
def : InstRW<[FPU, LSU, Lat15], (instregex "TC(E|D)B$")>;
def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "TCXB$")>;

//===----------------------------------------------------------------------===//
// FP: Floating-point control register instructions
//===----------------------------------------------------------------------===//

def : InstRW<[FXU, LSU, Lat4, GroupAlone], (instregex "EFPC$")>;
def : InstRW<[LSU, Lat3, GroupAlone], (instregex "SFPC$")>;
def : InstRW<[LSU, LSU, Lat6, GroupAlone], (instregex "LFPC$")>;
def : InstRW<[LSU, Lat3, GroupAlone], (instregex "STFPC$")>;
def : InstRW<[FXU, Lat30, GroupAlone], (instregex "SFASR$")>;
def : InstRW<[FXU, LSU, Lat30, GroupAlone], (instregex "LFAS$")>;
def : InstRW<[FXU, Lat2, GroupAlone], (instregex "SRNM(B|T)?$")>;

}

12 changes: 12 additions & 0 deletions lib/Target/SystemZ/SystemZScheduleZEC12.td
Original file line number Diff line number Diff line change
Expand Up @@ -769,5 +769,17 @@ def : InstRW<[FPU, FPU, Lat30], (instregex "CXBR$")>;
def : InstRW<[FPU, LSU, Lat15], (instregex "TC(E|D)B$")>;
def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "TCXB$")>;

//===----------------------------------------------------------------------===//
// FP: Floating-point control register instructions
//===----------------------------------------------------------------------===//

def : InstRW<[FXU, LSU, Lat4, GroupAlone], (instregex "EFPC$")>;
def : InstRW<[LSU, Lat3, GroupAlone], (instregex "SFPC$")>;
def : InstRW<[LSU, LSU, Lat6, GroupAlone], (instregex "LFPC$")>;
def : InstRW<[LSU, Lat3, GroupAlone], (instregex "STFPC$")>;
def : InstRW<[FXU, Lat30, GroupAlone], (instregex "SFASR$")>;
def : InstRW<[FXU, LSU, Lat30, GroupAlone], (instregex "LFAS$")>;
def : InstRW<[FXU, Lat2, GroupAlone], (instregex "SRNM(B|T)?$")>;

}

67 changes: 67 additions & 0 deletions test/CodeGen/SystemZ/fpc-intrinsics.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
; Test floating-point control register intrinsics.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s

declare void @llvm.s390.sfpc(i32)
declare i32 @llvm.s390.efpc()

; SFPC.
define void @test_sfpc(i32 %fpc) {
; CHECK-LABEL: test_sfpc:
; CHECK: sfpc %r2
; CHECK: br %r14
call void @llvm.s390.sfpc(i32 %fpc)
ret void
}

; EFPC.
define i32 @test_efpc() {
; CHECK-LABEL: test_efpc:
; CHECK: efpc %r2
; CHECK: br %r14
%res = call i32 @llvm.s390.efpc()
ret i32 %res
}

; LFPC.
define void @test_lfpc1(i32 *%ptr) {
; CHECK-LABEL: test_lfpc1:
; CHECK: lfpc 0(%r2)
; CHECK: br %r14
%fpc = load i32, i32 *%ptr
call void @llvm.s390.sfpc(i32 %fpc)
ret void
}

; LFPC with offset.
define void @test_lfpc2(i32 *%ptr) {
; CHECK-LABEL: test_lfpc2:
; CHECK: lfpc 4092(%r2)
; CHECK: br %r14
%ptr1 = getelementptr i32, i32 *%ptr, i32 1023
%fpc = load i32, i32 *%ptr1
call void @llvm.s390.sfpc(i32 %fpc)
ret void
}

; STFPC.
define void @test_stfpc1(i32 *%ptr) {
; CHECK-LABEL: test_stfpc1:
; CHECK: stfpc 0(%r2)
; CHECK: br %r14
%fpc = call i32 @llvm.s390.efpc()
store i32 %fpc, i32 *%ptr
ret void
}

; STFPC with offset.
define void @test_stfpc2(i32 *%ptr) {
; CHECK-LABEL: test_stfpc2:
; CHECK: stfpc 4092(%r2)
; CHECK: br %r14
%fpc = call i32 @llvm.s390.efpc()
%ptr1 = getelementptr i32, i32 *%ptr, i32 1023
store i32 %fpc, i32 *%ptr1
ret void
}

Loading

0 comments on commit 4b7476c

Please sign in to comment.