https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106602
--- Comment #5 from Vineet Gupta <vineetg at rivosinc dot com> --- Gimple for the test is _1 = a_2(D) << 6; _3 = _1 & 274877906880; // 0x3f_ffff_ffc0 And 0x3f_ffff_ffc0 = 0x40_0000_0000 - 0x40 For !TARGET_ZBA there's a combiner pattern to match the seq of instruction generated normally: define_insn_and_split "zero_extendsidi2_shifted" Trying 7, 8, 6 -> 9: 7: r78:DI=0x4000000000 8: r77:DI=r78:DI-0x40 REG_DEAD r78:DI REG_EQUAL 0x3fffffffc0 6: r76:DI=r79:DI<<0x6 REG_DEAD r79:DI 9: r75:DI=r76:DI&r77:DI Successfully matched this instruction: (set (reg:DI 75) (and:DI (ashift:DI (reg:DI 79) (const_int 6 [0x6])) (const_int 274877906880 [0x3fffffffc0]))) However for !bitmanip, RTL expansion splittable_const_int_operand() breaks up 0x40_0000_0000 into 1 << 38 (insn 7 6 8 2 (set (reg:DI 78) (const_int 1 [0x1])) (insn 8 7 9 2 (set (reg:DI 79) (ashift:DI (reg:DI 78) (const_int 38 [0x26]))) So we end up with 5 tot insn, which combine can't And splittable_const_int_operand() has following check if (TARGET_64BIT && TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (INTVAL (op))) return false; which explains why 1. zba alone doesn't generate slli.uw 2. zbs generates optimal slli+srli although these have nothing to do with zbs