@@ -3123,6 +3123,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)
3123
3123
assert (!op2->isUsedFromMemory ());
3124
3124
3125
3125
emitAttr cmpSize = EA_ATTR (genTypeSize (op1Type));
3126
+ assert (cmpSize == EA_4BYTE || cmpSize == EA_8BYTE);
3126
3127
3127
3128
assert (genTypeSize (op1Type) == genTypeSize (op2Type));
3128
3129
@@ -3205,192 +3206,126 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)
3205
3206
{
3206
3207
ssize_t imm = op2->AsIntCon ()->gtIconVal ;
3207
3208
3208
- switch (cmpSize)
3209
+ bool useAddSub = !(!tree->OperIs (GT_EQ, GT_NE) || (imm == -2048 ));
3210
+ bool useShiftRight =
3211
+ !isUnsigned && ((tree->OperIs (GT_LT) && (imm == 0 )) || (tree->OperIs (GT_LE) && (imm == -1 )));
3212
+ bool useLoadImm = isUnsigned && ((tree->OperIs (GT_LT, GT_GE) && (imm == 0 )) ||
3213
+ (tree->OperIs (GT_LE, GT_GT) && (imm == -1 )));
3214
+
3215
+ if (cmpSize == EA_4BYTE)
3209
3216
{
3210
- case EA_4BYTE:
3217
+ if (!useAddSub && !useShiftRight && !useLoadImm)
3211
3218
{
3212
3219
regNumber tmpRegOp1 = internalRegisters.GetSingle (tree);
3213
3220
assert (regOp1 != tmpRegOp1);
3214
- if (isUnsigned)
3215
- {
3216
- imm = static_cast <uint32_t >(imm);
3217
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32 );
3218
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32 );
3219
- }
3220
- else
3221
- {
3222
- imm = static_cast <int32_t >(imm);
3223
- emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3224
- }
3221
+ imm = static_cast <int32_t >(imm);
3222
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3225
3223
regOp1 = tmpRegOp1;
3226
- break ;
3227
3224
}
3228
- case EA_8BYTE:
3229
- break ;
3230
- default :
3231
- unreached ();
3232
3225
}
3233
3226
3234
- if (tree->OperIs (GT_LT))
3235
- {
3236
- if (!isUnsigned && emitter::isValidSimm12 (imm))
3237
- {
3238
- emit->emitIns_R_R_I (INS_slti, EA_PTRSIZE, targetReg, regOp1, imm);
3239
- }
3240
- else if (isUnsigned && emitter::isValidUimm11 (imm))
3241
- {
3242
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, imm);
3243
- }
3244
- else
3245
- {
3246
- emit->emitLoadImmediate (EA_PTRSIZE, REG_RA, imm);
3247
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA);
3248
- }
3249
- }
3250
- else if (tree->OperIs (GT_LE))
3251
- {
3252
- if (!isUnsigned && emitter::isValidSimm12 (imm + 1 ))
3253
- {
3254
- emit->emitIns_R_R_I (INS_slti, EA_PTRSIZE, targetReg, regOp1, imm + 1 );
3255
- }
3256
- else if (isUnsigned && emitter::isValidUimm11 (imm + 1 ) && (imm != (~0 )))
3257
- {
3258
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, imm + 1 );
3259
- }
3260
- else
3261
- {
3262
- emit->emitLoadImmediate (EA_PTRSIZE, REG_RA, imm + 1 );
3263
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA);
3264
- }
3265
- }
3266
- else if (tree->OperIs (GT_GT))
3227
+ if (tree->OperIs (GT_EQ, GT_NE))
3267
3228
{
3268
- if (!isUnsigned && emitter::isValidSimm12 (imm + 1 ))
3229
+ if ((imm != 0 ) || (cmpSize == EA_4BYTE ))
3269
3230
{
3270
- emit->emitIns_R_R_I (INS_slti, EA_PTRSIZE, targetReg, regOp1, imm + 1 );
3271
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3231
+ instruction diff = INS_xori;
3232
+ if (imm != -2048 )
3233
+ {
3234
+ assert (useAddSub);
3235
+ diff = (cmpSize == EA_4BYTE) ? INS_addiw : INS_addi;
3236
+ imm = -imm;
3237
+ }
3238
+ emit->emitIns_R_R_I (diff, cmpSize, targetReg, regOp1, imm);
3239
+ regOp1 = targetReg;
3272
3240
}
3273
- else if (isUnsigned && emitter::isValidUimm11 (imm + 1 ) && (imm != (~0 )))
3241
+ assert (emitter::isValidSimm12 (imm));
3242
+
3243
+ if (tree->OperIs (GT_EQ))
3274
3244
{
3275
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, imm + 1 );
3276
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3245
+ emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, 1 );
3277
3246
}
3278
3247
else
3279
3248
{
3280
- emit-> emitLoadImmediate (EA_PTRSIZE, REG_RA, imm );
3281
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt , EA_PTRSIZE, targetReg, REG_RA , regOp1);
3249
+ assert (tree-> OperIs (GT_NE) );
3250
+ emit->emitIns_R_R_R (INS_sltu, EA_PTRSIZE, targetReg, REG_ZERO , regOp1);
3282
3251
}
3283
3252
}
3284
- else if (tree-> OperIs (GT_GE))
3253
+ else
3285
3254
{
3286
- if (!isUnsigned && emitter::isValidSimm12 (imm))
3287
- {
3288
- emit->emitIns_R_R_I (INS_slti, EA_PTRSIZE, targetReg, regOp1, imm);
3289
- }
3290
- else if (isUnsigned && emitter::isValidUimm11 (imm))
3291
- {
3292
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, imm);
3293
- }
3294
- else
3255
+ assert (tree->OperIs (GT_LT, GT_LE, GT_GT, GT_GE));
3256
+ if (useLoadImm)
3295
3257
{
3296
- emit->emitLoadImmediate (EA_PTRSIZE, REG_RA, imm);
3297
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA);
3258
+ // unsigned (a <= ~0), (a >= 0) / (a > ~0), (a < 0) is always true / false
3259
+ imm = tree->OperIs (GT_GE, GT_LE) ? 1 : 0 ;
3260
+ emit->emitIns_R_R_I (INS_addi, EA_PTRSIZE, targetReg, REG_ZERO, imm);
3298
3261
}
3299
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3300
- }
3301
- else if (tree->OperIs (GT_NE))
3302
- {
3303
- if (!imm)
3262
+ else if (useShiftRight)
3304
3263
{
3305
- emit->emitIns_R_R_R (INS_sltu, EA_PTRSIZE, targetReg, REG_R0, regOp1);
3264
+ // signed (a < 0) or (a <= -1) is just the sign bit
3265
+ instruction srli = (cmpSize == EA_4BYTE) ? INS_srliw : INS_srli;
3266
+ emit->emitIns_R_R_I (srli, cmpSize, targetReg, regOp1, cmpSize * 8 - 1 );
3306
3267
}
3307
- else if (emitter::isValidUimm12 ( imm))
3268
+ else if ((tree-> OperIs (GT_GT) && ( imm == 0 )) || (tree-> OperIs (GT_GE) && (imm == 1 ) ))
3308
3269
{
3309
- emit-> emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, regOp1, imm) ;
3310
- emit->emitIns_R_R_R (INS_sltu , EA_PTRSIZE, targetReg, REG_R0, targetReg );
3270
+ instruction slt = isUnsigned ? INS_sltu : INS_slt ;
3271
+ emit->emitIns_R_R_R (slt , EA_PTRSIZE, targetReg, REG_ZERO, regOp1 );
3311
3272
}
3312
3273
else
3313
3274
{
3314
- emit->emitLoadImmediate (EA_PTRSIZE, REG_RA, imm);
3315
- emit->emitIns_R_R_R (INS_xor, EA_PTRSIZE, targetReg, regOp1, REG_RA);
3316
- emit->emitIns_R_R_R (INS_sltu, EA_PTRSIZE, targetReg, REG_R0, targetReg);
3317
- }
3318
- }
3319
- else if (tree->OperIs (GT_EQ))
3320
- {
3321
- if (!imm)
3322
- {
3323
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, regOp1, 1 );
3324
- }
3325
- else if (emitter::isValidUimm12 (imm))
3326
- {
3327
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, regOp1, imm);
3328
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, targetReg, 1 );
3329
- }
3330
- else
3331
- {
3332
- emit->emitLoadImmediate (EA_PTRSIZE, REG_RA, imm);
3333
- emit->emitIns_R_R_R (INS_xor, EA_PTRSIZE, targetReg, regOp1, REG_RA);
3334
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, targetReg, 1 );
3275
+ instruction slti = isUnsigned ? INS_sltiu : INS_slti;
3276
+ if (tree->OperIs (GT_LE, GT_GT))
3277
+ imm += 1 ;
3278
+ assert (emitter::isValidSimm12 (imm));
3279
+ assert (!isUnsigned || (imm != 0 )); // should be handled in useLoadImm
3280
+
3281
+ emit->emitIns_R_R_I (slti, EA_PTRSIZE, targetReg, regOp1, imm);
3282
+
3283
+ if (tree->OperIs (GT_GT, GT_GE))
3284
+ emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3335
3285
}
3336
3286
}
3337
3287
}
3338
3288
else
3339
3289
{
3340
3290
regNumber regOp2 = op2->GetRegNum ();
3341
3291
3342
- if (cmpSize == EA_4BYTE )
3292
+ if (tree-> OperIs (GT_EQ, GT_NE) )
3343
3293
{
3344
- regNumber tmpRegOp1 = REG_RA;
3345
- regNumber tmpRegOp2 = internalRegisters.GetSingle (tree);
3346
- assert (regOp1 != tmpRegOp2);
3347
- assert (regOp2 != tmpRegOp2);
3348
-
3349
- if (isUnsigned)
3294
+ instruction sub = (cmpSize == EA_4BYTE) ? INS_subw : INS_sub;
3295
+ emit->emitIns_R_R_R (sub, EA_PTRSIZE, targetReg, regOp1, regOp2);
3296
+ if (tree->OperIs (GT_EQ))
3350
3297
{
3351
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32 );
3352
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32 );
3353
-
3354
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp2, regOp2, 32 );
3355
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp2, tmpRegOp2, 32 );
3298
+ emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, targetReg, 1 );
3356
3299
}
3357
3300
else
3358
3301
{
3359
- emit-> emitIns_R_R_I (INS_slliw, EA_8BYTE, tmpRegOp1, regOp1, 0 );
3360
- emit->emitIns_R_R_I (INS_slliw, EA_8BYTE, tmpRegOp2, regOp2, 0 );
3302
+ assert (tree-> OperIs (GT_NE) );
3303
+ emit->emitIns_R_R_R (INS_sltu, EA_PTRSIZE, targetReg, REG_ZERO, targetReg );
3361
3304
}
3362
-
3363
- regOp1 = tmpRegOp1;
3364
- regOp2 = tmpRegOp2;
3365
- }
3366
-
3367
- if (tree->OperIs (GT_LT))
3368
- {
3369
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_8BYTE, targetReg, regOp1, regOp2);
3370
- }
3371
- else if (tree->OperIs (GT_LE))
3372
- {
3373
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_8BYTE, targetReg, regOp2, regOp1);
3374
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3375
- }
3376
- else if (tree->OperIs (GT_GT))
3377
- {
3378
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_8BYTE, targetReg, regOp2, regOp1);
3379
3305
}
3380
- else if (tree->OperIs (GT_GE))
3381
- {
3382
- emit->emitIns_R_R_R (isUnsigned ? INS_sltu : INS_slt, EA_8BYTE, targetReg, regOp1, regOp2);
3383
- emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3384
- }
3385
- else if (tree->OperIs (GT_NE))
3386
- {
3387
- emit->emitIns_R_R_R (INS_xor, EA_PTRSIZE, targetReg, regOp1, regOp2);
3388
- emit->emitIns_R_R_R (INS_sltu, EA_PTRSIZE, targetReg, REG_R0, targetReg);
3389
- }
3390
- else if (tree->OperIs (GT_EQ))
3306
+ else
3391
3307
{
3392
- emit->emitIns_R_R_R (INS_xor, EA_PTRSIZE, targetReg, regOp1, regOp2);
3393
- emit->emitIns_R_R_I (INS_sltiu, EA_PTRSIZE, targetReg, targetReg, 1 );
3308
+ assert (tree->OperIs (GT_LT, GT_LE, GT_GT, GT_GE));
3309
+ if (cmpSize == EA_4BYTE)
3310
+ {
3311
+ regNumber tmpRegOp1 = REG_RA;
3312
+ regNumber tmpRegOp2 = internalRegisters.GetSingle (tree);
3313
+ assert (regOp1 != tmpRegOp2);
3314
+ assert (regOp2 != tmpRegOp2);
3315
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3316
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp2, regOp2);
3317
+ regOp1 = tmpRegOp1;
3318
+ regOp2 = tmpRegOp2;
3319
+ }
3320
+
3321
+ instruction slt = isUnsigned ? INS_sltu : INS_slt;
3322
+ if (tree->OperIs (GT_LE, GT_GT))
3323
+ std::swap (regOp1, regOp2);
3324
+
3325
+ emit->emitIns_R_R_R (slt, EA_8BYTE, targetReg, regOp1, regOp2);
3326
+
3327
+ if (tree->OperIs (GT_LE, GT_GE))
3328
+ emit->emitIns_R_R_I (INS_xori, EA_PTRSIZE, targetReg, targetReg, 1 );
3394
3329
}
3395
3330
}
3396
3331
}
@@ -3452,19 +3387,8 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
3452
3387
{
3453
3388
regNumber tmpRegOp1 = rsGetRsvdReg ();
3454
3389
assert (regOp1 != tmpRegOp1);
3455
- if (cond.IsUnsigned ())
3456
- {
3457
- imm = static_cast <uint32_t >(imm);
3458
-
3459
- assert (regOp1 != tmpRegOp1);
3460
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32 );
3461
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32 );
3462
- }
3463
- else
3464
- {
3465
- imm = static_cast <int32_t >(imm);
3466
- emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3467
- }
3390
+ imm = static_cast <int32_t >(imm);
3391
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3468
3392
regOp1 = tmpRegOp1;
3469
3393
break ;
3470
3394
}
@@ -3500,15 +3424,7 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
3500
3424
{
3501
3425
regNumber tmpRegOp1 = rsGetRsvdReg ();
3502
3426
assert (regOp1 != tmpRegOp1);
3503
- if (cond.IsUnsigned ())
3504
- {
3505
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32 );
3506
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32 );
3507
- }
3508
- else
3509
- {
3510
- emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3511
- }
3427
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3512
3428
regOp1 = tmpRegOp1;
3513
3429
}
3514
3430
}
@@ -3557,20 +3473,8 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
3557
3473
regNumber tmpRegOp2 = rsGetRsvdReg ();
3558
3474
assert (regOp1 != tmpRegOp2);
3559
3475
assert (regOp2 != tmpRegOp2);
3560
-
3561
- if (cond.IsUnsigned ())
3562
- {
3563
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32 );
3564
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32 );
3565
- emit->emitIns_R_R_I (INS_slli, EA_8BYTE, tmpRegOp2, regOp2, 32 );
3566
- emit->emitIns_R_R_I (INS_srli, EA_8BYTE, tmpRegOp2, tmpRegOp2, 32 );
3567
- }
3568
- else
3569
- {
3570
- emit->emitIns_R_R_I (INS_slliw, EA_8BYTE, tmpRegOp1, regOp1, 0 );
3571
- emit->emitIns_R_R_I (INS_slliw, EA_8BYTE, tmpRegOp2, regOp2, 0 );
3572
- }
3573
-
3476
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
3477
+ emit->emitIns_R_R (INS_sext_w, EA_8BYTE, tmpRegOp2, regOp2);
3574
3478
regOp1 = tmpRegOp1;
3575
3479
regOp2 = tmpRegOp2;
3576
3480
}
0 commit comments