Skip to content

Commit

Permalink
Replace i1 max/min intrinsics to and/or
Browse files Browse the repository at this point in the history
i1 max/min intrinsics are not properly emited. They are now replaced with and/or instruction
  • Loading branch information
KanclerzPiotr authored and igcbot committed Jan 27, 2025
1 parent 47cd24a commit 57175aa
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ namespace
void replaceLRound(IntrinsicInst* I);
void replaceLRint(IntrinsicInst* I);
void replaceCountTheLeadingZeros(IntrinsicInst* I);
void replaceMinMax(IntrinsicInst* I);
void replaceI1MinMax(IntrinsicInst* I);
void replaceI64MinMax(IntrinsicInst* I);

static const std::map< Intrinsic::ID, MemFuncPtr_t > m_intrinsicToFunc;
Expand Down Expand Up @@ -139,10 +141,10 @@ const std::map< Intrinsic::ID, ReplaceUnsupportedIntrinsics::MemFuncPtr_t > Repl
{ Intrinsic::lrint, &ReplaceUnsupportedIntrinsics::replaceLRint },
{ Intrinsic::llrint, &ReplaceUnsupportedIntrinsics::replaceLRint },
{ Intrinsic::ctlz, &ReplaceUnsupportedIntrinsics::replaceCountTheLeadingZeros },
{ Intrinsic::smax, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
{ Intrinsic::smin, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
{ Intrinsic::umax, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
{ Intrinsic::umin, &ReplaceUnsupportedIntrinsics::replaceI64MinMax }
{ Intrinsic::smax, &ReplaceUnsupportedIntrinsics::replaceMinMax },
{ Intrinsic::smin, &ReplaceUnsupportedIntrinsics::replaceMinMax },
{ Intrinsic::umax, &ReplaceUnsupportedIntrinsics::replaceMinMax },
{ Intrinsic::umin, &ReplaceUnsupportedIntrinsics::replaceMinMax }
};

ReplaceUnsupportedIntrinsics::ReplaceUnsupportedIntrinsics() : FunctionPass(ID)
Expand Down Expand Up @@ -1035,15 +1037,20 @@ void ReplaceUnsupportedIntrinsics::replaceLRint(IntrinsicInst* I) {
I->eraseFromParent();
}

void ReplaceUnsupportedIntrinsics::replaceMinMax(IntrinsicInst* I)
{
if(I->getType()->isIntegerTy(64))
replaceI64MinMax(I);

if(I->getType()->isIntegerTy(1))
replaceI1MinMax(I);
}
/*
Replaces i64 calls to llvm.smax, llvm.smin, llvm.umax, llvm.umin to
icmp + select instructionc that can be emulated.
*/
void ReplaceUnsupportedIntrinsics::replaceI64MinMax(IntrinsicInst* I)
{
if(!I->getType()->isIntegerTy(64))
return;

const SmallDenseMap<Intrinsic::ID, CmpInst::Predicate, 4> CmpPredMap {
{Intrinsic::smax, CmpInst::Predicate::ICMP_SGT},
{Intrinsic::smin, CmpInst::Predicate::ICMP_SLT},
Expand All @@ -1059,6 +1066,20 @@ void ReplaceUnsupportedIntrinsics::replaceI64MinMax(IntrinsicInst* I)
I->replaceAllUsesWith(Builder.CreateSelect(Cmp, LHS, RHS));
}

void ReplaceUnsupportedIntrinsics::replaceI1MinMax(IntrinsicInst* I)
{
IGCLLVM::IRBuilder<> Builder(I);

Value* LHS = I->getArgOperand(0), * RHS = I->getArgOperand(1);

auto IntrId = I->getIntrinsicID();

if (IntrId == Intrinsic::smax || IntrId == Intrinsic::umax)
I->replaceAllUsesWith(Builder.CreateOr(LHS, RHS));
else // Intrinsic::smin || Intrinsic::umin
I->replaceAllUsesWith(Builder.CreateAnd(LHS, RHS));
}

/*
Replaces llvm.ctlz.* intrinsics (count the leading zeros)
to llvm.ctlz.i32 because we support llvm.ctlz intrinsic
Expand Down
52 changes: 44 additions & 8 deletions IGC/Compiler/tests/ReplaceUnsupportedIntrinsics/minmax.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,74 @@

; RUN: igc_opt -igc-replace-unsupported-intrinsics -dce -S < %s 2>&1 | FileCheck %s

define i64 @test_smax(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_smax(
define i64 @test_smax_i64(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_smax_i64(
; %[[CMP:.*]] = icmp slt i64 %argL, %argR
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
; ret %[[RES]]
%1 = call i64 @llvm.smax.i64(i64 %argL, i64 %argR)
ret i64 %1
}

define i64 @test_smin(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_smin(
define i64 @test_smin_i64(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_smin_i64(
; %[[CMP:.*]] = icmp sgt i64 %argL, %argR
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
; ret %[[RES]]
%1 = call i64 @llvm.smin.i64(i64 %argL, i64 %argR)
ret i64 %1
}

define i64 @test_umax(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_umax(
define i64 @test_umax_i64(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_umax_i64(
; %[[CMP:.*]] = icmp ult i64 %argL, %argR
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
; ret %[[RES]]
%1 = call i64 @llvm.umax.i64(i64 %argL, i64 %argR)
ret i64 %1
}

define i64 @test_umin(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_umin(
define i64 @test_umin_i64(i64 %argL, i64 %argR) {
; CHECK-LABEL: define i64 @test_umin_i64(
; %[[CMP:.*]] = icmp ugt i64 %argL, %argR
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
; ret %[[RES]]
%1 = call i64 @llvm.umin.i64(i64 %argL, i64 %argR)
ret i64 %1
}

define i1 @test_smax_i1(i1 %argL, i1 %argR) {
; CHECK-LABEL: define i1 @test_smax_i1(
; %[[MAX:.*]] = or i1 %argL, %argR
; ret %[[MAX]]
%1 = call i1 @llvm.smax.i1(i1 %argL, i1 %argR)
ret i1 %1
}

define i1 @test_umax_i1(i1 %argL, i1 %argR) {
; CHECK-LABEL: define i1 @test_umax_i1(
; %[[MAX:.*]] = or ult i1 %argL, %argR
; ret %[[MAX]]
%1 = call i1 @llvm.umax.i1(i1 %argL, i1 %argR)
ret i1 %1
}

define i1 @test_smin_i1(i1 %argL, i1 %argR) {
; CHECK-LABEL: define i1 @test_smin_i1(
; %[[MIN:.*]] = and i1 %argL, %argR
; ret %[[MIN]]
%1 = call i1 @llvm.smin.i1(i1 %argL, i1 %argR)
ret i1 %1
}

define i1 @test_umin_i1(i1 %argL, i1 %argR) {
; CHECK-LABEL: define i1 @test_umin_i1(
; %[[MIN:.*]] = and i1 %argL, %argR
; ret %[[MIN]]
%1 = call i1 @llvm.umin.i1(i1 %argL, i1 %argR)
ret i1 %1
}

define i32 @test_smax_i32(i32 %argL, i32 %argR) {
; CHECK-LABEL: define i32 @test_smax_i32(
; %1 = call i32 @llvm.smax.i32(i32 %argL, i32 %argR)
Expand All @@ -58,4 +90,8 @@ declare i64 @llvm.smax.i64(i64, i64)
declare i64 @llvm.smin.i64(i64, i64)
declare i64 @llvm.umax.i64(i64, i64)
declare i64 @llvm.umin.i64(i64, i64)
declare i1 @llvm.smax.i1(i1, i1)
declare i1 @llvm.umax.i1(i1, i1)
declare i1 @llvm.smin.i1(i1, i1)
declare i1 @llvm.umin.i1(i1, i1)
declare i32 @llvm.smax.i32(i32, i32)

0 comments on commit 57175aa

Please sign in to comment.