| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name _ --version 5 |
| ; Vary legal integer types in data layout. |
| ; RUN: opt < %s -passes=instcombine -S -data-layout=n32 | FileCheck %s --check-prefix=ALL --check-prefix=CHECK32 |
| ; RUN: opt < %s -passes=instcombine -S -data-layout=n32:64 | FileCheck %s --check-prefix=ALL --check-prefix=CHECK64 |
| |
| define i32 @positive1(i64 %a) { |
| ; ALL-LABEL: define i32 @positive1( |
| ; ALL-SAME: i64 [[A:%.*]]) { |
| ; ALL-NEXT: [[ENTRY:.*]]: |
| ; ALL-NEXT: [[TRUNC:%.*]] = trunc i64 [[A]] to i32 |
| ; ALL-NEXT: switch i32 [[TRUNC]], label %[[SW_DEFAULT:.*]] [ |
| ; ALL-NEXT: i32 10, label %[[RETURN:.*]] |
| ; ALL-NEXT: i32 100, label %[[SW_BB1:.*]] |
| ; ALL-NEXT: i32 1001, label %[[SW_BB2:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[SW_BB1]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_BB2]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_DEFAULT]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[RETURN]]: |
| ; ALL-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 24, %[[SW_DEFAULT]] ], [ 123, %[[SW_BB2]] ], [ 213, %[[SW_BB1]] ], [ 231, %[[ENTRY]] ] |
| ; ALL-NEXT: ret i32 [[RETVAL_0]] |
| ; |
| entry: |
| %and = and i64 %a, 4294967295 |
| switch i64 %and, label %sw.default [ |
| i64 10, label %return |
| i64 100, label %sw.bb1 |
| i64 1001, label %sw.bb2 |
| ] |
| |
| sw.bb1: |
| br label %return |
| |
| sw.bb2: |
| br label %return |
| |
| sw.default: |
| br label %return |
| |
| return: |
| %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] |
| ret i32 %retval.0 |
| } |
| |
| define i32 @negative1(i64 %a) { |
| ; ALL-LABEL: define i32 @negative1( |
| ; ALL-SAME: i64 [[A:%.*]]) { |
| ; ALL-NEXT: [[ENTRY:.*]]: |
| ; ALL-NEXT: [[TRUNC:%.*]] = trunc i64 [[A]] to i32 |
| ; ALL-NEXT: switch i32 [[TRUNC]], label %[[SW_DEFAULT:.*]] [ |
| ; ALL-NEXT: i32 -10, label %[[RETURN:.*]] |
| ; ALL-NEXT: i32 -100, label %[[SW_BB1:.*]] |
| ; ALL-NEXT: i32 -1001, label %[[SW_BB2:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[SW_BB1]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_BB2]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_DEFAULT]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[RETURN]]: |
| ; ALL-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 24, %[[SW_DEFAULT]] ], [ 123, %[[SW_BB2]] ], [ 213, %[[SW_BB1]] ], [ 231, %[[ENTRY]] ] |
| ; ALL-NEXT: ret i32 [[RETVAL_0]] |
| ; |
| entry: |
| %or = or i64 %a, -4294967296 |
| switch i64 %or, label %sw.default [ |
| i64 -10, label %return |
| i64 -100, label %sw.bb1 |
| i64 -1001, label %sw.bb2 |
| ] |
| |
| sw.bb1: |
| br label %return |
| |
| sw.bb2: |
| br label %return |
| |
| sw.default: |
| br label %return |
| |
| return: |
| %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] |
| ret i32 %retval.0 |
| } |
| |
| ; Make sure truncating a constant int larger than 64-bit doesn't trigger an |
| ; assertion. |
| |
| define i32 @trunc72to68(i72 %a) { |
| ; ALL-LABEL: define i32 @trunc72to68( |
| ; ALL-SAME: i72 [[A:%.*]]) { |
| ; ALL-NEXT: [[ENTRY:.*]]: |
| ; ALL-NEXT: [[TRUNC:%.*]] = trunc i72 [[A]] to i68 |
| ; ALL-NEXT: switch i68 [[TRUNC]], label %[[SW_DEFAULT:.*]] [ |
| ; ALL-NEXT: i68 10, label %[[RETURN:.*]] |
| ; ALL-NEXT: i68 100, label %[[SW_BB1:.*]] |
| ; ALL-NEXT: i68 1001, label %[[SW_BB2:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[SW_BB1]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_BB2]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_DEFAULT]]: |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[RETURN]]: |
| ; ALL-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 24, %[[SW_DEFAULT]] ], [ 123, %[[SW_BB2]] ], [ 213, %[[SW_BB1]] ], [ 231, %[[ENTRY]] ] |
| ; ALL-NEXT: ret i32 [[RETVAL_0]] |
| ; |
| entry: |
| %and = and i72 %a, 295147905179352825855 |
| switch i72 %and, label %sw.default [ |
| i72 10, label %return |
| i72 100, label %sw.bb1 |
| i72 1001, label %sw.bb2 |
| ] |
| |
| sw.bb1: |
| br label %return |
| |
| sw.bb2: |
| br label %return |
| |
| sw.default: |
| br label %return |
| |
| return: |
| %retval.0 = phi i32 [ 24, %sw.default ], [ 123, %sw.bb2 ], [ 213, %sw.bb1 ], [ 231, %entry ] |
| ret i32 %retval.0 |
| } |
| |
| ; Make sure to avoid assertion crashes and use the type before |
| ; truncation to generate the sub constant expressions that leads |
| ; to the recomputed condition. |
| ; We allow truncate from i64 to i58 if in 32-bit mode, |
| ; because both are illegal. |
| |
| define void @trunc64to58(i64 %a) { |
| ; CHECK32-LABEL: define void @trunc64to58( |
| ; CHECK32-SAME: i64 [[A:%.*]]) { |
| ; CHECK32-NEXT: [[ENTRY:.*:]] |
| ; CHECK32-NEXT: [[TMP0:%.*]] = trunc i64 [[A]] to i58 |
| ; CHECK32-NEXT: [[TMP1:%.*]] = and i58 [[TMP0]], 15 |
| ; CHECK32-NEXT: [[TRUNC:%.*]] = mul nuw i58 [[TMP1]], 18717182647723699 |
| ; CHECK32-NEXT: switch i58 [[TRUNC]], label %[[SW_DEFAULT:.*]] [ |
| ; CHECK32-NEXT: i58 0, label %[[SW_BB1:.*]] |
| ; CHECK32-NEXT: i58 18717182647723699, label %[[SW_BB2:.*]] |
| ; CHECK32-NEXT: ] |
| ; CHECK32: [[SW_BB1]]: |
| ; CHECK32-NEXT: br label %[[SW_DEFAULT]] |
| ; CHECK32: [[SW_BB2]]: |
| ; CHECK32-NEXT: br label %[[SW_DEFAULT]] |
| ; CHECK32: [[SW_DEFAULT]]: |
| ; CHECK32-NEXT: ret void |
| ; |
| ; CHECK64-LABEL: define void @trunc64to58( |
| ; CHECK64-SAME: i64 [[A:%.*]]) { |
| ; CHECK64-NEXT: [[ENTRY:.*:]] |
| ; CHECK64-NEXT: [[_TMP0:%.*]] = and i64 [[A]], 15 |
| ; CHECK64-NEXT: [[TMP0:%.*]] = mul nuw nsw i64 [[_TMP0]], 18717182647723699 |
| ; CHECK64-NEXT: switch i64 [[TMP0]], label %[[SW_DEFAULT:.*]] [ |
| ; CHECK64-NEXT: i64 0, label %[[SW_BB1:.*]] |
| ; CHECK64-NEXT: i64 18717182647723699, label %[[SW_BB2:.*]] |
| ; CHECK64-NEXT: ] |
| ; CHECK64: [[SW_BB1]]: |
| ; CHECK64-NEXT: br label %[[SW_DEFAULT]] |
| ; CHECK64: [[SW_BB2]]: |
| ; CHECK64-NEXT: br label %[[SW_DEFAULT]] |
| ; CHECK64: [[SW_DEFAULT]]: |
| ; CHECK64-NEXT: ret void |
| ; |
| entry: |
| %tmp0 = and i64 %a, 15 |
| %tmp1 = mul i64 %tmp0, -6425668444178048401 |
| %tmp2 = add i64 %tmp1, 5170979678563097242 |
| %tmp3 = mul i64 %tmp2, 1627972535142754813 |
| switch i64 %tmp3, label %sw.default [ |
| i64 847514119312061490, label %sw.bb1 |
| i64 866231301959785189, label %sw.bb2 |
| ] |
| |
| sw.bb1: |
| br label %sw.default |
| |
| sw.bb2: |
| br label %sw.default |
| |
| sw.default: |
| ret void |
| } |
| |
| ; https://llvm.org/bugs/show_bug.cgi?id=31260 |
| |
| define i8 @PR31260(i8 %x) { |
| ; ALL-LABEL: define i8 @PR31260( |
| ; ALL-SAME: i8 [[X:%.*]]) { |
| ; ALL-NEXT: [[ENTRY:.*:]] |
| ; ALL-NEXT: [[T4:%.*]] = and i8 [[X]], 2 |
| ; ALL-NEXT: switch i8 [[T4]], label %[[EXIT:.*]] [ |
| ; ALL-NEXT: i8 0, label %[[CASE126:.*]] |
| ; ALL-NEXT: i8 2, label %[[CASE124:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[EXIT]]: |
| ; ALL-NEXT: ret i8 1 |
| ; ALL: [[CASE126]]: |
| ; ALL-NEXT: ret i8 3 |
| ; ALL: [[CASE124]]: |
| ; ALL-NEXT: ret i8 5 |
| ; |
| entry: |
| %t4 = and i8 %x, 2 |
| %t5 = add nsw i8 %t4, -126 |
| switch i8 %t5, label %exit [ |
| i8 -126, label %case126 |
| i8 -124, label %case124 |
| ] |
| |
| exit: |
| ret i8 1 |
| case126: |
| ret i8 3 |
| case124: |
| ret i8 5 |
| } |
| |
| ; Make sure the arithmetic evaluation of the switch |
| ; condition is evaluated on the original type |
| define i32 @trunc32to16(i32 %a0) #0 { |
| ; ALL-LABEL: define i32 @trunc32to16( |
| ; ALL-SAME: i32 [[A0:%.*]]) { |
| ; ALL-NEXT: [[ENTRY:.*:]] |
| ; ALL-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 |
| ; ALL-NEXT: [[XOR:%.*]] = lshr i32 [[A0]], 16 |
| ; ALL-NEXT: [[TMP0:%.*]] = trunc nuw i32 [[XOR]] to i16 |
| ; ALL-NEXT: [[TRUNC:%.*]] = xor i16 [[TMP0]], 15784 |
| ; ALL-NEXT: switch i16 [[TRUNC]], label %[[SW_EPILOG:.*]] [ |
| ; ALL-NEXT: i16 63, label %[[SW_BB:.*]] |
| ; ALL-NEXT: i16 1, label %[[SW_BB1:.*]] |
| ; ALL-NEXT: i16 100, label %[[SW_BB2:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[SW_BB]]: |
| ; ALL-NEXT: store i32 90, ptr [[RETVAL]], align 4 |
| ; ALL-NEXT: br label %[[RETURN:.*]] |
| ; ALL: [[SW_BB1]]: |
| ; ALL-NEXT: store i32 91, ptr [[RETVAL]], align 4 |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_BB2]]: |
| ; ALL-NEXT: store i32 92, ptr [[RETVAL]], align 4 |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[SW_EPILOG]]: |
| ; ALL-NEXT: store i32 113, ptr [[RETVAL]], align 4 |
| ; ALL-NEXT: br label %[[RETURN]] |
| ; ALL: [[RETURN]]: |
| ; ALL-NEXT: [[RVAL:%.*]] = load i32, ptr [[RETVAL]], align 4 |
| ; ALL-NEXT: ret i32 [[RVAL]] |
| ; |
| entry: |
| %retval = alloca i32, align 4 |
| %xor = xor i32 %a0, 1034460917 |
| %shr = lshr i32 %xor, 16 |
| %add = add i32 %shr, -917677090 |
| switch i32 %add, label %sw.epilog [ |
| i32 -917677027, label %sw.bb |
| i32 -917677089, label %sw.bb1 |
| i32 -917676990, label %sw.bb2 |
| ] |
| |
| sw.bb: ; preds = %entry |
| store i32 90, ptr %retval, align 4 |
| br label %return |
| |
| sw.bb1: ; preds = %entry |
| store i32 91, ptr %retval, align 4 |
| br label %return |
| |
| sw.bb2: ; preds = %entry |
| store i32 92, ptr %retval, align 4 |
| br label %return |
| |
| sw.epilog: ; preds = %entry |
| store i32 113, ptr %retval, align 4 |
| br label %return |
| |
| return: ; preds = %sw.epilog, %sw.bb2, |
| %rval = load i32, ptr %retval, align 4 |
| ret i32 %rval |
| } |
| |
| ; https://llvm.org/bugs/show_bug.cgi?id=29009 |
| |
| @a = global i32 0, align 4 |
| @njob = global i32 0, align 4 |
| |
| declare i32 @goo() |
| |
| ; Make sure we do not shrink to illegal types (i3 in this case) |
| ; if original type is legal (i32 in this case) |
| |
| define void @PR29009() { |
| ; ALL-LABEL: define void @PR29009() { |
| ; ALL-NEXT: br label %[[BB1:.*]] |
| ; ALL: [[BB1]]: |
| ; ALL-NEXT: [[TMP2:%.*]] = load volatile i32, ptr @njob, align 4 |
| ; ALL-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP2]], 0 |
| ; ALL-NEXT: br i1 [[DOTNOT]], label %[[BB10:.*]], label %[[BB3:.*]] |
| ; ALL: [[BB3]]: |
| ; ALL-NEXT: [[TMP4:%.*]] = call i32 @goo() |
| ; ALL-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 7 |
| ; ALL-NEXT: switch i32 [[TMP5]], label %[[BB6:.*]] [ |
| ; ALL-NEXT: i32 0, label %[[BB7:.*]] |
| ; ALL-NEXT: i32 3, label %[[BB8:.*]] |
| ; ALL-NEXT: ] |
| ; ALL: [[BB6]]: |
| ; ALL-NEXT: store i32 6, ptr @a, align 4 |
| ; ALL-NEXT: br label %[[BB9:.*]] |
| ; ALL: [[BB7]]: |
| ; ALL-NEXT: store i32 1, ptr @a, align 4 |
| ; ALL-NEXT: br label %[[BB9]] |
| ; ALL: [[BB8]]: |
| ; ALL-NEXT: store i32 2, ptr @a, align 4 |
| ; ALL-NEXT: br label %[[BB9]] |
| ; ALL: [[BB9]]: |
| ; ALL-NEXT: br label %[[BB1]] |
| ; ALL: [[BB10]]: |
| ; ALL-NEXT: ret void |
| ; |
| br label %1 |
| |
| ; <label>:1: ; preds = %10, %0 |
| %2 = load volatile i32, ptr @njob, align 4 |
| %3 = icmp ne i32 %2, 0 |
| br i1 %3, label %4, label %11 |
| |
| ; <label>:4: ; preds = %1 |
| %5 = call i32 @goo() |
| %6 = and i32 %5, 7 |
| switch i32 %6, label %7 [ |
| i32 0, label %8 |
| i32 3, label %9 |
| ] |
| |
| ; <label>:7: ; preds = %4 |
| store i32 6, ptr @a, align 4 |
| br label %10 |
| |
| ; <label>:8: ; preds = %4 |
| store i32 1, ptr @a, align 4 |
| br label %10 |
| |
| ; <label>:9: ; preds = %4 |
| store i32 2, ptr @a, align 4 |
| br label %10 |
| |
| ; <label>:10: ; preds = %13, %12, %11, %10, %9, %8, %7 |
| br label %1 |
| |
| ; <label>:11: ; preds = %1 |
| ret void |
| } |
| |