[ARM] Ensure CSINC has one use in CSINV combine
authorDavid Green <david.green@arm.com>
Thu, 29 Apr 2021 09:59:14 +0000 (10:59 +0100)
committerDavid Green <david.green@arm.com>
Thu, 29 Apr 2021 09:59:14 +0000 (10:59 +0100)
Otherwise the CMP glue may be used in multiple nodes, needing to be
emitted multiple times. Currently this either increases instruction
count or fails as it attempt to insert the same node multiple times.

llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/test/CodeGen/Thumb2/csel.ll

index 24dded2..1ea4cb4 100644 (file)
@@ -12766,7 +12766,7 @@ static SDValue PerformSubCSINCCombine(SDNode *N,
   if (N->getValueType(0) != MVT::i32 || !isNullConstant(N->getOperand(0)))
     return SDValue();
   SDValue CSINC = N->getOperand(1);
-  if (CSINC.getOpcode() != ARMISD::CSINC)
+  if (CSINC.getOpcode() != ARMISD::CSINC || !CSINC.hasOneUse())
     return SDValue();
 
   ConstantSDNode *X = dyn_cast<ConstantSDNode>(CSINC.getOperand(0));
index 5a56fb6..137aef3 100644 (file)
@@ -336,3 +336,31 @@ entry:
   ret i32 %xor
 }
 
+define i32 @csinc_to_csinv(i32 %a) {
+; CHECK-LABEL: csinc_to_csinv:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    cmp r0, #46
+; CHECK-NEXT:    csetm r0, lt
+; CHECK-NEXT:    bx lr
+entry:
+  %cmp = icmp sgt i32 %a, 45
+  %spec.select = select i1 %cmp, i32 0, i32 1
+  %s = sub i32 0, %spec.select
+  ret i32 %s
+}
+
+define i32 @csinc_to_csinv_multi(i32 %a) {
+; CHECK-LABEL: csinc_to_csinv_multi:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    cmp r0, #46
+; CHECK-NEXT:    cset r0, lt
+; CHECK-NEXT:    rsbs r1, r0, #0
+; CHECK-NEXT:    eors r0, r1
+; CHECK-NEXT:    bx lr
+entry:
+  %cmp = icmp sgt i32 %a, 45
+  %spec.select = select i1 %cmp, i32 0, i32 1
+  %s = sub i32 0, %spec.select
+  %t = xor i32 %s, %spec.select
+  ret i32 %t
+}