Skip to content

Commit

Permalink
AMDGPU: Add replacement bfe intrinsics
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295899 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
arsenm committed Feb 22, 2017
1 parent 9ba3c4d commit c2d34b5
Show file tree
Hide file tree
Showing 6 changed files with 1,343 additions and 1 deletion.
9 changes: 8 additions & 1 deletion include/llvm/IR/IntrinsicsAMDGPU.td
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,14 @@ def int_amdgcn_ds_swizzle :
GCCBuiltin<"__builtin_amdgcn_ds_swizzle">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;

// llvm.amdgcn.lerp
def int_amdgcn_ubfe : Intrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
>;

def int_amdgcn_sbfe : Intrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
>;

def int_amdgcn_lerp :
GCCBuiltin<"__builtin_amdgcn_lerp">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
Expand Down
6 changes: 6 additions & 0 deletions lib/Target/AMDGPU/SIISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2825,6 +2825,12 @@ SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
Op.getOperand(1), Op.getOperand(2));
case Intrinsic::amdgcn_sffbh:
return DAG.getNode(AMDGPUISD::FFBH_I32, DL, VT, Op.getOperand(1));
case Intrinsic::amdgcn_sbfe:
return DAG.getNode(AMDGPUISD::BFE_I32, DL, VT,
Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
case Intrinsic::amdgcn_ubfe:
return DAG.getNode(AMDGPUISD::BFE_U32, DL, VT,
Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
case Intrinsic::amdgcn_cvt_pkrtz: {
// FIXME: Stop adding cast if v2f16 legal.
EVT VT = Op.getValueType();
Expand Down
73 changes: 73 additions & 0 deletions lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3231,6 +3231,79 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {

break;
}
case Intrinsic::amdgcn_ubfe:
case Intrinsic::amdgcn_sbfe: {
// Decompose simple cases into standard shifts.
Value *Src = II->getArgOperand(0);
if (isa<UndefValue>(Src))
return replaceInstUsesWith(*II, Src);

unsigned Width;
Type *Ty = II->getType();
unsigned IntSize = Ty->getIntegerBitWidth();

ConstantInt *CWidth = dyn_cast<ConstantInt>(II->getArgOperand(2));
if (CWidth) {
Width = CWidth->getZExtValue();
if ((Width & (IntSize - 1)) == 0)
return replaceInstUsesWith(*II, ConstantInt::getNullValue(Ty));

if (Width >= IntSize) {
// Hardware ignores high bits, so remove those.
II->setArgOperand(2, ConstantInt::get(CWidth->getType(),
Width & (IntSize - 1)));
return II;
}
}

unsigned Offset;
ConstantInt *COffset = dyn_cast<ConstantInt>(II->getArgOperand(1));
if (COffset) {
Offset = COffset->getZExtValue();
if (Offset >= IntSize) {
II->setArgOperand(1, ConstantInt::get(COffset->getType(),
Offset & (IntSize - 1)));
return II;
}
}

bool Signed = II->getIntrinsicID() == Intrinsic::amdgcn_sbfe;

// TODO: Also emit sub if only width is constant.
if (!CWidth && COffset && Offset == 0) {
Constant *KSize = ConstantInt::get(COffset->getType(), IntSize);
Value *ShiftVal = Builder->CreateSub(KSize, II->getArgOperand(2));
ShiftVal = Builder->CreateZExt(ShiftVal, II->getType());

Value *Shl = Builder->CreateShl(Src, ShiftVal);
Value *RightShift = Signed ?
Builder->CreateAShr(Shl, ShiftVal) :
Builder->CreateLShr(Shl, ShiftVal);
RightShift->takeName(II);
return replaceInstUsesWith(*II, RightShift);
}

if (!CWidth || !COffset)
break;

// TODO: This allows folding to undef when the hardware has specific
// behavior?
if (Offset + Width < IntSize) {
Value *Shl = Builder->CreateShl(Src, IntSize - Offset - Width);
Value *RightShift = Signed ?
Builder->CreateAShr(Shl, IntSize - Width) :
Builder->CreateLShr(Shl, IntSize - Width);
RightShift->takeName(II);
return replaceInstUsesWith(*II, RightShift);
}

Value *RightShift = Signed ?
Builder->CreateAShr(Src, Offset) :
Builder->CreateLShr(Src, Offset);

RightShift->takeName(II);
return replaceInstUsesWith(*II, RightShift);
}
case Intrinsic::stackrestore: {
// If the save is right next to the restore, remove the restore. This can
// happen when variable allocas are DCE'd.
Expand Down
Loading

0 comments on commit c2d34b5

Please sign in to comment.