Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5703,14 +5703,21 @@ if (X == Y && isPowerOf2_32(VT.getScalarSizeInBits())) { // 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 (TLI.isOperationLegal(RotateOpcode, VT)) { setValue(&I, DAG.getNode(RotateOpcode, sdl, VT, X, Z)); return nullptr; } + + // Some targets only rotate one way. Try the opposite direction. + RotateOpcode = IsFSHL ? ISD::ROTR : ISD::ROTL; + if (TLI.isOperationLegal(RotateOpcode, VT)) { + // Negate the shift amount because it is safe to ignore the high bits. + SDValue NegShAmt = DAG.getNode(ISD::SUB, sdl, VT, Zero, Z); + setValue(&I, DAG.getNode(RotateOpcode, sdl, VT, X, NegShAmt)); + return nullptr; + } + // fshl (rotl): (X << (Z % BW)) | (X >> ((0 - Z) % BW)) // fshr (rotr): (X << ((0 - Z) % BW)) | (X >> (Z % BW)) SDValue NegZ = DAG.getNode(ISD::SUB, sdl, VT, Zero, Z); Index: llvm/trunk/test/CodeGen/AArch64/funnel-shift-rot.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/funnel-shift-rot.ll +++ llvm/trunk/test/CodeGen/AArch64/funnel-shift-rot.ll @@ -65,10 +65,8 @@ define i64 @rotl_i64(i64 %x, i64 %z) { ; CHECK-LABEL: rotl_i64: ; CHECK: // %bb.0: -; CHECK-NEXT: neg w9, w1 -; CHECK-NEXT: lsl x8, x0, x1 -; CHECK-NEXT: lsr x9, x0, x9 -; CHECK-NEXT: orr x0, x8, x9 +; CHECK-NEXT: neg x8, x1 +; CHECK-NEXT: ror x0, x0, x8 ; CHECK-NEXT: ret %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z) ret i64 %f Index: llvm/trunk/test/CodeGen/PowerPC/funnel-shift-rot.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/funnel-shift-rot.ll +++ llvm/trunk/test/CodeGen/PowerPC/funnel-shift-rot.ll @@ -145,7 +145,6 @@ ; CHECK-LABEL: rotr_i32: ; CHECK: # %bb.0: ; CHECK-NEXT: neg 4, 4 -; CHECK-NEXT: clrlwi 4, 4, 27 ; CHECK-NEXT: rlwnm 3, 3, 4, 0, 31 ; CHECK-NEXT: blr %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z) @@ -156,8 +155,7 @@ ; CHECK-LABEL: rotr_i64: ; CHECK: # %bb.0: ; CHECK-NEXT: neg 4, 4 -; 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.fshr.i64(i64 %x, i64 %x, i64 %z) ret i64 %f