Skip to content

Commit

Permalink
[PowerPC] Exploit Prefixed Load/Stores using the refactored Load/Stor…
Browse files Browse the repository at this point in the history
…e Implementation

This patch exploits the prefixed load and store instructions utilizing the
refactored load/store implementation introduced in D93370.

Prefixed load and store instructions are emitted whenever we are loading or
storing a value with an offset that fits into a 34-bit signed immediate.
Patterns for the prefixed load and stores are added in this patch, as well as
the implementation that detects when we are loading and storing a value with an
offset that fits in 34-bits.

Differential Revision: https://reviews.llvm.org/D96075
  • Loading branch information
amy-kwan committed Sep 14, 2021
1 parent a1ae56d commit 5041a48
Show file tree
Hide file tree
Showing 26 changed files with 1,127 additions and 1,122 deletions.
7 changes: 7 additions & 0 deletions llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
Expand Up @@ -270,6 +270,13 @@ namespace {
None) == PPC::AM_PCRel;
}

/// SelectPDForm - Returns true if address N can be represented by Prefixed
/// DForm addressing mode (a base register, plus a signed 34-bit immediate.
bool SelectPDForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
None) == PPC::AM_PrefixDForm;
}

/// SelectXForm - Returns true if address N can be represented by the
/// addressing mode of XForm instructions (an indexed [r+r] operation).
bool SelectXForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
Expand Down
51 changes: 45 additions & 6 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Expand Up @@ -1518,10 +1518,9 @@ void PPCTargetLowering::initializeAddrModeMap() {
PPC::MOF_RPlusSImm16Mult16 | PPC::MOF_Vector | PPC::MOF_SubtargetP9,
PPC::MOF_NotAddNorCst | PPC::MOF_Vector | PPC::MOF_SubtargetP9,
PPC::MOF_AddrIsSImm32 | PPC::MOF_Vector | PPC::MOF_SubtargetP9,
PPC::MOF_RPlusSImm16Mult16 | PPC::MOF_Vector256 | PPC::MOF_SubtargetP10,
PPC::MOF_NotAddNorCst | PPC::MOF_Vector256 | PPC::MOF_SubtargetP10,
PPC::MOF_AddrIsSImm32 | PPC::MOF_Vector256 | PPC::MOF_SubtargetP10,
};
AddrModesMap[PPC::AM_PrefixDForm] = {PPC::MOF_RPlusSImm34 |
PPC::MOF_SubtargetP10};
// TODO: Add mapping for quadword load/store.
}

Expand Down Expand Up @@ -17267,6 +17266,9 @@ PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(unsigned Flags) const {
for (auto FlagSet : AddrModesMap.at(PPC::AM_DQForm))
if ((Flags & FlagSet) == FlagSet)
return PPC::AM_DQForm;
for (auto FlagSet : AddrModesMap.at(PPC::AM_PrefixDForm))
if ((Flags & FlagSet) == FlagSet)
return PPC::AM_PrefixDForm;
// If no other forms are selected, return an X-Form as it is the most
// general addressing mode.
return PPC::AM_XForm;
Expand Down Expand Up @@ -17386,6 +17388,22 @@ unsigned PPCTargetLowering::computeMOFlags(const SDNode *Parent, SDValue N,
if ((FlagSet & PPC::MOF_SubtargetP10) && isPCRelNode(N))
return FlagSet;

// If the node is the paired load/store intrinsics, compute flags for
// address computation and return early.
unsigned ParentOp = Parent->getOpcode();
if (Subtarget.isISA3_1() && ((ParentOp == ISD::INTRINSIC_W_CHAIN) ||
(ParentOp == ISD::INTRINSIC_VOID))) {
unsigned ID = cast<ConstantSDNode>(Parent->getOperand(1))->getZExtValue();
assert(
((ID == Intrinsic::ppc_vsx_lxvp) || (ID == Intrinsic::ppc_vsx_stxvp)) &&
"Only the paired load and store (lxvp/stxvp) intrinsics are valid.");
SDValue IntrinOp = (ID == Intrinsic::ppc_vsx_lxvp) ? Parent->getOperand(2)
: Parent->getOperand(3);
computeFlagsForAddressComputation(IntrinOp, FlagSet, DAG);
FlagSet |= PPC::MOF_Vector;
return FlagSet;
}

// Mark this as something we don't want to handle here if it is atomic
// or pre-increment instruction.
if (const LSBaseSDNode *LSB = dyn_cast<LSBaseSDNode>(Parent))
Expand All @@ -17410,9 +17428,12 @@ unsigned PPCTargetLowering::computeMOFlags(const SDNode *Parent, SDValue N,
} else if (MemVT.isVector() && !MemVT.isFloatingPoint()) { // Integer vectors.
if (Size == 128)
FlagSet |= PPC::MOF_Vector;
else if (Size == 256)
FlagSet |= PPC::MOF_Vector256;
else
else if (Size == 256) {
assert(Subtarget.pairedVectorMemops() &&
"256-bit vectors are only available when paired vector memops is "
"enabled!");
FlagSet |= PPC::MOF_Vector;
} else
llvm_unreachable("Not expecting illegal vectors!");
} else { // Floating point type: can be scalar, f128 or vector types.
if (Size == 32 || Size == 64)
Expand Down Expand Up @@ -17609,6 +17630,24 @@ PPC::AddrMode PPCTargetLowering::SelectOptimalAddrMode(const SDNode *Parent,
Base = N;
break;
}
case PPC::AM_PrefixDForm: {
int64_t Imm34 = 0;
unsigned Opcode = N.getOpcode();
if (((Opcode == ISD::ADD) || (Opcode == ISD::OR)) &&
(isIntS34Immediate(N.getOperand(1), Imm34))) {
// N is an Add/OR Node, and it's operand is a 34-bit signed immediate.
Disp = DAG.getTargetConstant(Imm34, DL, N.getValueType());
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0)))
Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType());
else
Base = N.getOperand(0);
} else if (isIntS34Immediate(N, Imm34)) {
// The address is a 34-bit signed immediate.
Disp = DAG.getTargetConstant(Imm34, DL, N.getValueType());
Base = DAG.getRegister(PPC::ZERO8, N.getValueType());
}
break;
}
case PPC::AM_PCRel: {
// When selecting PC-Relative instructions, "Base" is not utilized as
// we select the address as [PC+imm].
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/PPCISelLowering.h
Expand Up @@ -717,6 +717,7 @@ namespace llvm {
AM_DForm,
AM_DSForm,
AM_DQForm,
AM_PrefixDForm,
AM_XForm,
AM_PCRel
};
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.td
Expand Up @@ -1159,6 +1159,7 @@ def DQForm : ComplexPattern<iPTR, 2, "SelectDQForm", [], [SDNPWantParent]>;
def XForm : ComplexPattern<iPTR, 2, "SelectXForm", [], [SDNPWantParent]>;
def ForceXForm : ComplexPattern<iPTR, 2, "SelectForceXForm", [], [SDNPWantParent]>;
def PCRelForm : ComplexPattern<iPTR, 2, "SelectPCRelForm", [], [SDNPWantParent]>;
def PDForm : ComplexPattern<iPTR, 2, "SelectPDForm", [], [SDNPWantParent]>;

//===----------------------------------------------------------------------===//
// PowerPC Instruction Predicate Definitions.
Expand Down
110 changes: 103 additions & 7 deletions llvm/lib/Target/PowerPC/PPCInstrPrefix.td
Expand Up @@ -1666,18 +1666,18 @@ let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops, PrefixInstrs] i

let Predicates = [PairedVectorMemops] in {
// Intrinsics for Paired Vector Loads.
def : Pat<(v256i1 (int_ppc_vsx_lxvp iaddrX16:$src)), (LXVP memrix16:$src)>;
def : Pat<(v256i1 (int_ppc_vsx_lxvp xaddrX16:$src)), (LXVPX xaddrX16:$src)>;
def : Pat<(v256i1 (int_ppc_vsx_lxvp DQForm:$src)), (LXVP memrix16:$src)>;
def : Pat<(v256i1 (int_ppc_vsx_lxvp XForm:$src)), (LXVPX XForm:$src)>;
let Predicates = [PairedVectorMemops, PrefixInstrs] in {
def : Pat<(v256i1 (int_ppc_vsx_lxvp iaddrX34:$src)), (PLXVP memri34:$src)>;
def : Pat<(v256i1 (int_ppc_vsx_lxvp PDForm:$src)), (PLXVP memri34:$src)>;
}
// Intrinsics for Paired Vector Stores.
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, iaddrX16:$dst),
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, DQForm:$dst),
(STXVP $XSp, memrix16:$dst)>;
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, xaddrX16:$dst),
(STXVPX $XSp, xaddrX16:$dst)>;
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, XForm:$dst),
(STXVPX $XSp, XForm:$dst)>;
let Predicates = [PairedVectorMemops, PrefixInstrs] in {
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, iaddrX34:$dst),
def : Pat<(int_ppc_vsx_stxvp v256i1:$XSp, PDForm:$dst),
(PSTXVP $XSp, memri34:$dst)>;
}
}
Expand Down Expand Up @@ -2671,6 +2671,45 @@ def : Pat<(f64 nzFPImmAsi64:$A),
// nand(A, nand(B, C))
def : xxevalPattern<(or (vnot v4i32:$vA), (and v4i32:$vB, v4i32:$vC)),
!sub(255, 14)>;

// Anonymous patterns to select prefixed VSX loads and stores.
// Load / Store f128
def : Pat<(f128 (load PDForm:$src)),
(COPY_TO_REGCLASS (PLXV memri34:$src), VRRC)>;
def : Pat<(store f128:$XS, PDForm:$dst),
(PSTXV (COPY_TO_REGCLASS $XS, VSRC), memri34:$dst)>;

// Load / Store v4i32
def : Pat<(v4i32 (load PDForm:$src)), (PLXV memri34:$src)>;
def : Pat<(store v4i32:$XS, PDForm:$dst), (PSTXV $XS, memri34:$dst)>;

// Load / Store v2i64
def : Pat<(v2i64 (load PDForm:$src)), (PLXV memri34:$src)>;
def : Pat<(store v2i64:$XS, PDForm:$dst), (PSTXV $XS, memri34:$dst)>;

// Load / Store v4f32
def : Pat<(v4f32 (load PDForm:$src)), (PLXV memri34:$src)>;
def : Pat<(store v4f32:$XS, PDForm:$dst), (PSTXV $XS, memri34:$dst)>;

// Load / Store v2f64
def : Pat<(v2f64 (load PDForm:$src)), (PLXV memri34:$src)>;
def : Pat<(store v2f64:$XS, PDForm:$dst), (PSTXV $XS, memri34:$dst)>;

// Cases For PPCstore_scal_int_from_vsr
def : Pat<(PPCstore_scal_int_from_vsr
(f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), PDForm:$dst, 8),
(PSTXSD (XSCVDPUXDS f64:$src), PDForm:$dst)>;
def : Pat<(PPCstore_scal_int_from_vsr
(f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), PDForm:$dst, 8),
(PSTXSD (XSCVDPSXDS f64:$src), PDForm:$dst)>;
def : Pat<(PPCstore_scal_int_from_vsr
(f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), PDForm:$dst, 8),
(PSTXSD (COPY_TO_REGCLASS (XSCVQPUDZ f128:$src), VFRC),
PDForm:$dst)>;
def : Pat<(PPCstore_scal_int_from_vsr
(f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), PDForm:$dst, 8),
(PSTXSD (COPY_TO_REGCLASS (XSCVQPSDZ f128:$src), VFRC),
PDForm:$dst)>;
}

let Predicates = [PrefixInstrs] in {
Expand All @@ -2694,6 +2733,63 @@ let Predicates = [PrefixInstrs] in {
(XXBLENDVW $A, $B, $C)>;
def : Pat<(int_ppc_vsx_xxblendvd v2i64:$A, v2i64:$B, v2i64:$C),
(XXBLENDVD $A, $B, $C)>;

// Anonymous patterns to select prefixed loads and stores.
// Load i32
def : Pat<(i32 (extloadi1 PDForm:$src)), (PLBZ memri34:$src)>;
def : Pat<(i32 (zextloadi1 PDForm:$src)), (PLBZ memri34:$src)>;
def : Pat<(i32 (extloadi8 PDForm:$src)), (PLBZ memri34:$src)>;
def : Pat<(i32 (zextloadi8 PDForm:$src)), (PLBZ memri34:$src)>;
def : Pat<(i32 (extloadi16 PDForm:$src)), (PLHZ memri34:$src)>;
def : Pat<(i32 (zextloadi16 PDForm:$src)), (PLHZ memri34:$src)>;
def : Pat<(i32 (sextloadi16 PDForm:$src)), (PLHA memri34:$src)>;
def : Pat<(i32 (load PDForm:$src)), (PLWZ memri34:$src)>;

// Store i32
def : Pat<(truncstorei8 i32:$rS, PDForm:$dst), (PSTB gprc:$rS, memri34:$dst)>;
def : Pat<(truncstorei16 i32:$rS, PDForm:$dst), (PSTH gprc:$rS, memri34:$dst)>;
def : Pat<(store i32:$rS, PDForm:$dst), (PSTW gprc:$rS, memri34:$dst)>;

// Load i64
def : Pat<(i64 (extloadi1 PDForm:$src)), (PLBZ8 memri34:$src)>;
def : Pat<(i64 (zextloadi1 PDForm:$src)), (PLBZ8 memri34:$src)>;
def : Pat<(i64 (extloadi8 PDForm:$src)), (PLBZ8 memri34:$src)>;
def : Pat<(i64 (zextloadi8 PDForm:$src)), (PLBZ8 memri34:$src)>;
def : Pat<(i64 (extloadi16 PDForm:$src)), (PLHZ8 memri34:$src)>;
def : Pat<(i64 (zextloadi16 PDForm:$src)), (PLHZ8 memri34:$src)>;
def : Pat<(i64 (sextloadi16 PDForm:$src)), (PLHA8 memri34:$src)>;
def : Pat<(i64 (extloadi32 PDForm:$src)), (PLWZ8 memri34:$src)>;
def : Pat<(i64 (zextloadi32 PDForm:$src)), (PLWZ8 memri34:$src)>;
def : Pat<(i64 (sextloadi32 PDForm:$src)), (PLWA8 memri34:$src)>;
def : Pat<(i64 (load PDForm:$src)), (PLD memri34:$src)>;

// Store i64
def : Pat<(truncstorei8 i64:$rS, PDForm:$dst), (PSTB8 g8rc:$rS, memri34:$dst)>;
def : Pat<(truncstorei16 i64:$rS, PDForm:$dst), (PSTH8 g8rc:$rS, memri34:$dst)>;
def : Pat<(truncstorei32 i64:$rS, PDForm:$dst), (PSTW8 g8rc:$rS, memri34:$dst)>;
def : Pat<(store i64:$rS, PDForm:$dst), (PSTD g8rc:$rS, memri34:$dst)>;

// Load / Store f32
def : Pat<(f32 (load PDForm:$src)), (PLFS memri34:$src)>;
def : Pat<(store f32:$FRS, PDForm:$dst), (PSTFS $FRS, memri34:$dst)>;

// Load / Store f64
def : Pat<(f64 (extloadf32 PDForm:$src)),
(COPY_TO_REGCLASS (PLFS memri34:$src), VSFRC)>;
def : Pat<(f64 (load PDForm:$src)), (PLFD memri34:$src)>;
def : Pat<(store f64:$FRS, PDForm:$dst), (PSTFD $FRS, memri34:$dst)>;

// Atomic Load
def : Pat<(atomic_load_8 PDForm:$src), (PLBZ memri34:$src)>;
def : Pat<(atomic_load_16 PDForm:$src), (PLHZ memri34:$src)>;
def : Pat<(atomic_load_32 PDForm:$src), (PLWZ memri34:$src)>;
def : Pat<(atomic_load_64 PDForm:$src), (PLD memri34:$src)>;

// Atomic Store
def : Pat<(atomic_store_8 PDForm:$dst, i32:$RS), (PSTB $RS, memri34:$dst)>;
def : Pat<(atomic_store_16 PDForm:$dst, i32:$RS), (PSTH $RS, memri34:$dst)>;
def : Pat<(atomic_store_32 PDForm:$dst, i32:$RS), (PSTW $RS, memri34:$dst)>;
def : Pat<(atomic_store_64 PDForm:$dst, i64:$RS), (PSTD $RS, memri34:$dst)>;
}

def InsertEltShift {
Expand Down
21 changes: 19 additions & 2 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
Expand Up @@ -135,6 +135,23 @@ PPCRegisterInfo::PPCRegisterInfo(const PPCTargetMachine &TM)
ImmToIdxMap[PPC::SPELWZ] = PPC::SPELWZX;

// Power10
ImmToIdxMap[PPC::PLBZ] = PPC::LBZX; ImmToIdxMap[PPC::PLBZ8] = PPC::LBZX8;
ImmToIdxMap[PPC::PLHZ] = PPC::LHZX; ImmToIdxMap[PPC::PLHZ8] = PPC::LHZX8;
ImmToIdxMap[PPC::PLHA] = PPC::LHAX; ImmToIdxMap[PPC::PLHA8] = PPC::LHAX8;
ImmToIdxMap[PPC::PLWZ] = PPC::LWZX; ImmToIdxMap[PPC::PLWZ8] = PPC::LWZX8;
ImmToIdxMap[PPC::PLWA] = PPC::LWAX; ImmToIdxMap[PPC::PLWA8] = PPC::LWAX;
ImmToIdxMap[PPC::PLD] = PPC::LDX; ImmToIdxMap[PPC::PSTD] = PPC::STDX;

ImmToIdxMap[PPC::PSTB] = PPC::STBX; ImmToIdxMap[PPC::PSTB8] = PPC::STBX8;
ImmToIdxMap[PPC::PSTH] = PPC::STHX; ImmToIdxMap[PPC::PSTH8] = PPC::STHX8;
ImmToIdxMap[PPC::PSTW] = PPC::STWX; ImmToIdxMap[PPC::PSTW8] = PPC::STWX8;

ImmToIdxMap[PPC::PLFS] = PPC::LFSX; ImmToIdxMap[PPC::PSTFS] = PPC::STFSX;
ImmToIdxMap[PPC::PLFD] = PPC::LFDX; ImmToIdxMap[PPC::PSTFD] = PPC::STFDX;
ImmToIdxMap[PPC::PLXSSP] = PPC::LXSSPX; ImmToIdxMap[PPC::PSTXSSP] = PPC::STXSSPX;
ImmToIdxMap[PPC::PLXSD] = PPC::LXSDX; ImmToIdxMap[PPC::PSTXSD] = PPC::STXSDX;
ImmToIdxMap[PPC::PLXV] = PPC::LXVX; ImmToIdxMap[PPC::PSTXV] = PPC::STXVX;

ImmToIdxMap[PPC::LXVP] = PPC::LXVPX;
ImmToIdxMap[PPC::STXVP] = PPC::STXVPX;
ImmToIdxMap[PPC::PLXVP] = PPC::LXVPX;
Expand Down Expand Up @@ -1347,7 +1364,7 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MachineFunction &MF = *MBB.getParent();
const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
// Get the instruction info.
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
const PPCInstrInfo &TII = *Subtarget.getInstrInfo();
// Get the frame info.
MachineFrameInfo &MFI = MF.getFrameInfo();
DebugLoc dl = MI.getDebugLoc();
Expand Down Expand Up @@ -1459,7 +1476,7 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
bool OffsetFitsMnemonic = (OpC == PPC::EVSTDD || OpC == PPC::EVLDD) ?
isUInt<8>(Offset) :
isInt<16>(Offset);
if (OpC == PPC::PLXVP || OpC == PPC::PSTXVP)
if (TII.isPrefixed(MI.getOpcode()))
OffsetFitsMnemonic = isInt<34>(Offset);
if (!noImmForm && ((OffsetFitsMnemonic &&
((Offset % offsetMinAlign(MI)) == 0)) ||
Expand Down
17 changes: 7 additions & 10 deletions llvm/test/CodeGen/PowerPC/aix-vec_insert_elt.ll
Expand Up @@ -667,7 +667,7 @@ define <2 x double> @testDouble2(<2 x double> %a, i8* %b, i32 zeroext %idx1, i32
; CHECK-32-P10-NEXT: rlwinm 5, 5, 3, 28, 28
; CHECK-32-P10-NEXT: stfdx 0, 6, 4
; CHECK-32-P10-NEXT: lxv 0, -32(1)
; CHECK-32-P10-NEXT: lfd 1, 1(3)
; CHECK-32-P10-NEXT: plfd 1, 1(3), 0
; CHECK-32-P10-NEXT: addi 3, 1, -16
; CHECK-32-P10-NEXT: stxv 0, -16(1)
; CHECK-32-P10-NEXT: stfdx 1, 3, 5
Expand Down Expand Up @@ -737,12 +737,11 @@ define <2 x double> @testDouble3(<2 x double> %a, i8* %b, i32 zeroext %idx1, i32
;
; CHECK-32-P10-LABEL: testDouble3:
; CHECK-32-P10: # %bb.0: # %entry
; CHECK-32-P10-NEXT: lis 6, 1
; CHECK-32-P10-NEXT: rlwinm 4, 4, 3, 28, 28
; CHECK-32-P10-NEXT: rlwinm 5, 5, 3, 28, 28
; CHECK-32-P10-NEXT: lfdx 0, 3, 6
; CHECK-32-P10-NEXT: addi 6, 1, -32
; CHECK-32-P10-NEXT: plfd 0, 65536(3), 0
; CHECK-32-P10-DAG: addi 6, 1, -32
; CHECK-32-P10-DAG: rlwinm 4, 4, 3, 28, 28
; CHECK-32-P10-NEXT: stxv 34, -32(1)
; CHECK-32-P10-NEXT: rlwinm 5, 5, 3, 28, 28
; CHECK-32-P10-NEXT: stfdx 0, 6, 4
; CHECK-32-P10-NEXT: lxv 0, -32(1)
; CHECK-32-P10-NEXT: lfd 1, 0(3)
Expand Down Expand Up @@ -874,15 +873,13 @@ define <2 x double> @testDoubleImm4(<2 x double> %a, i32* %b) {
;
; CHECK-64-P10-LABEL: testDoubleImm4:
; CHECK-64-P10: # %bb.0: # %entry
; CHECK-64-P10-NEXT: lis 4, 4
; CHECK-64-P10-NEXT: lfdx 0, 3, 4
; CHECK-64-P10-NEXT: plfd 0, 262144(3), 0
; CHECK-64-P10-NEXT: xxpermdi 34, 0, 34, 1
; CHECK-64-P10-NEXT: blr
;
; CHECK-32-P10-LABEL: testDoubleImm4:
; CHECK-32-P10: # %bb.0: # %entry
; CHECK-32-P10-NEXT: lis 4, 4
; CHECK-32-P10-NEXT: lfdx 0, 3, 4
; CHECK-32-P10-NEXT: plfd 0, 262144(3), 0
; CHECK-32-P10-NEXT: xxpermdi 34, 0, 34, 1
; CHECK-32-P10-NEXT: blr
entry:
Expand Down

0 comments on commit 5041a48

Please sign in to comment.