[PowerPC] Enforce side effects to FPSCR read/set intrinsics
authorQiu Chaofan <qiucofan@cn.ibm.com>
Thu, 4 Nov 2021 03:44:04 +0000 (11:44 +0800)
committerQiu Chaofan <qiucofan@cn.ibm.com>
Thu, 4 Nov 2021 03:45:32 +0000 (11:45 +0800)
Currently, FPSCR is not modeled, so in some early passes (such as
early-cse), the read/set intrinsics to FPSCR may get incorrect
simplification.

Reviewed By: jsji

Differential Revision: https://reviews.llvm.org/D112380

llvm/include/llvm/IR/IntrinsicsPowerPC.td
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/test/CodeGen/PowerPC/read-set-flm.ll

index 8b158aa..4161e3b 100644 (file)
@@ -31,10 +31,12 @@ let TargetPrefix = "ppc" in {  // All intrinsics start with "llvm.ppc.".
 
   // Get content from current FPSCR register
   def int_ppc_readflm : GCCBuiltin<"__builtin_readflm">,
-                        Intrinsic<[llvm_double_ty], [], [IntrNoMem]>;
+                        Intrinsic<[llvm_double_ty], [],
+                                  [IntrNoMerge, IntrHasSideEffects]>;
   // Set FPSCR register, and return previous content
   def int_ppc_setflm : GCCBuiltin<"__builtin_setflm">,
-                       Intrinsic<[llvm_double_ty], [llvm_double_ty], []>;
+                       Intrinsic<[llvm_double_ty], [llvm_double_ty],
+                                 [IntrHasSideEffects]>;
 
   // Intrinsics for [double]word extended forms of divide instructions
   def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">,
index 22f6464..3aaf5c3 100644 (file)
@@ -3108,14 +3108,14 @@ def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM),
              PPC970_DGroup_Single, PPC970_Unit_FPU;
 }
 
-let Defs = [RM] in {
+let Defs = [RM], hasSideEffects = 1 in {
   let isCodeGenOnly = 1 in
   def MTFSFb  : XFLForm<63, 711, (outs), (ins i32imm:$FM, f8rc:$rT),
                         "mtfsf $FM, $rT", IIC_IntMTFSB0,
                         [(int_ppc_mtfsf timm:$FM, f64:$rT)]>,
                 PPC970_DGroup_Single, PPC970_Unit_FPU;
 }
-let Uses = [RM] in {
+let Uses = [RM], hasSideEffects = 1 in {
   def MFFS   : XForm_42<63, 583, (outs f8rc:$rT), (ins),
                          "mffs $rT", IIC_IntMFFS,
                          [(set f64:$rT, (PPCmffs))]>,
@@ -4503,7 +4503,7 @@ def MCRFS : XLForm_3<63, 64, (outs crrc:$BF), (ins crrc:$BFA),
 // All MTFSF variants may change the rounding mode so conservatively set it
 // as an implicit def for all of them.
 let Predicates = [HasFPU] in {
-let Defs = [RM] in {
+let Defs = [RM], hasSideEffects = 1 in {
 let isCodeGenOnly = 1,
     Pattern = [(int_ppc_mtfsfi timm:$BF, timm:$U)], W = 0 in
 def MTFSFIb : XLForm_4<63, 134, (outs), (ins u3imm:$BF, u4imm:$U),
index aa651e1..1f4a905 100644 (file)
@@ -11,6 +11,7 @@ define double @in_nostrict(double %a, double %b, double %c, double %d) {
 ; CHECK-NEXT:    xsdivdp 1, 1, 2
 ; CHECK-NEXT:    xsadddp 1, 1, 3
 ; CHECK-NEXT:    xsadddp 0, 1, 0
+; CHECK-NEXT:    mffs 1
 ; CHECK-NEXT:    mtfsf 255, 4
 ; CHECK-NEXT:    xsdivdp 1, 3, 4
 ; CHECK-NEXT:    xsadddp 1, 1, 2
@@ -46,6 +47,7 @@ define double @in_strict(double %a, double %b, double %c, double %d) #0 {
 ; CHECK-NEXT:    xsdivdp 1, 1, 2
 ; CHECK-NEXT:    xsadddp 1, 1, 3
 ; CHECK-NEXT:    xsadddp 0, 1, 0
+; CHECK-NEXT:    mffs 1
 ; CHECK-NEXT:    mtfsf 255, 4
 ; CHECK-NEXT:    xsdivdp 1, 3, 4
 ; CHECK-NEXT:    xsadddp 1, 1, 2
@@ -74,9 +76,88 @@ entry:
   ret double %7
 }
 
+define void @cse_nomerge(double* %f1, double* %f2, double %f3) #0 {
+; CHECK-LABEL: cse_nomerge:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mflr 0
+; CHECK-NEXT:    .cfi_def_cfa_offset 64
+; CHECK-NEXT:    .cfi_offset lr, 16
+; CHECK-NEXT:    .cfi_offset r30, -24
+; CHECK-NEXT:    .cfi_offset f31, -8
+; CHECK-NEXT:    std 30, -24(1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd 31, -8(1) # 8-byte Folded Spill
+; CHECK-NEXT:    std 0, 16(1)
+; CHECK-NEXT:    stdu 1, -64(1)
+; CHECK-NEXT:    fmr 31, 1
+; CHECK-NEXT:    mr 30, 4
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    stfd 0, 0(3)
+; CHECK-NEXT:    bl effect_func
+; CHECK-NEXT:    nop
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    stfd 0, 0(30)
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    mtfsf 255, 31
+; CHECK-NEXT:    addi 1, 1, 64
+; CHECK-NEXT:    ld 0, 16(1)
+; CHECK-NEXT:    lfd 31, -8(1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld 30, -24(1) # 8-byte Folded Reload
+; CHECK-NEXT:    mtlr 0
+; CHECK-NEXT:    blr
+entry:
+  %0 = call double @llvm.ppc.readflm()
+  store double %0, double* %f1, align 8
+  call void @effect_func()
+  %1 = call double @llvm.ppc.readflm()
+  store double %1, double* %f2, align 8
+  %2 = call contract double @llvm.ppc.setflm(double %f3)
+  ret void
+}
+
+define void @cse_nomerge_readonly(double* %f1, double* %f2, double %f3) #0 {
+; CHECK-LABEL: cse_nomerge_readonly:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mflr 0
+; CHECK-NEXT:    .cfi_def_cfa_offset 64
+; CHECK-NEXT:    .cfi_offset lr, 16
+; CHECK-NEXT:    .cfi_offset r30, -24
+; CHECK-NEXT:    .cfi_offset f31, -8
+; CHECK-NEXT:    std 30, -24(1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd 31, -8(1) # 8-byte Folded Spill
+; CHECK-NEXT:    std 0, 16(1)
+; CHECK-NEXT:    stdu 1, -64(1)
+; CHECK-NEXT:    fmr 31, 1
+; CHECK-NEXT:    mr 30, 4
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    stfd 0, 0(3)
+; CHECK-NEXT:    bl readonly_func
+; CHECK-NEXT:    nop
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    stfd 0, 0(30)
+; CHECK-NEXT:    mffs 0
+; CHECK-NEXT:    mtfsf 255, 31
+; CHECK-NEXT:    addi 1, 1, 64
+; CHECK-NEXT:    ld 0, 16(1)
+; CHECK-NEXT:    lfd 31, -8(1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld 30, -24(1) # 8-byte Folded Reload
+; CHECK-NEXT:    mtlr 0
+; CHECK-NEXT:    blr
+entry:
+  %0 = call double @llvm.ppc.readflm()
+  store double %0, double* %f1, align 8
+  call void @readonly_func()
+  %1 = call double @llvm.ppc.readflm()
+  store double %1, double* %f2, align 8
+  %2 = call contract double @llvm.ppc.setflm(double %f3)
+  ret void
+}
+
+declare void @effect_func()
+declare void @readonly_func() #1
 declare double @llvm.ppc.readflm()
 declare double @llvm.ppc.setflm(double)
 declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
 declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
 
 attributes #0 = { strictfp }
+attributes #1 = { readonly }