@@ -1214,45 +1214,83 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
1214
1214
return 0 ;
1215
1215
}
1216
1216
1217
- static int
1218
- wrp_cmp_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta ,
1219
- enum br_mask br_mask , bool swap )
1217
+ static const struct jmp_code_map {
1218
+ enum br_mask br_mask ;
1219
+ bool swap ;
1220
+ } jmp_code_map [] = {
1221
+ [BPF_JGT >> 4 ] = { BR_BLO , true },
1222
+ [BPF_JGE >> 4 ] = { BR_BHS , false },
1223
+ [BPF_JLT >> 4 ] = { BR_BLO , false },
1224
+ [BPF_JLE >> 4 ] = { BR_BHS , true },
1225
+ [BPF_JSGT >> 4 ] = { BR_BLT , true },
1226
+ [BPF_JSGE >> 4 ] = { BR_BGE , false },
1227
+ [BPF_JSLT >> 4 ] = { BR_BLT , false },
1228
+ [BPF_JSLE >> 4 ] = { BR_BGE , true },
1229
+ };
1230
+
1231
+ static const struct jmp_code_map * nfp_jmp_code_get (struct nfp_insn_meta * meta )
1232
+ {
1233
+ unsigned int op ;
1234
+
1235
+ op = BPF_OP (meta -> insn .code ) >> 4 ;
1236
+ /* br_mask of 0 is BR_BEQ which we don't use in jump code table */
1237
+ if (WARN_ONCE (op >= ARRAY_SIZE (jmp_code_map ) ||
1238
+ !jmp_code_map [op ].br_mask ,
1239
+ "no code found for jump instruction" ))
1240
+ return NULL ;
1241
+
1242
+ return & jmp_code_map [op ];
1243
+ }
1244
+
1245
+ static int cmp_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
1220
1246
{
1221
1247
const struct bpf_insn * insn = & meta -> insn ;
1222
1248
u64 imm = insn -> imm ; /* sign extend */
1249
+ const struct jmp_code_map * code ;
1250
+ enum alu_op alu_op , carry_op ;
1223
1251
u8 reg = insn -> dst_reg * 2 ;
1224
1252
swreg tmp_reg ;
1225
1253
1254
+ code = nfp_jmp_code_get (meta );
1255
+ if (!code )
1256
+ return - EINVAL ;
1257
+
1258
+ alu_op = meta -> jump_neg_op ? ALU_OP_ADD : ALU_OP_SUB ;
1259
+ carry_op = meta -> jump_neg_op ? ALU_OP_ADD_C : ALU_OP_SUB_C ;
1260
+
1226
1261
tmp_reg = ur_load_imm_any (nfp_prog , imm & ~0U , imm_b (nfp_prog ));
1227
- if (!swap )
1228
- emit_alu (nfp_prog , reg_none (), reg_a (reg ), ALU_OP_SUB , tmp_reg );
1262
+ if (!code -> swap )
1263
+ emit_alu (nfp_prog , reg_none (), reg_a (reg ), alu_op , tmp_reg );
1229
1264
else
1230
- emit_alu (nfp_prog , reg_none (), tmp_reg , ALU_OP_SUB , reg_a (reg ));
1265
+ emit_alu (nfp_prog , reg_none (), tmp_reg , alu_op , reg_a (reg ));
1231
1266
1232
1267
tmp_reg = ur_load_imm_any (nfp_prog , imm >> 32 , imm_b (nfp_prog ));
1233
- if (!swap )
1268
+ if (!code -> swap )
1234
1269
emit_alu (nfp_prog , reg_none (),
1235
- reg_a (reg + 1 ), ALU_OP_SUB_C , tmp_reg );
1270
+ reg_a (reg + 1 ), carry_op , tmp_reg );
1236
1271
else
1237
1272
emit_alu (nfp_prog , reg_none (),
1238
- tmp_reg , ALU_OP_SUB_C , reg_a (reg + 1 ));
1273
+ tmp_reg , carry_op , reg_a (reg + 1 ));
1239
1274
1240
- emit_br (nfp_prog , br_mask , insn -> off , 0 );
1275
+ emit_br (nfp_prog , code -> br_mask , insn -> off , 0 );
1241
1276
1242
1277
return 0 ;
1243
1278
}
1244
1279
1245
- static int
1246
- wrp_cmp_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta ,
1247
- enum br_mask br_mask , bool swap )
1280
+ static int cmp_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
1248
1281
{
1249
1282
const struct bpf_insn * insn = & meta -> insn ;
1283
+ const struct jmp_code_map * code ;
1250
1284
u8 areg , breg ;
1251
1285
1286
+ code = nfp_jmp_code_get (meta );
1287
+ if (!code )
1288
+ return - EINVAL ;
1289
+
1252
1290
areg = insn -> dst_reg * 2 ;
1253
1291
breg = insn -> src_reg * 2 ;
1254
1292
1255
- if (swap ) {
1293
+ if (code -> swap ) {
1256
1294
areg ^= breg ;
1257
1295
breg ^= areg ;
1258
1296
areg ^= breg ;
@@ -1261,7 +1299,7 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
1261
1299
emit_alu (nfp_prog , reg_none (), reg_a (areg ), ALU_OP_SUB , reg_b (breg ));
1262
1300
emit_alu (nfp_prog , reg_none (),
1263
1301
reg_a (areg + 1 ), ALU_OP_SUB_C , reg_b (breg + 1 ));
1264
- emit_br (nfp_prog , br_mask , insn -> off , 0 );
1302
+ emit_br (nfp_prog , code -> br_mask , insn -> off , 0 );
1265
1303
1266
1304
return 0 ;
1267
1305
}
@@ -1400,7 +1438,7 @@ map_call_stack_common(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1400
1438
if (!load_lm_ptr )
1401
1439
return 0 ;
1402
1440
1403
- emit_csr_wr (nfp_prog , stack_reg (nfp_prog ), NFP_CSR_ACT_LM_ADDR0 );
1441
+ emit_csr_wr (nfp_prog , stack_reg (nfp_prog ), NFP_CSR_ACT_LM_ADDR0 );
1404
1442
wrp_nops (nfp_prog , 3 );
1405
1443
1406
1444
return 0 ;
@@ -2283,46 +2321,6 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
2283
2321
return 0 ;
2284
2322
}
2285
2323
2286
- static int jgt_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2287
- {
2288
- return wrp_cmp_imm (nfp_prog , meta , BR_BLO , true);
2289
- }
2290
-
2291
- static int jge_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2292
- {
2293
- return wrp_cmp_imm (nfp_prog , meta , BR_BHS , false);
2294
- }
2295
-
2296
- static int jlt_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2297
- {
2298
- return wrp_cmp_imm (nfp_prog , meta , BR_BLO , false);
2299
- }
2300
-
2301
- static int jle_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2302
- {
2303
- return wrp_cmp_imm (nfp_prog , meta , BR_BHS , true);
2304
- }
2305
-
2306
- static int jsgt_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2307
- {
2308
- return wrp_cmp_imm (nfp_prog , meta , BR_BLT , true);
2309
- }
2310
-
2311
- static int jsge_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2312
- {
2313
- return wrp_cmp_imm (nfp_prog , meta , BR_BGE , false);
2314
- }
2315
-
2316
- static int jslt_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2317
- {
2318
- return wrp_cmp_imm (nfp_prog , meta , BR_BLT , false);
2319
- }
2320
-
2321
- static int jsle_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2322
- {
2323
- return wrp_cmp_imm (nfp_prog , meta , BR_BGE , true);
2324
- }
2325
-
2326
2324
static int jset_imm (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2327
2325
{
2328
2326
const struct bpf_insn * insn = & meta -> insn ;
@@ -2392,46 +2390,6 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
2392
2390
return 0 ;
2393
2391
}
2394
2392
2395
- static int jgt_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2396
- {
2397
- return wrp_cmp_reg (nfp_prog , meta , BR_BLO , true);
2398
- }
2399
-
2400
- static int jge_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2401
- {
2402
- return wrp_cmp_reg (nfp_prog , meta , BR_BHS , false);
2403
- }
2404
-
2405
- static int jlt_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2406
- {
2407
- return wrp_cmp_reg (nfp_prog , meta , BR_BLO , false);
2408
- }
2409
-
2410
- static int jle_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2411
- {
2412
- return wrp_cmp_reg (nfp_prog , meta , BR_BHS , true);
2413
- }
2414
-
2415
- static int jsgt_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2416
- {
2417
- return wrp_cmp_reg (nfp_prog , meta , BR_BLT , true);
2418
- }
2419
-
2420
- static int jsge_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2421
- {
2422
- return wrp_cmp_reg (nfp_prog , meta , BR_BGE , false);
2423
- }
2424
-
2425
- static int jslt_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2426
- {
2427
- return wrp_cmp_reg (nfp_prog , meta , BR_BLT , false);
2428
- }
2429
-
2430
- static int jsle_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2431
- {
2432
- return wrp_cmp_reg (nfp_prog , meta , BR_BGE , true);
2433
- }
2434
-
2435
2393
static int jset_reg (struct nfp_prog * nfp_prog , struct nfp_insn_meta * meta )
2436
2394
{
2437
2395
return wrp_test_reg (nfp_prog , meta , ALU_OP_AND , BR_BNE );
@@ -2520,25 +2478,25 @@ static const instr_cb_t instr_cb[256] = {
2520
2478
[BPF_ST | BPF_MEM | BPF_DW ] = mem_st8 ,
2521
2479
[BPF_JMP | BPF_JA | BPF_K ] = jump ,
2522
2480
[BPF_JMP | BPF_JEQ | BPF_K ] = jeq_imm ,
2523
- [BPF_JMP | BPF_JGT | BPF_K ] = jgt_imm ,
2524
- [BPF_JMP | BPF_JGE | BPF_K ] = jge_imm ,
2525
- [BPF_JMP | BPF_JLT | BPF_K ] = jlt_imm ,
2526
- [BPF_JMP | BPF_JLE | BPF_K ] = jle_imm ,
2527
- [BPF_JMP | BPF_JSGT | BPF_K ] = jsgt_imm ,
2528
- [BPF_JMP | BPF_JSGE | BPF_K ] = jsge_imm ,
2529
- [BPF_JMP | BPF_JSLT | BPF_K ] = jslt_imm ,
2530
- [BPF_JMP | BPF_JSLE | BPF_K ] = jsle_imm ,
2481
+ [BPF_JMP | BPF_JGT | BPF_K ] = cmp_imm ,
2482
+ [BPF_JMP | BPF_JGE | BPF_K ] = cmp_imm ,
2483
+ [BPF_JMP | BPF_JLT | BPF_K ] = cmp_imm ,
2484
+ [BPF_JMP | BPF_JLE | BPF_K ] = cmp_imm ,
2485
+ [BPF_JMP | BPF_JSGT | BPF_K ] = cmp_imm ,
2486
+ [BPF_JMP | BPF_JSGE | BPF_K ] = cmp_imm ,
2487
+ [BPF_JMP | BPF_JSLT | BPF_K ] = cmp_imm ,
2488
+ [BPF_JMP | BPF_JSLE | BPF_K ] = cmp_imm ,
2531
2489
[BPF_JMP | BPF_JSET | BPF_K ] = jset_imm ,
2532
2490
[BPF_JMP | BPF_JNE | BPF_K ] = jne_imm ,
2533
2491
[BPF_JMP | BPF_JEQ | BPF_X ] = jeq_reg ,
2534
- [BPF_JMP | BPF_JGT | BPF_X ] = jgt_reg ,
2535
- [BPF_JMP | BPF_JGE | BPF_X ] = jge_reg ,
2536
- [BPF_JMP | BPF_JLT | BPF_X ] = jlt_reg ,
2537
- [BPF_JMP | BPF_JLE | BPF_X ] = jle_reg ,
2538
- [BPF_JMP | BPF_JSGT | BPF_X ] = jsgt_reg ,
2539
- [BPF_JMP | BPF_JSGE | BPF_X ] = jsge_reg ,
2540
- [BPF_JMP | BPF_JSLT | BPF_X ] = jslt_reg ,
2541
- [BPF_JMP | BPF_JSLE | BPF_X ] = jsle_reg ,
2492
+ [BPF_JMP | BPF_JGT | BPF_X ] = cmp_reg ,
2493
+ [BPF_JMP | BPF_JGE | BPF_X ] = cmp_reg ,
2494
+ [BPF_JMP | BPF_JLT | BPF_X ] = cmp_reg ,
2495
+ [BPF_JMP | BPF_JLE | BPF_X ] = cmp_reg ,
2496
+ [BPF_JMP | BPF_JSGT | BPF_X ] = cmp_reg ,
2497
+ [BPF_JMP | BPF_JSGE | BPF_X ] = cmp_reg ,
2498
+ [BPF_JMP | BPF_JSLT | BPF_X ] = cmp_reg ,
2499
+ [BPF_JMP | BPF_JSLE | BPF_X ] = cmp_reg ,
2542
2500
[BPF_JMP | BPF_JSET | BPF_X ] = jset_reg ,
2543
2501
[BPF_JMP | BPF_JNE | BPF_X ] = jne_reg ,
2544
2502
[BPF_JMP | BPF_CALL ] = call ,
@@ -2777,6 +2735,54 @@ static void nfp_bpf_opt_reg_init(struct nfp_prog *nfp_prog)
2777
2735
}
2778
2736
}
2779
2737
2738
+ /* abs(insn.imm) will fit better into unrestricted reg immediate -
2739
+ * convert add/sub of a negative number into a sub/add of a positive one.
2740
+ */
2741
+ static void nfp_bpf_opt_neg_add_sub (struct nfp_prog * nfp_prog )
2742
+ {
2743
+ struct nfp_insn_meta * meta ;
2744
+
2745
+ list_for_each_entry (meta , & nfp_prog -> insns , l ) {
2746
+ struct bpf_insn insn = meta -> insn ;
2747
+
2748
+ if (meta -> skip )
2749
+ continue ;
2750
+
2751
+ if (BPF_CLASS (insn .code ) != BPF_ALU &&
2752
+ BPF_CLASS (insn .code ) != BPF_ALU64 &&
2753
+ BPF_CLASS (insn .code ) != BPF_JMP )
2754
+ continue ;
2755
+ if (BPF_SRC (insn .code ) != BPF_K )
2756
+ continue ;
2757
+ if (insn .imm >= 0 )
2758
+ continue ;
2759
+
2760
+ if (BPF_CLASS (insn .code ) == BPF_JMP ) {
2761
+ switch (BPF_OP (insn .code )) {
2762
+ case BPF_JGE :
2763
+ case BPF_JSGE :
2764
+ case BPF_JLT :
2765
+ case BPF_JSLT :
2766
+ meta -> jump_neg_op = true;
2767
+ break ;
2768
+ default :
2769
+ continue ;
2770
+ }
2771
+ } else {
2772
+ if (BPF_OP (insn .code ) == BPF_ADD )
2773
+ insn .code = BPF_CLASS (insn .code ) | BPF_SUB ;
2774
+ else if (BPF_OP (insn .code ) == BPF_SUB )
2775
+ insn .code = BPF_CLASS (insn .code ) | BPF_ADD ;
2776
+ else
2777
+ continue ;
2778
+
2779
+ meta -> insn .code = insn .code | BPF_K ;
2780
+ }
2781
+
2782
+ meta -> insn .imm = - insn .imm ;
2783
+ }
2784
+ }
2785
+
2780
2786
/* Remove masking after load since our load guarantees this is not needed */
2781
2787
static void nfp_bpf_opt_ld_mask (struct nfp_prog * nfp_prog )
2782
2788
{
@@ -3212,6 +3218,7 @@ static int nfp_bpf_optimize(struct nfp_prog *nfp_prog)
3212
3218
{
3213
3219
nfp_bpf_opt_reg_init (nfp_prog );
3214
3220
3221
+ nfp_bpf_opt_neg_add_sub (nfp_prog );
3215
3222
nfp_bpf_opt_ld_mask (nfp_prog );
3216
3223
nfp_bpf_opt_ld_shift (nfp_prog );
3217
3224
nfp_bpf_opt_ldst_gather (nfp_prog );
0 commit comments