Skip to content

Missed optimization (unnecessary sext): y >= x should imply y - x >= 0 #142283

Open
@Explorer09

Description

@Explorer09

Test code

#include <stdint.h>
extern void subroutine(uint64_t x);

void func1(int32_t a, int32_t b) {
   if (a > b)
      return;
   subroutine(b - a);
}

void func2(int32_t a, int32_t b) {
   if (a > b)
      return;
   subroutine((uint64_t)(int32_t)(b - a));
}

void func3(int32_t a, int32_t b) {
   if (a > b)
      return;
   subroutine((uint64_t)(uint32_t)(b - a));
}

uint64_t func4(int32_t a, int32_t b) {
   if (a > b)
      return 0;
   return (b - a);
}

uint64_t func5(int32_t a, int32_t b) {
   if (a > b)
      return 0;
   return (uint64_t)(int32_t)(b - a);
}

uint64_t func6(int32_t a, int32_t b) {
   if (a > b)
      return 0;
   return (uint64_t)(uint32_t)(b - a);
}

Actual result (x86-64 clang 20.1.0 with -Os option): func1, func2, func4 and func5 made unnecessary sign extensions (movsxd instruction). (https://godbolt.org/z/s3zvnET5e)

Expected result: func1, func2 and func3 compile to same code. func4, func5 and func6 compile to same code.

After the (a > b) conditional, Clang should be able to know that (a <= b), which in turn implies (0 <= b - a). In other words, (b - a) would be always nonnegative.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions