| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s |
| |
| declare i32 @strcmp(ptr, ptr) |
| |
| @s0 = constant [1 x i8] c"\00" |
| @s1 = constant [2 x i8] c"0\00" |
| @s2 = constant [3 x i8] c"01\00" |
| @s3 = constant [4 x i8] c"012\00" |
| @s4 = constant [5 x i8] c"0123\00" |
| |
| ; Expand strcmp(C, "x"), strcmp(C, "xy"). |
| |
| define i1 @expand_strcmp_s0(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s0( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s0) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s0) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_eq_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_eq_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_eq_s1_commuted(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_eq_s1_commuted( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr @s1, ptr [[C:%.*]]) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr @s1, ptr %C) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_ne_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_ne_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp ne i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sgt_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sgt_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp sgt i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sge_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sge_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp sge i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_slt_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_slt_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp slt i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sle_s1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sle_s1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp sle i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_s1_fail_1(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s1_fail_1( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 1 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| %cmp = icmp eq i32 %call, 1 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_s1_fail_2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s1_fail_2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr @s1, ptr @s1) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr @s1, ptr @s1) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i32 @expand_strcmp_s1_fail_3(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s1_fail_3( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s1) |
| ; CHECK-NEXT: ret i32 [[CALL]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s1) |
| ret i32 %call |
| } |
| |
| define i1 @expand_strcmp_eq_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_eq_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_ne_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_ne_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp ne i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sgt_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sgt_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp sgt i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sge_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sge_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp sge i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_slt_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_slt_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp slt i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_sle_s2(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_sle_s2( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s2) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s2) |
| %cmp = icmp sle i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_s3(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s3( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s3) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s3) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |
| |
| define i1 @expand_strcmp_s4(ptr %C) { |
| ; CHECK-LABEL: @expand_strcmp_s4( |
| ; CHECK-NEXT: [[CALL:%.*]] = call i32 @strcmp(ptr [[C:%.*]], ptr @s4) |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| %call = call i32 @strcmp(ptr %C, ptr @s4) |
| %cmp = icmp eq i32 %call, 0 |
| ret i1 %cmp |
| } |