| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s |
| |
| define i32 @known_non_zero_by_or(i32 %x, i32 %y) { |
| ; CHECK-LABEL: define i32 @known_non_zero_by_or( |
| ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] |
| ; CHECK: [[IF_THEN]]: |
| ; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] |
| ; CHECK-NEXT: ret i32 [[VAL]] |
| ; CHECK: [[IF_ELSE]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %cond = icmp ne i32 %x, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| %val = or i32 %x, %y |
| %max = call i32 @llvm.umax.i32(i32 %val, i32 1) |
| ret i32 %max |
| |
| if.else: |
| ret i32 0 |
| } |
| |
| define i32 @known_non_zero_by_mul(i32 %x) { |
| ; CHECK-LABEL: define i32 @known_non_zero_by_mul( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] |
| ; CHECK: [[IF_THEN]]: |
| ; CHECK-NEXT: [[NONZERO1:%.*]] = mul nuw i32 [[X]], 3 |
| ; CHECK-NEXT: ret i32 [[NONZERO1]] |
| ; CHECK: [[IF_ELSE]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %cond = icmp ne i32 %x, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| %nonzero = mul nuw i32 %x, 3 |
| %max = call i32 @llvm.umax.i32(i32 %nonzero, i32 1) |
| ret i32 %max |
| |
| if.else: |
| ret i32 0 |
| } |
| |
| define i32 @known_non_zero_commute(i32 %x, i32 %y) { |
| ; CHECK-LABEL: define i32 @known_non_zero_commute( |
| ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] |
| ; CHECK: [[IF_THEN]]: |
| ; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] |
| ; CHECK-NEXT: ret i32 [[VAL]] |
| ; CHECK: [[IF_ELSE]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %cond = icmp ne i32 %x, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| %val = or i32 %x, %y |
| %max = call i32 @llvm.umax.i32(i32 1, i32 %val) |
| ret i32 %max |
| |
| if.else: |
| ret i32 0 |
| } |
| |
| ; Negative |
| define i32 @umax_ge_2(i32 %x, i32 %y) { |
| ; CHECK-LABEL: define i32 @umax_ge_2( |
| ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] |
| ; CHECK: [[IF_THEN]]: |
| ; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]] |
| ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 2) |
| ; CHECK-NEXT: ret i32 [[MAX]] |
| ; CHECK: [[IF_ELSE]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %cond = icmp ne i32 %x, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| %val = or i32 %x, %y |
| %max = call i32 @llvm.umax.i32(i32 %val, i32 2) |
| ret i32 %max |
| |
| if.else: |
| ret i32 0 |
| } |
| |
| define i32 @unknown_by_and(i32 %x, i32 %y) { |
| ; CHECK-LABEL: define i32 @unknown_by_and( |
| ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] |
| ; CHECK: [[IF_THEN]]: |
| ; CHECK-NEXT: [[VAL:%.*]] = and i32 [[X]], [[Y]] |
| ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 1) |
| ; CHECK-NEXT: ret i32 [[MAX]] |
| ; CHECK: [[IF_ELSE]]: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| %cond = icmp ne i32 %x, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| %val = and i32 %x, %y |
| %max = call i32 @llvm.umax.i32(i32 %val, i32 1) |
| ret i32 %max |
| |
| if.else: |
| ret i32 0 |
| } |