Skip to content

Commit 59cee32

Browse files
nemanjaimemfrob
authored andcommitted
[PowerPC] Implement intrinsics for mtfsf[i]
This provides intrinsics for emitting instructions that set the FPSCR (`mtfsf/mtfsfi`). The patch also conservatively marks the rounding mode as an implicit def for both since they both may set the rounding mode depending on the operands. Reviewed By: #powerpc, qiucf Differential Revision: https://reviews.llvm.org/D105957
1 parent 45be6e5 commit 59cee32

File tree

7 files changed

+148
-62
lines changed

7 files changed

+148
-62
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15620,6 +15620,13 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1562015620
Function *F = CGM.getIntrinsic(Intrinsic::ppc_popcntb, {ArgType, ArgType});
1562115621
return Builder.CreateCall(F, Ops, "popcntb");
1562215622
}
15623+
case PPC::BI__builtin_ppc_mtfsf: {
15624+
// The builtin takes a uint32 that needs to be cast to an
15625+
// f64 to be passed to the intrinsic.
15626+
Value *Cast = Builder.CreateUIToFP(Ops[1], DoubleTy);
15627+
llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtfsf);
15628+
return Builder.CreateCall(F, {Ops[0], Cast}, "");
15629+
}
1562315630
}
1562415631
}
1562515632

clang/test/CodeGen/builtins-ppc-xlcompat-math.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ void mtfsb1 () {
2424
}
2525

2626
// CHECK-LABEL: @mtfsf(
27-
// CHECK: [[UI_ADDR:%.*]] = alloca i32, align 4
28-
// CHECK-NEXT: store i32 [[UI:%.*]], i32* [[UI_ADDR]], align 4
29-
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[UI_ADDR]], align 4
30-
// CHECK-NEXT: call void @llvm.ppc.mtfsf(i32 8, i32 [[TMP0]])
27+
// CHECK: [[TMP0:%.*]] = uitofp i32 %{{.*}} to double
28+
// CHECK-NEXT: call void @llvm.ppc.mtfsf(i32 8, double [[TMP0]])
3129
// CHECK-NEXT: ret void
3230
//
3331
void mtfsf (unsigned int ui) {

llvm/include/llvm/IR/IntrinsicsPowerPC.td

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,9 +1636,8 @@ let TargetPrefix = "ppc" in {
16361636
: GCCBuiltin<"__builtin_ppc_mtfsb1">,
16371637
Intrinsic <[], [llvm_i32_ty],
16381638
[IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
1639-
def int_ppc_mtfsf
1640-
: GCCBuiltin<"__builtin_ppc_mtfsf">,
1641-
Intrinsic <[], [llvm_i32_ty, llvm_i32_ty],
1639+
def int_ppc_mtfsf :
1640+
Intrinsic <[], [llvm_i32_ty, llvm_double_ty],
16421641
[IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
16431642
def int_ppc_mtfsfi
16441643
: GCCBuiltin<"__builtin_ppc_mtfsfi">,

llvm/lib/Target/PowerPC/P9InstrResources.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,8 @@ def : InstRW<[P9_ALU_3C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C,
10791079
DISP_3SLOTS_1C, DISP_3SLOTS_1C],
10801080
(instrs
10811081
(instregex "MTFSF(b|_rec)?$"),
1082-
(instregex "MTFSFI(_rec)?$")
1082+
(instregex "MTFSFI(_rec)?$"),
1083+
MTFSFIb
10831084
)>;
10841085

10851086
// Cracked instruction made of two ALU ops.

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,7 +3103,8 @@ def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM),
31033103
let Defs = [RM] in {
31043104
let isCodeGenOnly = 1 in
31053105
def MTFSFb : XFLForm<63, 711, (outs), (ins i32imm:$FM, f8rc:$rT),
3106-
"mtfsf $FM, $rT", IIC_IntMTFSB0, []>,
3106+
"mtfsf $FM, $rT", IIC_IntMTFSB0,
3107+
[(int_ppc_mtfsf timm:$FM, f64:$rT)]>,
31073108
PPC970_DGroup_Single, PPC970_Unit_FPU;
31083109
}
31093110
let Uses = [RM] in {
@@ -4483,19 +4484,20 @@ def MTMSRD : XForm_mtmsr<31, 178, (outs), (ins gprc:$RS, u1imm:$L),
44834484
def MCRFS : XLForm_3<63, 64, (outs crrc:$BF), (ins crrc:$BFA),
44844485
"mcrfs $BF, $BFA", IIC_BrMCR>;
44854486

4486-
// If W is 0 and BF is 7, the 60:63 bits will be set, we should set the
4487-
// implicit-def RM.
4488-
def MTFSFI : XLForm_4<63, 134, (outs crrc:$BF), (ins i32imm:$U, i32imm:$W),
4487+
// All MTFSF variants may change the rounding mode so conservatively set it
4488+
// as an implicit def for all of them.
4489+
let Predicates = [HasFPU] in {
4490+
let Defs = [RM] in {
4491+
let isCodeGenOnly = 1,
4492+
Pattern = [(int_ppc_mtfsfi timm:$BF, timm:$U)], W = 0 in
4493+
def MTFSFIb : XLForm_4<63, 134, (outs), (ins u3imm:$BF, u4imm:$U),
4494+
"mtfsfi $BF, $U", IIC_IntMFFS>;
4495+
def MTFSFI : XLForm_4<63, 134, (outs), (ins u3imm:$BF, u4imm:$U, i32imm:$W),
44894496
"mtfsfi $BF, $U, $W", IIC_IntMFFS>;
44904497
let Defs = [CR1] in
4491-
def MTFSFI_rec : XLForm_4<63, 134, (outs crrc:$BF), (ins i32imm:$U, i32imm:$W),
4498+
def MTFSFI_rec : XLForm_4<63, 134, (outs), (ins u3imm:$BF, u4imm:$U, u1imm:$W),
44924499
"mtfsfi. $BF, $U, $W", IIC_IntMFFS>, isRecordForm;
44934500

4494-
def : InstAlias<"mtfsfi $BF, $U", (MTFSFI crrc:$BF, i32imm:$U, 0)>;
4495-
def : InstAlias<"mtfsfi. $BF, $U", (MTFSFI_rec crrc:$BF, i32imm:$U, 0)>;
4496-
4497-
let Predicates = [HasFPU] in {
4498-
let Defs = [RM] in {
44994501
def MTFSF : XFLForm_1<63, 711, (outs),
45004502
(ins i32imm:$FLM, f8rc:$FRB, u1imm:$L, i32imm:$W),
45014503
"mtfsf $FLM, $FRB, $L, $W", IIC_IntMFFS, []>;
@@ -4505,6 +4507,8 @@ def MTFSF_rec : XFLForm_1<63, 711, (outs),
45054507
"mtfsf. $FLM, $FRB, $L, $W", IIC_IntMFFS, []>, isRecordForm;
45064508
}
45074509

4510+
def : InstAlias<"mtfsfi $BF, $U", (MTFSFI u3imm:$BF, u4imm:$U, 0)>;
4511+
def : InstAlias<"mtfsfi. $BF, $U", (MTFSFI_rec u3imm:$BF, u4imm:$U, 0)>;
45084512
def : InstAlias<"mtfsf $FLM, $FRB", (MTFSF i32imm:$FLM, f8rc:$FRB, 0, 0)>;
45094513
def : InstAlias<"mtfsf. $FLM, $FRB", (MTFSF_rec i32imm:$FLM, f8rc:$FRB, 0, 0)>;
45104514
}

llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-math.ll

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,6 @@
1010
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr8 < %s |\
1111
; RUN: FileCheck %s --check-prefix=CHECK-PWR8
1212

13-
define dso_local void @mtfsb0() {
14-
; CHECK-PWR8-LABEL: mtfsb0:
15-
; CHECK-PWR8: # %bb.0: # %entry
16-
; CHECK-PWR8-NEXT: mtfsb0 10
17-
; CHECK-PWR8-NEXT: blr
18-
;
19-
; CHECK-NOVSX-LABEL: mtfsb0:
20-
; CHECK-NOVSX: # %bb.0: # %entry
21-
; CHECK-NOVSX-NEXT: mtfsb0 10
22-
; CHECK-NOVSX-NEXT: blr
23-
;
24-
; CHECK-PWR7-LABEL: mtfsb0:
25-
; CHECK-PWR7: # %bb.0: # %entry
26-
; CHECK-PWR7-NEXT: mtfsb0 10
27-
; CHECK-PWR7-NEXT: blr
28-
entry:
29-
tail call void @llvm.ppc.mtfsb0(i32 10)
30-
ret void
31-
}
32-
33-
declare void @llvm.ppc.mtfsb0(i32 immarg) #1
34-
35-
define dso_local void @mtfsb1() {
36-
; CHECK-PWR8-LABEL: mtfsb1:
37-
; CHECK-PWR8: # %bb.0: # %entry
38-
; CHECK-PWR8-NEXT: mtfsb1 0
39-
; CHECK-PWR8-NEXT: blr
40-
;
41-
; CHECK-NOVSX-LABEL: mtfsb1:
42-
; CHECK-NOVSX: # %bb.0: # %entry
43-
; CHECK-NOVSX-NEXT: mtfsb1 0
44-
; CHECK-NOVSX-NEXT: blr
45-
;
46-
; CHECK-PWR7-LABEL: mtfsb1:
47-
; CHECK-PWR7: # %bb.0: # %entry
48-
; CHECK-PWR7-NEXT: mtfsb1 0
49-
; CHECK-PWR7-NEXT: blr
50-
entry:
51-
tail call void @llvm.ppc.mtfsb1(i32 0)
52-
ret void
53-
}
54-
55-
declare void @llvm.ppc.mtfsb1(i32 immarg) #1
56-
5713
define dso_local double @fmsub_t0(double %d, double %d2, double %d3) {
5814
; CHECK-PWR8-LABEL: fmsub_t0:
5915
; CHECK-PWR8: # %bb.0: # %entry
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | \
3+
; RUN: FileCheck %s
4+
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix -mcpu=pwr7 \
5+
; RUN: < %s | FileCheck %s --check-prefix=CHECK-AIX64
6+
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr8 < %s | \
7+
; RUN: FileCheck %s --check-prefix=CHECK-AIX32
8+
9+
define dso_local void @mtfsb0() local_unnamed_addr #0 {
10+
; CHECK-PWR8-LABEL: mtfsb0:
11+
; CHECK-PWR8: # %bb.0: # %entry
12+
; CHECK-PWR8-NEXT: mtfsb0 10
13+
; CHECK-PWR8-NEXT: blr
14+
;
15+
; CHECK-PWR7-LABEL: mtfsb0:
16+
; CHECK-PWR7: # %bb.0: # %entry
17+
; CHECK-PWR7-NEXT: mtfsb0 10
18+
; CHECK-PWR7-NEXT: blr
19+
; CHECK-LABEL: mtfsb0:
20+
; CHECK: # %bb.0: # %entry
21+
; CHECK-NEXT: mtfsb0 10
22+
; CHECK-NEXT: blr
23+
;
24+
; CHECK-AIX64-LABEL: mtfsb0:
25+
; CHECK-AIX64: # %bb.0: # %entry
26+
; CHECK-AIX64-NEXT: mtfsb0 10
27+
; CHECK-AIX64-NEXT: blr
28+
;
29+
; CHECK-AIX32-LABEL: mtfsb0:
30+
; CHECK-AIX32: # %bb.0: # %entry
31+
; CHECK-AIX32-NEXT: mtfsb0 10
32+
; CHECK-AIX32-NEXT: blr
33+
entry:
34+
tail call void @llvm.ppc.mtfsb0(i32 10)
35+
ret void
36+
}
37+
38+
define dso_local void @mtfsb1() local_unnamed_addr #0 {
39+
; CHECK-PWR8-LABEL: mtfsb1:
40+
; CHECK-PWR8: # %bb.0: # %entry
41+
; CHECK-PWR8-NEXT: mtfsb1 0
42+
; CHECK-PWR8-NEXT: blr
43+
;
44+
; CHECK-PWR7-LABEL: mtfsb1:
45+
; CHECK-PWR7: # %bb.0: # %entry
46+
; CHECK-PWR7-NEXT: mtfsb1 0
47+
; CHECK-PWR7-NEXT: blr
48+
; CHECK-LABEL: mtfsb1:
49+
; CHECK: # %bb.0: # %entry
50+
; CHECK-NEXT: mtfsb1 0
51+
; CHECK-NEXT: blr
52+
;
53+
; CHECK-AIX64-LABEL: mtfsb1:
54+
; CHECK-AIX64: # %bb.0: # %entry
55+
; CHECK-AIX64-NEXT: mtfsb1 0
56+
; CHECK-AIX64-NEXT: blr
57+
;
58+
; CHECK-AIX32-LABEL: mtfsb1:
59+
; CHECK-AIX32: # %bb.0: # %entry
60+
; CHECK-AIX32-NEXT: mtfsb1 0
61+
; CHECK-AIX32-NEXT: blr
62+
entry:
63+
tail call void @llvm.ppc.mtfsb1(i32 0)
64+
ret void
65+
}
66+
67+
define dso_local void @callmtfsf(i32 zeroext %a) local_unnamed_addr {
68+
; CHECK-LABEL: callmtfsf:
69+
; CHECK: # %bb.0: # %entry
70+
; CHECK-NEXT: mtfprwz 0, 3
71+
; CHECK-NEXT: xscvuxddp 0, 0
72+
; CHECK-NEXT: mtfsf 7, 0
73+
; CHECK-NEXT: blr
74+
;
75+
; CHECK-AIX64-LABEL: callmtfsf:
76+
; CHECK-AIX64: # %bb.0: # %entry
77+
; CHECK-AIX64-NEXT: addi 4, 1, -4
78+
; CHECK-AIX64-NEXT: stw 3, -4(1)
79+
; CHECK-AIX64-NEXT: lfiwzx 0, 0, 4
80+
; CHECK-AIX64-NEXT: xscvuxddp 0, 0
81+
; CHECK-AIX64-NEXT: mtfsf 7, 0
82+
; CHECK-AIX64-NEXT: blr
83+
;
84+
; CHECK-AIX32-LABEL: callmtfsf:
85+
; CHECK-AIX32: # %bb.0: # %entry
86+
; CHECK-AIX32-NEXT: addi 4, 1, -4
87+
; CHECK-AIX32-NEXT: stw 3, -4(1)
88+
; CHECK-AIX32-NEXT: lfiwzx 0, 0, 4
89+
; CHECK-AIX32-NEXT: xscvuxddp 0, 0
90+
; CHECK-AIX32-NEXT: mtfsf 7, 0
91+
; CHECK-AIX32-NEXT: blr
92+
entry:
93+
%0 = uitofp i32 %a to double
94+
tail call void @llvm.ppc.mtfsf(i32 7, double %0)
95+
ret void
96+
}
97+
98+
define dso_local void @callmtfsfi(i32 zeroext %a) local_unnamed_addr {
99+
; CHECK-LABEL: callmtfsfi:
100+
; CHECK: # %bb.0: # %entry
101+
; CHECK-NEXT: mtfsfi 1, 3
102+
; CHECK-NEXT: blr
103+
;
104+
; CHECK-AIX64-LABEL: callmtfsfi:
105+
; CHECK-AIX64: # %bb.0: # %entry
106+
; CHECK-AIX64-NEXT: mtfsfi 1, 3
107+
; CHECK-AIX64-NEXT: blr
108+
;
109+
; CHECK-AIX32-LABEL: callmtfsfi:
110+
; CHECK-AIX32: # %bb.0: # %entry
111+
; CHECK-AIX32-NEXT: mtfsfi 1, 3
112+
; CHECK-AIX32-NEXT: blr
113+
entry:
114+
tail call void @llvm.ppc.mtfsfi(i32 1, i32 3)
115+
ret void
116+
}
117+
118+
declare void @llvm.ppc.mtfsb0(i32)
119+
declare void @llvm.ppc.mtfsb1(i32)
120+
declare void @llvm.ppc.mtfsfi(i32, i32)
121+
declare void @llvm.ppc.mtfsf(i32, double)

0 commit comments

Comments
 (0)