From 9c604a0dd6387225e4a612ff84007a2a23149174 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 27 Sep 2019 19:32:43 +0000 Subject: [PATCH] [NFC][PhaseOrdering] Add end-to-end tests for the 'two shifts by sext' problem We start with two separate sext's, but EarlyCSE runs before InstCombine, so when we get them, they are a single sext, and we just ignore that. Likewise, if we had a single sext, we don't do anything there. llvm-svn: 373115 --- .../Transforms/PhaseOrdering/two-shifts-by-sext.ll | 125 +++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll diff --git a/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll b/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll new file mode 100644 index 0000000..4d4a30e --- /dev/null +++ b/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll @@ -0,0 +1,125 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -O1 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-01 +; RUN: opt -O2 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-02 +; RUN: opt -O3 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-03 + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; int two_shifts_by_sext(int val, char len) { +; return (val << len) >> len; +; } +; +; int two_shifts_by_same_sext(int val, char len) { +; int wide_len = len; +; return (val << wide_len) >> wide_len; +; } +; +; void use_int32(int); +; int two_shifts_by_sext_with_extra_use(int val, char len) { +; use_int32(len); +; return (val << len) >> len; +; } +; +; int two_shifts_by_same_sext_with_extra_use(int val, char len) { +; int wide_len = len; +; use_int32(wide_len); +; return (val << wide_len) >> wide_len; +; } + +define i32 @two_shifts_by_sext(i32 %val, i8 signext %len) { +; CHECK-LABEL: @two_shifts_by_sext( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32 +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]] +; CHECK-NEXT: ret i32 [[SHR]] +; + %val.addr = alloca i32, align 4 + %len.addr = alloca i8, align 1 + store i32 %val, i32* %val.addr, align 4 + store i8 %len, i8* %len.addr, align 1 + %val.reloaded = load i32, i32* %val.addr, align 4 + %len.reloaded.0 = load i8, i8* %len.addr, align 1 + %conv = sext i8 %len.reloaded.0 to i32 + %shl = shl i32 %val.reloaded, %conv + %len.reloaded.1 = load i8, i8* %len.addr, align 1 + %conv1 = sext i8 %len.reloaded.1 to i32 + %shr = ashr i32 %shl, %conv1 + ret i32 %shr +} + +define i32 @two_shifts_by_same_sext(i32 %val, i8 signext %len) { +; CHECK-LABEL: @two_shifts_by_same_sext( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32 +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]] +; CHECK-NEXT: ret i32 [[SHR]] +; + %val.addr = alloca i32, align 4 + %len.addr = alloca i8, align 1 + %wide_len = alloca i32, align 4 + store i32 %val, i32* %val.addr, align 4 + store i8 %len, i8* %len.addr, align 1 + %len.reloaded.0 = load i8, i8* %len.addr, align 1 + %conv = sext i8 %len.reloaded.0 to i32 + store i32 %conv, i32* %wide_len, align 4 + %val.reloaded = load i32, i32* %val.addr, align 4 + %len.reloaded.1 = load i32, i32* %wide_len, align 4 + %shl = shl i32 %val.reloaded, %len.reloaded.1 + %len.reloaded.2 = load i32, i32* %wide_len, align 4 + %shr = ashr i32 %shl, %len.reloaded.2 + ret i32 %shr +} + +define i32 @two_shifts_by_sext_with_extra_use(i32 %val, i8 signext %len) { +; CHECK-LABEL: @two_shifts_by_sext_with_extra_use( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32 +; CHECK-NEXT: tail call void @use_int32(i32 [[CONV]]) +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]] +; CHECK-NEXT: ret i32 [[SHR]] +; + %val.addr = alloca i32, align 4 + %len.addr = alloca i8, align 1 + store i32 %val, i32* %val.addr, align 4 + store i8 %len, i8* %len.addr, align 1 + %len.reloaded.0 = load i8, i8* %len.addr, align 1 + %conv = sext i8 %len.reloaded.0 to i32 + call void @use_int32(i32 %conv) + %val.reloaded = load i32, i32* %val.addr, align 4 + %len.reloaded.1 = load i8, i8* %len.addr, align 1 + %conv1 = sext i8 %len.reloaded.1 to i32 + %shl = shl i32 %val.reloaded, %conv1 + %len.reloaded.2 = load i8, i8* %len.addr, align 1 + %conv2 = sext i8 %len.reloaded.2 to i32 + %shr = ashr i32 %shl, %conv2 + ret i32 %shr +} + +declare void @use_int32(i32) + +define i32 @two_shifts_by_same_sext_with_extra_use(i32 %val, i8 signext %len) { +; CHECK-LABEL: @two_shifts_by_same_sext_with_extra_use( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32 +; CHECK-NEXT: tail call void @use_int32(i32 [[CONV]]) +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]] +; CHECK-NEXT: ret i32 [[SHR]] +; + %val.addr = alloca i32, align 4 + %len.addr = alloca i8, align 1 + %wide_len = alloca i32, align 4 + store i32 %val, i32* %val.addr, align 4 + store i8 %len, i8* %len.addr, align 1 + %len.reloaded.0 = load i8, i8* %len.addr, align 1 + %conv = sext i8 %len.reloaded.0 to i32 + store i32 %conv, i32* %wide_len, align 4 + %val.reloaded = load i32, i32* %wide_len, align 4 + call void @use_int32(i32 %val.reloaded) + %len.reloaded.1 = load i32, i32* %val.addr, align 4 + %len.reloaded.2 = load i32, i32* %wide_len, align 4 + %shl = shl i32 %len.reloaded.1, %len.reloaded.2 + %wide_len.reloaded = load i32, i32* %wide_len, align 4 + %shr = ashr i32 %shl, %wide_len.reloaded + ret i32 %shr +} -- 2.7.4