diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp --- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -379,6 +379,7 @@ // Perform peephole optimizations. bool PPCMIPeephole::simplifyCode(void) { bool Simplified = false; + bool TrapOpt = false; MachineInstr* ToErase = nullptr; std::map TOCSaves; const TargetRegisterInfo *TRI = &TII->getRegisterInfo(); @@ -420,6 +421,13 @@ ToErase->eraseFromParent(); ToErase = nullptr; } + // If a conditional trap instruction got optimized to an + // unconditional trap, eliminate all the instructions between + // the trap and the terminator of the MBB. + if (TrapOpt && !MI.isTerminator()) { + ToErase = &MI; + continue; + } // Ignore debug instructions. if (MI.isDebugInstr()) @@ -997,6 +1005,49 @@ ++NumRotatesCollapsed; break; } + // We will replace TD/TW/TDI/TWI with an unconditional trap if it will + // always trap, we will delete the node if it will never trap. + case PPC::TDI: + case PPC::TWI: + case PPC::TD: + case PPC::TW: { + MachineInstr *LiMI1 = getVRegDefOrNull(&MI.getOperand(1), MRI); + MachineInstr *LiMI2 = getVRegDefOrNull(&MI.getOperand(2), MRI); + unsigned Opcode1 = LiMI1->getOpcode(); + unsigned Opcode2 = LiMI2->getOpcode(); + bool isOperand2Immeidate = MI.getOperand(2).isImm(); + // We can only do the optimization for the "reg + reg" form. + if (!(LiMI1 && (Opcode1 == PPC::LI || Opcode1 == PPC::LI8))) + break; + if (!isOperand2Immeidate && + !(LiMI2 && (Opcode2 == PPC::LI || Opcode2 == PPC::LI8))) + break; + + auto ImmOperand0 = MI.getOperand(0).getImm(); + auto ImmOperand1 = LiMI1->getOperand(1).getImm(); + auto ImmOperand2 = isOperand2Immeidate ? MI.getOperand(2).getImm() + : LiMI2->getOperand(1).getImm(); + + // We will replace the MI with an unconditional trap if it will always + // trap. + if ((ImmOperand0 == 31) || + ((ImmOperand0 & 0x10) && + ((int64_t)ImmOperand1 < (int64_t)ImmOperand2)) || + ((ImmOperand0 & 0x8) && + ((int64_t)ImmOperand1 > (int64_t)ImmOperand2)) || + ((ImmOperand0 & 0x2) && + ((uint64_t)ImmOperand1 < (uint64_t)ImmOperand2)) || + ((ImmOperand0 & 0x1) && + ((uint64_t)ImmOperand1 > (uint64_t)ImmOperand2)) || + ((ImmOperand0 & 0x4) && (ImmOperand1 == ImmOperand2))) { + BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::TRAP)); + TrapOpt = true; + } + // We will delete the MI if it will never trap. + ToErase = &MI; + Simplified = true; + break; + } } } @@ -1006,6 +1057,8 @@ ToErase->eraseFromParent(); ToErase = nullptr; } + // Reset TrapOpt to false at the end of the basic block. + TrapOpt = false; } // Eliminate all the TOC save instructions which are redundant. diff --git a/llvm/test/CodeGen/PowerPC/mi-peepholes-trap-opt.mir b/llvm/test/CodeGen/PowerPC/mi-peepholes-trap-opt.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/mi-peepholes-trap-opt.mir @@ -0,0 +1,448 @@ +# RUN: llc -mtriple powerpc64le-unknown-linux-gnu -mcpu=pwr8 -x mir < %s \ +# RUN: -verify-machineinstrs -start-before=ppc-mi-peepholes | FileCheck %s + +--- +name: conditional_trap_opt_reg_implicit_def +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = IMPLICIT_DEF + %1:gprc = IMPLICIT_DEF + %2:g8rc = IMPLICIT_DEF + %3:g8rc = IMPLICIT_DEF + TW 8, %0, %1 + TD 8, %2, %3 + TWI 24, %0, 0 + TDI 24, %2, 0 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_reg_implicit_def + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: twgt 3, 3 + # CHECK-NEXT: tdgt 3, 3 + # CHECK-NEXT: twnei 3, 0 + # CHECK-NEXT: tdnei 3, 0 + # CHECK-NEXT: blr +--- +name: conditional_trap_opt_TW_31 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 3 + %1:gprc = LI 0 + TW 31, %1, %0 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_31 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TW_16 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 5 + %1:gprc = LI 1 + TW 16, %1, %0 + TW 16, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_16 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TW_8 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -1 + %1:gprc = LI 10 + TW 8, %1, %0 + TW 8, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_8 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TW_2 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -1 + %1:gprc = LI 2 + TW 2, %1, %0 + TW 2, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_2 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TW_1 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -3 + %1:gprc = LI 4 + TW 1, %1, %0 + TW 1, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_1 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TW_4 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 5 + %1:gprc = LI 1 + TW 4, %1, %0 + TW 4, %1, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TW_4 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_31 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 3 + TWI 31, %0, 0 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_31 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_16 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 5 + %1:gprc = LI 1 + TWI 16, %1, 5 + TWI 16, %0, 1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_16 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_8 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -1 + %1:gprc = LI 10 + TWI 8, %1, -1 + TWI 8, %0, 10 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_8 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_2 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -1 + %1:gprc = LI 2 + TWI 2, %1, -1 + TWI 2, %0, 2 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_2 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_1 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI -3 + %1:gprc = LI 4 + TWI 1, %1, -3 + TWI 1, %0, 4 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_1 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TWI_4 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 5 + %1:gprc = LI 1 + TWI 4, %1, 5 + TWI 4, %1, 1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TWI_4 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_31 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 3 + %1:g8rc = LI8 0 + TD 31, %1, %0 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_31 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_16 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 5 + %1:g8rc = LI8 1 + TD 16, %1, %0 + TD 16, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_16 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_8 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -1 + %1:g8rc = LI8 10 + TD 8, %1, %0 + TD 8, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_8 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_2 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -1 + %1:g8rc = LI8 2 + TD 2, %1, %0 + TD 2, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_2 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_1 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -3 + %1:g8rc = LI8 4 + TD 1, %1, %0 + TD 1, %0, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_1 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TD_4 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 5 + %1:g8rc = LI8 1 + TD 4, %1, %0 + TD 4, %1, %1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TD_4 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_31 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 3 + TDI 31, %0, 0 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_31 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_16 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 5 + %1:g8rc = LI8 1 + TDI 16, %1, 5 + TDI 16, %0, 1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_16 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_8 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -1 + %1:g8rc = LI8 10 + TDI 8, %1, -1 + TDI 8, %0, 10 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_8 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_2 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -1 + %1:g8rc = LI8 2 + TDI 2, %1, -1 + TDI 2, %0, 2 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_2 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_1 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 -3 + %1:g8rc = LI8 4 + TDI 1, %1, -3 + TDI 1, %0, 4 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_1 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_TDI_4 +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:g8rc = LI8 5 + %1:g8rc = LI8 1 + TDI 4, %1, 5 + TDI 4, %1, 1 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_TDI_4 + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr + +--- +name: conditional_trap_opt_multiple_traps +alignment: 16 +tracksRegLiveness: true +body: | + bb.0.entry: + %0:gprc = LI 5 + %1:gprc = LI 1 + %2:g8rc = LI8 -1 + %3:g8rc = LI8 0 + TWI 31, %1, 5 + TDI 31, %3, 0 + TW 31, %0, %1 + TD 31, %2, %2 + BLR8 implicit $lr8, implicit $rm +... + # CHECK-LABEL: conditional_trap_opt_multiple_traps + # CHECK: # %bb.0: # %entry + # CHECK-NEXT: trap + # CHECK-NEXT: blr