Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9057,7 +9057,7 @@ unsigned NextOp = N0.getOpcode(); // fold (rot* (rot* x, c2), c1) - // -> (rot* x, ((c1 % bitsize) +- (c2 % bitsize)) % bitsize) + // -> (rot* x, ((c1 % bitsize) +- (c2 % bitsize) + bitsize) % bitsize) if (NextOp == ISD::ROTL || NextOp == ISD::ROTR) { SDNode *C1 = DAG.isConstantIntBuildVectorOrConstantInt(N1); SDNode *C2 = DAG.isConstantIntBuildVectorOrConstantInt(N0.getOperand(1)); @@ -9073,6 +9073,8 @@ if (Norm1 && Norm2) if (SDValue CombinedShift = DAG.FoldConstantArithmetic( CombineOp, dl, ShiftVT, {Norm1, Norm2})) { + CombinedShift = DAG.FoldConstantArithmetic(ISD::ADD, dl, ShiftVT, + {CombinedShift, BitsizeC}); SDValue CombinedShiftNorm = DAG.FoldConstantArithmetic( ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC}); return DAG.getNode(N->getOpcode(), dl, VT, N0->getOperand(0), Index: llvm/test/CodeGen/AArch64/rotate.ll =================================================================== --- llvm/test/CodeGen/AArch64/rotate.ll +++ llvm/test/CodeGen/AArch64/rotate.ll @@ -1,14 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64--linux-gnueabihf | FileCheck %s ;; This used to cause a backend crash about not being able to ;; select ROTL. Make sure if generates the basic ushr/shl. define <2 x i64> @testcase(ptr %in) { -; CHECK-LABEL: testcase -; CHECK: ushr {{v[0-9]+}}.2d -; CHECK: shl {{v[0-9]+}}.2d +; CHECK-LABEL: testcase: +; CHECK: // %bb.0: +; CHECK-NEXT: ldr q0, [x0] +; CHECK-NEXT: ushr v1.2d, v0.2d, #8 +; CHECK-NEXT: shl v0.2d, v0.2d, #56 +; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b +; CHECK-NEXT: ret %1 = load <2 x i64>, ptr %in %2 = lshr <2 x i64> %1, %3 = shl <2 x i64> %1, %4 = or <2 x i64> %2, %3 ret <2 x i64> %4 } + +;; This used to cause miscompile because rot combine +;; doesn't handle negative shift well. +define i5 @pr59898(i5 %x) { +; CHECK-LABEL: rotr_merge_i5: +; CHECK: // %bb.0: +; CHECK-NEXT: ubfx w8, w0, #1, #4 +; CHECK-NEXT: orr w0, w8, w0, lsl #4 +; CHECK-NEXT: ret + %r1 = call i5 @llvm.fshr.i5(i5 %x, i5 %x, i5 3) + %r2 = call i5 @llvm.fshl.i5(i5 %r1, i5 %r1, i5 2) + ret i5 %r2 +} + +declare i5 @llvm.fshl.i5(i5, i5, i5) +declare i5 @llvm.fshr.i5(i5, i5, i5)