diff options
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG/implied-and-or.ll')
-rw-r--r-- | llvm/test/Transforms/SimplifyCFG/implied-and-or.ll | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/implied-and-or.ll b/llvm/test/Transforms/SimplifyCFG/implied-and-or.ll new file mode 100644 index 00000000000..dd885c94bdc --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/implied-and-or.ll @@ -0,0 +1,250 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -simplifycfg | FileCheck %s + +declare void @foo() +declare void @bar() + +define void @test_and1(i32 %a, i32 %b) { +; CHECK-LABEL: @test_and1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: br i1 [[AND]], label [[TAKEN:%.*]], label [[END:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp eq i32 %b, 0 + %and = and i1 %cmp1, %cmp2 + br i1 %and, label %taken, label %end + +taken: + call void @bar() + %cmp3 = icmp eq i32 %a, 0 ;; <-- implied true + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + +; We can't infer anything if the result of the 'and' is false + +define void @test_and2(i32 %a, i32 %b) { +; CHECK-LABEL: @test_and2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: br i1 [[AND]], label [[END:%.*]], label [[TAKEN:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] +; CHECK: if.then: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp eq i32 %b, 0 + %and = and i1 %cmp1, %cmp2 + br i1 %and, label %end, label %taken + +taken: + call void @bar() + %cmp3 = icmp eq i32 %a, 0 + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + +define void @test_or1(i32 %a, i32 %b) { +; CHECK-LABEL: @test_or1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[TAKEN:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp eq i32 %b, 0 + %or = or i1 %cmp1, %cmp2 + br i1 %or, label %end, label %taken + +taken: + call void @bar() + %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + +; We can't infer anything if the result of the 'or' is true + +define void @test_or2(i32 %a, i32 %b) { +; CHECK-LABEL: @test_or2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: br i1 [[OR]], label [[TAKEN:%.*]], label [[END:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] +; CHECK: if.then: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp eq i32 %b, 0 + %or = or i1 %cmp1, %cmp2 + br i1 %or, label %taken, label %end + +taken: + call void @bar() + %cmp3 = icmp eq i32 %a, 0 + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + +; We can recurse a tree of 'and' or 'or's. + +define void @test_and_recurse1(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @test_and_recurse1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0 +; CHECK-NEXT: [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]] +; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]] +; CHECK-NEXT: br i1 [[AND2]], label [[TAKEN:%.*]], label [[END:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cmpa = icmp eq i32 %a, 0 + %cmpb = icmp eq i32 %b, 0 + %cmpc = icmp eq i32 %c, 0 + %and1 = and i1 %cmpa, %cmpb + %and2 = and i1 %and1, %cmpc + br i1 %and2, label %taken, label %end + +taken: + call void @bar() + %cmp3 = icmp eq i32 %a, 0 + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + +; Check to make sure we don't recurse too deep. + +define void @test_and_recurse2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, +; CHECK-LABEL: @test_and_recurse2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0 +; CHECK-NEXT: [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0 +; CHECK-NEXT: [[CMPD:%.*]] = icmp eq i32 [[D:%.*]], 0 +; CHECK-NEXT: [[CMPE:%.*]] = icmp eq i32 [[E:%.*]], 0 +; CHECK-NEXT: [[CMPF:%.*]] = icmp eq i32 [[F:%.*]], 0 +; CHECK-NEXT: [[CMPG:%.*]] = icmp eq i32 [[G:%.*]], 0 +; CHECK-NEXT: [[CMPH:%.*]] = icmp eq i32 [[H:%.*]], 0 +; CHECK-NEXT: [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]] +; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]] +; CHECK-NEXT: [[AND3:%.*]] = and i1 [[AND2]], [[CMPD]] +; CHECK-NEXT: [[AND4:%.*]] = and i1 [[AND3]], [[CMPE]] +; CHECK-NEXT: [[AND5:%.*]] = and i1 [[AND4]], [[CMPF]] +; CHECK-NEXT: [[AND6:%.*]] = and i1 [[AND5]], [[CMPG]] +; CHECK-NEXT: [[AND7:%.*]] = and i1 [[AND6]], [[CMPH]] +; CHECK-NEXT: br i1 [[AND7]], label [[TAKEN:%.*]], label [[END:%.*]] +; CHECK: taken: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] +; CHECK: if.then: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; + i32 %g, i32 %h) { +entry: + %cmpa = icmp eq i32 %a, 0 + %cmpb = icmp eq i32 %b, 0 + %cmpc = icmp eq i32 %c, 0 + %cmpd = icmp eq i32 %d, 0 + %cmpe = icmp eq i32 %e, 0 + %cmpf = icmp eq i32 %f, 0 + %cmpg = icmp eq i32 %g, 0 + %cmph = icmp eq i32 %h, 0 + %and1 = and i1 %cmpa, %cmpb + %and2 = and i1 %and1, %cmpc + %and3 = and i1 %and2, %cmpd + %and4 = and i1 %and3, %cmpe + %and5 = and i1 %and4, %cmpf + %and6 = and i1 %and5, %cmpg + %and7 = and i1 %and6, %cmph + br i1 %and7, label %taken, label %end + +taken: + call void @bar() + %cmp3 = icmp eq i32 %a, 0 ; <-- can be implied true + br i1 %cmp3, label %if.then, label %end + +if.then: + call void @foo() + br label %end + +end: + ret void +} + |