Skip to content

Commit ccbcebc

Browse files
authored
[LoongArch] Fix implicit PesudoXVINSGR2VR error (#152432)
According to the instructions manual, when `vr0` is changed, high 128 bit of `xr0` is undefined. Use `vinsgr2vr.b/h` to insert an `i8/i16` to low 128bit of a 256 vector may cause undefined behavior when high 128bit is used in later instructions.
1 parent 948abf1 commit ccbcebc

File tree

4 files changed

+417
-247
lines changed

4 files changed

+417
-247
lines changed

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/ADT/Statistic.h"
2323
#include "llvm/ADT/StringExtras.h"
2424
#include "llvm/CodeGen/ISDOpcodes.h"
25+
#include "llvm/CodeGen/MachineInstrBuilder.h"
2526
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
2627
#include "llvm/CodeGen/SelectionDAGNodes.h"
2728
#include "llvm/IR/IRBuilder.h"
@@ -6039,17 +6040,20 @@ static MachineBasicBlock *
60396040
emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB,
60406041
const LoongArchSubtarget &Subtarget) {
60416042
unsigned InsOp;
6043+
unsigned BroadcastOp;
60426044
unsigned HalfSize;
60436045
switch (MI.getOpcode()) {
60446046
default:
60456047
llvm_unreachable("Unexpected opcode");
60466048
case LoongArch::PseudoXVINSGR2VR_B:
60476049
HalfSize = 16;
6048-
InsOp = LoongArch::VINSGR2VR_B;
6050+
BroadcastOp = LoongArch::XVREPLGR2VR_B;
6051+
InsOp = LoongArch::XVEXTRINS_B;
60496052
break;
60506053
case LoongArch::PseudoXVINSGR2VR_H:
60516054
HalfSize = 8;
6052-
InsOp = LoongArch::VINSGR2VR_H;
6055+
BroadcastOp = LoongArch::XVREPLGR2VR_H;
6056+
InsOp = LoongArch::XVEXTRINS_H;
60536057
break;
60546058
}
60556059
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
@@ -6063,37 +6067,41 @@ emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB,
60636067
Register Elt = MI.getOperand(2).getReg();
60646068
unsigned Idx = MI.getOperand(3).getImm();
60656069

6066-
Register ScratchReg1 = XSrc;
6067-
if (Idx >= HalfSize) {
6068-
ScratchReg1 = MRI.createVirtualRegister(RC);
6069-
BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_D), ScratchReg1)
6070-
.addReg(XSrc)
6071-
.addImm(14);
6072-
}
6070+
if (XSrc.isVirtual() && MRI.getVRegDef(XSrc)->isImplicitDef() &&
6071+
Idx < HalfSize) {
6072+
Register ScratchSubReg1 = MRI.createVirtualRegister(SubRC);
6073+
Register ScratchSubReg2 = MRI.createVirtualRegister(SubRC);
60736074

6074-
Register ScratchSubReg1 = MRI.createVirtualRegister(SubRC);
6075-
Register ScratchSubReg2 = MRI.createVirtualRegister(SubRC);
6076-
BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), ScratchSubReg1)
6077-
.addReg(ScratchReg1, 0, LoongArch::sub_128);
6078-
BuildMI(*BB, MI, DL, TII->get(InsOp), ScratchSubReg2)
6079-
.addReg(ScratchSubReg1)
6080-
.addReg(Elt)
6081-
.addImm(Idx >= HalfSize ? Idx - HalfSize : Idx);
6075+
BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), ScratchSubReg1)
6076+
.addReg(XSrc, 0, LoongArch::sub_128);
6077+
BuildMI(*BB, MI, DL,
6078+
TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
6079+
: LoongArch::VINSGR2VR_B),
6080+
ScratchSubReg2)
6081+
.addReg(ScratchSubReg1)
6082+
.addReg(Elt)
6083+
.addImm(Idx);
6084+
6085+
BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), XDst)
6086+
.addImm(0)
6087+
.addReg(ScratchSubReg2)
6088+
.addImm(LoongArch::sub_128);
6089+
} else {
6090+
Register ScratchReg1 = MRI.createVirtualRegister(RC);
6091+
Register ScratchReg2 = MRI.createVirtualRegister(RC);
60826092

6083-
Register ScratchReg2 = XDst;
6084-
if (Idx >= HalfSize)
6085-
ScratchReg2 = MRI.createVirtualRegister(RC);
6093+
BuildMI(*BB, MI, DL, TII->get(BroadcastOp), ScratchReg1).addReg(Elt);
60866094

6087-
BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), ScratchReg2)
6088-
.addImm(0)
6089-
.addReg(ScratchSubReg2)
6090-
.addImm(LoongArch::sub_128);
6095+
BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
6096+
.addReg(ScratchReg1)
6097+
.addReg(XSrc)
6098+
.addImm(Idx >= HalfSize ? 48 : 18);
60916099

6092-
if (Idx >= HalfSize)
6093-
BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), XDst)
6100+
BuildMI(*BB, MI, DL, TII->get(InsOp), XDst)
60946101
.addReg(XSrc)
60956102
.addReg(ScratchReg2)
6096-
.addImm(2);
6103+
.addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
6104+
}
60976105

60986106
MI.eraseFromParent();
60996107
return BB;

0 commit comments

Comments
 (0)