diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1156,6 +1156,8 @@ setOperationAction(ISD::UMUL_LOHI, VT, Expand); setOperationAction(ISD::SMUL_LOHI, VT, Expand); setOperationAction(ISD::SELECT_CC, VT, Expand); + setOperationAction(ISD::ROTL, VT, Expand); + setOperationAction(ISD::ROTR, VT, Expand); } // Illegal unpacked integer vector types. diff --git a/llvm/test/CodeGen/AArch64/llvm-ir-to-intrinsic.ll b/llvm/test/CodeGen/AArch64/llvm-ir-to-intrinsic.ll --- a/llvm/test/CodeGen/AArch64/llvm-ir-to-intrinsic.ll +++ b/llvm/test/CodeGen/AArch64/llvm-ir-to-intrinsic.ll @@ -1075,3 +1075,134 @@ %cmp = icmp sgt %a, %b ret %cmp } + +; Funnel shifts +declare @llvm.fshl.nxv2i64(, , ) +declare @llvm.fshl.nxv4i64(, , ) +declare @llvm.fshr.nxv2i64(, , ) +define @fshl_i64( %a, %b, %c){ +; CHECK-LABEL: fshl_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z3.d, #-1 // =0xffffffffffffffff +; CHECK-NEXT: eor z3.d, z2.d, z3.d +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: lsr z1.d, z1.d, #1 +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: and z3.d, z3.d, #0x3f +; CHECK-NEXT: lsl z0.d, p0/m, z0.d, z2.d +; CHECK-NEXT: lsr z1.d, p0/m, z1.d, z3.d +; CHECK-NEXT: orr z0.d, z0.d, z1.d +; CHECK-NEXT: ret + %fshl = call @llvm.fshl.nxv2i64( %a, %b, %c) + ret %fshl +} + +define @fshl_illegal_i64( %a, %b, %c){ +; CHECK-LABEL: fshl_illegal_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z6.d, #-1 // =0xffffffffffffffff +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: eor z7.d, z5.d, z6.d +; CHECK-NEXT: and z5.d, z5.d, #0x3f +; CHECK-NEXT: lsl z1.d, p0/m, z1.d, z5.d +; CHECK-NEXT: eor z5.d, z4.d, z6.d +; CHECK-NEXT: lsr z2.d, z2.d, #1 +; CHECK-NEXT: lsr z3.d, z3.d, #1 +; CHECK-NEXT: and z4.d, z4.d, #0x3f +; CHECK-NEXT: and z5.d, z5.d, #0x3f +; CHECK-NEXT: and z7.d, z7.d, #0x3f +; CHECK-NEXT: lsl z0.d, p0/m, z0.d, z4.d +; CHECK-NEXT: lsr z2.d, p0/m, z2.d, z5.d +; CHECK-NEXT: lsr z3.d, p0/m, z3.d, z7.d +; CHECK-NEXT: orr z0.d, z0.d, z2.d +; CHECK-NEXT: orr z1.d, z1.d, z3.d +; CHECK-NEXT: ret + %fshl = call @llvm.fshl.nxv4i64( %a, %b, %c) + ret %fshl +} + +define @fshl_rot_i64( %a, %b){ +; CHECK-LABEL: fshl_rot_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z2.d, z1.d +; CHECK-NEXT: subr z1.d, z1.d, #0 // =0x0 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: and z1.d, z1.d, #0x3f +; CHECK-NEXT: lslr z2.d, p0/m, z2.d, z0.d +; CHECK-NEXT: lsr z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: orr z0.d, z2.d, z0.d +; CHECK-NEXT: ret + %fshl = call @llvm.fshl.nxv2i64( %a, %a, %b) + ret %fshl +} + + +define @fshl_rot_illegal_i64( %a, %b){ +; CHECK-LABEL: fshl_rot_illegal_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z4.d, z2.d +; CHECK-NEXT: subr z2.d, z2.d, #0 // =0x0 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: and z4.d, z4.d, #0x3f +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: lslr z4.d, p0/m, z4.d, z0.d +; CHECK-NEXT: lsr z0.d, p0/m, z0.d, z2.d +; CHECK-NEXT: mov z2.d, z3.d +; CHECK-NEXT: subr z3.d, z3.d, #0 // =0x0 +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: and z3.d, z3.d, #0x3f +; CHECK-NEXT: lslr z2.d, p0/m, z2.d, z1.d +; CHECK-NEXT: lsr z1.d, p0/m, z1.d, z3.d +; CHECK-NEXT: orr z0.d, z4.d, z0.d +; CHECK-NEXT: orr z1.d, z2.d, z1.d +; CHECK-NEXT: ret + %fshl = call @llvm.fshl.nxv4i64( %a, %a, %b) + ret %fshl +} + +define @fshl_rot_const_i64( %a){ +; CHECK-LABEL: fshl_rot_const_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: lsr z1.d, z0.d, #61 +; CHECK-NEXT: lsl z0.d, z0.d, #3 +; CHECK-NEXT: orr z0.d, z0.d, z1.d +; CHECK-NEXT: ret + %insert = insertelement poison, i64 3, i32 0 + %shuf = shufflevector %insert, poison, zeroinitializer + %fshl = call @llvm.fshl.nxv2i64( %a, %a, %shuf) + ret %fshl +} + +define @fshr_i64( %a, %b, %c){ +; CHECK-LABEL: fshr_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z3.d, #-1 // =0xffffffffffffffff +; CHECK-NEXT: eor z3.d, z2.d, z3.d +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: lsl z0.d, z0.d, #1 +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: and z3.d, z3.d, #0x3f +; CHECK-NEXT: lsr z1.d, p0/m, z1.d, z2.d +; CHECK-NEXT: lsl z0.d, p0/m, z0.d, z3.d +; CHECK-NEXT: orr z0.d, z0.d, z1.d +; CHECK-NEXT: ret + %fshr = call @llvm.fshr.nxv2i64( %a, %b, %c) + ret %fshr +} + +define @fshr_rot_i64( %a, %b){ +; CHECK-LABEL: fshr_rot_i64: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z2.d, z1.d +; CHECK-NEXT: subr z1.d, z1.d, #0 // =0x0 +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: and z2.d, z2.d, #0x3f +; CHECK-NEXT: and z1.d, z1.d, #0x3f +; CHECK-NEXT: lsrr z2.d, p0/m, z2.d, z0.d +; CHECK-NEXT: lsl z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: orr z0.d, z2.d, z0.d +; CHECK-NEXT: ret + %fshr = call @llvm.fshr.nxv2i64( %a, %a, %b) + ret %fshr +}