[ARM] Prevent large integer VQDMULH pattern crashes
authorDavid Green <david.green@arm.com>
Sat, 18 Sep 2021 17:47:02 +0000 (18:47 +0100)
committerDavid Green <david.green@arm.com>
Sat, 18 Sep 2021 17:47:02 +0000 (18:47 +0100)
Put a limit on the size of constant integers we test when looking for
VQDMULH, to prevent it from crashing from values more than 64bits.

llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/test/CodeGen/Thumb2/mve-vqdmulh.ll

index 3585921..cc66414 100644 (file)
@@ -12946,7 +12946,7 @@ static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG) {
   SDValue Shft;
   ConstantSDNode *Clamp;
 
-  if (!VT.isVector())
+  if (!VT.isVector() || VT.getScalarSizeInBits() > 64)
     return SDValue();
 
   if (N->getOpcode() == ISD::SMIN) {
index ef7786c..9192e3f 100644 (file)
@@ -499,6 +499,74 @@ for.cond.cleanup:                                 ; preds = %vector.body
   ret void
 }
 
+define <2 x i64> @large_i128(<2 x double> %x) {
+; CHECK-LABEL: large_i128:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    .save {r4, r5, r6, r7, r8, r9, lr}
+; CHECK-NEXT:    push.w {r4, r5, r6, r7, r8, r9, lr}
+; CHECK-NEXT:    .pad #4
+; CHECK-NEXT:    sub sp, #4
+; CHECK-NEXT:    mov r8, r3
+; CHECK-NEXT:    mov r5, r2
+; CHECK-NEXT:    bl __fixdfti
+; CHECK-NEXT:    subs r7, r2, #1
+; CHECK-NEXT:    mov.w r9, #1
+; CHECK-NEXT:    sbcs r7, r3, #0
+; CHECK-NEXT:    mov.w r4, #0
+; CHECK-NEXT:    mov.w r7, #0
+; CHECK-NEXT:    it lt
+; CHECK-NEXT:    movlt r7, #1
+; CHECK-NEXT:    cmp r7, #0
+; CHECK-NEXT:    csel r0, r0, r7, ne
+; CHECK-NEXT:    csel r3, r3, r7, ne
+; CHECK-NEXT:    csel r2, r2, r9, ne
+; CHECK-NEXT:    csel r1, r1, r7, ne
+; CHECK-NEXT:    rsbs r7, r0, #0
+; CHECK-NEXT:    sbcs.w r7, r4, r1
+; CHECK-NEXT:    sbcs.w r2, r4, r2
+; CHECK-NEXT:    sbcs.w r2, r4, r3
+; CHECK-NEXT:    mov.w r2, #0
+; CHECK-NEXT:    it lt
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    csel r6, r0, r2, ne
+; CHECK-NEXT:    csel r7, r1, r2, ne
+; CHECK-NEXT:    mov r0, r5
+; CHECK-NEXT:    mov r1, r8
+; CHECK-NEXT:    bl __fixdfti
+; CHECK-NEXT:    subs r5, r2, #1
+; CHECK-NEXT:    sbcs r5, r3, #0
+; CHECK-NEXT:    mov.w r5, #0
+; CHECK-NEXT:    it lt
+; CHECK-NEXT:    movlt r5, #1
+; CHECK-NEXT:    cmp r5, #0
+; CHECK-NEXT:    csel r0, r0, r5, ne
+; CHECK-NEXT:    csel r3, r3, r5, ne
+; CHECK-NEXT:    csel r2, r2, r9, ne
+; CHECK-NEXT:    csel r1, r1, r5, ne
+; CHECK-NEXT:    rsbs r5, r0, #0
+; CHECK-NEXT:    sbcs.w r5, r4, r1
+; CHECK-NEXT:    sbcs.w r2, r4, r2
+; CHECK-NEXT:    sbcs.w r2, r4, r3
+; CHECK-NEXT:    it lt
+; CHECK-NEXT:    movlt r4, #1
+; CHECK-NEXT:    cmp r4, #0
+; CHECK-NEXT:    csel r2, r0, r4, ne
+; CHECK-NEXT:    csel r3, r1, r4, ne
+; CHECK-NEXT:    mov r0, r6
+; CHECK-NEXT:    mov r1, r7
+; CHECK-NEXT:    add sp, #4
+; CHECK-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, pc}
+entry:
+  %conv = fptosi <2 x double> %x to <2 x i128>
+  %0 = icmp slt <2 x i128> %conv, <i128 18446744073709551616, i128 18446744073709551616>
+  %spec.store.select = select <2 x i1> %0, <2 x i128> %conv, <2 x i128> <i128 18446744073709551616, i128 18446744073709551616>
+  %1 = icmp sgt <2 x i128> %spec.store.select, zeroinitializer
+  %spec.store.select7 = select <2 x i1> %1, <2 x i128> %spec.store.select, <2 x i128> zeroinitializer
+  %conv6 = trunc <2 x i128> %spec.store.select7 to <2 x i64>
+  ret <2 x i64> %conv6
+}
+
 declare i64 @llvm.vector.reduce.add.v4i64(<4 x i64>)
 declare i32 @llvm.vector.reduce.add.v8i32(<8 x i32>)
 declare i32 @llvm.vector.reduce.add.v16i32(<16 x i32>)