Index: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3581,16 +3581,20 @@ } else { // The 32 bit and 64 bit instructions are quite different. if (SpecialShift32) { - // Left shifts use (N, 0, 31-N), right shifts use (32-N, N, 31). - uint64_t SH = RightShift ? 32 - ShAmt : ShAmt; + // Left shifts use (N, 0, 31-N). + // Right shifts use (32-N, N, 31) if 0 < N < 32. + // use (0, 0, 31) if N == 0. + uint64_t SH = ShAmt == 0 ? 0 : RightShift ? 32 - ShAmt : ShAmt; uint64_t MB = RightShift ? ShAmt : 0; uint64_t ME = RightShift ? 31 : 31 - ShAmt; replaceInstrOperandWithImm(MI, III.OpNoForForwarding, SH); MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(MB) .addImm(ME); } else { - // Left shifts use (N, 63-N), right shifts use (64-N, N). - uint64_t SH = RightShift ? 64 - ShAmt : ShAmt; + // Left shifts use (N, 63-N). + // Right shifts use (64-N, N) if 0 < N < 64. + // use (0, 0) if N == 0. + uint64_t SH = ShAmt == 0 ? 0 : RightShift ? 64 - ShAmt : ShAmt; uint64_t ME = RightShift ? ShAmt : 63 - ShAmt; replaceInstrOperandWithImm(MI, III.OpNoForForwarding, SH); MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(ME); Index: llvm/test/CodeGen/PowerPC/sh-overflow.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/sh-overflow.mir @@ -0,0 +1,157 @@ +# RUN: llc -O3 -mtriple=powerpc64le-unknown-linux-gnu -start-before ppc-mi-peepholes -ppc-asm-full-reg-names -verify-machineinstrs %s -o - | FileCheck %s + +--- | + ; ModuleID = 'convert-rr-to-ri-instrs.ll' + source_filename = "convert-rr-to-ri-instrs.ll" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; PowerPC Pre-Emit Peephole converts + ; renamable $r4 = LI 0 + ; renamable $r5 = SRW renamable $r3, renamable $r4 + ; to + ; renamable $r4 = LI 0 + ; renamable $r5 = RLWINM renamable $r3, 32, 0, 31 + ; so the assertion fails in assembly printing stage. The fix convert it to + ; renamable $r4 = LI 0 + ; renamable $r5 = RLWINM renamable $r3, 0, 0, 31 + ; instead. + define void @special_right_shift32_0() { + bb: + %tmp = load i32, i32* undef, align 4 + br label %bb1 + + bb1: ; preds = %bb8, %bb + %tmp3 = phi i32 [ %tmp9, %bb8 ], [ 0, %bb ] + %tmp4 = shl i32 1, %tmp3 + %tmp5 = and i32 %tmp, %tmp4 + %tmp6 = icmp eq i32 %tmp5, 0 + br i1 %tmp6, label %bb8, label %bb7 + + bb7: ; preds = %bb1 + unreachable + + bb8: ; preds = %bb1 + %tmp9 = add nuw nsw i32 %tmp3, 1 + br label %bb1 + } + + ; PowerPC Pre-Emit Peephole converts + ; renamable $x4 = LI8 0 + ; renamable $x5 = SRD renamable $x3, renamable $r4 + ; to + ; renamable $x4 = LI8 0 + ; renamable $x5 = RLDICL renamable $x3, 64, 0 + ; so the assertion fails in assembly printing stage. The fix convert it to + ; renamable $x4 = LI8 0 + ; renamable $x5 = RLDICL renamable $x3, 0, 0 + ; instead. + define void @special_right_shift64_0() { + bb: + %tmp = load i64, i64* undef, align 4 + br label %bb1 + + bb1: ; preds = %bb8, %bb + %tmp3 = phi i64 [ %tmp9, %bb8 ], [ 0, %bb ] + %tmp4 = shl i64 1, %tmp3 + %tmp5 = and i64 %tmp, %tmp4 + %tmp6 = icmp eq i64 %tmp5, 0 + br i1 %tmp6, label %bb8, label %bb7 + + bb7: ; preds = %bb1 + unreachable + + bb8: ; preds = %bb1 + %tmp9 = add nuw nsw i64 %tmp3, 1 + br label %bb1 + } + +... +--- +name: special_right_shift32_0 +alignment: 4 +tracksRegLiveness: true +registers: + - { id: 0, class: gprc } + - { id: 1, class: gprc_and_gprc_nor0 } + - { id: 2, class: gprc } + - { id: 3, class: gprc } + - { id: 4, class: g8rc_and_g8rc_nox0 } + - { id: 5, class: gprc } + - { id: 6, class: crbitrc } + - { id: 7, class: gprc } +frameInfo: + maxAlignment: 1 +machineFunctionInfo: {} +body: | + bb.0.bb: + %4:g8rc_and_g8rc_nox0 = IMPLICIT_DEF + %0:gprc = LWZ 0, killed %4 :: (load 4 from `i32* undef`) + %3:gprc = LI 0 + + bb.1.bb1: + successors: %bb.3(0x7fffffff), %bb.2(0x00000001) + + %1:gprc_and_gprc_nor0 = PHI %3, %bb.0, %2, %bb.3 + ; CHECK-LABEL: special_right_shift32_0: + ; CHECK: slwi r[[#]], r[[#]], 0 + %5:gprc = SRW %0, %1 + %7:gprc = ANDIo %5, 1, implicit-def $cr0 + %6:crbitrc = COPY $cr0gt + BCn killed %6, %bb.3 + B %bb.2 + + bb.2.bb7: + successors: + + + bb.3.bb8: + %2:gprc = nuw nsw ADDI %1, 1 + B %bb.1 + +... +--- +name: special_right_shift64_0 +alignment: 4 +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc_and_g8rc_nox0 } + - { id: 2, class: g8rc } + - { id: 3, class: g8rc } + - { id: 4, class: g8rc_and_g8rc_nox0 } + - { id: 5, class: gprc } + - { id: 6, class: g8rc } + - { id: 7, class: crbitrc } + - { id: 8, class: g8rc } +frameInfo: + maxAlignment: 1 +machineFunctionInfo: {} +body: | + bb.0.bb: + %4:g8rc_and_g8rc_nox0 = IMPLICIT_DEF + %0:g8rc = LD 0, killed %4 :: (load 8 from `i64* undef`, align 4) + %3:g8rc = LI8 0 + + bb.1.bb1: + successors: %bb.3(0x7fffffff), %bb.2(0x00000001) + + %1:g8rc_and_g8rc_nox0 = PHI %3, %bb.0, %2, %bb.3 + %5:gprc = COPY %1.sub_32 + ; CHECK-LABEL: special_right_shift64_0: + ; CHECK: rotldi r[[#]], r[[#]], 0 + %6:g8rc = SRD %0, killed %5 + %8:g8rc = ANDIo8 %6, 1, implicit-def $cr0 + %7:crbitrc = COPY $cr0gt + BCn killed %7, %bb.3 + B %bb.2 + + bb.2.bb7: + successors: + + + bb.3.bb8: + %2:g8rc = nuw nsw ADDI8 %1, 1 + B %bb.1 + +...