Skip to content

Commit 57175aa

Browse files
KanclerzPiotrigcbot
authored andcommitted
Replace i1 max/min intrinsics to and/or
i1 max/min intrinsics are not properly emited. They are now replaced with and/or instruction
1 parent 47cd24a commit 57175aa

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

IGC/Compiler/Optimizer/OpenCLPasses/ReplaceUnsupportedIntrinsics/ReplaceUnsupportedIntrinsics.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ namespace
109109
void replaceLRound(IntrinsicInst* I);
110110
void replaceLRint(IntrinsicInst* I);
111111
void replaceCountTheLeadingZeros(IntrinsicInst* I);
112+
void replaceMinMax(IntrinsicInst* I);
113+
void replaceI1MinMax(IntrinsicInst* I);
112114
void replaceI64MinMax(IntrinsicInst* I);
113115

114116
static const std::map< Intrinsic::ID, MemFuncPtr_t > m_intrinsicToFunc;
@@ -139,10 +141,10 @@ const std::map< Intrinsic::ID, ReplaceUnsupportedIntrinsics::MemFuncPtr_t > Repl
139141
{ Intrinsic::lrint, &ReplaceUnsupportedIntrinsics::replaceLRint },
140142
{ Intrinsic::llrint, &ReplaceUnsupportedIntrinsics::replaceLRint },
141143
{ Intrinsic::ctlz, &ReplaceUnsupportedIntrinsics::replaceCountTheLeadingZeros },
142-
{ Intrinsic::smax, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
143-
{ Intrinsic::smin, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
144-
{ Intrinsic::umax, &ReplaceUnsupportedIntrinsics::replaceI64MinMax },
145-
{ Intrinsic::umin, &ReplaceUnsupportedIntrinsics::replaceI64MinMax }
144+
{ Intrinsic::smax, &ReplaceUnsupportedIntrinsics::replaceMinMax },
145+
{ Intrinsic::smin, &ReplaceUnsupportedIntrinsics::replaceMinMax },
146+
{ Intrinsic::umax, &ReplaceUnsupportedIntrinsics::replaceMinMax },
147+
{ Intrinsic::umin, &ReplaceUnsupportedIntrinsics::replaceMinMax }
146148
};
147149

148150
ReplaceUnsupportedIntrinsics::ReplaceUnsupportedIntrinsics() : FunctionPass(ID)
@@ -1035,15 +1037,20 @@ void ReplaceUnsupportedIntrinsics::replaceLRint(IntrinsicInst* I) {
10351037
I->eraseFromParent();
10361038
}
10371039

1040+
void ReplaceUnsupportedIntrinsics::replaceMinMax(IntrinsicInst* I)
1041+
{
1042+
if(I->getType()->isIntegerTy(64))
1043+
replaceI64MinMax(I);
1044+
1045+
if(I->getType()->isIntegerTy(1))
1046+
replaceI1MinMax(I);
1047+
}
10381048
/*
10391049
Replaces i64 calls to llvm.smax, llvm.smin, llvm.umax, llvm.umin to
10401050
icmp + select instructionc that can be emulated.
10411051
*/
10421052
void ReplaceUnsupportedIntrinsics::replaceI64MinMax(IntrinsicInst* I)
10431053
{
1044-
if(!I->getType()->isIntegerTy(64))
1045-
return;
1046-
10471054
const SmallDenseMap<Intrinsic::ID, CmpInst::Predicate, 4> CmpPredMap {
10481055
{Intrinsic::smax, CmpInst::Predicate::ICMP_SGT},
10491056
{Intrinsic::smin, CmpInst::Predicate::ICMP_SLT},
@@ -1059,6 +1066,20 @@ void ReplaceUnsupportedIntrinsics::replaceI64MinMax(IntrinsicInst* I)
10591066
I->replaceAllUsesWith(Builder.CreateSelect(Cmp, LHS, RHS));
10601067
}
10611068

1069+
void ReplaceUnsupportedIntrinsics::replaceI1MinMax(IntrinsicInst* I)
1070+
{
1071+
IGCLLVM::IRBuilder<> Builder(I);
1072+
1073+
Value* LHS = I->getArgOperand(0), * RHS = I->getArgOperand(1);
1074+
1075+
auto IntrId = I->getIntrinsicID();
1076+
1077+
if (IntrId == Intrinsic::smax || IntrId == Intrinsic::umax)
1078+
I->replaceAllUsesWith(Builder.CreateOr(LHS, RHS));
1079+
else // Intrinsic::smin || Intrinsic::umin
1080+
I->replaceAllUsesWith(Builder.CreateAnd(LHS, RHS));
1081+
}
1082+
10621083
/*
10631084
Replaces llvm.ctlz.* intrinsics (count the leading zeros)
10641085
to llvm.ctlz.i32 because we support llvm.ctlz intrinsic

IGC/Compiler/tests/ReplaceUnsupportedIntrinsics/minmax.ll

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,74 @@
1010

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

13-
define i64 @test_smax(i64 %argL, i64 %argR) {
14-
; CHECK-LABEL: define i64 @test_smax(
13+
define i64 @test_smax_i64(i64 %argL, i64 %argR) {
14+
; CHECK-LABEL: define i64 @test_smax_i64(
1515
; %[[CMP:.*]] = icmp slt i64 %argL, %argR
1616
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
1717
; ret %[[RES]]
1818
%1 = call i64 @llvm.smax.i64(i64 %argL, i64 %argR)
1919
ret i64 %1
2020
}
2121

22-
define i64 @test_smin(i64 %argL, i64 %argR) {
23-
; CHECK-LABEL: define i64 @test_smin(
22+
define i64 @test_smin_i64(i64 %argL, i64 %argR) {
23+
; CHECK-LABEL: define i64 @test_smin_i64(
2424
; %[[CMP:.*]] = icmp sgt i64 %argL, %argR
2525
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
2626
; ret %[[RES]]
2727
%1 = call i64 @llvm.smin.i64(i64 %argL, i64 %argR)
2828
ret i64 %1
2929
}
3030

31-
define i64 @test_umax(i64 %argL, i64 %argR) {
32-
; CHECK-LABEL: define i64 @test_umax(
31+
define i64 @test_umax_i64(i64 %argL, i64 %argR) {
32+
; CHECK-LABEL: define i64 @test_umax_i64(
3333
; %[[CMP:.*]] = icmp ult i64 %argL, %argR
3434
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
3535
; ret %[[RES]]
3636
%1 = call i64 @llvm.umax.i64(i64 %argL, i64 %argR)
3737
ret i64 %1
3838
}
3939

40-
define i64 @test_umin(i64 %argL, i64 %argR) {
41-
; CHECK-LABEL: define i64 @test_umin(
40+
define i64 @test_umin_i64(i64 %argL, i64 %argR) {
41+
; CHECK-LABEL: define i64 @test_umin_i64(
4242
; %[[CMP:.*]] = icmp ugt i64 %argL, %argR
4343
; %[[RES:.*]] = select i1 %[[CMP]], i64 %argL, %argR
4444
; ret %[[RES]]
4545
%1 = call i64 @llvm.umin.i64(i64 %argL, i64 %argR)
4646
ret i64 %1
4747
}
4848

49+
define i1 @test_smax_i1(i1 %argL, i1 %argR) {
50+
; CHECK-LABEL: define i1 @test_smax_i1(
51+
; %[[MAX:.*]] = or i1 %argL, %argR
52+
; ret %[[MAX]]
53+
%1 = call i1 @llvm.smax.i1(i1 %argL, i1 %argR)
54+
ret i1 %1
55+
}
56+
57+
define i1 @test_umax_i1(i1 %argL, i1 %argR) {
58+
; CHECK-LABEL: define i1 @test_umax_i1(
59+
; %[[MAX:.*]] = or ult i1 %argL, %argR
60+
; ret %[[MAX]]
61+
%1 = call i1 @llvm.umax.i1(i1 %argL, i1 %argR)
62+
ret i1 %1
63+
}
64+
65+
define i1 @test_smin_i1(i1 %argL, i1 %argR) {
66+
; CHECK-LABEL: define i1 @test_smin_i1(
67+
; %[[MIN:.*]] = and i1 %argL, %argR
68+
; ret %[[MIN]]
69+
%1 = call i1 @llvm.smin.i1(i1 %argL, i1 %argR)
70+
ret i1 %1
71+
}
72+
73+
define i1 @test_umin_i1(i1 %argL, i1 %argR) {
74+
; CHECK-LABEL: define i1 @test_umin_i1(
75+
; %[[MIN:.*]] = and i1 %argL, %argR
76+
; ret %[[MIN]]
77+
%1 = call i1 @llvm.umin.i1(i1 %argL, i1 %argR)
78+
ret i1 %1
79+
}
80+
4981
define i32 @test_smax_i32(i32 %argL, i32 %argR) {
5082
; CHECK-LABEL: define i32 @test_smax_i32(
5183
; %1 = call i32 @llvm.smax.i32(i32 %argL, i32 %argR)
@@ -58,4 +90,8 @@ declare i64 @llvm.smax.i64(i64, i64)
5890
declare i64 @llvm.smin.i64(i64, i64)
5991
declare i64 @llvm.umax.i64(i64, i64)
6092
declare i64 @llvm.umin.i64(i64, i64)
93+
declare i1 @llvm.smax.i1(i1, i1)
94+
declare i1 @llvm.umax.i1(i1, i1)
95+
declare i1 @llvm.smin.i1(i1, i1)
96+
declare i1 @llvm.umin.i1(i1, i1)
6197
declare i32 @llvm.smax.i32(i32, i32)

0 commit comments

Comments
 (0)