Skip to content

Commit 4877c59

Browse files
authored
[SPIRV] Add PreLegalizer pattern matching for faceforward (#139959)
Tasks completed: - Pattern match`select(fcmp(dot(p2, p3), 0), p1, -p1)` to `faceforward(p1, p2, p3)` - Add pattern matching tests to `prelegalizercombiner-select-to-faceforward.mir` and `faceforward.ll` - Add CL extension error test `llvm/test/CodeGen/SPIRV/opencl/faceforward-error.ll` - Add CL extension test for no pattern matching in `llvm/test/CodeGen/SPIRV/opencl/faceforward.ll` Closes #137255.
1 parent 012721d commit 4877c59

File tree

7 files changed

+565
-63
lines changed

7 files changed

+565
-63
lines changed

llvm/lib/Target/SPIRV/SPIRVCombine.td

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@ def vector_length_sub_to_distance_lowering : GICombineRule <
1515
(apply [{ Helper.applySPIRVDistance(*${root}); }])
1616
>;
1717

18+
def vector_select_to_faceforward_lowering : GICombineRule <
19+
(defs root:$root),
20+
(match (wip_match_opcode G_SELECT):$root,
21+
[{ return Helper.matchSelectToFaceForward(*${root}); }]),
22+
(apply [{ Helper.applySPIRVFaceForward(*${root}); }])
23+
>;
24+
1825
def SPIRVPreLegalizerCombiner
1926
: GICombiner<"SPIRVPreLegalizerCombinerImpl",
20-
[vector_length_sub_to_distance_lowering]> {
27+
[vector_length_sub_to_distance_lowering, vector_select_to_faceforward_lowering]> {
2128
let CombineAllMethodName = "tryCombineAllImpl";
2229
}

llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,154 @@ void SPIRVCombinerHelper::applySPIRVDistance(MachineInstr &MI) const {
5858

5959
MI.eraseFromParent();
6060
}
61+
62+
/// This match is part of a combine that
63+
/// rewrites select(fcmp(dot(I, Ng), 0), N, -N) to faceforward(N, I, Ng)
64+
/// (vXf32 (g_select
65+
/// (g_fcmp
66+
/// (g_intrinsic dot(vXf32 I) (vXf32 Ng)
67+
/// 0)
68+
/// (vXf32 N)
69+
/// (vXf32 g_fneg (vXf32 N))))
70+
/// ->
71+
/// (vXf32 (g_intrinsic faceforward
72+
/// (vXf32 N) (vXf32 I) (vXf32 Ng)))
73+
///
74+
/// This only works for Vulkan shader targets.
75+
///
76+
bool SPIRVCombinerHelper::matchSelectToFaceForward(MachineInstr &MI) const {
77+
if (!STI.isShader())
78+
return false;
79+
80+
// Match overall select pattern.
81+
Register CondReg, TrueReg, FalseReg;
82+
if (!mi_match(MI.getOperand(0).getReg(), MRI,
83+
m_GISelect(m_Reg(CondReg), m_Reg(TrueReg), m_Reg(FalseReg))))
84+
return false;
85+
86+
// Match the FCMP condition.
87+
Register DotReg, CondZeroReg;
88+
CmpInst::Predicate Pred;
89+
if (!mi_match(CondReg, MRI,
90+
m_GFCmp(m_Pred(Pred), m_Reg(DotReg), m_Reg(CondZeroReg))) ||
91+
!(Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_ULT)) {
92+
if (!(Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_UGT))
93+
return false;
94+
std::swap(DotReg, CondZeroReg);
95+
}
96+
97+
// Check if FCMP is a comparison between a dot product and 0.
98+
MachineInstr *DotInstr = MRI.getVRegDef(DotReg);
99+
if (DotInstr->getOpcode() != TargetOpcode::G_INTRINSIC ||
100+
cast<GIntrinsic>(DotInstr)->getIntrinsicID() != Intrinsic::spv_fdot) {
101+
Register DotOperand1, DotOperand2;
102+
// Check for scalar dot product.
103+
if (!mi_match(DotReg, MRI,
104+
m_GFMul(m_Reg(DotOperand1), m_Reg(DotOperand2))) ||
105+
!MRI.getType(DotOperand1).isScalar() ||
106+
!MRI.getType(DotOperand2).isScalar())
107+
return false;
108+
}
109+
110+
const ConstantFP *ZeroVal;
111+
if (!mi_match(CondZeroReg, MRI, m_GFCst(ZeroVal)) || !ZeroVal->isZero())
112+
return false;
113+
114+
// Check if select's false operand is the negation of the true operand.
115+
auto AreNegatedConstantsOrSplats = [&](Register TrueReg, Register FalseReg) {
116+
std::optional<FPValueAndVReg> TrueVal, FalseVal;
117+
if (!mi_match(TrueReg, MRI, m_GFCstOrSplat(TrueVal)) ||
118+
!mi_match(FalseReg, MRI, m_GFCstOrSplat(FalseVal)))
119+
return false;
120+
APFloat TrueValNegated = TrueVal->Value;
121+
TrueValNegated.changeSign();
122+
return FalseVal->Value.compare(TrueValNegated) == APFloat::cmpEqual;
123+
};
124+
125+
if (!mi_match(TrueReg, MRI, m_GFNeg(m_SpecificReg(FalseReg))) &&
126+
!mi_match(FalseReg, MRI, m_GFNeg(m_SpecificReg(TrueReg)))) {
127+
std::optional<FPValueAndVReg> MulConstant;
128+
MachineInstr *TrueInstr = MRI.getVRegDef(TrueReg);
129+
MachineInstr *FalseInstr = MRI.getVRegDef(FalseReg);
130+
if (TrueInstr->getOpcode() == TargetOpcode::G_BUILD_VECTOR &&
131+
FalseInstr->getOpcode() == TargetOpcode::G_BUILD_VECTOR &&
132+
TrueInstr->getNumOperands() == FalseInstr->getNumOperands()) {
133+
for (unsigned I = 1; I < TrueInstr->getNumOperands(); ++I)
134+
if (!AreNegatedConstantsOrSplats(TrueInstr->getOperand(I).getReg(),
135+
FalseInstr->getOperand(I).getReg()))
136+
return false;
137+
} else if (mi_match(TrueReg, MRI,
138+
m_GFMul(m_SpecificReg(FalseReg),
139+
m_GFCstOrSplat(MulConstant))) ||
140+
mi_match(FalseReg, MRI,
141+
m_GFMul(m_SpecificReg(TrueReg),
142+
m_GFCstOrSplat(MulConstant))) ||
143+
mi_match(TrueReg, MRI,
144+
m_GFMul(m_GFCstOrSplat(MulConstant),
145+
m_SpecificReg(FalseReg))) ||
146+
mi_match(FalseReg, MRI,
147+
m_GFMul(m_GFCstOrSplat(MulConstant),
148+
m_SpecificReg(TrueReg)))) {
149+
if (!MulConstant || !MulConstant->Value.isExactlyValue(-1.0))
150+
return false;
151+
} else if (!AreNegatedConstantsOrSplats(TrueReg, FalseReg))
152+
return false;
153+
}
154+
155+
return true;
156+
}
157+
158+
void SPIRVCombinerHelper::applySPIRVFaceForward(MachineInstr &MI) const {
159+
// Extract the operands for N, I, and Ng from the match criteria.
160+
Register CondReg = MI.getOperand(1).getReg();
161+
MachineInstr *CondInstr = MRI.getVRegDef(CondReg);
162+
Register DotReg = CondInstr->getOperand(2).getReg();
163+
CmpInst::Predicate Pred = cast<GFCmp>(CondInstr)->getCond();
164+
if (Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_UGT)
165+
DotReg = CondInstr->getOperand(3).getReg();
166+
MachineInstr *DotInstr = MRI.getVRegDef(DotReg);
167+
Register DotOperand1, DotOperand2;
168+
if (DotInstr->getOpcode() == TargetOpcode::G_FMUL) {
169+
DotOperand1 = DotInstr->getOperand(1).getReg();
170+
DotOperand2 = DotInstr->getOperand(2).getReg();
171+
} else {
172+
DotOperand1 = DotInstr->getOperand(2).getReg();
173+
DotOperand2 = DotInstr->getOperand(3).getReg();
174+
}
175+
Register TrueReg = MI.getOperand(2).getReg();
176+
Register FalseReg = MI.getOperand(3).getReg();
177+
MachineInstr *TrueInstr = MRI.getVRegDef(TrueReg);
178+
if (TrueInstr->getOpcode() == TargetOpcode::G_FNEG ||
179+
TrueInstr->getOpcode() == TargetOpcode::G_FMUL)
180+
std::swap(TrueReg, FalseReg);
181+
MachineInstr *FalseInstr = MRI.getVRegDef(FalseReg);
182+
183+
Register ResultReg = MI.getOperand(0).getReg();
184+
Builder.setInstrAndDebugLoc(MI);
185+
Builder.buildIntrinsic(Intrinsic::spv_faceforward, ResultReg)
186+
.addUse(TrueReg) // N
187+
.addUse(DotOperand1) // I
188+
.addUse(DotOperand2); // Ng
189+
190+
SPIRVGlobalRegistry *GR =
191+
MI.getMF()->getSubtarget<SPIRVSubtarget>().getSPIRVGlobalRegistry();
192+
auto RemoveAllUses = [&](Register Reg) {
193+
SmallVector<MachineInstr *, 4> UsesToErase;
194+
for (auto &UseMI : MRI.use_instructions(Reg))
195+
UsesToErase.push_back(&UseMI);
196+
197+
// calling eraseFromParent to early invalidates the iterator.
198+
for (auto *MIToErase : UsesToErase)
199+
MIToErase->eraseFromParent();
200+
};
201+
202+
RemoveAllUses(CondReg); // remove all uses of FCMP Result
203+
GR->invalidateMachineInstr(CondInstr);
204+
CondInstr->eraseFromParent(); // remove FCMP instruction
205+
RemoveAllUses(DotReg); // remove all uses of spv_fdot/G_FMUL Result
206+
GR->invalidateMachineInstr(DotInstr);
207+
DotInstr->eraseFromParent(); // remove spv_fdot/G_FMUL instruction
208+
RemoveAllUses(FalseReg);
209+
GR->invalidateMachineInstr(FalseInstr);
210+
FalseInstr->eraseFromParent();
211+
}

llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class SPIRVCombinerHelper : public CombinerHelper {
3131

3232
bool matchLengthToDistance(MachineInstr &MI) const;
3333
void applySPIRVDistance(MachineInstr &MI) const;
34+
bool matchSelectToFaceForward(MachineInstr &MI) const;
35+
void applySPIRVFaceForward(MachineInstr &MI) const;
3436
};
3537

3638
} // end namespace llvm
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# RUN: llc -verify-machineinstrs -O0 -mtriple spirv-vulkan1.3-unknown -run-pass=spirv-prelegalizer-combiner %s -o - | FileCheck %s
2+
# REQUIRES: asserts
3+
---
4+
name: faceforward_instcombine_float
5+
tracksRegLiveness: true
6+
legalized: true
7+
body: |
8+
bb.1.entry:
9+
; CHECK-LABEL: name: faceforward_instcombine_float
10+
; CHECK-NOT: %9:_(s32) = G_FCONSTANT float 0.000000e+00
11+
; CHECK-NOT: %8:_(s32) = G_FMUL %1:fid, %2:fid
12+
; CHECK-NOT: %10:_(s1) = G_FCMP floatpred(olt), %8:_(s32), %9:_
13+
; CHECK-NOT: %11:_(s32) = G_FNEG %0:fid
14+
; CHECK-NOT: %12:id(s32) = G_SELECT %10:_(s1), %0:fid, %11:_
15+
; CHECK: %10:id(s32) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %2(s32), %3(s32), %4(s32)
16+
; CHECK: OpReturnValue %10(s32)
17+
%3:type(s64) = OpTypeFloat 32
18+
%5:type(s64) = OpTypeFunction %3:type(s64), %3:type(s64), %3:type(s64), %3:type(s64)
19+
OpName %0:fid(s32), 97
20+
OpName %1:fid(s32), 98
21+
OpName %2:fid(s32), 99
22+
%4:iid(s64) = OpFunction %3:type(s64), 0, %5:type(s64)
23+
%0:fid(s32) = OpFunctionParameter %3:type(s64)
24+
%1:fid(s32) = OpFunctionParameter %3:type(s64)
25+
%2:fid(s32) = OpFunctionParameter %3:type(s64)
26+
OpName %4:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 116
27+
%9:_(s32) = G_FCONSTANT float 0.000000e+00
28+
%8:_(s32) = G_FMUL %1:fid, %2:fid
29+
%10:_(s1) = G_FCMP floatpred(olt), %8:_(s32), %9:_
30+
%11:_(s32) = G_FNEG %0:fid
31+
%12:id(s32) = G_SELECT %10:_(s1), %0:fid, %11:_
32+
OpReturnValue %12:id(s32)
33+
---
34+
name: faceforward_instcombine_float4
35+
tracksRegLiveness: true
36+
legalized: true
37+
body: |
38+
bb.1.entry:
39+
; CHECK-LABEL: name: faceforward_instcombine_float4
40+
; CHECK-NOT: %10:_(s32) = G_FCONSTANT float 0.000000e+00
41+
; CHECK-NOT: %9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
42+
; CHECK-NOT: %11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
43+
; CHECK-NOT: %12:_(<4 x s32>) = G_FNEG %0:vfid
44+
; CHECK-NOT: %13:id(<4 x s32>) = G_SELECT %11:_(s1), %0:vfid, %12:_
45+
; CHECK: %11:id(<4 x s32>) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %3(<4 x s32>), %4(<4 x s32>), %5(<4 x s32>)
46+
; CHECK: OpReturnValue %11(<4 x s32>)
47+
%4:type(s64) = OpTypeVector %3:type(s64), 4
48+
%6:type(s64) = OpTypeFunction %4:type(s64), %4:type(s64), %4:type(s64), %4:type(s64)
49+
%3:type(s64) = OpTypeFloat 32
50+
OpName %0:vfid(<4 x s32>), 97
51+
OpName %1:vfid(<4 x s32>), 98
52+
OpName %2:vfid(<4 x s32>), 99
53+
%5:iid(s64) = OpFunction %4:type(s64), 0, %6:type(s64)
54+
%0:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
55+
%1:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
56+
%2:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
57+
OpName %5:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 13428
58+
%10:_(s32) = G_FCONSTANT float 0.000000e+00
59+
%9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
60+
%11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
61+
%12:_(<4 x s32>) = G_FNEG %0:vfid
62+
%13:id(<4 x s32>) = G_SELECT %11:_(s1), %0:vfid, %12:_
63+
OpReturnValue %13:id(<4 x s32>)
64+
---
65+
name: faceforward_instcombine_float_constants
66+
tracksRegLiveness: true
67+
legalized: true
68+
body: |
69+
bb.1.entry:
70+
; CHECK-LABEL: name: faceforward_instcombine_float_constants
71+
; CHECK-NOT: %9:_(s32) = G_FCONSTANT float 0.000000e+00
72+
; CHECK-NOT: %13:_(s32) = G_FCONSTANT float -1.000000e+00
73+
; CHECK-NOT: %8:_(s32) = G_FMUL %1:fid, %2:fid
74+
; CHECK-NOT: %10:_(s1) = G_FCMP floatpred(olt), %8:_(s32), %9:_
75+
; CHECK-NOT: %11:id(s32) = G_SELECT %10:_(s1), %12:_, %13:_
76+
; CHECK: %7:_(s32) = G_FCONSTANT float 1.000000e+00
77+
; CHECK: %11:id(s32) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %7(s32), %3(s32), %4(s32)
78+
; CHECK: OpReturnValue %11(s32)
79+
%3:type(s64) = OpTypeFloat 32
80+
%5:type(s64) = OpTypeFunction %3:type(s64), %3:type(s64), %3:type(s64), %3:type(s64)
81+
OpName %0:fid(s32), 97
82+
OpName %1:fid(s32), 98
83+
OpName %2:fid(s32), 99
84+
%4:iid(s64) = OpFunction %3:type(s64), 0, %5:type(s64)
85+
%0:fid(s32) = OpFunctionParameter %3:type(s64)
86+
%1:fid(s32) = OpFunctionParameter %3:type(s64)
87+
%2:fid(s32) = OpFunctionParameter %3:type(s64)
88+
OpName %4:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 1868783476, 1635021678, 7566446
89+
%9:_(s32) = G_FCONSTANT float 0.000000e+00
90+
%12:_(s32) = G_FCONSTANT float 1.000000e+00
91+
%13:_(s32) = G_FCONSTANT float -1.000000e+00
92+
%8:_(s32) = G_FMUL %1:fid, %2:fid
93+
%10:_(s1) = G_FCMP floatpred(olt), %8:_(s32), %9:_
94+
%11:id(s32) = G_SELECT %10:_(s1), %12:_, %13:_
95+
OpReturnValue %11:id(s32)
96+
---
97+
name: faceforward_instcombine_float4_constants
98+
tracksRegLiveness: true
99+
legalized: true
100+
body: |
101+
bb.1.entry:
102+
; CHECK-LABEL: name: faceforward_instcombine_float4_constants
103+
; CHECK-NOT: %10:_(s32) = G_FCONSTANT float 0.000000e+00
104+
; CHECK-NOT: %16:_(s32) = G_FCONSTANT float -1.000000e+00
105+
; CHECK-NOT: %15:_(<4 x s32>) = G_BUILD_VECTOR %16:_(s32), %16:_(s32), %16:_(s32), %16:_(s32)
106+
; CHECK-NOT: %9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
107+
; CHECK-NOT: %11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
108+
; CHECK-NOT: %12:id(<4 x s32>) = G_SELECT %11:_(s1), %13:_, %15:_
109+
; CHECK: %8:_(s32) = G_FCONSTANT float 1.000000e+00
110+
; CHECK: %9:_(<4 x s32>) = G_BUILD_VECTOR %8(s32), %8(s32), %8(s32), %8(s32)
111+
; CHECK: %14:id(<4 x s32>) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %9(<4 x s32>), %4(<4 x s32>), %5(<4 x s32>)
112+
; CHECK: OpReturnValue %14(<4 x s32>)
113+
%4:type(s64) = OpTypeVector %3:type(s64), 4
114+
%6:type(s64) = OpTypeFunction %4:type(s64), %4:type(s64), %4:type(s64), %4:type(s64)
115+
%3:type(s64) = OpTypeFloat 32
116+
OpName %0:vfid(<4 x s32>), 97
117+
OpName %1:vfid(<4 x s32>), 98
118+
OpName %2:vfid(<4 x s32>), 99
119+
%5:iid(s64) = OpFunction %4:type(s64), 0, %6:type(s64)
120+
%0:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
121+
%1:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
122+
%2:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
123+
OpName %5:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 1667183732, 1953721967, 1937010273, 0
124+
%10:_(s32) = G_FCONSTANT float 0.000000e+00
125+
%14:_(s32) = G_FCONSTANT float 1.000000e+00
126+
%13:_(<4 x s32>) = G_BUILD_VECTOR %14:_(s32), %14:_(s32), %14:_(s32), %14:_(s32)
127+
%16:_(s32) = G_FCONSTANT float -1.000000e+00
128+
%15:_(<4 x s32>) = G_BUILD_VECTOR %16:_(s32), %16:_(s32), %16:_(s32), %16:_(s32)
129+
%9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
130+
%11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
131+
%12:id(<4 x s32>) = G_SELECT %11:_(s1), %13:_, %15:_
132+
OpReturnValue %12:id(<4 x s32>)
133+
---
134+
name: faceforward_instcombine_float4_false_fmul
135+
tracksRegLiveness: true
136+
legalized: true
137+
body: |
138+
bb.1.entry:
139+
; CHECK-LABEL: name: faceforward_instcombine_float4_false_fmul
140+
; CHECK-NOT: %10:_(s32) = G_FCONSTANT float 0.000000e+00
141+
; CHECK-NOT: %13:_(s32) = G_FCONSTANT float -1.000000e+00
142+
; CHECK-NOT: %12:_(<4 x s32>) = G_BUILD_VECTOR %13:_(s32), %13:_(s32), %13:_(s32), %13:_(s32)
143+
; CHECK-NOT: %9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
144+
; CHECK-NOT: %11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
145+
; CHECK-NOT: %14:_(<4 x s32>) = G_FMUL %0:vfid, %12:_
146+
; CHECK-NOT: %15:id(<4 x s32>) = G_SELECT %11:_(s1), %0:vfid, %14:_
147+
; CHECK: %13:id(<4 x s32>) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %3(<4 x s32>), %4(<4 x s32>), %5(<4 x s32>)
148+
; CHECK: OpReturnValue %13(<4 x s32>)
149+
%4:type(s64) = OpTypeVector %3:type(s64), 4
150+
%6:type(s64) = OpTypeFunction %4:type(s64), %4:type(s64), %4:type(s64), %4:type(s64)
151+
%3:type(s64) = OpTypeFloat 32
152+
OpName %0:vfid(<4 x s32>), 97
153+
OpName %1:vfid(<4 x s32>), 98
154+
OpName %2:vfid(<4 x s32>), 99
155+
%5:iid(s64) = OpFunction %4:type(s64), 0, %6:type(s64)
156+
%0:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
157+
%1:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
158+
%2:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
159+
OpName %5:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 1717515380, 1702063201, 1970103903, 108
160+
%10:_(s32) = G_FCONSTANT float 0.000000e+00
161+
%13:_(s32) = G_FCONSTANT float -1.000000e+00
162+
%12:_(<4 x s32>) = G_BUILD_VECTOR %13:_(s32), %13:_(s32), %13:_(s32), %13:_(s32)
163+
%9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
164+
%11:_(s1) = G_FCMP floatpred(olt), %9:_(s32), %10:_
165+
%14:_(<4 x s32>) = G_FMUL %0:vfid, %12:_
166+
%15:id(<4 x s32>) = G_SELECT %11:_(s1), %0:vfid, %14:_
167+
OpReturnValue %15:id(<4 x s32>)
168+
---
169+
name: faceforward_instcombine_float4_ogt
170+
tracksRegLiveness: true
171+
legalized: true
172+
body: |
173+
bb.1.entry:
174+
; CHECK-LABEL: name: faceforward_instcombine_float4
175+
; CHECK-NOT: %10:_(s32) = G_FCONSTANT float 0.000000e+00
176+
; CHECK-NOT: %9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
177+
; CHECK-NOT: %11:_(s1) = G_FCMP floatpred(ogt), %10:_(s32), %9:_
178+
; CHECK-NOT: %12:_(<4 x s32>) = G_FNEG %0:vfid
179+
; CHECK-NOT: %13:id(<4 x s32>) = G_SELECT %11:_(s1), %12:_, %0:vfid
180+
; CHECK: %11:id(<4 x s32>) = G_INTRINSIC intrinsic(@llvm.spv.faceforward), %3(<4 x s32>), %4(<4 x s32>), %5(<4 x s32>)
181+
; CHECK: OpReturnValue %11(<4 x s32>)
182+
%4:type(s64) = OpTypeVector %3:type(s64), 4
183+
%6:type(s64) = OpTypeFunction %4:type(s64), %4:type(s64), %4:type(s64), %4:type(s64)
184+
%3:type(s64) = OpTypeFloat 32
185+
OpName %0:vfid(<4 x s32>), 97
186+
OpName %1:vfid(<4 x s32>), 98
187+
OpName %2:vfid(<4 x s32>), 99
188+
%5:iid(s64) = OpFunction %4:type(s64), 0, %6:type(s64)
189+
%0:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
190+
%1:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
191+
%2:vfid(<4 x s32>) = OpFunctionParameter %4:type(s64)
192+
OpName %5:iid(s64), 1701011814, 2003988326, 1600418401, 1953721961, 1651339107, 1600482921, 1634692198, 1868510324, 29799
193+
%10:_(s32) = G_FCONSTANT float 0.000000e+00
194+
%9:_(s32) = G_INTRINSIC intrinsic(@llvm.spv.fdot), %1:vfid(<4 x s32>), %2:vfid(<4 x s32>)
195+
%11:_(s1) = G_FCMP floatpred(ogt), %10:_(s32), %9:_
196+
%12:_(<4 x s32>) = G_FNEG %0:vfid
197+
%13:id(<4 x s32>) = G_SELECT %11:_(s1), %12:_, %0:vfid
198+
OpReturnValue %13:id(<4 x s32>)
199+

0 commit comments

Comments
 (0)