[SystemZ] Do not use glue to represent condition code dependencies
Currently, an instruction setting the condition code is linked to
the instruction using the condition code via a "glue" link in the
SelectionDAG. This has a number of drawbacks; in particular, it
means the same CC cannot be used by multiple users. It also makes
it more difficult to efficiently implement SADDO et. al.
This patch changes the back-end to represent CC dependencies as
normal values during SelectionDAG matching, along the lines of
how this is handled in the X86 back-end already.
In addition to the core mechanics of updating all relevant patterns,
this requires a number of additional changes:
- We now need to be able to spill/restore a CC value into a GPR
if necessary. This means providing a copyPhysReg implementation
for moves involving CC, and defining getCrossCopyRegClass.
- Since we still prefer to avoid such spills, we provide an override
for IsProfitableToFold to avoid creating a merged LOAD / ICMP if
this would result in multiple users of the CC.
- combineCCMask no longer requires a single CC user, and no longer
need to be careful about preventing invalid glue/chain cycles.
- emitSelect needs to be more careful in marking CC live-in to
the basic block it generates. Also, we can now optimize the
case of multiple subsequent selects with the same condition
just like X86 does.
llvm-svn: 331202
diff --git a/llvm/test/CodeGen/SystemZ/cond-move-02.ll b/llvm/test/CodeGen/SystemZ/cond-move-02.ll
index 2e2bacd..ea0ef983 100644
--- a/llvm/test/CodeGen/SystemZ/cond-move-02.ll
+++ b/llvm/test/CodeGen/SystemZ/cond-move-02.ll
@@ -4,9 +4,9 @@
define i32 @f1(i32 %x) {
; CHECK-LABEL: f1:
-; CHECK: lhi [[REG:%r[0-5]]], 0
; CHECK: chi %r2, 0
-; CHECK: lochilh [[REG]], 42
+; CHECK: lhi %r2, 0
+; CHECK: lochilh %r2, 42
; CHECK: br %r14
%cond = icmp ne i32 %x, 0
%res = select i1 %cond, i32 42, i32 0
@@ -35,9 +35,9 @@
define i64 @f4(i64 %x) {
; CHECK-LABEL: f4:
-; CHECK: lghi [[REG:%r[0-5]]], 0
; CHECK: cghi %r2, 0
-; CHECK: locghilh [[REG]], 42
+; CHECK: lghi %r2, 0
+; CHECK: locghilh %r2, 42
; CHECK: br %r14
%cond = icmp ne i64 %x, 0
%res = select i1 %cond, i64 42, i64 0
diff --git a/llvm/test/CodeGen/SystemZ/int-cmp-48.ll b/llvm/test/CodeGen/SystemZ/int-cmp-48.ll
index 821283d..c68a673 100644
--- a/llvm/test/CodeGen/SystemZ/int-cmp-48.ll
+++ b/llvm/test/CodeGen/SystemZ/int-cmp-48.ll
@@ -28,9 +28,8 @@
; Check that we do not fold across an aliasing store.
define void @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK: llc [[REG:%r[0-5]]], 0(%r2)
-; CHECK-DAG: mvi 0(%r2), 0
-; CHECK-DAG: tmll [[REG]], 1
+; CHECK: tm 0(%r2), 1
+; CHECK: mvi 0(%r2), 0
; CHECK: ber %r14
; CHECK: br %r14
entry:
diff --git a/llvm/test/CodeGen/SystemZ/int-cmp-55.ll b/llvm/test/CodeGen/SystemZ/int-cmp-55.ll
new file mode 100644
index 0000000..5028784
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/int-cmp-55.ll
@@ -0,0 +1,19 @@
+; Check that we don't insert unnecessary CC spills
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu
+
+declare signext i32 @f()
+
+define signext i32 @test(i32* %ptr) {
+; CHECK-NOT: ipm
+
+entry:
+ %0 = load i32, i32* %ptr, align 4
+ %tobool = icmp eq i32 %0, 0
+ %call = tail call signext i32 @f()
+ %1 = icmp slt i32 %call, 40
+ %2 = or i1 %tobool, %1
+ %retv = select i1 %2, i32 %call, i32 40
+ ret i32 %retv
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/multiselect.ll b/llvm/test/CodeGen/SystemZ/multiselect.ll
new file mode 100644
index 0000000..d2078ff
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/multiselect.ll
@@ -0,0 +1,21 @@
+; Test that multiple select statements using the same condition are expanded
+; into a single conditional branch.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+define void @test(i32 signext %positive, double %base, double %offset, double* %rmin, double* %rmax) {
+entry:
+; CHECK: cijlh %r2, 0,
+; CHECK-NOT: cij
+; CHECK-NOT: je
+; CHECK-NOT: jlh
+
+ %tobool = icmp eq i32 %positive, 0
+ %add = fadd double %base, %offset
+ %min = select i1 %tobool, double %add, double %base
+ %max = select i1 %tobool, double %base, double %add
+ store double %min, double* %rmin, align 8
+ store double %max, double* %rmax, align 8
+ ret void
+}
+