forked from OSchip/llvm-project
Reapply "[mips][FastISel] Implement shift ops for Mips fast-isel.""
This reapplies r235194, which was reverted in r235495 because it was causing a failure in our out-of-tree buildbots for MIPS. With the sign-extension patch in r235718, this patch doesn't cause any problem any more. llvm-svn: 235878
This commit is contained in:
parent
b19cf2082f
commit
7a6b18783f
|
@ -100,6 +100,7 @@ private:
|
|||
bool selectRet(const Instruction *I);
|
||||
bool selectTrunc(const Instruction *I);
|
||||
bool selectIntExt(const Instruction *I);
|
||||
bool selectShift(const Instruction *I);
|
||||
|
||||
// Utility helper routines.
|
||||
bool isTypeLegal(Type *Ty, MVT &VT);
|
||||
|
@ -1413,6 +1414,81 @@ unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
|
|||
return Success ? DestReg : 0;
|
||||
}
|
||||
|
||||
bool MipsFastISel::selectShift(const Instruction *I) {
|
||||
MVT RetVT;
|
||||
|
||||
if (!isTypeSupported(I->getType(), RetVT))
|
||||
return false;
|
||||
|
||||
unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
|
||||
if (!ResultReg)
|
||||
return false;
|
||||
|
||||
unsigned Opcode = I->getOpcode();
|
||||
const Value *Op0 = I->getOperand(0);
|
||||
unsigned Op0Reg = getRegForValue(Op0);
|
||||
if (!Op0Reg)
|
||||
return false;
|
||||
|
||||
// If AShr or LShr, then we need to make sure the operand0 is sign extended.
|
||||
if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) {
|
||||
unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
|
||||
if (!TempReg)
|
||||
return false;
|
||||
|
||||
MVT Op0MVT = TLI.getValueType(Op0->getType(), true).getSimpleVT();
|
||||
bool IsZExt = Opcode == Instruction::LShr;
|
||||
if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt))
|
||||
return false;
|
||||
|
||||
Op0Reg = TempReg;
|
||||
}
|
||||
|
||||
if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||
uint64_t ShiftVal = C->getZExtValue();
|
||||
|
||||
switch (Opcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected instruction.");
|
||||
case Instruction::Shl:
|
||||
Opcode = Mips::SLL;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
Opcode = Mips::SRA;
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
Opcode = Mips::SRL;
|
||||
break;
|
||||
}
|
||||
|
||||
emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal);
|
||||
updateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned Op1Reg = getRegForValue(I->getOperand(1));
|
||||
if (!Op1Reg)
|
||||
return false;
|
||||
|
||||
switch (Opcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected instruction.");
|
||||
case Instruction::Shl:
|
||||
Opcode = Mips::SLLV;
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
Opcode = Mips::SRAV;
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
Opcode = Mips::SRLV;
|
||||
break;
|
||||
}
|
||||
|
||||
emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
|
||||
updateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
|
||||
if (!TargetSupported)
|
||||
return false;
|
||||
|
@ -1423,6 +1499,10 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
|
|||
return selectLoad(I);
|
||||
case Instruction::Store:
|
||||
return selectStore(I);
|
||||
case Instruction::Shl:
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
return selectShift(I);
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel \
|
||||
; RUN: -fast-isel-abort=1 -mcpu=mips32r2 < %s | FileCheck %s
|
||||
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel \
|
||||
; RUN: -fast-isel-abort=1 -mcpu=mips32 < %s | FileCheck %s
|
||||
|
||||
@s1 = global i16 -89, align 2
|
||||
@s2 = global i16 4, align 2
|
||||
@us1 = global i16 -503, align 2
|
||||
@us2 = global i16 5, align 2
|
||||
@s3 = common global i16 0, align 2
|
||||
@us3 = common global i16 0, align 2
|
||||
|
||||
define void @sll() {
|
||||
entry:
|
||||
%0 = load i16, i16* @s1, align 2
|
||||
%1 = load i16, i16* @s2, align 2
|
||||
%shl = shl i16 %0, %1
|
||||
store i16 %shl, i16* @s3, align 2
|
||||
; CHECK-LABEL: sll:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[S3_ADDR:[0-9]+]], %got(s3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S2_ADDR:[0-9]+]], %got(s2)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[S1:[0-9]+]], 0($[[S1_ADDR]])
|
||||
; CHECK-DAG: lhu $[[S2:[0-9]+]], 0($[[S2_ADDR]])
|
||||
; CHECK: sllv $[[RES:[0-9]+]], $[[S1]], $[[S2]]
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @slli() {
|
||||
entry:
|
||||
%0 = load i16, i16* @s1, align 2
|
||||
%shl = shl i16 %0, 5
|
||||
store i16 %shl, i16* @s3, align 2
|
||||
; CHECK-LABEL: slli:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[S3_ADDR:[0-9]+]], %got(s3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[S1:[0-9]+]], 0($[[S1_ADDR]])
|
||||
; CHECK: sll $[[RES:[0-9]+]], $[[S1]], 5
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @srl() {
|
||||
entry:
|
||||
%0 = load i16, i16* @us1, align 2
|
||||
%1 = load i16, i16* @us2, align 2
|
||||
%shr = lshr i16 %0, %1
|
||||
store i16 %shr, i16* @us3, align 2
|
||||
ret void
|
||||
; CHECK-LABEL: srl:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[US3_ADDR:[0-9]+]], %got(us3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[US2_ADDR:[0-9]+]], %got(us2)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[US1_ADDR:[0-9]+]], %got(us1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[US1:[0-9]+]], 0($[[US1_ADDR]])
|
||||
; CHECK-DAG: lhu $[[US2:[0-9]+]], 0($[[US2_ADDR]])
|
||||
; CHECK: srlv $[[RES:[0-9]+]], $[[US1]], $[[US2]]
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
}
|
||||
|
||||
define void @srli() {
|
||||
entry:
|
||||
%0 = load i16, i16* @us1, align 2
|
||||
%shr = lshr i16 %0, 4
|
||||
store i16 %shr, i16* @us3, align 2
|
||||
; CHECK-LABEL: srli:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[US3_ADDR:[0-9]+]], %got(us3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[US1_ADDR:[0-9]+]], %got(us1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[US1:[0-9]+]], 0($[[US1_ADDR]])
|
||||
; CHECK: srl $[[RES:[0-9]+]], $[[US1]], 4
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sra() {
|
||||
entry:
|
||||
%0 = load i16, i16* @s1, align 2
|
||||
%1 = load i16, i16* @s2, align 2
|
||||
%shr = ashr i16 %0, %1
|
||||
store i16 %shr, i16* @s3, align 2
|
||||
; CHECK-LABEL: sra:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[S3_ADDR:[0-9]+]], %got(s3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S2_ADDR:[0-9]+]], %got(s2)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[S1:[0-9]+]], 0($[[S1_ADDR]])
|
||||
; CHECK-DAG: lhu $[[S2:[0-9]+]], 0($[[S2_ADDR]])
|
||||
; CHECK: srav $[[RES:[0-9]+]], $[[S1]], $[[S2]]
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @srai() {
|
||||
entry:
|
||||
%0 = load i16, i16* @s1, align 2
|
||||
%shr = ashr i16 %0, 2
|
||||
store i16 %shr, i16* @s3, align 2
|
||||
; CHECK-LABEL: srai:
|
||||
; CHECK: lui $[[REG_GPa:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK-DAG: addiu $[[REG_GPb:[0-9]+]], $[[REG_GPa]], %lo(_gp_disp)
|
||||
; CHECK-DAG: addu $[[REG_GP:[0-9]+]], $[[REG_GPb]], $25
|
||||
; CHECK-DAG: lw $[[S3_ADDR:[0-9]+]], %got(s3)($[[REG_GP]])
|
||||
; CHECK-DAG: lw $[[S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]])
|
||||
; CHECK-DAG: lhu $[[S1:[0-9]+]], 0($[[S1_ADDR]])
|
||||
; CHECK: sra $[[RES:[0-9]+]], $[[S1]], 2
|
||||
; CHECK: sh $[[RES]], 0($[[S3_ADDR]])
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue