]> granicus.if.org Git - llvm/commitdiff
[SelectionDAG] try to convert funnel shift directly to rotate if legal
authorSanjay Patel <spatel@rotateright.com>
Wed, 25 Jul 2018 21:38:30 +0000 (21:38 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 25 Jul 2018 21:38:30 +0000 (21:38 +0000)
If the DAGCombiner's rotate matching was working as expected,
I don't think we'd see any test diffs here.

This sidesteps the issue of custom lowering for rotates raised in PR38243:
https://bugs.llvm.org/show_bug.cgi?id=38243
...by only dealing with legal operations.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337966 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/ISDOpcodes.h
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
test/CodeGen/AArch64/funnel-shift-rot.ll
test/CodeGen/PowerPC/funnel-shift-rot.ll
test/CodeGen/X86/funnel-shift-rot.ll

index 14084e6e1bffbfeefad3ab662704d42c16338d6b..80bd796d53749a8499b7904b03891ed19a0f3fc0 100644 (file)
@@ -377,6 +377,8 @@ namespace ISD {
     /// When the 1st operand is a vector, the shift amount must be in the same
     /// type. (TLI.getShiftAmountTy() will return the same type when the input
     /// type is a vector.)
+    /// For rotates, the shift amount is treated as an unsigned amount modulo
+    /// the element size of the first operand.
     SHL, SRA, SRL, ROTL, ROTR,
 
     /// Byte Swap and Counting operators.
index b9c7a8f5bc332cc01d6b12d06aca960554435575..12ce222075b6943375d21960ea31e36f3defe51d 100644 (file)
@@ -5672,7 +5672,16 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
     SDValue Z = getValue(I.getArgOperand(2));
     EVT VT = X.getValueType();
 
-    // TODO: When X == Y, this is rotate. Create the node directly if legal.
+    // When X == Y, this is rotate. Create the node directly if legal.
+    // TODO: This should also be done if the operation is custom, but we have
+    // to make sure targets are handling the modulo shift amount as expected.
+    // TODO: If the rotate direction (left or right) corresponding to the shift
+    // is not available, adjust the shift value and invert the direction.
+    auto RotateOpcode = IsFSHL ? ISD::ROTL : ISD::ROTR;
+    if (X == Y && TLI.isOperationLegal(RotateOpcode, VT)) {
+      setValue(&I, DAG.getNode(RotateOpcode, sdl, VT, X, Z));
+      return nullptr;
+    }
 
     // Get the shift amount and inverse shift amount, modulo the bit-width.
     SDValue BitWidthC = DAG.getConstant(VT.getScalarSizeInBits(), sdl, VT);
index 0b3bc665bdf65dee4b40b609e4c374273fc9ce3c..af612eafd33355df05988f54a345474799e4fa1c 100644 (file)
@@ -163,11 +163,7 @@ define i32 @rotr_i32(i32 %x, i32 %z) {
 define i64 @rotr_i64(i64 %x, i64 %z) {
 ; CHECK-LABEL: rotr_i64:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    orr w9, wzr, #0x40
-; CHECK-NEXT:    sub w9, w9, w1
-; CHECK-NEXT:    lsr x8, x0, x1
-; CHECK-NEXT:    lsl x9, x0, x9
-; CHECK-NEXT:    orr x0, x9, x8
+; CHECK-NEXT:    ror x0, x0, x1
 ; CHECK-NEXT:    ret
   %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)
   ret i64 %f
index b238504edc1e0f71b265738c6a28fb69908a7013..d93c9361b35bdc5e1e227e2c53662d434282e60f 100644 (file)
@@ -55,7 +55,6 @@ define i16 @rotl_i16(i16 %x, i16 %z) {
 define i32 @rotl_i32(i32 %x, i32 %z) {
 ; CHECK-LABEL: rotl_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    rlwinm 4, 4, 0, 27, 31
 ; CHECK-NEXT:    rlwnm 3, 3, 4, 0, 31
 ; CHECK-NEXT:    blr
   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)
@@ -65,8 +64,7 @@ define i32 @rotl_i32(i32 %x, i32 %z) {
 define i64 @rotl_i64(i64 %x, i64 %z) {
 ; CHECK-LABEL: rotl_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    rlwinm 4, 4, 0, 26, 31
-; CHECK-NEXT:    rotld 3, 3, 4
+; CHECK-NEXT:    rldcl 3, 3, 4, 0
 ; CHECK-NEXT:    blr
   %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
   ret i64 %f
index 2cdea080eeae36ffddfff7b4198ab3891a48e12a..edbdd8d9b927bc2cb834772449f40f1cd1b8c4a8 100644 (file)
@@ -169,12 +169,12 @@ define i8 @rotr_i8_const_shift(i8 %x) nounwind {
 ; X32-SSE2-LABEL: rotr_i8_const_shift:
 ; X32-SSE2:       # %bb.0:
 ; X32-SSE2-NEXT:    movb {{[0-9]+}}(%esp), %al
-; X32-SSE2-NEXT:    rolb $5, %al
+; X32-SSE2-NEXT:    rorb $3, %al
 ; X32-SSE2-NEXT:    retl
 ;
 ; X64-AVX2-LABEL: rotr_i8_const_shift:
 ; X64-AVX2:       # %bb.0:
-; X64-AVX2-NEXT:    rolb $5, %dil
+; X64-AVX2-NEXT:    rorb $3, %dil
 ; X64-AVX2-NEXT:    movl %edi, %eax
 ; X64-AVX2-NEXT:    retq
   %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3)
@@ -185,12 +185,12 @@ define i32 @rotr_i32_const_shift(i32 %x) nounwind {
 ; X32-SSE2-LABEL: rotr_i32_const_shift:
 ; X32-SSE2:       # %bb.0:
 ; X32-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X32-SSE2-NEXT:    roll $29, %eax
+; X32-SSE2-NEXT:    rorl $3, %eax
 ; X32-SSE2-NEXT:    retl
 ;
 ; X64-AVX2-LABEL: rotr_i32_const_shift:
 ; X64-AVX2:       # %bb.0:
-; X64-AVX2-NEXT:    roll $29, %edi
+; X64-AVX2-NEXT:    rorl $3, %edi
 ; X64-AVX2-NEXT:    movl %edi, %eax
 ; X64-AVX2-NEXT:    retq
   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3)