Skip to content

missing instcombine: select (icmp ugt A, N), (shr A, M), 0 -> shr A, M, when N < 2^M #54089

@zygoloid

Description

@zygoloid

Example, seen in the wild in libcap-ng:

void f(int, int);
void g(unsigned int capability) {
 	int idx;

	if (capability > 31) {
		idx = capability>>5;
		capability %= 32;
	} else
		idx = 0;

        f(idx, capability);
}

produces:

define dso_local void @g(i32 noundef %0) local_unnamed_addr #0 {
  %2 = icmp ugt i32 %0, 31
  %3 = lshr i32 %0, 5
  %4 = and i32 %0, 31
  %5 = select i1 %2, i32 %3, i32 0
  tail call void @f(i32 noundef %5, i32 noundef %4) #2
  ret void
}

This could be optimized further to:

define dso_local void @g(i32 noundef %0) local_unnamed_addr #0 {
  %1 = lshr i32 %0, 5
  %2 = and i32 %0, 31
  tail call void @f(i32 noundef %1, i32 noundef %2) #2
  ret void
}

The general pattern here is:

select (icmp ugt A, N), (shr A, M), 0 -> shr A, M

whenever N < 2M.

Metadata

Metadata

Assignees

No one assigned

    Labels

    llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions