@@ -105,12 +105,17 @@ class SPIRVInstructionSelector : public InstructionSelector {
105
105
106
106
bool selectFirstBitSet32 (Register ResVReg, const SPIRVType *ResType,
107
107
MachineInstr &I, Register SrcReg,
108
- unsigned Opcode ) const ;
108
+ unsigned BitSetOpcode ) const ;
109
109
110
110
bool selectFirstBitSet64 (Register ResVReg, const SPIRVType *ResType,
111
111
MachineInstr &I, Register SrcReg,
112
112
unsigned BitSetOpcode, bool SwapPrimarySide) const ;
113
113
114
+ bool selectFirstBitSet64Overflow (Register ResVReg, const SPIRVType *ResType,
115
+ MachineInstr &I, Register SrcReg,
116
+ unsigned BitSetOpcode,
117
+ bool SwapPrimarySide) const ;
118
+
114
119
bool selectGlobalValue (Register ResVReg, MachineInstr &I,
115
120
const MachineInstr *Init = nullptr ) const ;
116
121
@@ -3157,51 +3162,42 @@ bool SPIRVInstructionSelector::selectFirstBitSet16(
3157
3162
selectFirstBitSet32 (ResVReg, ResType, I, ExtReg, BitSetOpcode);
3158
3163
}
3159
3164
3160
- bool SPIRVInstructionSelector::selectFirstBitSet32 (Register ResVReg,
3161
- const SPIRVType *ResType,
3162
- MachineInstr &I,
3163
- Register SrcReg,
3164
- unsigned Opcode) const {
3165
+ bool SPIRVInstructionSelector::selectFirstBitSet32 (
3166
+ Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
3167
+ Register SrcReg, unsigned BitSetOpcode) const {
3165
3168
return BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpExtInst))
3166
3169
.addDef (ResVReg)
3167
3170
.addUse (GR.getSPIRVTypeID (ResType))
3168
3171
.addImm (static_cast <uint32_t >(SPIRV::InstructionSet::GLSL_std_450))
3169
- .addImm (Opcode )
3172
+ .addImm (BitSetOpcode )
3170
3173
.addUse (SrcReg)
3171
3174
.constrainAllUses (TII, TRI, RBI);
3172
3175
}
3173
3176
3174
- bool SPIRVInstructionSelector::selectFirstBitSet64 (
3177
+ bool SPIRVInstructionSelector::selectFirstBitSet64Overflow (
3175
3178
Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
3176
3179
Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
3180
+
3177
3181
unsigned ComponentCount = GR.getScalarOrVectorComponentCount (ResType);
3178
3182
SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType (ResType);
3179
3183
bool ZeroAsNull = STI.isOpenCLEnv ();
3180
3184
Register ConstIntZero =
3181
3185
GR.getOrCreateConstInt (0 , I, BaseType, TII, ZeroAsNull);
3182
- Register ConstIntOne =
3183
- GR.getOrCreateConstInt (1 , I, BaseType, TII, ZeroAsNull);
3186
+ unsigned LeftComponentCount = ComponentCount / 2 ;
3187
+ unsigned RightComponentCount = ComponentCount - LeftComponentCount;
3188
+ bool LeftIsVector = LeftComponentCount > 1 ;
3184
3189
3185
- // SPIRV doesn't support vectors with more than 4 components. Since the
3186
- // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
3187
- // operate on vectors with 2 or less components. When largers vectors are
3188
- // seen. Split them, recurse, then recombine them.
3189
- if (ComponentCount > 2 ) {
3190
- unsigned LeftComponentCount = ComponentCount / 2 ;
3191
- unsigned RightComponentCount = ComponentCount - LeftComponentCount;
3192
- bool LeftIsVector = LeftComponentCount > 1 ;
3193
-
3194
- // Split the SrcReg in half into 2 smaller vec registers
3195
- // (ie i64x4 -> i64x2, i64x2)
3196
- MachineIRBuilder MIRBuilder (I);
3197
- SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType (64 , MIRBuilder);
3198
- SPIRVType *LeftVecOpType;
3199
- SPIRVType *LeftVecResType;
3200
- if (LeftIsVector) {
3201
- LeftVecOpType =
3202
- GR.getOrCreateSPIRVVectorType (OpType, LeftComponentCount, MIRBuilder);
3203
- LeftVecResType = GR.getOrCreateSPIRVVectorType (
3204
- BaseType, LeftComponentCount, MIRBuilder);
3190
+ // Split the SrcReg in half into 2 smaller vec registers
3191
+ // (ie i64x4 -> i64x2, i64x2)
3192
+ MachineIRBuilder MIRBuilder (I);
3193
+ SPIRVType *OpType = GR.getOrCreateSPIRVIntegerType (64 , MIRBuilder);
3194
+ SPIRVType *LeftVecOpType;
3195
+ SPIRVType *LeftVecResType;
3196
+ if (LeftIsVector) {
3197
+ LeftVecOpType =
3198
+ GR.getOrCreateSPIRVVectorType (OpType, LeftComponentCount, MIRBuilder);
3199
+ LeftVecResType =
3200
+ GR.getOrCreateSPIRVVectorType (BaseType, LeftComponentCount, MIRBuilder);
3205
3201
} else {
3206
3202
LeftVecOpType = OpType;
3207
3203
LeftVecResType = BaseType;
@@ -3219,6 +3215,8 @@ bool SPIRVInstructionSelector::selectFirstBitSet64(
3219
3215
3220
3216
bool Result;
3221
3217
3218
+ // Extract the left half from the SrcReg into LeftSideIn
3219
+ // accounting for the special case when it only has one element
3222
3220
if (LeftIsVector) {
3223
3221
auto MIB =
3224
3222
BuildMI (*I.getParent (), I, I.getDebugLoc (),
@@ -3240,6 +3238,9 @@ bool SPIRVInstructionSelector::selectFirstBitSet64(
3240
3238
SPIRV::OpVectorExtractDynamic);
3241
3239
}
3242
3240
3241
+ // Extract the right half from the SrcReg into RightSideIn.
3242
+ // Right will always be a vector since the only time one element is left is
3243
+ // when Component == 3, and in that case Left is one element.
3243
3244
auto MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (),
3244
3245
TII.get (SPIRV::OpVectorShuffle))
3245
3246
.addDef (RightSideIn)
@@ -3254,7 +3255,7 @@ bool SPIRVInstructionSelector::selectFirstBitSet64(
3254
3255
3255
3256
Result = Result && MIB.constrainAllUses (TII, TRI, RBI);
3256
3257
3257
- // Recursively call selectFirstBitSet64 on the 2 registers
3258
+ // Recursively call selectFirstBitSet64 on the 2 halves
3258
3259
Register LeftSideOut =
3259
3260
MRI->createVirtualRegister (GR.getRegClass (LeftVecResType));
3260
3261
Register RightSideOut =
@@ -3271,6 +3272,26 @@ bool SPIRVInstructionSelector::selectFirstBitSet64(
3271
3272
return Result &&
3272
3273
selectOpWithSrcs (ResVReg, ResType, I, {LeftSideOut, RightSideOut},
3273
3274
SPIRV::OpCompositeConstruct);
3275
+ }
3276
+
3277
+ bool SPIRVInstructionSelector::selectFirstBitSet64 (
3278
+ Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
3279
+ Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
3280
+ unsigned ComponentCount = GR.getScalarOrVectorComponentCount (ResType);
3281
+ SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType (ResType);
3282
+ bool ZeroAsNull = STI.isOpenCLEnv ();
3283
+ Register ConstIntZero =
3284
+ GR.getOrCreateConstInt (0 , I, BaseType, TII, ZeroAsNull);
3285
+ Register ConstIntOne =
3286
+ GR.getOrCreateConstInt (1 , I, BaseType, TII, ZeroAsNull);
3287
+
3288
+ // SPIRV doesn't support vectors with more than 4 components. Since the
3289
+ // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
3290
+ // operate on vectors with 2 or less components. When largers vectors are
3291
+ // seen. Split them, recurse, then recombine them.
3292
+ if (ComponentCount > 2 ) {
3293
+ return selectFirstBitSet64Overflow (ResVReg, ResType, I, SrcReg,
3294
+ BitSetOpcode, SwapPrimarySide);
3274
3295
}
3275
3296
3276
3297
// 1. Split int64 into 2 pieces using a bitcast
@@ -3362,6 +3383,9 @@ bool SPIRVInstructionSelector::selectFirstBitSet64(
3362
3383
Register SecondaryReg;
3363
3384
Register PrimaryShiftReg;
3364
3385
Register SecondaryShiftReg;
3386
+
3387
+ // By default the emitted opcodes check for the set bit from the MSB side.
3388
+ // Setting SwapPrimarySide checks the set bit from the LSB side
3365
3389
if (SwapPrimarySide) {
3366
3390
PrimaryReg = LowReg;
3367
3391
SecondaryReg = HighReg;
0 commit comments